conode 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.
- package/.github/workflows/cicd.yml +42 -0
- package/.github/workflows/upgrade.yml +74 -0
- package/LICENSE +13 -0
- package/README.md +94 -0
- package/jest.config.js +16 -0
- package/package.json +38 -0
- package/src/__tests__/index.ts +77 -0
- package/src/index.ts +63 -0
- package/tsconfig.json +31 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
name: CI/CD
|
|
2
|
+
|
|
3
|
+
on: [push, pull_request]
|
|
4
|
+
|
|
5
|
+
jobs:
|
|
6
|
+
build:
|
|
7
|
+
runs-on: ubuntu-latest
|
|
8
|
+
strategy:
|
|
9
|
+
matrix:
|
|
10
|
+
node-version: [16.x]
|
|
11
|
+
steps:
|
|
12
|
+
- name: Checkout code
|
|
13
|
+
uses: actions/checkout@v2
|
|
14
|
+
|
|
15
|
+
- name: Use Node.js ${{ matrix.node-version }}
|
|
16
|
+
uses: actions/setup-node@v1
|
|
17
|
+
with:
|
|
18
|
+
node-version: ${{ matrix.node-version }}
|
|
19
|
+
registry-url: https://registry.npmjs.org/
|
|
20
|
+
|
|
21
|
+
- name: Environment log
|
|
22
|
+
id: env
|
|
23
|
+
run: |
|
|
24
|
+
node --version
|
|
25
|
+
yarn --version
|
|
26
|
+
|
|
27
|
+
- name: Install dependecies
|
|
28
|
+
run: |
|
|
29
|
+
yarn install --frozen-lockfile
|
|
30
|
+
|
|
31
|
+
- name: Run build process
|
|
32
|
+
run: |
|
|
33
|
+
yarn build
|
|
34
|
+
|
|
35
|
+
- name: Run testing
|
|
36
|
+
run: |
|
|
37
|
+
yarn test
|
|
38
|
+
|
|
39
|
+
- name: Upload test coverage
|
|
40
|
+
uses: codecov/codecov-action@v1
|
|
41
|
+
with:
|
|
42
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
name: Autoupdate
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
schedule:
|
|
5
|
+
- cron: 0 0 * * *
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
matrix:
|
|
13
|
+
node-version: [14.x]
|
|
14
|
+
steps:
|
|
15
|
+
- name: Checkout code
|
|
16
|
+
uses: actions/checkout@v2
|
|
17
|
+
|
|
18
|
+
- name: Use Node.js ${{ matrix.node-version }}
|
|
19
|
+
uses: actions/setup-node@v1
|
|
20
|
+
with:
|
|
21
|
+
node-version: ${{ matrix.node-version }}
|
|
22
|
+
registry-url: https://registry.npmjs.org/
|
|
23
|
+
|
|
24
|
+
- name: Environment log
|
|
25
|
+
id: env
|
|
26
|
+
run: |
|
|
27
|
+
node --version
|
|
28
|
+
yarn --version
|
|
29
|
+
|
|
30
|
+
- name: Install dependecies
|
|
31
|
+
run: |
|
|
32
|
+
yarn install --frozen-lockfile
|
|
33
|
+
|
|
34
|
+
- name: Upgrade
|
|
35
|
+
id: updates
|
|
36
|
+
run: |
|
|
37
|
+
PENDING=$(yarn outdated --json|tail -1|jq '.data.body'|jq length)
|
|
38
|
+
echo "::set-output name=PENDING::$PENDING"
|
|
39
|
+
yarn upgrade
|
|
40
|
+
DONE=$(yarn outdated --json|tail -1|jq '.data.body'|jq length)
|
|
41
|
+
echo "::set-output name=DONE::$DONE"
|
|
42
|
+
|
|
43
|
+
- name: Run build process
|
|
44
|
+
if: steps.updates.outputs.PENDING != steps.updates.outputs.DONE
|
|
45
|
+
run: |
|
|
46
|
+
yarn build
|
|
47
|
+
|
|
48
|
+
- name: Run tests
|
|
49
|
+
if: steps.updates.outputs.PENDING != steps.updates.outputs.DONE
|
|
50
|
+
run: |
|
|
51
|
+
yarn test
|
|
52
|
+
|
|
53
|
+
- name: Commit updates
|
|
54
|
+
if: steps.updates.outputs.PENDING != steps.updates.outputs.DONE
|
|
55
|
+
run: |
|
|
56
|
+
git config --global user.email "3axap4eHko@github.com"
|
|
57
|
+
git config --global user.name "Ivan Zakharchanka"
|
|
58
|
+
git add --all
|
|
59
|
+
git commit -am "autoupdate"
|
|
60
|
+
npm version patch
|
|
61
|
+
|
|
62
|
+
- name: Publish
|
|
63
|
+
if: steps.updates.outputs.PENDING != steps.updates.outputs.DONE
|
|
64
|
+
run: |
|
|
65
|
+
echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > .npmrc
|
|
66
|
+
npm publish
|
|
67
|
+
git push
|
|
68
|
+
git push --tags
|
|
69
|
+
|
|
70
|
+
- name: Push updates
|
|
71
|
+
if: steps.updates.outputs.PENDING != steps.updates.outputs.DONE
|
|
72
|
+
run: |
|
|
73
|
+
git push
|
|
74
|
+
git push --tags
|
package/LICENSE
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Copyright (c) 2021-present Ivan Zakharchanka
|
|
2
|
+
|
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
you may not use this file except in compliance with the License.
|
|
5
|
+
You may obtain a copy of the License at
|
|
6
|
+
|
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
|
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
See the License for the specific language governing permissions and
|
|
13
|
+
limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# CoNode
|
|
2
|
+
|
|
3
|
+
0-Deps, simple and fast context library for NodeJS
|
|
4
|
+
|
|
5
|
+
[![Build Status][github-image]][github-url]
|
|
6
|
+
[![NPM version][npm-image]][npm-url]
|
|
7
|
+
[![Downloads][downloads-image]][npm-url]
|
|
8
|
+
[![Coverage Status][codecov-image]][codecov-url]
|
|
9
|
+
[![Maintainability][codeclimate-image]][codeclimate-url]
|
|
10
|
+
[![Snyk][snyk-image]][snyk-url]
|
|
11
|
+
|
|
12
|
+
## Table of Contents
|
|
13
|
+
|
|
14
|
+
- [Features](#features)
|
|
15
|
+
- [Browser Support](#browser-support)
|
|
16
|
+
- [Installing](#installing)
|
|
17
|
+
- [Examples](#examples)
|
|
18
|
+
- [License](#license)
|
|
19
|
+
|
|
20
|
+
## Features
|
|
21
|
+
|
|
22
|
+
- Provides usefull wrappers of [AsyncLocalStorage](https://nodejs.org/api/async_context.html)
|
|
23
|
+
- TypeScript support
|
|
24
|
+
0
|
|
25
|
+
## Installing
|
|
26
|
+
|
|
27
|
+
Using yarn:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
yarn add conode
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Using npm:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
yarn add conode
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Examples
|
|
40
|
+
|
|
41
|
+
Functional approach
|
|
42
|
+
```typescript
|
|
43
|
+
import { createContext } from '../index';
|
|
44
|
+
const auth = createContext();
|
|
45
|
+
|
|
46
|
+
const action = () => {
|
|
47
|
+
const jwt = auth.getContext();
|
|
48
|
+
console.log(jwt);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
auth.contextualize(jwt, action);
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Class approach
|
|
55
|
+
```typescript
|
|
56
|
+
import { contextualize, Context } from '../index';
|
|
57
|
+
|
|
58
|
+
const action = () => {
|
|
59
|
+
const service = Service.getContext();
|
|
60
|
+
console.log(service.getSomething());
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
class Service extends Context() {
|
|
64
|
+
@contextualize
|
|
65
|
+
async run() {
|
|
66
|
+
await action();
|
|
67
|
+
}
|
|
68
|
+
getSomething() {
|
|
69
|
+
return 'something';
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const service = new Service();
|
|
74
|
+
|
|
75
|
+
service.run();
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## License
|
|
79
|
+
|
|
80
|
+
License [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
|
81
|
+
Copyright (c) 2022-present Ivan Zakharchanka
|
|
82
|
+
|
|
83
|
+
[npm-url]: https://www.npmjs.com/package/conode
|
|
84
|
+
[downloads-image]: https://img.shields.io/npm/dw/conode.svg?maxAge=43200
|
|
85
|
+
[npm-image]: https://img.shields.io/npm/v/conode.svg?maxAge=43200
|
|
86
|
+
[github-url]: https://github.com/3axap4eHko/conode/actions/workflows/cicd.yml
|
|
87
|
+
[github-image]: https://github.com/3axap4eHko/conode/actions/workflows/cicd.yml/badge.svg
|
|
88
|
+
[codecov-url]: https://codecov.io/gh/3axap4eHko/conode
|
|
89
|
+
[codecov-image]: https://codecov.io/gh/3axap4eHko/conode/branch/master/graph/badge.svg?token=JZ8QCGH6PI
|
|
90
|
+
[codeclimate-url]: https://codeclimate.com/github/3axap4eHko/conode/maintainability
|
|
91
|
+
[codeclimate-image]: https://api.codeclimate.com/v1/badges/0ba20f27f6db2b0fec8c/maintainability
|
|
92
|
+
[snyk-url]: https://snyk.io/test/npm/conode/latest
|
|
93
|
+
[snyk-image]: https://img.shields.io/snyk/vulnerabilities/github/3axap4eHko/conode.svg?maxAge=43200
|
|
94
|
+
|
package/jest.config.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
verbose: true,
|
|
3
|
+
testEnvironment: 'node',
|
|
4
|
+
collectCoverage: !!process.env.CI,
|
|
5
|
+
preset: 'ts-jest',
|
|
6
|
+
collectCoverageFrom: [
|
|
7
|
+
'src/**/*.ts',
|
|
8
|
+
],
|
|
9
|
+
coveragePathIgnorePatterns: [
|
|
10
|
+
'/node_modules/',
|
|
11
|
+
'__fixtures__',
|
|
12
|
+
'__mocks__',
|
|
13
|
+
'__tests__',
|
|
14
|
+
],
|
|
15
|
+
coverageDirectory: './coverage',
|
|
16
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "conode",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "tsc",
|
|
8
|
+
"test": "jest"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/3axap4eHko/conode.git"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"node context",
|
|
16
|
+
"context",
|
|
17
|
+
"async context",
|
|
18
|
+
"async",
|
|
19
|
+
"promise context"
|
|
20
|
+
],
|
|
21
|
+
"author": "Ivan Zakharchanka",
|
|
22
|
+
"license": "Apache-2.0",
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/3axap4eHko/conode/issues"
|
|
25
|
+
},
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=16.0.0"
|
|
28
|
+
},
|
|
29
|
+
"homepage": "https://github.com/3axap4eHko/conode#readme",
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/jest": "^27.4.1",
|
|
32
|
+
"@types/node": "^17.0.27",
|
|
33
|
+
"jest": "27",
|
|
34
|
+
"ts-jest": "^27.1.4",
|
|
35
|
+
"typescript": "^4.6.3"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {}
|
|
38
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { createContext, Context, contextualize } from '../index';
|
|
2
|
+
|
|
3
|
+
describe('test', () => {
|
|
4
|
+
it('Should create a context', async () => {
|
|
5
|
+
const context = createContext();
|
|
6
|
+
expect(context).toHaveProperty('contextualize');
|
|
7
|
+
expect(context).toHaveProperty('getContext');
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it('Should execute in the context', async () => {
|
|
11
|
+
const context = createContext();
|
|
12
|
+
const value1 = { test: 1 };
|
|
13
|
+
const value2 = { test: 1 };
|
|
14
|
+
const error = new Error();
|
|
15
|
+
|
|
16
|
+
const action1 = jest.fn(async () => {
|
|
17
|
+
expect(context.getContext()).toStrictEqual(value1);
|
|
18
|
+
});
|
|
19
|
+
const action2 = jest.fn(async () => {
|
|
20
|
+
expect(context.getContext()).toStrictEqual(value2);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const action3 = jest.fn(async () => {
|
|
24
|
+
throw error;
|
|
25
|
+
});
|
|
26
|
+
expect(context.contextualize(value2, action3)).rejects.toStrictEqual(error);
|
|
27
|
+
expect(action3).toBeCalled();
|
|
28
|
+
expect(action2).not.toBeCalled();
|
|
29
|
+
expect(action1).not.toBeCalled();
|
|
30
|
+
|
|
31
|
+
await context.contextualize(value2, action2);
|
|
32
|
+
expect(action2).toBeCalled();
|
|
33
|
+
expect(action1).not.toBeCalled();
|
|
34
|
+
await context.contextualize(value1, action1);
|
|
35
|
+
expect(action1).toBeCalled();
|
|
36
|
+
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('Should mixin no class context', async () => {
|
|
40
|
+
class Test extends Context() { }
|
|
41
|
+
const test = new Test();
|
|
42
|
+
const action = jest.fn(async () => {
|
|
43
|
+
expect(Test.context).toStrictEqual(test);
|
|
44
|
+
});
|
|
45
|
+
await test.contextualize(action);
|
|
46
|
+
expect(action).toBeCalled();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('Should mixin class context', async () => {
|
|
50
|
+
class A {}
|
|
51
|
+
class Test extends Context(A) { }
|
|
52
|
+
const test = new Test();
|
|
53
|
+
const action = jest.fn(async () => {
|
|
54
|
+
expect(Test.context).toStrictEqual(test);
|
|
55
|
+
});
|
|
56
|
+
await test.contextualize(action);
|
|
57
|
+
expect(action).toBeCalled();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('Should decorate method', async () => {
|
|
61
|
+
const action = jest.fn(async () => {
|
|
62
|
+
expect(Test.context).toStrictEqual(test);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
class Test extends Context() {
|
|
66
|
+
|
|
67
|
+
@contextualize
|
|
68
|
+
async run() {
|
|
69
|
+
await action();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const test = new Test();
|
|
74
|
+
await test.run();
|
|
75
|
+
expect(action).toBeCalled();
|
|
76
|
+
});
|
|
77
|
+
});
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from 'async_hooks';
|
|
2
|
+
|
|
3
|
+
export type Callback = () => any;
|
|
4
|
+
|
|
5
|
+
export const createContext = <T>() => {
|
|
6
|
+
const storage = new AsyncLocalStorage<T>();
|
|
7
|
+
|
|
8
|
+
return {
|
|
9
|
+
contextualize(value: T, callback: Callback) {
|
|
10
|
+
return new Promise<void>((resolve, reject) => {
|
|
11
|
+
storage.run(value, async () => {
|
|
12
|
+
try {
|
|
13
|
+
await callback();
|
|
14
|
+
resolve();
|
|
15
|
+
} catch (e) {
|
|
16
|
+
reject(e);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
},
|
|
21
|
+
getContext() {
|
|
22
|
+
return storage.getStore();
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
type Constructor = new (...args: any[]) => {};
|
|
28
|
+
|
|
29
|
+
export function Context(Base?: Constructor) {
|
|
30
|
+
const context = createContext();
|
|
31
|
+
|
|
32
|
+
return Base
|
|
33
|
+
? class Contextual extends Base {
|
|
34
|
+
static get context() {
|
|
35
|
+
return context.getContext();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async contextualize(callback: Callback) {
|
|
39
|
+
return context.contextualize(this, callback);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
: class Contextual {
|
|
43
|
+
static get context() {
|
|
44
|
+
return context.getContext();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async contextualize(callback: Callback) {
|
|
48
|
+
return context.contextualize(this, callback);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface Contextualized {
|
|
54
|
+
contextualize(callback: Callback): Promise<any>;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function contextualize<T extends Contextualized>(target: T, _: string, descriptor: TypedPropertyDescriptor<Callback>) {
|
|
58
|
+
const method = descriptor.value!;
|
|
59
|
+
function contextualized() {
|
|
60
|
+
return target.contextualize(() => method.apply(this, arguments));
|
|
61
|
+
};
|
|
62
|
+
descriptor.value = contextualized as any;
|
|
63
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES6",
|
|
4
|
+
"module": "CommonJS",
|
|
5
|
+
"moduleResolution": "node",
|
|
6
|
+
"noImplicitAny": true,
|
|
7
|
+
"removeComments": true,
|
|
8
|
+
"preserveConstEnums": true,
|
|
9
|
+
"experimentalDecorators": true,
|
|
10
|
+
"esModuleInterop": true,
|
|
11
|
+
"sourceMap": true,
|
|
12
|
+
"declaration": true,
|
|
13
|
+
"lib": [
|
|
14
|
+
"esnext",
|
|
15
|
+
"dom",
|
|
16
|
+
"dom.iterable"
|
|
17
|
+
],
|
|
18
|
+
"rootDir": "src",
|
|
19
|
+
"outDir": "build"
|
|
20
|
+
},
|
|
21
|
+
"include": [
|
|
22
|
+
"src/*.ts",
|
|
23
|
+
"src/Request.ts"
|
|
24
|
+
],
|
|
25
|
+
"exclude": [
|
|
26
|
+
"node_modules",
|
|
27
|
+
"src/**/__tests__",
|
|
28
|
+
"src/**/__fixtures__",
|
|
29
|
+
"src/**/__mocks__"
|
|
30
|
+
]
|
|
31
|
+
}
|