@thangnv-dev/context-common 0.0.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.
@@ -0,0 +1,24 @@
1
+ import 'temporal-polyfill/global';
2
+ export type ContextKey<T = unknown> = symbol & {
3
+ readonly __contextValue?: T;
4
+ };
5
+ export declare class Context {
6
+ private static readonly backgroundController;
7
+ private static readonly backgroundContext;
8
+ readonly parent: Context | null;
9
+ readonly signal: AbortSignal;
10
+ readonly abortSignal: AbortSignal;
11
+ private readonly valueSlot;
12
+ private constructor();
13
+ static background(): Context;
14
+ static todo(): Context;
15
+ static createKey<T = unknown>(description?: string): ContextKey<T>;
16
+ withValue<T>(key: ContextKey<T> | symbol | string, valueData: T): Context;
17
+ value<T>(key: ContextKey<T> | symbol | string): T | undefined;
18
+ withSignal(nextSignal: AbortSignal): Context;
19
+ withTimeout(durationInput: Temporal.Duration): Context;
20
+ done(): AbortSignal;
21
+ err(): unknown | null;
22
+ throwIfCanceled(): void;
23
+ }
24
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,0BAA0B,CAAA;AAGjC,MAAM,MAAM,UAAU,CAAC,CAAC,GAAG,OAAO,IAAI,MAAM,GAAG;IAAE,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,CAAA;CAAE,CAAA;AAmB9E,qBAAa,OAAO;IAClB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAAwB;IACpE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAIxC;IAED,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAA;IAC/B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAC5B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkB;IAE5C,OAAO;IAOP,MAAM,CAAC,UAAU,IAAI,OAAO;IAI5B,MAAM,CAAC,IAAI,IAAI,OAAO;IAItB,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,OAAO,EAAE,WAAW,SAAgB,GAAG,UAAU,CAAC,CAAC,CAAC;IAIzE,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,MAAM,EAAE,SAAS,EAAE,CAAC,GAAG,OAAO;IAOzE,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,MAAM,GAAG,CAAC,GAAG,SAAS;IAe7D,UAAU,CAAC,UAAU,EAAE,WAAW,GAAG,OAAO;IAsC5C,WAAW,CAAC,aAAa,EAAE,QAAQ,CAAC,QAAQ,GAAG,OAAO;IAWtD,IAAI,IAAI,WAAW;IAInB,GAAG,IAAI,OAAO,GAAG,IAAI;IAOrB,eAAe,IAAI,IAAI;CAMxB"}
@@ -0,0 +1,111 @@
1
+ import 'temporal-polyfill/global';
2
+ import { ContextCanceledError } from './errors.js';
3
+ function durationToTimeoutMs(duration) {
4
+ const totalMilliseconds = duration.total({ unit: 'milliseconds' });
5
+ if (!Number.isFinite(totalMilliseconds)) {
6
+ throw new TypeError('duration must resolve to a finite number of milliseconds');
7
+ }
8
+ return Math.min(2_147_483_647, Math.max(0, Math.ceil(totalMilliseconds)));
9
+ }
10
+ function getAbortReason(signal) {
11
+ return signal.reason ?? new ContextCanceledError();
12
+ }
13
+ export class Context {
14
+ static backgroundController = new AbortController();
15
+ static backgroundContext = new Context(null, Context.backgroundController.signal, null);
16
+ parent;
17
+ signal;
18
+ abortSignal;
19
+ valueSlot;
20
+ constructor(parent, signal, valueSlot) {
21
+ this.parent = parent;
22
+ this.signal = signal;
23
+ this.abortSignal = signal;
24
+ this.valueSlot = valueSlot;
25
+ }
26
+ static background() {
27
+ return Context.backgroundContext;
28
+ }
29
+ static todo() {
30
+ return Context.backgroundContext;
31
+ }
32
+ static createKey(description = 'context-key') {
33
+ return Symbol(description);
34
+ }
35
+ withValue(key, valueData) {
36
+ if (key === undefined || key === null) {
37
+ throw new TypeError('key must not be null or undefined');
38
+ }
39
+ return new Context(this, this.signal, { key, data: valueData });
40
+ }
41
+ value(key) {
42
+ if (this.valueSlot && this.valueSlot.key === key) {
43
+ return this.valueSlot.data;
44
+ }
45
+ let current = this.parent;
46
+ while (current !== null) {
47
+ if (current.valueSlot && current.valueSlot.key === key) {
48
+ return current.valueSlot.data;
49
+ }
50
+ current = current.parent;
51
+ }
52
+ return undefined;
53
+ }
54
+ withSignal(nextSignal) {
55
+ const controller = new AbortController();
56
+ const onParentAbort = () => {
57
+ if (!controller.signal.aborted) {
58
+ controller.abort(getAbortReason(this.signal));
59
+ }
60
+ };
61
+ const onSignalAbort = () => {
62
+ if (!controller.signal.aborted) {
63
+ controller.abort(getAbortReason(nextSignal));
64
+ }
65
+ };
66
+ if (this.signal.aborted) {
67
+ onParentAbort();
68
+ }
69
+ else {
70
+ this.signal.addEventListener('abort', onParentAbort, { once: true });
71
+ }
72
+ if (!controller.signal.aborted) {
73
+ if (nextSignal.aborted) {
74
+ onSignalAbort();
75
+ }
76
+ else {
77
+ nextSignal.addEventListener('abort', onSignalAbort, { once: true });
78
+ }
79
+ }
80
+ const cleanup = () => {
81
+ this.signal.removeEventListener('abort', onParentAbort);
82
+ nextSignal.removeEventListener('abort', onSignalAbort);
83
+ };
84
+ controller.signal.addEventListener('abort', cleanup, { once: true });
85
+ return new Context(this, controller.signal, null);
86
+ }
87
+ withTimeout(durationInput) {
88
+ const duration = Temporal.Duration.from(durationInput);
89
+ if (duration.sign < 0) {
90
+ throw new TypeError('duration must not be negative');
91
+ }
92
+ const timeoutMs = durationToTimeoutMs(duration);
93
+ return this.withSignal(AbortSignal.timeout(timeoutMs));
94
+ }
95
+ done() {
96
+ return this.signal;
97
+ }
98
+ err() {
99
+ if (!this.signal.aborted) {
100
+ return null;
101
+ }
102
+ return this.signal.reason ?? new ContextCanceledError();
103
+ }
104
+ throwIfCanceled() {
105
+ const currentError = this.err();
106
+ if (currentError) {
107
+ throw currentError;
108
+ }
109
+ }
110
+ }
111
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { StandardError } from '@thangnv-dev/error-common';
2
+ export declare class ContextCanceledError extends StandardError {
3
+ constructor(message?: string, cause?: unknown);
4
+ }
5
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAIzD,qBAAa,oBAAqB,SAAQ,aAAa;gBACzC,OAAO,SAAqB,EAAE,KAAK,CAAC,EAAE,OAAO;CAS1D"}
package/dist/errors.js ADDED
@@ -0,0 +1,14 @@
1
+ import { StandardError } from '@thangnv-dev/error-common';
2
+ const CONTEXT_PACKAGE = '@thangnv-dev/context-common';
3
+ export class ContextCanceledError extends StandardError {
4
+ constructor(message = 'context canceled', cause) {
5
+ super({
6
+ package: CONTEXT_PACKAGE,
7
+ code: 'CONTEXT_CANCELED',
8
+ cause,
9
+ message,
10
+ });
11
+ this.name = 'ContextCanceledError';
12
+ }
13
+ }
14
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAEzD,MAAM,eAAe,GAAG,6BAA6B,CAAA;AAErD,MAAM,OAAO,oBAAqB,SAAQ,aAAa;IACrD,YAAY,OAAO,GAAG,kBAAkB,EAAE,KAAe;QACvD,KAAK,CAAC;YACJ,OAAO,EAAE,eAAe;YACxB,IAAI,EAAE,kBAAkB;YACxB,KAAK;YACL,OAAO;SACR,CAAC,CAAA;QACF,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAA;IACpC,CAAC;CACF"}
@@ -0,0 +1,4 @@
1
+ export { Context } from './context.js';
2
+ export { ContextCanceledError } from './errors.js';
3
+ export type { ContextKey } from './context.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAClD,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { Context } from './context.js';
2
+ export { ContextCanceledError } from './errors.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA"}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@thangnv-dev/context-common",
3
+ "version": "0.0.1",
4
+ "private": false,
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "type": "module",
9
+ "main": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "default": "./dist/index.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsc -p tsconfig.build.json",
22
+ "lint": "eslint .",
23
+ "typecheck": "tsc --noEmit",
24
+ "test": "vitest run"
25
+ },
26
+ "dependencies": {
27
+ "@thangnv-dev/error-common": "workspace:^"
28
+ },
29
+ "devDependencies": {
30
+ "@typescript-eslint/eslint-plugin": "^8.56.0",
31
+ "@typescript-eslint/parser": "^8.56.0",
32
+ "eslint": "^10.0.0",
33
+ "temporal-polyfill": "^0.3.0",
34
+ "typescript": "^5.9.3",
35
+ "vitest": "^4.0.18"
36
+ },
37
+ "peerDependencies": {
38
+ "temporal-polyfill": "*"
39
+ }
40
+ }