@rsdk/actx 4.2.0-next.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/CHANGELOG.md +10 -0
- package/dist/async-context.d.ts +7 -0
- package/dist/async-context.interceptor.d.ts +10 -0
- package/dist/async-context.interceptor.js +25 -0
- package/dist/async-context.interceptor.js.map +1 -0
- package/dist/async-context.js +36 -0
- package/dist/async-context.js.map +1 -0
- package/dist/async-context.module.d.ts +2 -0
- package/dist/async-context.module.js +26 -0
- package/dist/async-context.module.js.map +1 -0
- package/dist/async-context.provider.d.ts +16 -0
- package/dist/async-context.provider.js +28 -0
- package/dist/async-context.provider.js.map +1 -0
- package/dist/async-context.storage.d.ts +3 -0
- package/dist/async-context.storage.js +6 -0
- package/dist/async-context.storage.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/jest.config.e2e.js +1 -0
- package/jest.config.js +1 -0
- package/jest.config.unit.js +1 -0
- package/package.json +21 -0
- package/src/async-context.interceptor.ts +27 -0
- package/src/async-context.module.ts +14 -0
- package/src/async-context.provider.ts +47 -0
- package/src/async-context.storage.ts +3 -0
- package/src/async-context.ts +39 -0
- package/src/index.ts +6 -0
- package/tsconfig.build.json +12 -0
- package/tsconfig.json +7 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Change Log
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
|
+
|
|
6
|
+
## [4.2.0-next.1](https://github.com/R-Vision/rsdk/compare/v4.2.0-next.0...v4.2.0-next.1) (2024-02-02)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* rework work with async context ([#201](https://github.com/R-Vision/rsdk/issues/201)) ([26de1a8](https://github.com/R-Vision/rsdk/commit/26de1a814692bcd082c2f1aaedad1215ec0df1a0))
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CallHandler, ExecutionContext, NestInterceptor } from '@nestjs/common';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
/**
|
|
4
|
+
* Interceptor for initialize `AsyncLocalStorage`.
|
|
5
|
+
* Official recipe https://docs.nestjs.com/recipes/async-local-storage doesn't work with microservices.
|
|
6
|
+
* One of correctly working realization - https://github.com/Papooch/nestjs-cls/blob/26afd86edd9ef17af49f613d1b7af95b36d5ca97/packages/core/src/lib/cls-initializers/cls.interceptor.ts#L28.
|
|
7
|
+
*/
|
|
8
|
+
export declare class AsyncContextInterceptor implements NestInterceptor {
|
|
9
|
+
intercept(_context: ExecutionContext, next: CallHandler): Observable<any>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AsyncContextInterceptor = void 0;
|
|
4
|
+
const rxjs_1 = require("rxjs");
|
|
5
|
+
const async_context_storage_1 = require("./async-context.storage");
|
|
6
|
+
/**
|
|
7
|
+
* Interceptor for initialize `AsyncLocalStorage`.
|
|
8
|
+
* Official recipe https://docs.nestjs.com/recipes/async-local-storage doesn't work with microservices.
|
|
9
|
+
* One of correctly working realization - https://github.com/Papooch/nestjs-cls/blob/26afd86edd9ef17af49f613d1b7af95b36d5ca97/packages/core/src/lib/cls-initializers/cls.interceptor.ts#L28.
|
|
10
|
+
*/
|
|
11
|
+
class AsyncContextInterceptor {
|
|
12
|
+
intercept(_context, next) {
|
|
13
|
+
return new rxjs_1.Observable((observer) => {
|
|
14
|
+
async_context_storage_1.AsyncContextStorage.run(new Map(), () => {
|
|
15
|
+
next.handle().subscribe({
|
|
16
|
+
complete: () => observer.complete(),
|
|
17
|
+
error: (error) => observer.error(error),
|
|
18
|
+
next: (res) => observer.next(res),
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.AsyncContextInterceptor = AsyncContextInterceptor;
|
|
25
|
+
//# sourceMappingURL=async-context.interceptor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"async-context.interceptor.js","sourceRoot":"","sources":["../src/async-context.interceptor.ts"],"names":[],"mappings":";;;AAKA,+BAAkC;AAElC,mEAA8D;AAE9D;;;;GAIG;AACH,MAAa,uBAAuB;IAClC,SAAS,CAAC,QAA0B,EAAE,IAAiB;QACrD,OAAO,IAAI,iBAAU,CAAC,CAAC,QAAQ,EAAE,EAAE;YACjC,2CAAmB,CAAC,GAAG,CAAC,IAAI,GAAG,EAAY,EAAE,GAAG,EAAE;gBAChD,IAAI,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC;oBACtB,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE;oBACnC,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC;oBACvC,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC;iBAClC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAZD,0DAYC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AsyncContext = void 0;
|
|
4
|
+
const async_context_storage_1 = require("./async-context.storage");
|
|
5
|
+
class AsyncContext {
|
|
6
|
+
static set(key, v, rewritable = false) {
|
|
7
|
+
const store = AsyncContext.getStoreOrThrow();
|
|
8
|
+
AsyncContext.assertRewritable(key, rewritable);
|
|
9
|
+
store.set(key, v);
|
|
10
|
+
}
|
|
11
|
+
static get(key) {
|
|
12
|
+
const store = async_context_storage_1.AsyncContextStorage.getStore();
|
|
13
|
+
return store?.get(key);
|
|
14
|
+
}
|
|
15
|
+
static has(key) {
|
|
16
|
+
const store = async_context_storage_1.AsyncContextStorage.getStore();
|
|
17
|
+
return store?.has(key) ?? false;
|
|
18
|
+
}
|
|
19
|
+
static getStoreOrThrow() {
|
|
20
|
+
const store = async_context_storage_1.AsyncContextStorage.getStore();
|
|
21
|
+
if (!store) {
|
|
22
|
+
throw new Error('AsyncContext is not provided');
|
|
23
|
+
}
|
|
24
|
+
return store;
|
|
25
|
+
}
|
|
26
|
+
static assertRewritable(key, rewritable) {
|
|
27
|
+
if (rewritable) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (AsyncContext.has(key)) {
|
|
31
|
+
throw new Error('Unexpected rewrite');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.AsyncContext = AsyncContext;
|
|
36
|
+
//# sourceMappingURL=async-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"async-context.js","sourceRoot":"","sources":["../src/async-context.ts"],"names":[],"mappings":";;;AAAA,mEAA8D;AAE9D,MAAa,YAAY;IACvB,MAAM,CAAC,GAAG,CAAC,GAAW,EAAE,CAAU,EAAE,UAAU,GAAG,KAAK;QACpD,MAAM,KAAK,GAAG,YAAY,CAAC,eAAe,EAAE,CAAC;QAE7C,YAAY,CAAC,gBAAgB,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;QAC/C,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,MAAM,CAAC,GAAG,CAAI,GAAW;QACvB,MAAM,KAAK,GAAG,2CAAmB,CAAC,QAAQ,EAAE,CAAC;QAE7C,OAAO,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAED,MAAM,CAAC,GAAG,CAAC,GAAW;QACpB,MAAM,KAAK,GAAG,2CAAmB,CAAC,QAAQ,EAAE,CAAC;QAE7C,OAAO,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC;IAClC,CAAC;IAEO,MAAM,CAAC,eAAe;QAC5B,MAAM,KAAK,GAAG,2CAAmB,CAAC,QAAQ,EAAE,CAAC;QAC7C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAClD,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAEO,MAAM,CAAC,gBAAgB,CAAC,GAAW,EAAE,UAAmB;QAC9D,IAAI,UAAU,EAAE,CAAC;YACf,OAAO;QACT,CAAC;QACD,IAAI,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;CACF;AApCD,oCAoCC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.AsyncContextModule = void 0;
|
|
10
|
+
const common_1 = require("@nestjs/common");
|
|
11
|
+
const core_1 = require("@nestjs/core");
|
|
12
|
+
const async_context_interceptor_1 = require("./async-context.interceptor");
|
|
13
|
+
let AsyncContextModule = class AsyncContextModule {
|
|
14
|
+
};
|
|
15
|
+
exports.AsyncContextModule = AsyncContextModule;
|
|
16
|
+
exports.AsyncContextModule = AsyncContextModule = __decorate([
|
|
17
|
+
(0, common_1.Module)({
|
|
18
|
+
providers: [
|
|
19
|
+
{
|
|
20
|
+
provide: core_1.APP_INTERCEPTOR,
|
|
21
|
+
useValue: new async_context_interceptor_1.AsyncContextInterceptor(),
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
})
|
|
25
|
+
], AsyncContextModule);
|
|
26
|
+
//# sourceMappingURL=async-context.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"async-context.module.js","sourceRoot":"","sources":["../src/async-context.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,uCAA+C;AAE/C,2EAAsE;AAU/D,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;CAAG,CAAA;AAArB,gDAAkB;6BAAlB,kBAAkB;IAR9B,IAAA,eAAM,EAAC;QACN,SAAS,EAAE;YACT;gBACE,OAAO,EAAE,sBAAe;gBACxB,QAAQ,EAAE,IAAI,mDAAuB,EAAE;aACxC;SACF;KACF,CAAC;GACW,kBAAkB,CAAG"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface AsyncContextProvider<V> {
|
|
2
|
+
get(): V | undefined;
|
|
3
|
+
getOrThrow(): V;
|
|
4
|
+
set(v: V): void;
|
|
5
|
+
get isSettled(): boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare const createAsyncContextProvider: <V = never>(config: {
|
|
8
|
+
/**
|
|
9
|
+
* Only for debugging
|
|
10
|
+
*/
|
|
11
|
+
name: string;
|
|
12
|
+
/**
|
|
13
|
+
* Can to rewrite after settled
|
|
14
|
+
*/
|
|
15
|
+
rewritable?: boolean;
|
|
16
|
+
}) => AsyncContextProvider<V>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createAsyncContextProvider = void 0;
|
|
4
|
+
const async_context_1 = require("./async-context");
|
|
5
|
+
const createAsyncContextProvider = (config) => {
|
|
6
|
+
const token = config.name;
|
|
7
|
+
let isSettled = false;
|
|
8
|
+
return {
|
|
9
|
+
get isSettled() {
|
|
10
|
+
return isSettled;
|
|
11
|
+
},
|
|
12
|
+
get() {
|
|
13
|
+
return async_context_1.AsyncContext.get(token);
|
|
14
|
+
},
|
|
15
|
+
getOrThrow() {
|
|
16
|
+
if (!async_context_1.AsyncContext.has(token)) {
|
|
17
|
+
throw new Error('Value not provided: ' + token);
|
|
18
|
+
}
|
|
19
|
+
return async_context_1.AsyncContext.get(token);
|
|
20
|
+
},
|
|
21
|
+
set(v) {
|
|
22
|
+
isSettled = true;
|
|
23
|
+
async_context_1.AsyncContext.set(token, v, config.rewritable);
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
exports.createAsyncContextProvider = createAsyncContextProvider;
|
|
28
|
+
//# sourceMappingURL=async-context.provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"async-context.provider.js","sourceRoot":"","sources":["../src/async-context.provider.ts"],"names":[],"mappings":";;;AAAA,mDAA+C;AAYxC,MAAM,0BAA0B,GAAG,CAAY,MASrD,EAA2B,EAAE;IAC5B,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC;IAE1B,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,OAAO;QACL,IAAI,SAAS;YACX,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,GAAG;YACD,OAAO,4BAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACjC,CAAC;QAED,UAAU;YACR,IAAI,CAAC,4BAAY,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC7B,MAAM,IAAI,KAAK,CAAC,sBAAsB,GAAG,KAAK,CAAC,CAAC;YAClD,CAAC;YACD,OAAO,4BAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACjC,CAAC;QAED,GAAG,CAAC,CAAI;YACN,SAAS,GAAG,IAAI,CAAC;YACjB,4BAAY,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;QAChD,CAAC;KACF,CAAC;AACJ,CAAC,CAAC;AAlCW,QAAA,0BAA0B,8BAkCrC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AsyncContextStorage = void 0;
|
|
4
|
+
const node_async_hooks_1 = require("node:async_hooks");
|
|
5
|
+
exports.AsyncContextStorage = new node_async_hooks_1.AsyncLocalStorage();
|
|
6
|
+
//# sourceMappingURL=async-context.storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"async-context.storage.js","sourceRoot":"","sources":["../src/async-context.storage.ts"],"names":[],"mappings":";;;AAAA,uDAAqD;AAExC,QAAA,mBAAmB,GAAG,IAAI,oCAAiB,EAAiB,CAAC"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createAsyncContextProvider = exports.AsyncContextModule = void 0;
|
|
4
|
+
var async_context_module_1 = require("./async-context.module");
|
|
5
|
+
Object.defineProperty(exports, "AsyncContextModule", { enumerable: true, get: function () { return async_context_module_1.AsyncContextModule; } });
|
|
6
|
+
var async_context_provider_1 = require("./async-context.provider");
|
|
7
|
+
Object.defineProperty(exports, "createAsyncContextProvider", { enumerable: true, get: function () { return async_context_provider_1.createAsyncContextProvider; } });
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,+DAA4D;AAAnD,0HAAA,kBAAkB,OAAA;AAE3B,mEAGkC;AAFhC,oIAAA,0BAA0B,OAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('@rsdk/jest/jest.config.e2e');
|
package/jest.config.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('@rsdk/jest/jest.config');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('@rsdk/jest/jest.config.unit');
|
package/package.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rsdk/actx",
|
|
3
|
+
"version": "4.2.0-next.1",
|
|
4
|
+
"description": "Library for AsyncLocalStorage",
|
|
5
|
+
"license": "Apache License 2.0",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"url": "https://github.com/R-Vision/rsdk"
|
|
11
|
+
},
|
|
12
|
+
"main": "dist/index.js",
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"rxjs": "^7.8.1"
|
|
15
|
+
},
|
|
16
|
+
"peerDependencies": {
|
|
17
|
+
"@nestjs/common": "^10.0.0",
|
|
18
|
+
"@nestjs/core": "^10.0.0"
|
|
19
|
+
},
|
|
20
|
+
"gitHead": "e42244b7badde74fec2badc60a85d53878fe75ae"
|
|
21
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CallHandler,
|
|
3
|
+
ExecutionContext,
|
|
4
|
+
NestInterceptor,
|
|
5
|
+
} from '@nestjs/common';
|
|
6
|
+
import { Observable } from 'rxjs';
|
|
7
|
+
|
|
8
|
+
import { AsyncContextStorage } from './async-context.storage';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Interceptor for initialize `AsyncLocalStorage`.
|
|
12
|
+
* Official recipe https://docs.nestjs.com/recipes/async-local-storage doesn't work with microservices.
|
|
13
|
+
* One of correctly working realization - https://github.com/Papooch/nestjs-cls/blob/26afd86edd9ef17af49f613d1b7af95b36d5ca97/packages/core/src/lib/cls-initializers/cls.interceptor.ts#L28.
|
|
14
|
+
*/
|
|
15
|
+
export class AsyncContextInterceptor implements NestInterceptor {
|
|
16
|
+
intercept(_context: ExecutionContext, next: CallHandler): Observable<any> {
|
|
17
|
+
return new Observable((observer) => {
|
|
18
|
+
AsyncContextStorage.run(new Map<any, any>(), () => {
|
|
19
|
+
next.handle().subscribe({
|
|
20
|
+
complete: () => observer.complete(),
|
|
21
|
+
error: (error) => observer.error(error),
|
|
22
|
+
next: (res) => observer.next(res),
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Module } from '@nestjs/common';
|
|
2
|
+
import { APP_INTERCEPTOR } from '@nestjs/core';
|
|
3
|
+
|
|
4
|
+
import { AsyncContextInterceptor } from './async-context.interceptor';
|
|
5
|
+
|
|
6
|
+
@Module({
|
|
7
|
+
providers: [
|
|
8
|
+
{
|
|
9
|
+
provide: APP_INTERCEPTOR,
|
|
10
|
+
useValue: new AsyncContextInterceptor(),
|
|
11
|
+
},
|
|
12
|
+
],
|
|
13
|
+
})
|
|
14
|
+
export class AsyncContextModule {}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { AsyncContext } from './async-context';
|
|
2
|
+
|
|
3
|
+
export interface AsyncContextProvider<V> {
|
|
4
|
+
get(): V | undefined;
|
|
5
|
+
|
|
6
|
+
getOrThrow(): V;
|
|
7
|
+
|
|
8
|
+
set(v: V): void;
|
|
9
|
+
|
|
10
|
+
get isSettled(): boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const createAsyncContextProvider = <V = never>(config: {
|
|
14
|
+
/**
|
|
15
|
+
* Only for debugging
|
|
16
|
+
*/
|
|
17
|
+
name: string;
|
|
18
|
+
/**
|
|
19
|
+
* Can to rewrite after settled
|
|
20
|
+
*/
|
|
21
|
+
rewritable?: boolean;
|
|
22
|
+
}): AsyncContextProvider<V> => {
|
|
23
|
+
const token = config.name;
|
|
24
|
+
|
|
25
|
+
let isSettled = false;
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
get isSettled(): boolean {
|
|
29
|
+
return isSettled;
|
|
30
|
+
},
|
|
31
|
+
get(): V | undefined {
|
|
32
|
+
return AsyncContext.get(token);
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
getOrThrow(): V {
|
|
36
|
+
if (!AsyncContext.has(token)) {
|
|
37
|
+
throw new Error('Value not provided: ' + token);
|
|
38
|
+
}
|
|
39
|
+
return AsyncContext.get(token);
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
set(v: V): void {
|
|
43
|
+
isSettled = true;
|
|
44
|
+
AsyncContext.set(token, v, config.rewritable);
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { AsyncContextStorage } from './async-context.storage';
|
|
2
|
+
|
|
3
|
+
export class AsyncContext {
|
|
4
|
+
static set(key: string, v: unknown, rewritable = false): void {
|
|
5
|
+
const store = AsyncContext.getStoreOrThrow();
|
|
6
|
+
|
|
7
|
+
AsyncContext.assertRewritable(key, rewritable);
|
|
8
|
+
store.set(key, v);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
static get<V>(key: string): V {
|
|
12
|
+
const store = AsyncContextStorage.getStore();
|
|
13
|
+
|
|
14
|
+
return store?.get(key);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
static has(key: string): boolean {
|
|
18
|
+
const store = AsyncContextStorage.getStore();
|
|
19
|
+
|
|
20
|
+
return store?.has(key) ?? false;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
private static getStoreOrThrow(): Map<any, any> {
|
|
24
|
+
const store = AsyncContextStorage.getStore();
|
|
25
|
+
if (!store) {
|
|
26
|
+
throw new Error('AsyncContext is not provided');
|
|
27
|
+
}
|
|
28
|
+
return store;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
private static assertRewritable(key: string, rewritable: boolean): void {
|
|
32
|
+
if (rewritable) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (AsyncContext.has(key)) {
|
|
36
|
+
throw new Error('Unexpected rewrite');
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
package/src/index.ts
ADDED