@naturalcycles/nodejs-lib 12.80.4 → 12.81.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/dist/index.d.ts CHANGED
@@ -72,5 +72,6 @@ export * from './validation/joi/joi.shared.schemas';
72
72
  export * from './validation/joi/joi.validation.error';
73
73
  export * from './validation/joi/joi.validation.util';
74
74
  export * from './script';
75
+ export * from './jwt/jwt.service';
75
76
  export type { GlobbyOptions, FastGlobOptions, ValidationErrorItem, AnySchema, Got, AfterResponseHook, BeforeErrorHook, BeforeRequestHook, };
76
77
  export { globby, fastGlob, RequestError, TimeoutError, Ajv };
package/dist/index.js CHANGED
@@ -77,3 +77,4 @@ tslib_1.__exportStar(require("./validation/joi/joi.shared.schemas"), exports);
77
77
  tslib_1.__exportStar(require("./validation/joi/joi.validation.error"), exports);
78
78
  tslib_1.__exportStar(require("./validation/joi/joi.validation.util"), exports);
79
79
  tslib_1.__exportStar(require("./script"), exports);
80
+ tslib_1.__exportStar(require("./jwt/jwt.service"), exports);
@@ -0,0 +1,55 @@
1
+ /// <reference types="node" />
2
+ import { AnyObject, ErrorData, JWTString } from '@naturalcycles/js-lib';
3
+ import type { Algorithm, VerifyOptions, JwtHeader, SignOptions } from 'jsonwebtoken';
4
+ import * as jsonwebtoken from 'jsonwebtoken';
5
+ import { AnySchemaTyped } from '../validation/joi/joi.model';
6
+ export { jsonwebtoken };
7
+ export type { Algorithm, VerifyOptions, SignOptions, JwtHeader };
8
+ export interface JWTServiceCfg {
9
+ /**
10
+ * Public key is required to Verify incoming tokens.
11
+ * Optional if you only want to Decode or Sign.
12
+ */
13
+ publicKey?: string | Buffer;
14
+ /**
15
+ * Private key is required to Sign (create) outgoing tokens.
16
+ * Optional if you only want to Decode or Verify.
17
+ */
18
+ privateKey?: string | Buffer;
19
+ /**
20
+ * Recommended: ES256
21
+ */
22
+ algorithm: Algorithm;
23
+ /**
24
+ * If provided - will be applied to every Sign operation.
25
+ */
26
+ signOptions?: SignOptions;
27
+ /**
28
+ * If provided - will be applied to every Sign operation.
29
+ */
30
+ verifyOptions?: VerifyOptions;
31
+ /**
32
+ * If set - errors thrown from this service will be extended
33
+ * with this errorData (in err.data)
34
+ */
35
+ errorData?: ErrorData;
36
+ }
37
+ /**
38
+ * Wraps popular `jsonwebtoken` library.
39
+ * You should create one instance of JWTService for each pair of private/public key.
40
+ *
41
+ * Generate key pair like this:
42
+ * openssl ecparam -name secp256k1 -genkey -noout -out key.pem
43
+ * openssl ec -in key.pem -pubout > key.pub.pem
44
+ */
45
+ export declare class JWTService {
46
+ cfg: JWTServiceCfg;
47
+ constructor(cfg: JWTServiceCfg);
48
+ sign<T extends AnyObject>(payload: T, schema?: AnySchemaTyped<T>, opt?: SignOptions): JWTString;
49
+ verify<T extends AnyObject>(token: JWTString, schema?: AnySchemaTyped<T>, opt?: VerifyOptions): T;
50
+ decode<T extends AnyObject>(token: JWTString, schema?: AnySchemaTyped<T>): {
51
+ header: JwtHeader;
52
+ payload: T;
53
+ signature: string;
54
+ };
55
+ }
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JWTService = exports.jsonwebtoken = void 0;
4
+ const js_lib_1 = require("@naturalcycles/js-lib");
5
+ const jsonwebtoken = require("jsonwebtoken");
6
+ exports.jsonwebtoken = jsonwebtoken;
7
+ const joi_shared_schemas_1 = require("../validation/joi/joi.shared.schemas");
8
+ const joi_validation_util_1 = require("../validation/joi/joi.validation.util");
9
+ // todo: define JWTError and list possible options
10
+ /**
11
+ * Wraps popular `jsonwebtoken` library.
12
+ * You should create one instance of JWTService for each pair of private/public key.
13
+ *
14
+ * Generate key pair like this:
15
+ * openssl ecparam -name secp256k1 -genkey -noout -out key.pem
16
+ * openssl ec -in key.pem -pubout > key.pub.pem
17
+ */
18
+ class JWTService {
19
+ constructor(cfg) {
20
+ this.cfg = cfg;
21
+ }
22
+ sign(payload, schema, opt = {}) {
23
+ (0, js_lib_1._assert)(this.cfg.privateKey, 'JWTService: privateKey is required to be able to verify, but not provided');
24
+ if (schema) {
25
+ (0, joi_validation_util_1.validate)(payload, schema);
26
+ }
27
+ return jsonwebtoken.sign(payload, this.cfg.privateKey, {
28
+ algorithm: this.cfg.algorithm,
29
+ noTimestamp: true,
30
+ ...this.cfg.signOptions,
31
+ ...opt,
32
+ });
33
+ }
34
+ verify(token, schema, opt = {}) {
35
+ (0, js_lib_1._assert)(this.cfg.publicKey, 'JWTService: publicKey is required to be able to verify, but not provided');
36
+ try {
37
+ const data = jsonwebtoken.verify(token, this.cfg.publicKey, {
38
+ algorithms: [this.cfg.algorithm],
39
+ ...this.cfg.verifyOptions,
40
+ ...opt,
41
+ });
42
+ if (schema) {
43
+ (0, joi_validation_util_1.validate)(data, schema);
44
+ }
45
+ return data;
46
+ }
47
+ catch (err) {
48
+ if (this.cfg.errorData) {
49
+ (0, js_lib_1._typeCast)(err);
50
+ (0, js_lib_1._errorDataAppend)(err, {
51
+ ...this.cfg.errorData,
52
+ });
53
+ }
54
+ throw err;
55
+ }
56
+ }
57
+ decode(token, schema) {
58
+ const data = jsonwebtoken.decode(token, {
59
+ complete: true,
60
+ });
61
+ (0, js_lib_1._assert)(data, 'invalid token, decoded value is null', {
62
+ ...this.cfg.errorData,
63
+ });
64
+ (0, joi_validation_util_1.validate)(data.payload, schema || joi_shared_schemas_1.anyObjectSchema);
65
+ return data;
66
+ }
67
+ }
68
+ exports.JWTService = JWTService;
@@ -1,10 +1,10 @@
1
1
  export interface IDebug {
2
2
  (namespace: string): IDebugger;
3
- coerce(val: any): any;
4
- disable(): string;
5
- enable(namespaces: string): void;
6
- enabled(namespaces: string): boolean;
7
- log(...args: any[]): any;
3
+ coerce: (val: any) => any;
4
+ disable: () => string;
5
+ enable: (namespaces: string) => void;
6
+ enabled: (namespaces: string) => boolean;
7
+ log: (...args: any[]) => any;
8
8
  names: RegExp[];
9
9
  skips: RegExp[];
10
10
  formatters: DebugFormatters;
@@ -16,8 +16,8 @@ export interface IDebugger {
16
16
  (...args: any[]): void;
17
17
  color: string;
18
18
  enabled: boolean;
19
- log(...args: any[]): any;
19
+ log: (...args: any[]) => any;
20
20
  namespace: string;
21
- destroy(): boolean;
21
+ destroy: () => boolean;
22
22
  }
23
23
  export declare const Debug: IDebug;
@@ -75,7 +75,7 @@ export interface TransformLogProgressOptions<IN = any> extends TransformOptions
75
75
  *
76
76
  * chunk is undefined for "final" stats, otherwise is defined.
77
77
  */
78
- extra?(chunk: IN | undefined, index: number): AnyObject;
78
+ extra?: (chunk: IN | undefined, index: number) => AnyObject;
79
79
  /**
80
80
  * If specified - will multiply the counter by this number.
81
81
  * Useful e.g when using `transformBuffer({ batchSize: 500 })`, so
@@ -29,7 +29,7 @@ export interface TransformMapOptions<IN = any, OUT = IN> {
29
29
  * If defined - will be called on every error happening in the stream.
30
30
  * Called BEFORE observable will emit error (unless skipErrors is set to true).
31
31
  */
32
- onError?(err: Error, input: IN): any;
32
+ onError?: (err: Error, input: IN) => any;
33
33
  /**
34
34
  * Progress metric
35
35
  *
@@ -27,7 +27,7 @@ export interface TransformMapSyncOptions<IN = any, OUT = IN> {
27
27
  * If defined - will be called on every error happening in the stream.
28
28
  * Called BEFORE observable will emit error (unless skipErrors is set to true).
29
29
  */
30
- onError?(err: Error, input: IN): any;
30
+ onError?: (err: Error, input: IN) => any;
31
31
  /**
32
32
  * Progress metric
33
33
  *
@@ -2,8 +2,8 @@ import * as JoiLib from 'joi';
2
2
  import { ExtendedNumberSchema } from './number.extensions';
3
3
  import { ExtendedStringSchema } from './string.extensions';
4
4
  export interface ExtendedJoi extends JoiLib.Root {
5
- string(): ExtendedStringSchema;
6
- number(): ExtendedNumberSchema;
5
+ string: () => ExtendedStringSchema;
6
+ number: () => ExtendedNumberSchema;
7
7
  }
8
8
  /**
9
9
  * This is the only right place to import Joi from
@@ -2,6 +2,6 @@ import * as Joi from 'joi';
2
2
  import { Extension, NumberSchema } from 'joi';
3
3
  import { AnySchemaTyped } from './joi.model';
4
4
  export interface ExtendedNumberSchema extends NumberSchema, AnySchemaTyped<number> {
5
- dividable(q: number): this;
5
+ dividable: (q: number) => this;
6
6
  }
7
7
  export declare function numberExtensions(joi: typeof Joi): Extension;
@@ -2,7 +2,7 @@ import { Extension, StringSchema } from 'joi';
2
2
  import * as Joi from 'joi';
3
3
  import { AnySchemaTyped } from './joi.model';
4
4
  export interface ExtendedStringSchema extends StringSchema, AnySchemaTyped<string> {
5
- dateString(min?: string, max?: string): this;
5
+ dateString: (min?: string, max?: string) => this;
6
6
  }
7
7
  export interface JoiDateStringOptions {
8
8
  min?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/nodejs-lib",
3
- "version": "12.80.4",
3
+ "version": "12.81.1",
4
4
  "scripts": {
5
5
  "prepare": "husky install",
6
6
  "docs-serve": "vuepress dev docs",
@@ -15,6 +15,7 @@
15
15
  },
16
16
  "dependencies": {
17
17
  "@naturalcycles/js-lib": "^14.0.0",
18
+ "@types/jsonwebtoken": "^8.5.9",
18
19
  "@types/through2-concurrent": "^2.0.0",
19
20
  "ajv": "^8.6.2",
20
21
  "ajv-formats": "^2.1.0",
@@ -31,6 +32,7 @@
31
32
  "globby": "^11.0.0",
32
33
  "got": "^11.0.1",
33
34
  "joi": "17.4.2",
35
+ "jsonwebtoken": "^8.5.1",
34
36
  "lru-cache": "^7.4.0",
35
37
  "move-file": "^2.0.0",
36
38
  "through2-concurrent": "^2.0.0",
package/src/index.ts CHANGED
@@ -72,6 +72,7 @@ export * from './validation/joi/joi.shared.schemas'
72
72
  export * from './validation/joi/joi.validation.error'
73
73
  export * from './validation/joi/joi.validation.util'
74
74
  export * from './script'
75
+ export * from './jwt/jwt.service'
75
76
 
76
77
  export type {
77
78
  GlobbyOptions,
@@ -0,0 +1,143 @@
1
+ import {
2
+ _assert,
3
+ _errorDataAppend,
4
+ _typeCast,
5
+ AnyObject,
6
+ ErrorData,
7
+ JWTString,
8
+ } from '@naturalcycles/js-lib'
9
+ import type { Algorithm, VerifyOptions, JwtHeader, SignOptions } from 'jsonwebtoken'
10
+ import * as jsonwebtoken from 'jsonwebtoken'
11
+ import { AnySchemaTyped } from '../validation/joi/joi.model'
12
+ import { anyObjectSchema } from '../validation/joi/joi.shared.schemas'
13
+ import { validate } from '../validation/joi/joi.validation.util'
14
+ export { jsonwebtoken }
15
+ export type { Algorithm, VerifyOptions, SignOptions, JwtHeader }
16
+
17
+ export interface JWTServiceCfg {
18
+ /**
19
+ * Public key is required to Verify incoming tokens.
20
+ * Optional if you only want to Decode or Sign.
21
+ */
22
+ publicKey?: string | Buffer
23
+ /**
24
+ * Private key is required to Sign (create) outgoing tokens.
25
+ * Optional if you only want to Decode or Verify.
26
+ */
27
+ privateKey?: string | Buffer
28
+
29
+ /**
30
+ * Recommended: ES256
31
+ */
32
+ algorithm: Algorithm
33
+
34
+ /**
35
+ * If provided - will be applied to every Sign operation.
36
+ */
37
+ signOptions?: SignOptions
38
+
39
+ /**
40
+ * If provided - will be applied to every Sign operation.
41
+ */
42
+ verifyOptions?: VerifyOptions
43
+
44
+ /**
45
+ * If set - errors thrown from this service will be extended
46
+ * with this errorData (in err.data)
47
+ */
48
+ errorData?: ErrorData
49
+ }
50
+
51
+ // todo: define JWTError and list possible options
52
+
53
+ /**
54
+ * Wraps popular `jsonwebtoken` library.
55
+ * You should create one instance of JWTService for each pair of private/public key.
56
+ *
57
+ * Generate key pair like this:
58
+ * openssl ecparam -name secp256k1 -genkey -noout -out key.pem
59
+ * openssl ec -in key.pem -pubout > key.pub.pem
60
+ */
61
+ export class JWTService {
62
+ constructor(public cfg: JWTServiceCfg) {}
63
+
64
+ sign<T extends AnyObject>(
65
+ payload: T,
66
+ schema?: AnySchemaTyped<T>,
67
+ opt: SignOptions = {},
68
+ ): JWTString {
69
+ _assert(
70
+ this.cfg.privateKey,
71
+ 'JWTService: privateKey is required to be able to verify, but not provided',
72
+ )
73
+
74
+ if (schema) {
75
+ validate(payload, schema)
76
+ }
77
+
78
+ return jsonwebtoken.sign(payload, this.cfg.privateKey, {
79
+ algorithm: this.cfg.algorithm,
80
+ noTimestamp: true,
81
+ ...this.cfg.signOptions,
82
+ ...opt,
83
+ })
84
+ }
85
+
86
+ verify<T extends AnyObject>(
87
+ token: JWTString,
88
+ schema?: AnySchemaTyped<T>,
89
+ opt: VerifyOptions = {},
90
+ ): T {
91
+ _assert(
92
+ this.cfg.publicKey,
93
+ 'JWTService: publicKey is required to be able to verify, but not provided',
94
+ )
95
+
96
+ try {
97
+ const data = jsonwebtoken.verify(token, this.cfg.publicKey, {
98
+ algorithms: [this.cfg.algorithm],
99
+ ...this.cfg.verifyOptions,
100
+ ...opt,
101
+ }) as T
102
+
103
+ if (schema) {
104
+ validate(data, schema)
105
+ }
106
+
107
+ return data
108
+ } catch (err) {
109
+ if (this.cfg.errorData) {
110
+ _typeCast<Error>(err)
111
+ _errorDataAppend(err, {
112
+ ...this.cfg.errorData,
113
+ })
114
+ }
115
+ throw err
116
+ }
117
+ }
118
+
119
+ decode<T extends AnyObject>(
120
+ token: JWTString,
121
+ schema?: AnySchemaTyped<T>,
122
+ ): {
123
+ header: JwtHeader
124
+ payload: T
125
+ signature: string
126
+ } {
127
+ const data = jsonwebtoken.decode(token, {
128
+ complete: true,
129
+ }) as {
130
+ header: JwtHeader
131
+ payload: T
132
+ signature: string
133
+ } | null
134
+
135
+ _assert(data, 'invalid token, decoded value is null', {
136
+ ...this.cfg.errorData,
137
+ })
138
+
139
+ validate(data.payload, schema || anyObjectSchema)
140
+
141
+ return data
142
+ }
143
+ }
package/src/log/debug.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  // Types based on @types/debug
2
2
  export interface IDebug {
3
3
  (namespace: string): IDebugger
4
- coerce(val: any): any
5
- disable(): string
6
- enable(namespaces: string): void
7
- enabled(namespaces: string): boolean
8
- log(...args: any[]): any
4
+ coerce: (val: any) => any
5
+ disable: () => string
6
+ enable: (namespaces: string) => void
7
+ enabled: (namespaces: string) => boolean
8
+ log: (...args: any[]) => any
9
9
 
10
10
  names: RegExp[]
11
11
  skips: RegExp[]
@@ -23,9 +23,9 @@ export interface IDebugger {
23
23
 
24
24
  color: string
25
25
  enabled: boolean
26
- log(...args: any[]): any
26
+ log: (...args: any[]) => any
27
27
  namespace: string
28
- destroy(): boolean
28
+ destroy: () => boolean
29
29
  // extend: (namespace: string, delimiter?: string) => IDebugger
30
30
  }
31
31
 
@@ -100,7 +100,7 @@ export interface TransformLogProgressOptions<IN = any> extends TransformOptions
100
100
  *
101
101
  * chunk is undefined for "final" stats, otherwise is defined.
102
102
  */
103
- extra?(chunk: IN | undefined, index: number): AnyObject
103
+ extra?: (chunk: IN | undefined, index: number) => AnyObject
104
104
 
105
105
  /**
106
106
  * If specified - will multiply the counter by this number.
@@ -48,7 +48,7 @@ export interface TransformMapOptions<IN = any, OUT = IN> {
48
48
  * If defined - will be called on every error happening in the stream.
49
49
  * Called BEFORE observable will emit error (unless skipErrors is set to true).
50
50
  */
51
- onError?(err: Error, input: IN): any
51
+ onError?: (err: Error, input: IN) => any
52
52
 
53
53
  /**
54
54
  * Progress metric
@@ -43,7 +43,7 @@ export interface TransformMapSyncOptions<IN = any, OUT = IN> {
43
43
  * If defined - will be called on every error happening in the stream.
44
44
  * Called BEFORE observable will emit error (unless skipErrors is set to true).
45
45
  */
46
- onError?(err: Error, input: IN): any
46
+ onError?: (err: Error, input: IN) => any
47
47
 
48
48
  /**
49
49
  * Progress metric
@@ -5,9 +5,9 @@ import { ExtendedStringSchema, stringExtensions } from './string.extensions'
5
5
 
6
6
  export interface ExtendedJoi extends JoiLib.Root {
7
7
  // eslint-disable-next-line id-blacklist
8
- string(): ExtendedStringSchema
8
+ string: () => ExtendedStringSchema
9
9
  // eslint-disable-next-line id-blacklist
10
- number(): ExtendedNumberSchema
10
+ number: () => ExtendedNumberSchema
11
11
  }
12
12
 
13
13
  /**
@@ -3,7 +3,7 @@ import { Extension, NumberSchema } from 'joi'
3
3
  import { AnySchemaTyped } from './joi.model'
4
4
 
5
5
  export interface ExtendedNumberSchema extends NumberSchema, AnySchemaTyped<number> {
6
- dividable(q: number): this
6
+ dividable: (q: number) => this
7
7
  }
8
8
 
9
9
  export function numberExtensions(joi: typeof Joi): Extension {
@@ -4,7 +4,7 @@ import * as Joi from 'joi'
4
4
  import { AnySchemaTyped } from './joi.model'
5
5
 
6
6
  export interface ExtendedStringSchema extends StringSchema, AnySchemaTyped<string> {
7
- dateString(min?: string, max?: string): this
7
+ dateString: (min?: string, max?: string) => this
8
8
  }
9
9
 
10
10
  export interface JoiDateStringOptions {