@lowerdeck/execution-context 1.0.0
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/.turbo/turbo-build.log +11 -0
- package/.turbo/turbo-test.log +26 -0
- package/package.json +36 -0
- package/src/execution-context.ts +27 -0
- package/src/index.ts +2 -0
- package/src/with-execution-context.ts +93 -0
- package/tsconfig.json +13 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
|
|
2
|
+
[0m[2m[35m$[0m [2m[1mmicrobundle[0m
|
|
3
|
+
[34mBuild "@lowerdeck/unique" to dist:[39m
|
|
4
|
+
[32m77 B[39m: [37mindex.cjs[39m.gz
|
|
5
|
+
[32m58 B[39m: [37mindex.cjs[39m.br
|
|
6
|
+
[32m66 B[39m: [37mindex.module.js[39m.gz
|
|
7
|
+
[32m50 B[39m: [37mindex.module.js[39m.br
|
|
8
|
+
[32m88 B[39m: [37mindex.module.js[39m.gz
|
|
9
|
+
[32m72 B[39m: [37mindex.module.js[39m.br
|
|
10
|
+
[32m170 B[39m: [37mindex.umd.js[39m.gz
|
|
11
|
+
[32m137 B[39m: [37mindex.umd.js[39m.br
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
|
|
2
|
+
[0m[2m[35m$[0m [2m[1mvitest run --passWithNoTests[0m
|
|
3
|
+
[?25l
|
|
4
|
+
[1m[46m RUN [49m[22m [36mv3.2.4 [39m[90m/Users/tobias/code/metorial/metorial-enterprise/oss/src/packages/shared/unique[39m
|
|
5
|
+
|
|
6
|
+
[?2026h
|
|
7
|
+
[1m[33m ❯ [39m[22msrc/index.test.ts[2m [queued][22m
|
|
8
|
+
|
|
9
|
+
[2m Test Files [22m[1m[32m0 passed[39m[22m[90m (1)[39m
|
|
10
|
+
[2m Tests [22m[1m[32m0 passed[39m[22m[90m (0)[39m
|
|
11
|
+
[2m Start at [22m10:23:39
|
|
12
|
+
[2m Duration [22m101ms
|
|
13
|
+
[?2026l[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K [32m✓[39m src/index.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m 2[2mms[22m[39m
|
|
14
|
+
[32m✓[39m unique[2m > [22mshould return an array with unique elements[32m 1[2mms[22m[39m
|
|
15
|
+
[32m✓[39m unique[2m > [22mshould handle an empty array[32m 0[2mms[22m[39m
|
|
16
|
+
[32m✓[39m unique[2m > [22mshould handle an array with all unique elements[32m 0[2mms[22m[39m
|
|
17
|
+
[32m✓[39m unique[2m > [22mshould handle an array with all duplicate elements[32m 0[2mms[22m[39m
|
|
18
|
+
[32m✓[39m unique[2m > [22mshould work with strings[32m 0[2mms[22m[39m
|
|
19
|
+
[32m✓[39m unique[2m > [22mshould work with mixed types[32m 0[2mms[22m[39m
|
|
20
|
+
|
|
21
|
+
[2m Test Files [22m [1m[32m1 passed[39m[22m[90m (1)[39m
|
|
22
|
+
[2m Tests [22m [1m[32m6 passed[39m[22m[90m (6)[39m
|
|
23
|
+
[2m Start at [22m 10:23:39
|
|
24
|
+
[2m Duration [22m 218ms[2m (transform 29ms, setup 0ms, collect 28ms, tests 2ms, environment 0ms, prepare 40ms)[22m
|
|
25
|
+
|
|
26
|
+
[?25h
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lowerdeck/execution-context",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"author": "Tobias Herber",
|
|
8
|
+
"license": "Apache 2",
|
|
9
|
+
"type": "module",
|
|
10
|
+
"source": "src/index.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"require": "./dist/index.cjs",
|
|
14
|
+
"import": "./dist/index.module.js",
|
|
15
|
+
"default": "./dist/index.module.js"
|
|
16
|
+
},
|
|
17
|
+
"main": "./dist/index.cjs",
|
|
18
|
+
"module": "./dist/index.module.js",
|
|
19
|
+
"types": "dist/index.d.ts",
|
|
20
|
+
"unpkg": "./dist/index.umd.js",
|
|
21
|
+
"scripts": {
|
|
22
|
+
"test": "vitest run --passWithNoTests",
|
|
23
|
+
"lint": "prettier src/**/*.ts --check",
|
|
24
|
+
"build": "microbundle"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@lowerdeck/id": "^1.0.0",
|
|
28
|
+
"@lowerdeck/sentry": "^1.0.0"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"microbundle": "^0.15.1",
|
|
32
|
+
"@lowerdeck/tsconfig": "^1.0.0",
|
|
33
|
+
"typescript": "^5.8.3",
|
|
34
|
+
"vitest": "^3.1.2"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { generateId } from '@lowerdeck/id';
|
|
2
|
+
|
|
3
|
+
export type ExecutionContext = {
|
|
4
|
+
contextId: string;
|
|
5
|
+
parent?: ExecutionContext;
|
|
6
|
+
} & (
|
|
7
|
+
| {
|
|
8
|
+
type: 'request';
|
|
9
|
+
userId?: string;
|
|
10
|
+
memberId?: string;
|
|
11
|
+
apiKeyId?: string;
|
|
12
|
+
machineAccessId?: string;
|
|
13
|
+
ip: string;
|
|
14
|
+
userAgent: string;
|
|
15
|
+
}
|
|
16
|
+
| { type: 'scheduled'; cron: string; name: string }
|
|
17
|
+
| { type: 'job'; queue: string }
|
|
18
|
+
| { type: 'unknown' }
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
export let createExecutionContext = (
|
|
22
|
+
input: ExecutionContext & { contextId?: string | undefined }
|
|
23
|
+
) => {
|
|
24
|
+
if (!input.contextId) input.contextId = generateId('ctx_');
|
|
25
|
+
|
|
26
|
+
return input as ExecutionContext;
|
|
27
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { getSentry } from '@lowerdeck/sentry';
|
|
2
|
+
import { AsyncLocalStorage } from 'async_hooks';
|
|
3
|
+
import { ExecutionContext } from './execution-context';
|
|
4
|
+
|
|
5
|
+
let Sentry = getSentry();
|
|
6
|
+
|
|
7
|
+
export let ctxStorage = new AsyncLocalStorage<{
|
|
8
|
+
context: ExecutionContext;
|
|
9
|
+
afterHooks?: Array<() => Promise<void | any>>;
|
|
10
|
+
}>();
|
|
11
|
+
|
|
12
|
+
export let withExecutionContext = async <T>(
|
|
13
|
+
cb: (ctx: ExecutionContext) => Promise<T>
|
|
14
|
+
): Promise<T> => {
|
|
15
|
+
let ctx = ctxStorage.getStore();
|
|
16
|
+
if (!ctx) {
|
|
17
|
+
throw new Error('No execution context found');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return await cb(ctx.context);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export let withExecutionContextOptional = async <T>(
|
|
24
|
+
cb: (ctx: ExecutionContext | null) => Promise<T>
|
|
25
|
+
): Promise<T> => {
|
|
26
|
+
let ctx = ctxStorage.getStore();
|
|
27
|
+
return await cb(ctx?.context ?? null);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export let addAfterHook = async (hook: () => Promise<void | any>) => {
|
|
31
|
+
let ctx = ctxStorage.getStore();
|
|
32
|
+
if (!ctx) {
|
|
33
|
+
throw new Error('No execution context found');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (!ctx.afterHooks) {
|
|
37
|
+
throw new Error('After hooks not enabled for this execution context');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
ctx.afterHooks.push(hook);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export let provideExecutionContext = async <T>(
|
|
44
|
+
ctx: ExecutionContext,
|
|
45
|
+
cb: () => Promise<T>
|
|
46
|
+
): Promise<T> => {
|
|
47
|
+
let afterHooks: Array<() => Promise<void | any>> = [];
|
|
48
|
+
|
|
49
|
+
Sentry.setContext('executionContext', ctx);
|
|
50
|
+
|
|
51
|
+
let res = await ctxStorage.run(
|
|
52
|
+
{
|
|
53
|
+
context: ctx,
|
|
54
|
+
afterHooks
|
|
55
|
+
},
|
|
56
|
+
async () => await cb()
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
for (let hook of afterHooks) {
|
|
60
|
+
hook().catch(err => {
|
|
61
|
+
Sentry.captureException(err);
|
|
62
|
+
|
|
63
|
+
console.error('Error in after hook', {
|
|
64
|
+
err,
|
|
65
|
+
context: ctx
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return res;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export let setExecutionContextSync = (ctx: ExecutionContext) => {
|
|
74
|
+
ctxStorage.enterWith({
|
|
75
|
+
context: ctx
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export let updateExecutionContext = (ctx: Partial<ExecutionContext>) => {
|
|
80
|
+
let currentCtx = getExecutionContext();
|
|
81
|
+
|
|
82
|
+
Object.assign(currentCtx, ctx);
|
|
83
|
+
|
|
84
|
+
return currentCtx;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export let getExecutionContext = () => {
|
|
88
|
+
let ctx = ctxStorage.getStore();
|
|
89
|
+
if (!ctx) {
|
|
90
|
+
throw new Error('No execution context found');
|
|
91
|
+
}
|
|
92
|
+
return ctx.context;
|
|
93
|
+
};
|