Skip to content

Commit a40e628

Browse files
committed
AsyncContext v1.0.1
1 parent a80837c commit a40e628

21 files changed

+5266
-1
lines changed

.github/workflows/cd.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: CD
2+
3+
on:
4+
push:
5+
tags:
6+
- v*
7+
8+
jobs:
9+
publish:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v4
13+
- uses: actions/setup-node@v4
14+
with:
15+
node-version: 'lts/*'
16+
registry-url: 'https://registry.npmjs.org'
17+
- run: npm install
18+
- run: npm run compile
19+
- run: npm publish
20+
env:
21+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

.github/workflows/ci.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
jobs:
8+
test:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- uses: actions/checkout@v4
12+
- uses: actions/setup-node@v4
13+
with:
14+
node-version: 'lts/*'
15+
- run: npm install
16+
- run: npm test

README.md

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,88 @@
11
# async-context-tc39
2-
TC39 proposal implementation for AsyncContext
2+
[![CI](https://img.shields.io/github/actions/workflow/status/artelk/async-context-tc39/ci.yml?branch=main)](https://github.com/artelk/async-context-tc39/actions?query=workflow%3ACI)
3+
[![npm](https://img.shields.io/npm/v/async-context-tc39)](https://www.npmjs.com/package/async-context-tc39)
4+
5+
TC39 proposal implementation for AsyncContext.
6+
7+
## Summary
8+
9+
This is an implementation of the proposal https://github.com/tc39/proposal-async-context that works with JavaScript native `await`s in browser.
10+
All the `await`s on the path between where the context value is set and where it is used should be wrapped into Ѧ-functions to capture and restore the current context
11+
(that is required because the `await`s use a native mechanism that is not interceptable/hookable at all).
12+
Use eslint-plugin-async-context-tc39 that will search for all the `await` expressions not wrapped into the Ѧ-functions in your project and fix them.
13+
14+
Most of the tests were copied from the project https://github.com/iliasbhal/simple-async-context (the TC39 implementation that requires the code to be built to ES6).
15+
16+
## Install
17+
18+
```bash
19+
npm install async-context-tc39
20+
```
21+
22+
## Usage:
23+
24+
```ts
25+
import { AsyncContext } from 'async-context-tc39';
26+
27+
const asyncContext = new AsyncContext.Variable<string>();
28+
29+
//...
30+
it("test", async () => {
31+
const deepCallback = async () => {
32+
expect(asyncContext.get()).toBe("Inner");
33+
Ѧ(await wait(30).Ѧ);
34+
expect(asyncContext.get()).toBe("Inner");
35+
};
36+
37+
const innerCallback = () => asyncContext.run("Inner", async () => {
38+
expect(asyncContext.get()).toBe("Inner");
39+
Ѧ(await wait(30).Ѧ);
40+
expect(asyncContext.get()).toBe("Inner");
41+
Ѧ(await deepCallback().Ѧ);
42+
expect(asyncContext.get()).toBe("Inner");
43+
Ѧ(await wait(30).Ѧ);
44+
expect(asyncContext.get()).toBe("Inner");
45+
});
46+
47+
const total = () => asyncContext.run("Outer", async () => {
48+
expect(asyncContext.get()).toBe("Outer");
49+
Ѧ(await innerCallback().Ѧ);
50+
expect(asyncContext.get()).toBe("Outer");
51+
Ѧ(await innerCallback().Ѧ);
52+
expect(asyncContext.get()).toBe("Outer");
53+
Ѧ(await innerCallback().Ѧ);
54+
expect(asyncContext.get()).toBe("Outer");
55+
});
56+
57+
expect(asyncContext.get()).toBe(undefined);
58+
Ѧ(await total().Ѧ);
59+
expect(asyncContext.get()).toBe(undefined);
60+
});
61+
```
62+
63+
## Classes
64+
65+
```ts
66+
namespace AsyncContext {
67+
class Variable<T> {
68+
constructor(options: AsyncVariableOptions<T>);
69+
get name(): string;
70+
get(): T | undefined;
71+
run<R>(value: T, fn: (...args: any[])=> R, ...args: any[]): R;
72+
wrap<Fn extends (...args: any) => any>(value: T, callback: Fn): Fn;
73+
}
74+
75+
interface AsyncVariableOptions<T> {
76+
name?: string;
77+
defaultValue?: T;
78+
}
79+
80+
class Snapshot {
81+
constructor();
82+
run<R>(fn: (...args: any[]) => R, ...args: any[]): R;
83+
static wrap<T, R>(fn: (this: T, ...args: any[]) => R): (this: T, ...args: any[]) => R;
84+
}
85+
}
86+
```
87+
88+
See README.md on https://github.com/tc39/proposal-async-context for datails

eslint.config.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import eslint from '@eslint/js';
2+
import tseslint from 'typescript-eslint';
3+
//import actc39 from 'eslint-plugin-async-context-tc39';
4+
5+
export default tseslint.config(
6+
{ ignores: ['dist/'] },
7+
eslint.configs.recommended,
8+
tseslint.configs.recommended,
9+
//actc39.configs['flat/recommended'],
10+
);

0 commit comments

Comments
 (0)