@take-out/helpers 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/async/asyncContext.cjs +12 -9
- package/dist/cjs/async/asyncContext.native.js +3 -1
- package/dist/cjs/async/asyncContext.native.js.map +1 -1
- package/dist/cjs/async/asyncContext.test.cjs +28 -0
- package/dist/cjs/async/asyncContext.test.native.js +64 -0
- package/dist/cjs/async/asyncContext.test.native.js.map +1 -0
- package/dist/esm/async/asyncContext.mjs +11 -9
- package/dist/esm/async/asyncContext.mjs.map +1 -1
- package/dist/esm/async/asyncContext.native.js +2 -1
- package/dist/esm/async/asyncContext.native.js.map +1 -1
- package/dist/esm/async/asyncContext.test.mjs +29 -0
- package/dist/esm/async/asyncContext.test.mjs.map +1 -0
- package/dist/esm/async/asyncContext.test.native.js +62 -0
- package/dist/esm/async/asyncContext.test.native.js.map +1 -0
- package/package.json +1 -1
- package/src/async/asyncContext.native.ts +2 -0
- package/src/async/asyncContext.test.ts +45 -0
- package/src/async/asyncContext.ts +19 -9
- package/types/async/asyncContext.d.ts +8 -0
- package/types/async/asyncContext.d.ts.map +2 -2
- package/types/async/asyncContext.native.d.ts +1 -0
- package/types/async/asyncContext.native.d.ts.map +2 -2
- package/types/async/asyncContext.test.d.ts +3 -0
- package/types/async/asyncContext.test.d.ts.map +11 -0
|
@@ -20,12 +20,17 @@ var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
|
|
|
20
20
|
}), mod);
|
|
21
21
|
var asyncContext_exports = {};
|
|
22
22
|
__export(asyncContext_exports, {
|
|
23
|
-
createAsyncContext: () => createAsyncContext
|
|
23
|
+
createAsyncContext: () => createAsyncContext,
|
|
24
|
+
setupAsyncLocalStorage: () => setupAsyncLocalStorage
|
|
24
25
|
});
|
|
25
26
|
module.exports = __toCommonJS(asyncContext_exports);
|
|
26
27
|
var import_isServerRuntime = require("../server/isServerRuntime.cjs");
|
|
27
|
-
let nodeAsyncLocalStorageCache = null
|
|
28
|
+
let nodeAsyncLocalStorageCache = null,
|
|
29
|
+
configuredAsyncLocalStorage = null;
|
|
28
30
|
const nodeModuleId = ["node", "async_hooks"].join(":");
|
|
31
|
+
function setupAsyncLocalStorage(AsyncLocalStorage) {
|
|
32
|
+
configuredAsyncLocalStorage = AsyncLocalStorage;
|
|
33
|
+
}
|
|
29
34
|
async function getNodeAsyncLocalStorage() {
|
|
30
35
|
if (!nodeAsyncLocalStorageCache) try {
|
|
31
36
|
nodeAsyncLocalStorageCache = (await import(/* @vite-ignore */
|
|
@@ -38,18 +43,16 @@ async function getNodeAsyncLocalStorage() {
|
|
|
38
43
|
function createAsyncContext() {
|
|
39
44
|
if ((0, import_isServerRuntime.isServerRuntime)()) {
|
|
40
45
|
let storage = null;
|
|
41
|
-
|
|
46
|
+
const storageReady = Promise.resolve(configuredAsyncLocalStorage).then(AsyncLocalStorage => AsyncLocalStorage || getNodeAsyncLocalStorage()).then(AsyncLocalStorage => {
|
|
42
47
|
AsyncLocalStorage && !storage && (storage = new AsyncLocalStorage());
|
|
43
|
-
})
|
|
48
|
+
});
|
|
49
|
+
return {
|
|
44
50
|
get() {
|
|
45
|
-
if (!storage)
|
|
46
|
-
console.warn("\u26A0\uFE0F called AsyncContext before load!");
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
51
|
+
if (!storage) throw new Error("AsyncContext storage not initialized");
|
|
49
52
|
return storage.getStore();
|
|
50
53
|
},
|
|
51
54
|
async run(value, fn) {
|
|
52
|
-
if (!storage) throw new Error("
|
|
55
|
+
if (storage || (await storageReady), !storage) throw new Error("AsyncContext storage unavailable in server runtime");
|
|
53
56
|
return storage.run(value, fn);
|
|
54
57
|
}
|
|
55
58
|
};
|
|
@@ -22,9 +22,11 @@ var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
|
|
|
22
22
|
}), mod);
|
|
23
23
|
var asyncContext_native_exports = {};
|
|
24
24
|
__export(asyncContext_native_exports, {
|
|
25
|
-
createAsyncContext: () => createAsyncContext
|
|
25
|
+
createAsyncContext: () => createAsyncContext,
|
|
26
|
+
setupAsyncLocalStorage: () => setupAsyncLocalStorage
|
|
26
27
|
});
|
|
27
28
|
module.exports = __toCommonJS(asyncContext_native_exports);
|
|
29
|
+
function setupAsyncLocalStorage(_AsyncLocalStorage) {}
|
|
28
30
|
function createAsyncContext() {
|
|
29
31
|
var currentContext,
|
|
30
32
|
contextStack = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["asyncContext_native_exports","__export","createAsyncContext","module","exports","__toCommonJS","currentContext","contextStack","get","run","value","fn","prevContext","push","OriginalPromise","Promise","OriginalThen","prototype","then","OriginalCatch","catch","OriginalFinally","finally","wrapCallback","callback","context","_len","arguments","length","args","Array","_key","prevContext2","onFulfilled","onRejected","call","onFinally","result","pop"],"sources":["../../../src/async/asyncContext.native.ts"],"sourcesContent":[null],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,2BAAA;AAAAC,QAAA,CAAAD,2BAAA;EAAAE,kBAAA,EAAAA,CAAA,KAAAA;AAAA;AAAAC,MAAA,CAAAC,OAAA,GAAAC,YAAA,
|
|
1
|
+
{"version":3,"names":["asyncContext_native_exports","__export","createAsyncContext","setupAsyncLocalStorage","module","exports","__toCommonJS","_AsyncLocalStorage","currentContext","contextStack","get","run","value","fn","prevContext","push","OriginalPromise","Promise","OriginalThen","prototype","then","OriginalCatch","catch","OriginalFinally","finally","wrapCallback","callback","context","_len","arguments","length","args","Array","_key","prevContext2","onFulfilled","onRejected","call","onFinally","result","pop"],"sources":["../../../src/async/asyncContext.native.ts"],"sourcesContent":[null],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,2BAAA;AAAAC,QAAA,CAAAD,2BAAA;EAAAE,kBAAA,EAAAA,CAAA,KAAAA,kBAAA;EAAAC,sBAAA,EAAAA,CAAA,KAAAA;AAAA;AAAAC,MAAA,CAAAC,OAAA,GAAAC,YAAA,CAAAN,2BAAA;AAAO,SAASG,uBAAuBI,kBAAA,EAAoB,CAAC;AAErD,SAASL,mBAAA,EAAqB;EACjC,IAAIM,cAAA;IACAC,YAAA,GAAe,EAAC;EACpB,OAAO;IACHC,IAAA,EAAO;MACH,OAAOF,cAAA;IACX;IACA,MAAMG,IAAKC,KAAA,EAAOC,EAAA,EAAI;MAClB,IAAIC,WAAA,GAAcN,cAAA;MAClBA,cAAA,GAAiBI,KAAA,EACjBH,YAAA,CAAaM,IAAA,CAAKD,WAAW;MAE7B,IAAIE,eAAA,GAAkBC,OAAA;QAClBC,YAAA,GAAeF,eAAA,CAAgBG,SAAA,CAAUC,IAAA;QACzCC,aAAA,GAAgBL,eAAA,CAAgBG,SAAA,CAAUG,KAAA;QAC1CC,eAAA,GAAkBP,eAAA,CAAgBG,SAAA,CAAUK,OAAA;MAChD,SAASC,aAAaC,QAAA,EAAUC,OAAA,EAAS;QACrC,OAAKD,QAAA,IACE,YAAW;UACd,SAAQE,IAAA,GAAOC,SAAA,CAAUC,MAAA,EAAQC,IAAA,GAAO,IAAIC,KAAA,CAAMJ,IAAI,GAAGK,IAAA,GAAO,GAAGA,IAAA,GAAOL,IAAA,EAAMK,IAAA,IAC5EF,IAAA,CAAKE,IAAI,IAAIJ,SAAA,CAAUI,IAAI;UAE/B,IAAIC,YAAA,GAAc1B,cAAA;UAClBA,cAAA,GAAiBmB,OAAA;UACjB,IAAI;YACA,OAAOD,QAAA,CAAS,GAAGK,IAAI;UAC3B,UAAE;YACEvB,cAAA,GAAiB0B,YAAA;UACrB;QACJ;MACJ;MAGAlB,eAAA,CAAgBG,SAAA,CAAUC,IAAA,GAAO,UAASe,WAAA,EAAaC,UAAA,EAAY;QAC/D,IAAIT,OAAA,GAAUnB,cAAA;QACd,OAAOU,YAAA,CAAamB,IAAA,CAAK,MAAMZ,YAAA,CAAaU,WAAA,EAAaR,OAAO,GAAGF,YAAA,CAAaW,UAAA,EAAYT,OAAO,CAAC;MACxG,GACAX,eAAA,CAAgBG,SAAA,CAAUG,KAAA,GAAQ,UAASc,UAAA,EAAY;QACnD,IAAIT,OAAA,GAAUnB,cAAA;QACd,OAAOa,aAAA,CAAcgB,IAAA,CAAK,MAAMZ,YAAA,CAAaW,UAAA,EAAYT,OAAO,CAAC;MACrE,GACAX,eAAA,CAAgBG,SAAA,CAAUK,OAAA,GAAU,UAASc,SAAA,EAAW;QACpD,IAAIX,OAAA,GAAUnB,cAAA;QACd,OAAOe,eAAA,CAAgBc,IAAA,CAAK,MAAMZ,YAAA,CAAaa,SAAA,EAAWX,OAAO,CAAC;MACtE;MACA,IAAI;QACA,IAAIY,MAAA,GAAS,MAAM1B,EAAA,CAAG;QACtB,OAAO0B,MAAA;MACX,UAAE;QAGEvB,eAAA,CAAgBG,SAAA,CAAUC,IAAA,GAAOF,YAAA,EACjCF,eAAA,CAAgBG,SAAA,CAAUG,KAAA,GAAQD,aAAA,EAClCL,eAAA,CAAgBG,SAAA,CAAUK,OAAA,GAAUD,eAAA,EACpCd,YAAA,CAAa+B,GAAA,CAAI,GACjBhC,cAAA,GAAiBM,WAAA;MACrB;IACJ;EACJ;AACJ","ignoreList":[]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
var import_vitest = require("vitest"),
|
|
2
|
+
import_asyncContext = require("./asyncContext.cjs");
|
|
3
|
+
class TestAsyncLocalStorage {
|
|
4
|
+
store;
|
|
5
|
+
getStore() {
|
|
6
|
+
return this.store;
|
|
7
|
+
}
|
|
8
|
+
run(store, callback) {
|
|
9
|
+
const prevStore = this.store;
|
|
10
|
+
this.store = store;
|
|
11
|
+
try {
|
|
12
|
+
return callback();
|
|
13
|
+
} finally {
|
|
14
|
+
this.store = prevStore;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
(0, import_vitest.describe)("createAsyncContext", () => {
|
|
19
|
+
(0, import_vitest.test)("uses configured async local storage when provided", async () => {
|
|
20
|
+
(0, import_asyncContext.setupAsyncLocalStorage)(TestAsyncLocalStorage);
|
|
21
|
+
const context = (0, import_asyncContext.createAsyncContext)();
|
|
22
|
+
await (0, import_vitest.expect)(context.run("viewer-1", async () => context.get())).resolves.toBe("viewer-1"), (0, import_asyncContext.setupAsyncLocalStorage)(null);
|
|
23
|
+
}), (0, import_vitest.test)("initializes server storage before first run", async () => {
|
|
24
|
+
(0, import_asyncContext.setupAsyncLocalStorage)(null);
|
|
25
|
+
const context = (0, import_asyncContext.createAsyncContext)();
|
|
26
|
+
await (0, import_vitest.expect)(context.run("viewer-1", async () => context.get())).resolves.toBe("viewer-1");
|
|
27
|
+
});
|
|
28
|
+
});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var import_vitest = require("vitest"),
|
|
4
|
+
import_asyncContext = require("./asyncContext.native.js");
|
|
5
|
+
function _class_call_check(instance, Constructor) {
|
|
6
|
+
if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function");
|
|
7
|
+
}
|
|
8
|
+
function _defineProperties(target, props) {
|
|
9
|
+
for (var i = 0; i < props.length; i++) {
|
|
10
|
+
var descriptor = props[i];
|
|
11
|
+
descriptor.enumerable = descriptor.enumerable || !1, descriptor.configurable = !0, "value" in descriptor && (descriptor.writable = !0), Object.defineProperty(target, descriptor.key, descriptor);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function _create_class(Constructor, protoProps, staticProps) {
|
|
15
|
+
return protoProps && _defineProperties(Constructor.prototype, protoProps), staticProps && _defineProperties(Constructor, staticProps), Constructor;
|
|
16
|
+
}
|
|
17
|
+
function _define_property(obj, key, value) {
|
|
18
|
+
return key in obj ? Object.defineProperty(obj, key, {
|
|
19
|
+
value,
|
|
20
|
+
enumerable: !0,
|
|
21
|
+
configurable: !0,
|
|
22
|
+
writable: !0
|
|
23
|
+
}) : obj[key] = value, obj;
|
|
24
|
+
}
|
|
25
|
+
var TestAsyncLocalStorage = /* @__PURE__ */function () {
|
|
26
|
+
"use strict";
|
|
27
|
+
|
|
28
|
+
function TestAsyncLocalStorage2() {
|
|
29
|
+
_class_call_check(this, TestAsyncLocalStorage2), _define_property(this, "store", void 0);
|
|
30
|
+
}
|
|
31
|
+
return _create_class(TestAsyncLocalStorage2, [{
|
|
32
|
+
key: "getStore",
|
|
33
|
+
value: function () {
|
|
34
|
+
return this.store;
|
|
35
|
+
}
|
|
36
|
+
}, {
|
|
37
|
+
key: "run",
|
|
38
|
+
value: function (store, callback) {
|
|
39
|
+
var prevStore = this.store;
|
|
40
|
+
this.store = store;
|
|
41
|
+
try {
|
|
42
|
+
return callback();
|
|
43
|
+
} finally {
|
|
44
|
+
this.store = prevStore;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}]), TestAsyncLocalStorage2;
|
|
48
|
+
}();
|
|
49
|
+
(0, import_vitest.describe)("createAsyncContext", function () {
|
|
50
|
+
(0, import_vitest.test)("uses configured async local storage when provided", async function () {
|
|
51
|
+
(0, import_asyncContext.setupAsyncLocalStorage)(TestAsyncLocalStorage);
|
|
52
|
+
var context = (0, import_asyncContext.createAsyncContext)();
|
|
53
|
+
await (0, import_vitest.expect)(context.run("viewer-1", async function () {
|
|
54
|
+
return context.get();
|
|
55
|
+
})).resolves.toBe("viewer-1"), (0, import_asyncContext.setupAsyncLocalStorage)(null);
|
|
56
|
+
}), (0, import_vitest.test)("initializes server storage before first run", async function () {
|
|
57
|
+
(0, import_asyncContext.setupAsyncLocalStorage)(null);
|
|
58
|
+
var context = (0, import_asyncContext.createAsyncContext)();
|
|
59
|
+
await (0, import_vitest.expect)(context.run("viewer-1", async function () {
|
|
60
|
+
return context.get();
|
|
61
|
+
})).resolves.toBe("viewer-1");
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
//# sourceMappingURL=asyncContext.test.native.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["import_vitest","require","import_asyncContext","_class_call_check","instance","Constructor","TypeError","_defineProperties","target","props","i","length","descriptor","enumerable","configurable","writable","Object","defineProperty","key","_create_class","protoProps","staticProps","prototype","_define_property","obj","value","TestAsyncLocalStorage","TestAsyncLocalStorage2"],"sources":["../../../src/async/asyncContext.test.ts"],"sourcesContent":[null],"mappings":"AAAA;;AAIA,IAAAA,aAAM,GAAAC,OAAA,CAAyB;EAAAC,mBAAA,GAAAD,OAAA;AAAA,SACrBE,kBAAAC,QAAA,EAAAC,WAAA;EAER,MAAAD,QAA0B,YAAAC,WAAA,GACxB,UAAOC,SAAK;AAAA;AACd,SAEOC,iBAAgCA,CAAAC,MAAA,EAAAC,KAAA;EACrC,SAAMC,CAAA,MAAAA,CAAA,GAAYD,KAAK,CAAAE,MAAA,EAAAD,CAAA;IACvB,IAAAE,UAAa,GAAAH,KAAA,CAAAC,CAAA;IACbE,UAAI,CAAAC,UAAA,GAAAD,UAAA,CAAAC,UAAA,QAAAD,UAAA,CAAAE,YAAA,kBAAAF,UAAA,KAAAA,UAAA,CAAAG,QAAA,QAAAC,MAAA,CAAAC,cAAA,CAAAT,MAAA,EAAAI,UAAA,CAAAM,GAAA,EAAAN,UAAA;EACF;AAAgB;AAEhB,SAAAO,aAAaA,CAAAd,WAAA,EAAAe,UAAA,EAAAC,WAAA;EAAA,OACfD,UAAA,IAAAb,iBAAA,CAAAF,WAAA,CAAAiB,SAAA,EAAAF,UAAA,GAAAC,WAAA,IAAAd,iBAAA,CAAAF,WAAA,EAAAgB,WAAA,GAAAhB,WAAA;AAAA;AAEJ,SAAAkB,iBAAAC,GAAA,EAAAN,GAAA,EAAAO,KAAA;EAAA,OAEAP,GAAA,IAAAM,GAAA,GAAAR,MAAS,CAAAC,cAAA,CAAAO,GAAA,EAAAN,GAAsB;IAC7BO,KAAA;IACEZ,UAAA;IAEAC,YAAM;IAENC,QAAA,EAAM;EAAoE,KACxES,GAAA,CAAAN,GAAA,IAAAO,KAAA,EAAAD,GAAA;AAAA;AAGyB,IAC5BE,qBAED,kBAAK;EACH;;EAEA,SAAMC,sBAAUA,CAAA;IAEhBxB,iBAAM,OAAAwB,sBAAmB,GAAAJ,gBAAY,KAAY,SAAQ,EAAK,KAAG;EAAS;EACxE,OACFJ,aAAA,CAAAQ,sBAAA,GACD;IACFT,GAAA","ignoreList":[]}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { isServerRuntime } from "../server/isServerRuntime.mjs";
|
|
2
|
-
let nodeAsyncLocalStorageCache = null
|
|
2
|
+
let nodeAsyncLocalStorageCache = null,
|
|
3
|
+
configuredAsyncLocalStorage = null;
|
|
3
4
|
const nodeModuleId = ["node", "async_hooks"].join(":");
|
|
5
|
+
function setupAsyncLocalStorage(AsyncLocalStorage) {
|
|
6
|
+
configuredAsyncLocalStorage = AsyncLocalStorage;
|
|
7
|
+
}
|
|
4
8
|
async function getNodeAsyncLocalStorage() {
|
|
5
9
|
if (!nodeAsyncLocalStorageCache) try {
|
|
6
10
|
nodeAsyncLocalStorageCache = (await import(/* @vite-ignore */
|
|
@@ -13,18 +17,16 @@ async function getNodeAsyncLocalStorage() {
|
|
|
13
17
|
function createAsyncContext() {
|
|
14
18
|
if (isServerRuntime()) {
|
|
15
19
|
let storage = null;
|
|
16
|
-
|
|
20
|
+
const storageReady = Promise.resolve(configuredAsyncLocalStorage).then(AsyncLocalStorage => AsyncLocalStorage || getNodeAsyncLocalStorage()).then(AsyncLocalStorage => {
|
|
17
21
|
AsyncLocalStorage && !storage && (storage = new AsyncLocalStorage());
|
|
18
|
-
})
|
|
22
|
+
});
|
|
23
|
+
return {
|
|
19
24
|
get() {
|
|
20
|
-
if (!storage)
|
|
21
|
-
console.warn("\u26A0\uFE0F called AsyncContext before load!");
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
25
|
+
if (!storage) throw new Error("AsyncContext storage not initialized");
|
|
24
26
|
return storage.getStore();
|
|
25
27
|
},
|
|
26
28
|
async run(value, fn) {
|
|
27
|
-
if (!storage) throw new Error("
|
|
29
|
+
if (storage || (await storageReady), !storage) throw new Error("AsyncContext storage unavailable in server runtime");
|
|
28
30
|
return storage.run(value, fn);
|
|
29
31
|
}
|
|
30
32
|
};
|
|
@@ -73,5 +75,5 @@ function createBrowserAsyncContext() {
|
|
|
73
75
|
}
|
|
74
76
|
};
|
|
75
77
|
}
|
|
76
|
-
export { createAsyncContext };
|
|
78
|
+
export { createAsyncContext, setupAsyncLocalStorage };
|
|
77
79
|
//# sourceMappingURL=asyncContext.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["isServerRuntime","nodeAsyncLocalStorageCache","nodeModuleId","join","
|
|
1
|
+
{"version":3,"names":["isServerRuntime","nodeAsyncLocalStorageCache","configuredAsyncLocalStorage","nodeModuleId","join","setupAsyncLocalStorage","AsyncLocalStorage","getNodeAsyncLocalStorage","createAsyncContext","storage","storageReady","Promise","resolve","then","get","Error","getStore","run","value","fn","createBrowserAsyncContext","currentContext","contextStack","prevContext","push","OriginalPromise","OriginalThen","prototype","OriginalCatch","catch","OriginalFinally","finally","wrapCallback","callback","context","args","prevContext2","onFulfilled","onRejected","call","onFinally","pop"],"sources":["../../../src/async/asyncContext.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
function setupAsyncLocalStorage(_AsyncLocalStorage) {}
|
|
1
2
|
function createAsyncContext() {
|
|
2
3
|
var currentContext,
|
|
3
4
|
contextStack = [];
|
|
@@ -43,5 +44,5 @@ function createAsyncContext() {
|
|
|
43
44
|
}
|
|
44
45
|
};
|
|
45
46
|
}
|
|
46
|
-
export { createAsyncContext };
|
|
47
|
+
export { createAsyncContext, setupAsyncLocalStorage };
|
|
47
48
|
//# sourceMappingURL=asyncContext.native.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["createAsyncContext","currentContext","contextStack","get","run","value","fn","prevContext","push","OriginalPromise","Promise","OriginalThen","prototype","then","OriginalCatch","catch","OriginalFinally","finally","wrapCallback","callback","context","_len","arguments","length","args","Array","_key","prevContext2","onFulfilled","onRejected","call","onFinally","result","pop"],"sources":["../../../src/async/asyncContext.native.ts"],"sourcesContent":[null],"mappings":"
|
|
1
|
+
{"version":3,"names":["setupAsyncLocalStorage","_AsyncLocalStorage","createAsyncContext","currentContext","contextStack","get","run","value","fn","prevContext","push","OriginalPromise","Promise","OriginalThen","prototype","then","OriginalCatch","catch","OriginalFinally","finally","wrapCallback","callback","context","_len","arguments","length","args","Array","_key","prevContext2","onFulfilled","onRejected","call","onFinally","result","pop"],"sources":["../../../src/async/asyncContext.native.ts"],"sourcesContent":[null],"mappings":"AAAO,SAASA,uBAAuBC,kBAAA,EAAoB,CAAC;AAErD,SAASC,mBAAA,EAAqB;EACjC,IAAIC,cAAA;IACAC,YAAA,GAAe,EAAC;EACpB,OAAO;IACHC,IAAA,EAAO;MACH,OAAOF,cAAA;IACX;IACA,MAAMG,IAAKC,KAAA,EAAOC,EAAA,EAAI;MAClB,IAAIC,WAAA,GAAcN,cAAA;MAClBA,cAAA,GAAiBI,KAAA,EACjBH,YAAA,CAAaM,IAAA,CAAKD,WAAW;MAE7B,IAAIE,eAAA,GAAkBC,OAAA;QAClBC,YAAA,GAAeF,eAAA,CAAgBG,SAAA,CAAUC,IAAA;QACzCC,aAAA,GAAgBL,eAAA,CAAgBG,SAAA,CAAUG,KAAA;QAC1CC,eAAA,GAAkBP,eAAA,CAAgBG,SAAA,CAAUK,OAAA;MAChD,SAASC,aAAaC,QAAA,EAAUC,OAAA,EAAS;QACrC,OAAKD,QAAA,IACE,YAAW;UACd,SAAQE,IAAA,GAAOC,SAAA,CAAUC,MAAA,EAAQC,IAAA,GAAO,IAAIC,KAAA,CAAMJ,IAAI,GAAGK,IAAA,GAAO,GAAGA,IAAA,GAAOL,IAAA,EAAMK,IAAA,IAC5EF,IAAA,CAAKE,IAAI,IAAIJ,SAAA,CAAUI,IAAI;UAE/B,IAAIC,YAAA,GAAc1B,cAAA;UAClBA,cAAA,GAAiBmB,OAAA;UACjB,IAAI;YACA,OAAOD,QAAA,CAAS,GAAGK,IAAI;UAC3B,UAAE;YACEvB,cAAA,GAAiB0B,YAAA;UACrB;QACJ;MACJ;MAGAlB,eAAA,CAAgBG,SAAA,CAAUC,IAAA,GAAO,UAASe,WAAA,EAAaC,UAAA,EAAY;QAC/D,IAAIT,OAAA,GAAUnB,cAAA;QACd,OAAOU,YAAA,CAAamB,IAAA,CAAK,MAAMZ,YAAA,CAAaU,WAAA,EAAaR,OAAO,GAAGF,YAAA,CAAaW,UAAA,EAAYT,OAAO,CAAC;MACxG,GACAX,eAAA,CAAgBG,SAAA,CAAUG,KAAA,GAAQ,UAASc,UAAA,EAAY;QACnD,IAAIT,OAAA,GAAUnB,cAAA;QACd,OAAOa,aAAA,CAAcgB,IAAA,CAAK,MAAMZ,YAAA,CAAaW,UAAA,EAAYT,OAAO,CAAC;MACrE,GACAX,eAAA,CAAgBG,SAAA,CAAUK,OAAA,GAAU,UAASc,SAAA,EAAW;QACpD,IAAIX,OAAA,GAAUnB,cAAA;QACd,OAAOe,eAAA,CAAgBc,IAAA,CAAK,MAAMZ,YAAA,CAAaa,SAAA,EAAWX,OAAO,CAAC;MACtE;MACA,IAAI;QACA,IAAIY,MAAA,GAAS,MAAM1B,EAAA,CAAG;QACtB,OAAO0B,MAAA;MACX,UAAE;QAGEvB,eAAA,CAAgBG,SAAA,CAAUC,IAAA,GAAOF,YAAA,EACjCF,eAAA,CAAgBG,SAAA,CAAUG,KAAA,GAAQD,aAAA,EAClCL,eAAA,CAAgBG,SAAA,CAAUK,OAAA,GAAUD,eAAA,EACpCd,YAAA,CAAa+B,GAAA,CAAI,GACjBhC,cAAA,GAAiBM,WAAA;MACrB;IACJ;EACJ;AACJ","ignoreList":[]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
2
|
+
import { createAsyncContext, setupAsyncLocalStorage } from "./asyncContext.mjs";
|
|
3
|
+
class TestAsyncLocalStorage {
|
|
4
|
+
store;
|
|
5
|
+
getStore() {
|
|
6
|
+
return this.store;
|
|
7
|
+
}
|
|
8
|
+
run(store, callback) {
|
|
9
|
+
const prevStore = this.store;
|
|
10
|
+
this.store = store;
|
|
11
|
+
try {
|
|
12
|
+
return callback();
|
|
13
|
+
} finally {
|
|
14
|
+
this.store = prevStore;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
describe("createAsyncContext", () => {
|
|
19
|
+
test("uses configured async local storage when provided", async () => {
|
|
20
|
+
setupAsyncLocalStorage(TestAsyncLocalStorage);
|
|
21
|
+
const context = createAsyncContext();
|
|
22
|
+
await expect(context.run("viewer-1", async () => context.get())).resolves.toBe("viewer-1"), setupAsyncLocalStorage(null);
|
|
23
|
+
}), test("initializes server storage before first run", async () => {
|
|
24
|
+
setupAsyncLocalStorage(null);
|
|
25
|
+
const context = createAsyncContext();
|
|
26
|
+
await expect(context.run("viewer-1", async () => context.get())).resolves.toBe("viewer-1");
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
//# sourceMappingURL=asyncContext.test.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["describe","expect","test","createAsyncContext","setupAsyncLocalStorage","TestAsyncLocalStorage","store","getStore","run","callback","prevStore","context","get","resolves","toBe"],"sources":["../../../src/async/asyncContext.test.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,QAAA,EAAUC,MAAA,EAAQC,IAAA,QAAY;AAEvC,SAASC,kBAAA,EAAoBC,sBAAA,QAA8B;AAE3D,MAAMC,qBAAA,CAAyB;EACrBC,KAAA;EAERC,SAAA,EAA0B;IACxB,OAAO,KAAKD,KAAA;EACd;EAEAE,IAAOF,KAAA,EAAUG,QAAA,EAAsB;IACrC,MAAMC,SAAA,GAAY,KAAKJ,KAAA;IACvB,KAAKA,KAAA,GAAQA,KAAA;IACb,IAAI;MACF,OAAOG,QAAA,CAAS;IAClB,UAAE;MACA,KAAKH,KAAA,GAAQI,SAAA;IACf;EACF;AACF;AAEAV,QAAA,CAAS,sBAAsB,MAAM;EACnCE,IAAA,CAAK,qDAAqD,YAAY;IACpEE,sBAAA,CAAuBC,qBAAqB;IAE5C,MAAMM,OAAA,GAAUR,kBAAA,CAA2B;IAE3C,MAAMF,MAAA,CAAOU,OAAA,CAAQH,GAAA,CAAI,YAAY,YAAYG,OAAA,CAAQC,GAAA,CAAI,CAAC,CAAC,EAAEC,QAAA,CAASC,IAAA,CACxE,UACF,GAEAV,sBAAA,CAAuB,IAAI;EAC7B,CAAC,GAEDF,IAAA,CAAK,+CAA+C,YAAY;IAC9DE,sBAAA,CAAuB,IAAI;IAE3B,MAAMO,OAAA,GAAUR,kBAAA,CAA2B;IAE3C,MAAMF,MAAA,CAAOU,OAAA,CAAQH,GAAA,CAAI,YAAY,YAAYG,OAAA,CAAQC,GAAA,CAAI,CAAC,CAAC,EAAEC,QAAA,CAASC,IAAA,CACxE,UACF;EACF,CAAC;AACH,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
2
|
+
import { createAsyncContext, setupAsyncLocalStorage } from "./asyncContext.native.js";
|
|
3
|
+
function _class_call_check(instance, Constructor) {
|
|
4
|
+
if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function");
|
|
5
|
+
}
|
|
6
|
+
function _defineProperties(target, props) {
|
|
7
|
+
for (var i = 0; i < props.length; i++) {
|
|
8
|
+
var descriptor = props[i];
|
|
9
|
+
descriptor.enumerable = descriptor.enumerable || !1, descriptor.configurable = !0, "value" in descriptor && (descriptor.writable = !0), Object.defineProperty(target, descriptor.key, descriptor);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function _create_class(Constructor, protoProps, staticProps) {
|
|
13
|
+
return protoProps && _defineProperties(Constructor.prototype, protoProps), staticProps && _defineProperties(Constructor, staticProps), Constructor;
|
|
14
|
+
}
|
|
15
|
+
function _define_property(obj, key, value) {
|
|
16
|
+
return key in obj ? Object.defineProperty(obj, key, {
|
|
17
|
+
value,
|
|
18
|
+
enumerable: !0,
|
|
19
|
+
configurable: !0,
|
|
20
|
+
writable: !0
|
|
21
|
+
}) : obj[key] = value, obj;
|
|
22
|
+
}
|
|
23
|
+
var TestAsyncLocalStorage = /* @__PURE__ */function () {
|
|
24
|
+
"use strict";
|
|
25
|
+
|
|
26
|
+
function TestAsyncLocalStorage2() {
|
|
27
|
+
_class_call_check(this, TestAsyncLocalStorage2), _define_property(this, "store", void 0);
|
|
28
|
+
}
|
|
29
|
+
return _create_class(TestAsyncLocalStorage2, [{
|
|
30
|
+
key: "getStore",
|
|
31
|
+
value: function () {
|
|
32
|
+
return this.store;
|
|
33
|
+
}
|
|
34
|
+
}, {
|
|
35
|
+
key: "run",
|
|
36
|
+
value: function (store, callback) {
|
|
37
|
+
var prevStore = this.store;
|
|
38
|
+
this.store = store;
|
|
39
|
+
try {
|
|
40
|
+
return callback();
|
|
41
|
+
} finally {
|
|
42
|
+
this.store = prevStore;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}]), TestAsyncLocalStorage2;
|
|
46
|
+
}();
|
|
47
|
+
describe("createAsyncContext", function () {
|
|
48
|
+
test("uses configured async local storage when provided", async function () {
|
|
49
|
+
setupAsyncLocalStorage(TestAsyncLocalStorage);
|
|
50
|
+
var context = createAsyncContext();
|
|
51
|
+
await expect(context.run("viewer-1", async function () {
|
|
52
|
+
return context.get();
|
|
53
|
+
})).resolves.toBe("viewer-1"), setupAsyncLocalStorage(null);
|
|
54
|
+
}), test("initializes server storage before first run", async function () {
|
|
55
|
+
setupAsyncLocalStorage(null);
|
|
56
|
+
var context = createAsyncContext();
|
|
57
|
+
await expect(context.run("viewer-1", async function () {
|
|
58
|
+
return context.get();
|
|
59
|
+
})).resolves.toBe("viewer-1");
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
//# sourceMappingURL=asyncContext.test.native.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["describe","expect","test","createAsyncContext","setupAsyncLocalStorage","_class_call_check","instance","Constructor","TypeError","_defineProperties","target","props","i","length","descriptor","enumerable","configurable","writable","Object","defineProperty","key","_create_class","protoProps","staticProps","prototype","_define_property","obj","value","TestAsyncLocalStorage","TestAsyncLocalStorage2"],"sources":["../../../src/async/asyncContext.test.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,QAAA,EAAUC,MAAA,EAAQC,IAAA,QAAY;AAEvC,SAASC,kBAAA,EAAoBC,sBAAA,QAA8B;AAE3D,SAAMC,kBAAAC,QAAyB,EAAAC,WAAA;EACrB,MAAAD,QAAA,YAAAC,WAAA,GAER,UAA0BC,SAAA;AACxB;AAAY,SACdC,kBAAAC,MAAA,EAAAC,KAAA;EAEA,KAAO,IAAAC,CAAA,GAAU,GAAAA,CAAA,GAAAD,KAAsB,CAAAE,MAAA,EAAAD,CAAA;IACrC,IAAAE,UAAM,GAAAH,KAAY,CAAKC,CAAA;IACvBE,UAAK,CAAAC,UAAQ,GAAAD,UAAA,CAAAC,UAAA,QAAAD,UAAA,CAAAE,YAAA,kBAAAF,UAAA,KAAAA,UAAA,CAAAG,QAAA,QAAAC,MAAA,CAAAC,cAAA,CAAAT,MAAA,EAAAI,UAAA,CAAAM,GAAA,EAAAN,UAAA;EACb;AACE;AAAgB,SAClBO,aAAEA,CAAAd,WAAA,EAAAe,UAAA,EAAAC,WAAA;EACA,OAAAD,UAAa,IAAAb,iBAAA,CAAAF,WAAA,CAAAiB,SAAA,EAAAF,UAAA,GAAAC,WAAA,IAAAd,iBAAA,CAAAF,WAAA,EAAAgB,WAAA,GAAAhB,WAAA;AAAA;AACf,SACFkB,iBAAAC,GAAA,EAAAN,GAAA,EAAAO,KAAA;EACF,OAAAP,GAAA,IAAAM,GAAA,GAAAR,MAAA,CAAAC,cAAA,CAAAO,GAAA,EAAAN,GAAA;IAEAO,KAAS;IACPZ,UAAK;IACHC,YAAA;IAEAC,QAAM;EAEN,KAAAS,GAAM,CAAAN,GAAA,IAAOO,KAAA,EAAQD,GAAA;AAAqD;AACxE,IACFE,qBAEA,kBAA2B;EAC7B,YAEK;;EACH,SAAAC,sBAA2BA,CAAA;IAE3BxB,iBAAgB,OAAAwB,sBAA2B,GAAAJ,gBAAA;EAE3C;EAA0E,OACxEJ,aAAA,CAAAQ,sBAAA,GACF;IACDT,GAAA;IACFO,KAAA,WAAAA,CAAA","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -3,6 +3,8 @@ interface AsyncContext<T> {
|
|
|
3
3
|
run<R>(value: T, fn: () => R | Promise<R>): Promise<R>
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
+
export function setupAsyncLocalStorage(_AsyncLocalStorage: unknown): void {}
|
|
7
|
+
|
|
6
8
|
// react native implementation - no node:async_hooks available
|
|
7
9
|
export function createAsyncContext<T>(): AsyncContext<T> {
|
|
8
10
|
let currentContext: T | undefined
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import { createAsyncContext, setupAsyncLocalStorage } from './asyncContext'
|
|
4
|
+
|
|
5
|
+
class TestAsyncLocalStorage<T> {
|
|
6
|
+
private store: T | undefined
|
|
7
|
+
|
|
8
|
+
getStore(): T | undefined {
|
|
9
|
+
return this.store
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
run<R>(store: T, callback: () => R): R {
|
|
13
|
+
const prevStore = this.store
|
|
14
|
+
this.store = store
|
|
15
|
+
try {
|
|
16
|
+
return callback()
|
|
17
|
+
} finally {
|
|
18
|
+
this.store = prevStore
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
describe('createAsyncContext', () => {
|
|
24
|
+
test('uses configured async local storage when provided', async () => {
|
|
25
|
+
setupAsyncLocalStorage(TestAsyncLocalStorage)
|
|
26
|
+
|
|
27
|
+
const context = createAsyncContext<string>()
|
|
28
|
+
|
|
29
|
+
await expect(context.run('viewer-1', async () => context.get())).resolves.toBe(
|
|
30
|
+
'viewer-1',
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
setupAsyncLocalStorage(null)
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
test('initializes server storage before first run', async () => {
|
|
37
|
+
setupAsyncLocalStorage(null)
|
|
38
|
+
|
|
39
|
+
const context = createAsyncContext<string>()
|
|
40
|
+
|
|
41
|
+
await expect(context.run('viewer-1', async () => context.get())).resolves.toBe(
|
|
42
|
+
'viewer-1',
|
|
43
|
+
)
|
|
44
|
+
})
|
|
45
|
+
})
|
|
@@ -15,10 +15,17 @@ interface AsyncLocalStorageConstructor {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
let nodeAsyncLocalStorageCache: AsyncLocalStorageConstructor | null = null
|
|
18
|
+
let configuredAsyncLocalStorage: AsyncLocalStorageConstructor | null = null
|
|
18
19
|
|
|
19
20
|
// hide from vite/esbuild static analysis to avoid browser compat warning
|
|
20
21
|
const nodeModuleId = ['node', 'async_hooks'].join(':')
|
|
21
22
|
|
|
23
|
+
export function setupAsyncLocalStorage(
|
|
24
|
+
AsyncLocalStorage: AsyncLocalStorageConstructor | null,
|
|
25
|
+
): void {
|
|
26
|
+
configuredAsyncLocalStorage = AsyncLocalStorage
|
|
27
|
+
}
|
|
28
|
+
|
|
22
29
|
async function getNodeAsyncLocalStorage(): Promise<AsyncLocalStorageConstructor | null> {
|
|
23
30
|
if (!nodeAsyncLocalStorageCache) {
|
|
24
31
|
try {
|
|
@@ -36,25 +43,28 @@ export function createAsyncContext<T>(): AsyncContext<T> {
|
|
|
36
43
|
if (isServerRuntime()) {
|
|
37
44
|
let storage: NodeAsyncLocalStorage<T> | null = null
|
|
38
45
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
const storageReady = Promise.resolve(configuredAsyncLocalStorage)
|
|
47
|
+
.then((AsyncLocalStorage) => AsyncLocalStorage || getNodeAsyncLocalStorage())
|
|
48
|
+
.then((AsyncLocalStorage) => {
|
|
49
|
+
if (AsyncLocalStorage && !storage) {
|
|
50
|
+
storage = new AsyncLocalStorage<T>()
|
|
51
|
+
}
|
|
52
|
+
})
|
|
44
53
|
|
|
45
54
|
return {
|
|
46
55
|
get(): T | undefined {
|
|
47
56
|
if (!storage) {
|
|
48
|
-
|
|
49
|
-
return
|
|
57
|
+
throw new Error(`AsyncContext storage not initialized`)
|
|
50
58
|
}
|
|
51
|
-
|
|
52
59
|
return storage.getStore()
|
|
53
60
|
},
|
|
54
61
|
|
|
55
62
|
async run<R>(value: T, fn: () => R | Promise<R>): Promise<R> {
|
|
56
63
|
if (!storage) {
|
|
57
|
-
|
|
64
|
+
await storageReady
|
|
65
|
+
}
|
|
66
|
+
if (!storage) {
|
|
67
|
+
throw new Error(`AsyncContext storage unavailable in server runtime`)
|
|
58
68
|
}
|
|
59
69
|
return storage.run(value, fn)
|
|
60
70
|
},
|
|
@@ -2,6 +2,14 @@ interface AsyncContext<T> {
|
|
|
2
2
|
get(): T | undefined;
|
|
3
3
|
run<R>(value: T, fn: () => R | Promise<R>): Promise<R>;
|
|
4
4
|
}
|
|
5
|
+
interface NodeAsyncLocalStorage<T> {
|
|
6
|
+
getStore(): T | undefined;
|
|
7
|
+
run<R>(store: T, callback: () => R): R;
|
|
8
|
+
}
|
|
9
|
+
interface AsyncLocalStorageConstructor {
|
|
10
|
+
new <T>(): NodeAsyncLocalStorage<T>;
|
|
11
|
+
}
|
|
12
|
+
export declare function setupAsyncLocalStorage(AsyncLocalStorage: AsyncLocalStorageConstructor | null): void;
|
|
5
13
|
export declare function createAsyncContext<T>(): AsyncContext<T>;
|
|
6
14
|
export {};
|
|
7
15
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
|
-
"mappings": "UAEU,aAAa,GAAG;CACxB,OAAO;CACP,IAAI,GAAG,OAAO,GAAG,UAAU,IAAI,QAAQ,KAAK,QAAQ;;
|
|
2
|
+
"mappings": "UAEU,aAAa,GAAG;CACxB,OAAO;CACP,IAAI,GAAG,OAAO,GAAG,UAAU,IAAI,QAAQ,KAAK,QAAQ;;UAG5C,sBAAsB,GAAG;CACjC,YAAY;CACZ,IAAI,GAAG,OAAO,GAAG,gBAAgB,IAAI;;UAG7B,6BAA6B;MAChC,MAAM,sBAAsB;;AASnC,OAAO,iBAAS,uBACd,mBAAmB;AAkBrB,OAAO,iBAAS,mBAAmB,MAAM,aAAa",
|
|
3
3
|
"names": [],
|
|
4
4
|
"sources": [
|
|
5
5
|
"src/async/asyncContext.ts"
|
|
6
6
|
],
|
|
7
7
|
"version": 3,
|
|
8
8
|
"sourcesContent": [
|
|
9
|
-
"import { isServerRuntime } from '../server/isServerRuntime'\n\ninterface AsyncContext<T> {\n get(): T | undefined\n run<R>(value: T, fn: () => R | Promise<R>): Promise<R>\n}\n\ninterface NodeAsyncLocalStorage<T> {\n getStore(): T | undefined\n run<R>(store: T, callback: () => R): R\n}\n\ninterface AsyncLocalStorageConstructor {\n new <T>(): NodeAsyncLocalStorage<T>\n}\n\nlet nodeAsyncLocalStorageCache: AsyncLocalStorageConstructor | null = null\n\n// hide from vite/esbuild static analysis to avoid browser compat warning\nconst nodeModuleId = ['node', 'async_hooks'].join(':')\n\nasync function getNodeAsyncLocalStorage(): Promise<AsyncLocalStorageConstructor | null> {\n if (!nodeAsyncLocalStorageCache) {\n try {\n const module = await import(/* @vite-ignore */ nodeModuleId)\n nodeAsyncLocalStorageCache =\n module.AsyncLocalStorage as AsyncLocalStorageConstructor\n } catch {\n return null\n }\n }\n return nodeAsyncLocalStorageCache\n}\n\nexport function createAsyncContext<T>(): AsyncContext<T> {\n if (isServerRuntime()) {\n let storage: NodeAsyncLocalStorage<T> | null = null\n\n getNodeAsyncLocalStorage().then((AsyncLocalStorage) => {\n
|
|
9
|
+
"import { isServerRuntime } from '../server/isServerRuntime'\n\ninterface AsyncContext<T> {\n get(): T | undefined\n run<R>(value: T, fn: () => R | Promise<R>): Promise<R>\n}\n\ninterface NodeAsyncLocalStorage<T> {\n getStore(): T | undefined\n run<R>(store: T, callback: () => R): R\n}\n\ninterface AsyncLocalStorageConstructor {\n new <T>(): NodeAsyncLocalStorage<T>\n}\n\nlet nodeAsyncLocalStorageCache: AsyncLocalStorageConstructor | null = null\nlet configuredAsyncLocalStorage: AsyncLocalStorageConstructor | null = null\n\n// hide from vite/esbuild static analysis to avoid browser compat warning\nconst nodeModuleId = ['node', 'async_hooks'].join(':')\n\nexport function setupAsyncLocalStorage(\n AsyncLocalStorage: AsyncLocalStorageConstructor | null,\n): void {\n configuredAsyncLocalStorage = AsyncLocalStorage\n}\n\nasync function getNodeAsyncLocalStorage(): Promise<AsyncLocalStorageConstructor | null> {\n if (!nodeAsyncLocalStorageCache) {\n try {\n const module = await import(/* @vite-ignore */ nodeModuleId)\n nodeAsyncLocalStorageCache =\n module.AsyncLocalStorage as AsyncLocalStorageConstructor\n } catch {\n return null\n }\n }\n return nodeAsyncLocalStorageCache\n}\n\nexport function createAsyncContext<T>(): AsyncContext<T> {\n if (isServerRuntime()) {\n let storage: NodeAsyncLocalStorage<T> | null = null\n\n const storageReady = Promise.resolve(configuredAsyncLocalStorage)\n .then((AsyncLocalStorage) => AsyncLocalStorage || getNodeAsyncLocalStorage())\n .then((AsyncLocalStorage) => {\n if (AsyncLocalStorage && !storage) {\n storage = new AsyncLocalStorage<T>()\n }\n })\n\n return {\n get(): T | undefined {\n if (!storage) {\n throw new Error(`AsyncContext storage not initialized`)\n }\n return storage.getStore()\n },\n\n async run<R>(value: T, fn: () => R | Promise<R>): Promise<R> {\n if (!storage) {\n await storageReady\n }\n if (!storage) {\n throw new Error(`AsyncContext storage unavailable in server runtime`)\n }\n return storage.run(value, fn)\n },\n }\n } else {\n // browser implementation using promise patching\n return createBrowserAsyncContext<T>()\n }\n}\n\nfunction createBrowserAsyncContext<T>(): AsyncContext<T> {\n let currentContext: T | undefined\n const contextStack: (T | undefined)[] = []\n\n return {\n get(): T | undefined {\n return currentContext\n },\n async run<R>(value: T, fn: () => R | Promise<R>): Promise<R> {\n const prevContext = currentContext\n currentContext = value\n contextStack.push(prevContext)\n\n // store original Promise methods\n const OriginalPromise = Promise\n const OriginalThen = OriginalPromise.prototype.then\n const OriginalCatch = OriginalPromise.prototype.catch\n const OriginalFinally = OriginalPromise.prototype.finally\n\n function wrapCallback(\n callback: Function | undefined | null,\n context: T | undefined,\n ): Function | undefined | null {\n if (!callback) return callback\n return (...args: any[]) => {\n const prevContext = currentContext\n currentContext = context\n try {\n return callback(...args)\n } finally {\n currentContext = prevContext\n }\n }\n }\n\n // patch Promise methods to capture and restore context\n // eslint-disable-next-line no-then-property -- intentional patching for context propagation\n OriginalPromise.prototype.then = function (\n this: Promise<any>,\n onFulfilled?: any,\n onRejected?: any,\n ): Promise<any> {\n const context = currentContext\n return OriginalThen.call(\n this,\n wrapCallback(onFulfilled, context) as any,\n wrapCallback(onRejected, context) as any,\n )\n }\n\n OriginalPromise.prototype.catch = function (\n this: Promise<any>,\n onRejected?: any,\n ): Promise<any> {\n const context = currentContext\n return OriginalCatch.call(this, wrapCallback(onRejected, context) as any)\n }\n\n OriginalPromise.prototype.finally = function (\n this: Promise<any>,\n onFinally?: any,\n ): Promise<any> {\n const context = currentContext\n return OriginalFinally.call(this, wrapCallback(onFinally, context) as any)\n }\n\n try {\n const result = await fn()\n return result\n } finally {\n // restore original Promise methods\n // eslint-disable-next-line no-then-property -- restoring original methods\n OriginalPromise.prototype.then = OriginalThen\n OriginalPromise.prototype.catch = OriginalCatch\n OriginalPromise.prototype.finally = OriginalFinally\n\n contextStack.pop()\n currentContext = prevContext\n }\n },\n }\n}\n"
|
|
10
10
|
]
|
|
11
11
|
}
|
|
@@ -2,6 +2,7 @@ interface AsyncContext<T> {
|
|
|
2
2
|
get(): T | undefined;
|
|
3
3
|
run<R>(value: T, fn: () => R | Promise<R>): Promise<R>;
|
|
4
4
|
}
|
|
5
|
+
export declare function setupAsyncLocalStorage(_AsyncLocalStorage: unknown): void;
|
|
5
6
|
export declare function createAsyncContext<T>(): AsyncContext<T>;
|
|
6
7
|
export {};
|
|
7
8
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
|
-
"mappings": "UAAU,aAAa,GAAG;CACxB,OAAO;CACP,IAAI,GAAG,OAAO,GAAG,UAAU,IAAI,QAAQ,KAAK,QAAQ;;
|
|
2
|
+
"mappings": "UAAU,aAAa,GAAG;CACxB,OAAO;CACP,IAAI,GAAG,OAAO,GAAG,UAAU,IAAI,QAAQ,KAAK,QAAQ;;AAGtD,OAAO,iBAAS,uBAAuB;AAGvC,OAAO,iBAAS,mBAAmB,MAAM,aAAa",
|
|
3
3
|
"names": [],
|
|
4
4
|
"sources": [
|
|
5
5
|
"src/async/asyncContext.native.ts"
|
|
6
6
|
],
|
|
7
7
|
"version": 3,
|
|
8
8
|
"sourcesContent": [
|
|
9
|
-
"interface AsyncContext<T> {\n get(): T | undefined\n run<R>(value: T, fn: () => R | Promise<R>): Promise<R>\n}\n\n// react native implementation - no node:async_hooks available\nexport function createAsyncContext<T>(): AsyncContext<T> {\n let currentContext: T | undefined\n const contextStack: (T | undefined)[] = []\n\n return {\n get(): T | undefined {\n return currentContext\n },\n async run<R>(value: T, fn: () => R | Promise<R>): Promise<R> {\n const prevContext = currentContext\n currentContext = value\n contextStack.push(prevContext)\n\n // store original Promise methods\n const OriginalPromise = Promise\n const OriginalThen = OriginalPromise.prototype.then\n const OriginalCatch = OriginalPromise.prototype.catch\n const OriginalFinally = OriginalPromise.prototype.finally\n\n function wrapCallback(\n callback: Function | undefined | null,\n context: T | undefined,\n ): Function | undefined | null {\n if (!callback) return callback\n return (...args: any[]) => {\n const prevContext = currentContext\n currentContext = context\n try {\n return callback(...args)\n } finally {\n currentContext = prevContext\n }\n }\n }\n\n // patch Promise methods to capture and restore context\n // eslint-disable-next-line no-then-property -- intentional patching for context propagation\n OriginalPromise.prototype.then = function (\n this: Promise<any>,\n onFulfilled?: any,\n onRejected?: any,\n ): Promise<any> {\n const context = currentContext\n return OriginalThen.call(\n this,\n wrapCallback(onFulfilled, context) as any,\n wrapCallback(onRejected, context) as any,\n )\n }\n\n OriginalPromise.prototype.catch = function (\n this: Promise<any>,\n onRejected?: any,\n ): Promise<any> {\n const context = currentContext\n return OriginalCatch.call(this, wrapCallback(onRejected, context) as any)\n }\n\n OriginalPromise.prototype.finally = function (\n this: Promise<any>,\n onFinally?: any,\n ): Promise<any> {\n const context = currentContext\n return OriginalFinally.call(this, wrapCallback(onFinally, context) as any)\n }\n\n try {\n const result = await fn()\n return result\n } finally {\n // restore original Promise methods\n // eslint-disable-next-line no-then-property -- restoring original methods\n OriginalPromise.prototype.then = OriginalThen\n OriginalPromise.prototype.catch = OriginalCatch\n OriginalPromise.prototype.finally = OriginalFinally\n\n contextStack.pop()\n currentContext = prevContext\n }\n },\n }\n}\n"
|
|
9
|
+
"interface AsyncContext<T> {\n get(): T | undefined\n run<R>(value: T, fn: () => R | Promise<R>): Promise<R>\n}\n\nexport function setupAsyncLocalStorage(_AsyncLocalStorage: unknown): void {}\n\n// react native implementation - no node:async_hooks available\nexport function createAsyncContext<T>(): AsyncContext<T> {\n let currentContext: T | undefined\n const contextStack: (T | undefined)[] = []\n\n return {\n get(): T | undefined {\n return currentContext\n },\n async run<R>(value: T, fn: () => R | Promise<R>): Promise<R> {\n const prevContext = currentContext\n currentContext = value\n contextStack.push(prevContext)\n\n // store original Promise methods\n const OriginalPromise = Promise\n const OriginalThen = OriginalPromise.prototype.then\n const OriginalCatch = OriginalPromise.prototype.catch\n const OriginalFinally = OriginalPromise.prototype.finally\n\n function wrapCallback(\n callback: Function | undefined | null,\n context: T | undefined,\n ): Function | undefined | null {\n if (!callback) return callback\n return (...args: any[]) => {\n const prevContext = currentContext\n currentContext = context\n try {\n return callback(...args)\n } finally {\n currentContext = prevContext\n }\n }\n }\n\n // patch Promise methods to capture and restore context\n // eslint-disable-next-line no-then-property -- intentional patching for context propagation\n OriginalPromise.prototype.then = function (\n this: Promise<any>,\n onFulfilled?: any,\n onRejected?: any,\n ): Promise<any> {\n const context = currentContext\n return OriginalThen.call(\n this,\n wrapCallback(onFulfilled, context) as any,\n wrapCallback(onRejected, context) as any,\n )\n }\n\n OriginalPromise.prototype.catch = function (\n this: Promise<any>,\n onRejected?: any,\n ): Promise<any> {\n const context = currentContext\n return OriginalCatch.call(this, wrapCallback(onRejected, context) as any)\n }\n\n OriginalPromise.prototype.finally = function (\n this: Promise<any>,\n onFinally?: any,\n ): Promise<any> {\n const context = currentContext\n return OriginalFinally.call(this, wrapCallback(onFinally, context) as any)\n }\n\n try {\n const result = await fn()\n return result\n } finally {\n // restore original Promise methods\n // eslint-disable-next-line no-then-property -- restoring original methods\n OriginalPromise.prototype.then = OriginalThen\n OriginalPromise.prototype.catch = OriginalCatch\n OriginalPromise.prototype.finally = OriginalFinally\n\n contextStack.pop()\n currentContext = prevContext\n }\n },\n }\n}\n"
|
|
10
10
|
]
|
|
11
11
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mappings": "",
|
|
3
|
+
"names": [],
|
|
4
|
+
"sources": [
|
|
5
|
+
"src/async/asyncContext.test.ts"
|
|
6
|
+
],
|
|
7
|
+
"version": 3,
|
|
8
|
+
"sourcesContent": [
|
|
9
|
+
"import { describe, expect, test } from 'vitest'\n\nimport { createAsyncContext, setupAsyncLocalStorage } from './asyncContext'\n\nclass TestAsyncLocalStorage<T> {\n private store: T | undefined\n\n getStore(): T | undefined {\n return this.store\n }\n\n run<R>(store: T, callback: () => R): R {\n const prevStore = this.store\n this.store = store\n try {\n return callback()\n } finally {\n this.store = prevStore\n }\n }\n}\n\ndescribe('createAsyncContext', () => {\n test('uses configured async local storage when provided', async () => {\n setupAsyncLocalStorage(TestAsyncLocalStorage)\n\n const context = createAsyncContext<string>()\n\n await expect(context.run('viewer-1', async () => context.get())).resolves.toBe(\n 'viewer-1',\n )\n\n setupAsyncLocalStorage(null)\n })\n\n test('initializes server storage before first run', async () => {\n setupAsyncLocalStorage(null)\n\n const context = createAsyncContext<string>()\n\n await expect(context.run('viewer-1', async () => context.get())).resolves.toBe(\n 'viewer-1',\n )\n })\n})\n"
|
|
10
|
+
]
|
|
11
|
+
}
|