chain-simple 1.3.3 → 2.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/built/{index.d.ts → cjs/index.d.ts} +5 -4
- package/built/{index.js → cjs/index.js} +35 -30
- package/built/esm/index.d.ts +51 -0
- package/built/esm/index.js +174 -0
- package/built/esm/logger.d.ts +4 -0
- package/built/esm/logger.js +7 -0
- package/lib/index.ts +36 -26
- package/package.json +15 -7
- package/readme.md +5 -5
- package/tsconfig.esm.json +18 -0
- package/tsconfig.json +6 -7
- /package/built/{logger.d.ts → cjs/logger.d.ts} +0 -0
- /package/built/{logger.js → cjs/logger.js} +0 -0
|
@@ -5,6 +5,7 @@ export type TChainable<T extends Record<string, TFn>> = {
|
|
|
5
5
|
};
|
|
6
6
|
type TConfig = {
|
|
7
7
|
getEntity?: string;
|
|
8
|
+
extendOnly?: boolean;
|
|
8
9
|
extendProxed?: (propName: any) => {
|
|
9
10
|
[k: string]: any;
|
|
10
11
|
} | ((item: any) => {
|
|
@@ -16,7 +17,7 @@ type TConfig = {
|
|
|
16
17
|
};
|
|
17
18
|
/**
|
|
18
19
|
* @example
|
|
19
|
-
* const {
|
|
20
|
+
* const {chainProps} = require('chain-simple');
|
|
20
21
|
* const obj = {
|
|
21
22
|
* async method1() {
|
|
22
23
|
* return Promise.resolve(1).then(value => {
|
|
@@ -37,7 +38,7 @@ type TConfig = {
|
|
|
37
38
|
* });
|
|
38
39
|
* },
|
|
39
40
|
* };
|
|
40
|
-
* const chainableObj =
|
|
41
|
+
* const chainableObj = chainProps(obj);
|
|
41
42
|
* obj.method1().method3().then((val) => console.log(val))
|
|
42
43
|
*
|
|
43
44
|
*
|
|
@@ -45,6 +46,6 @@ type TConfig = {
|
|
|
45
46
|
* @param {{getEntity: string}} [config] config to describe how to get original not project object
|
|
46
47
|
* @returns {object} object with chainable properties
|
|
47
48
|
*/
|
|
48
|
-
declare function
|
|
49
|
+
declare function chainProps(item: any, config?: TConfig): any;
|
|
49
50
|
declare function makeConstructorInstancePropertiesChainable(constructorFunction: any, config?: TConfig): any;
|
|
50
|
-
export {
|
|
51
|
+
export { chainProps, makeConstructorInstancePropertiesChainable };
|
|
@@ -1,12 +1,31 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.chainProps = chainProps;
|
|
4
|
+
exports.makeConstructorInstancePropertiesChainable = makeConstructorInstancePropertiesChainable;
|
|
4
5
|
const sat_utils_1 = require("sat-utils");
|
|
5
6
|
const logger_1 = require("./logger");
|
|
6
7
|
logger_1.logger.setLogLevel(process.env.CHAIN_SIMPLE_LOG_LEVEL);
|
|
8
|
+
function extendProxed(target, propName, receiver, config) {
|
|
9
|
+
if ((0, sat_utils_1.isObject)(config) && (0, sat_utils_1.isFunction)(config.extendProxed) && (0, sat_utils_1.isUndefined)(Reflect.get(target, propName, receiver))) {
|
|
10
|
+
try {
|
|
11
|
+
const extension = config.extendProxed(propName);
|
|
12
|
+
if ((0, sat_utils_1.isObject)(extension)) {
|
|
13
|
+
Object.assign(target, extension);
|
|
14
|
+
}
|
|
15
|
+
else if ((0, sat_utils_1.isFunction)(extension)) {
|
|
16
|
+
const result = extension(target);
|
|
17
|
+
Object.assign(target, result);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
console.error(error);
|
|
22
|
+
}
|
|
23
|
+
return target;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
7
26
|
/**
|
|
8
27
|
* @example
|
|
9
|
-
* const {
|
|
28
|
+
* const {chainProps} = require('chain-simple');
|
|
10
29
|
* const obj = {
|
|
11
30
|
* async method1() {
|
|
12
31
|
* return Promise.resolve(1).then(value => {
|
|
@@ -27,7 +46,7 @@ logger_1.logger.setLogLevel(process.env.CHAIN_SIMPLE_LOG_LEVEL);
|
|
|
27
46
|
* });
|
|
28
47
|
* },
|
|
29
48
|
* };
|
|
30
|
-
* const chainableObj =
|
|
49
|
+
* const chainableObj = chainProps(obj);
|
|
31
50
|
* obj.method1().method3().then((val) => console.log(val))
|
|
32
51
|
*
|
|
33
52
|
*
|
|
@@ -35,7 +54,7 @@ logger_1.logger.setLogLevel(process.env.CHAIN_SIMPLE_LOG_LEVEL);
|
|
|
35
54
|
* @param {{getEntity: string}} [config] config to describe how to get original not project object
|
|
36
55
|
* @returns {object} object with chainable properties
|
|
37
56
|
*/
|
|
38
|
-
function
|
|
57
|
+
function chainProps(item, config) {
|
|
39
58
|
const promiseCallableProps = ['then', 'catch', 'finally'];
|
|
40
59
|
const propsList = [];
|
|
41
60
|
if ((0, sat_utils_1.isObject)(config) && config.getEntityPropList) {
|
|
@@ -47,23 +66,27 @@ function makePropertiesChainable(item, config) {
|
|
|
47
66
|
: config.getEntityPropList));
|
|
48
67
|
}
|
|
49
68
|
if (!(0, sat_utils_1.canBeProxed)(item)) {
|
|
50
|
-
throw new TypeError('
|
|
69
|
+
throw new TypeError('chainProps(): first argument should be an entity that can be proxed');
|
|
51
70
|
}
|
|
52
71
|
if (!(0, sat_utils_1.isUndefined)(config) && !(0, sat_utils_1.isObject)(config)) {
|
|
53
|
-
throw new TypeError('
|
|
72
|
+
throw new TypeError('chainProps(): second argument should be an object');
|
|
54
73
|
}
|
|
74
|
+
const _config = { ...config };
|
|
55
75
|
let proxifiedResult = item;
|
|
56
76
|
const proxed = new Proxy(item, {
|
|
57
77
|
get(_t, p, r) {
|
|
58
|
-
var _a;
|
|
59
78
|
if (propsList.length && propsList.includes(p)) {
|
|
60
|
-
const propValue =
|
|
79
|
+
const propValue = Reflect.getOwnPropertyDescriptor(item, p)?.value;
|
|
61
80
|
if ((0, sat_utils_1.isFunction)(propValue) || (0, sat_utils_1.isAsyncFunction)(propValue)) {
|
|
62
81
|
return item[p].bind(item);
|
|
63
82
|
}
|
|
64
83
|
return item[p];
|
|
65
84
|
}
|
|
66
|
-
if (
|
|
85
|
+
if (_config.extendOnly) {
|
|
86
|
+
extendProxed(item, p, r, config);
|
|
87
|
+
return item[p];
|
|
88
|
+
}
|
|
89
|
+
if (_config.getEntity === p) {
|
|
67
90
|
return item;
|
|
68
91
|
}
|
|
69
92
|
if (p === Symbol.toStringTag) {
|
|
@@ -79,24 +102,8 @@ function makePropertiesChainable(item, config) {
|
|
|
79
102
|
return proxifiedResult;
|
|
80
103
|
};
|
|
81
104
|
}
|
|
82
|
-
if (!promiseCallableProps.includes(p)
|
|
83
|
-
(
|
|
84
|
-
(0, sat_utils_1.isObject)(config) &&
|
|
85
|
-
(0, sat_utils_1.isFunction)(config.extendProxed)) {
|
|
86
|
-
try {
|
|
87
|
-
const extension = config.extendProxed(p);
|
|
88
|
-
if ((0, sat_utils_1.isObject)(extension)) {
|
|
89
|
-
Object.assign(item, extension);
|
|
90
|
-
}
|
|
91
|
-
else if ((0, sat_utils_1.isFunction)(extension)) {
|
|
92
|
-
// @ts-ignore
|
|
93
|
-
const result = extension(item);
|
|
94
|
-
Object.assign(item, result);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
catch (error) {
|
|
98
|
-
console.error(error);
|
|
99
|
-
}
|
|
105
|
+
if (!promiseCallableProps.includes(p)) {
|
|
106
|
+
extendProxed(item, p, r, config);
|
|
100
107
|
}
|
|
101
108
|
const isCallable = (0, sat_utils_1.isFunction)(Reflect.get(item, p, r)) || (0, sat_utils_1.isAsyncFunction)(Reflect.get(item, p, r));
|
|
102
109
|
if (!isCallable && !(0, sat_utils_1.isPromise)(proxifiedResult) && item[p] && !proxifiedResult[p]) {
|
|
@@ -153,17 +160,15 @@ function makePropertiesChainable(item, config) {
|
|
|
153
160
|
});
|
|
154
161
|
return proxed;
|
|
155
162
|
}
|
|
156
|
-
exports.makePropertiesChainable = makePropertiesChainable;
|
|
157
163
|
function handlerConstructor(config) {
|
|
158
164
|
return {
|
|
159
165
|
construct(target, args) {
|
|
160
166
|
const item = new target(...args);
|
|
161
|
-
return
|
|
167
|
+
return chainProps(item, config);
|
|
162
168
|
},
|
|
163
169
|
};
|
|
164
170
|
}
|
|
165
171
|
function makeConstructorInstancePropertiesChainable(constructorFunction, config) {
|
|
166
172
|
return new Proxy(constructorFunction, handlerConstructor(config));
|
|
167
173
|
}
|
|
168
|
-
exports.makeConstructorInstancePropertiesChainable = makeConstructorInstancePropertiesChainable;
|
|
169
174
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
type TFn = (...args: any) => any;
|
|
2
|
+
type TReplaceReturnType<T extends TFn, TNewReturnType> = (...args: Parameters<T>) => TNewReturnType;
|
|
3
|
+
export type TChainable<T extends Record<string, TFn>> = {
|
|
4
|
+
[K in keyof T]: TReplaceReturnType<T[K], ReturnType<T[K]> & TChainable<T>>;
|
|
5
|
+
};
|
|
6
|
+
type TConfig = {
|
|
7
|
+
getEntity?: string;
|
|
8
|
+
extendOnly?: boolean;
|
|
9
|
+
extendProxed?: (propName: any) => {
|
|
10
|
+
[k: string]: any;
|
|
11
|
+
} | ((item: any) => {
|
|
12
|
+
[k: string]: any;
|
|
13
|
+
});
|
|
14
|
+
getEntityPropList?: string[] | {
|
|
15
|
+
[k: string]: any;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* @example
|
|
20
|
+
* const {chainProps} = require('chain-simple');
|
|
21
|
+
* const obj = {
|
|
22
|
+
* async method1() {
|
|
23
|
+
* return Promise.resolve(1).then(value => {
|
|
24
|
+
* console.log('method1', value);
|
|
25
|
+
* return value;
|
|
26
|
+
* });
|
|
27
|
+
* },
|
|
28
|
+
* async method2() {
|
|
29
|
+
* return Promise.resolve(2).then(value => {
|
|
30
|
+
* console.log('method2', value);
|
|
31
|
+
* return value;
|
|
32
|
+
* });
|
|
33
|
+
* },
|
|
34
|
+
* async method3() {
|
|
35
|
+
* return Promise.resolve(3).then(value => {
|
|
36
|
+
* console.log('method3', value);
|
|
37
|
+
* return value;
|
|
38
|
+
* });
|
|
39
|
+
* },
|
|
40
|
+
* };
|
|
41
|
+
* const chainableObj = chainProps(obj);
|
|
42
|
+
* obj.method1().method3().then((val) => console.log(val))
|
|
43
|
+
*
|
|
44
|
+
*
|
|
45
|
+
* @param {!object} item
|
|
46
|
+
* @param {{getEntity: string}} [config] config to describe how to get original not project object
|
|
47
|
+
* @returns {object} object with chainable properties
|
|
48
|
+
*/
|
|
49
|
+
declare function chainProps(item: any, config?: TConfig): any;
|
|
50
|
+
declare function makeConstructorInstancePropertiesChainable(constructorFunction: any, config?: TConfig): any;
|
|
51
|
+
export { chainProps, makeConstructorInstancePropertiesChainable };
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.chainProps = chainProps;
|
|
4
|
+
exports.makeConstructorInstancePropertiesChainable = makeConstructorInstancePropertiesChainable;
|
|
5
|
+
const sat_utils_1 = require("sat-utils");
|
|
6
|
+
const logger_1 = require("./logger");
|
|
7
|
+
logger_1.logger.setLogLevel(process.env.CHAIN_SIMPLE_LOG_LEVEL);
|
|
8
|
+
function extendProxed(target, propName, receiver, config) {
|
|
9
|
+
if ((0, sat_utils_1.isObject)(config) && (0, sat_utils_1.isFunction)(config.extendProxed) && (0, sat_utils_1.isUndefined)(Reflect.get(target, propName, receiver))) {
|
|
10
|
+
try {
|
|
11
|
+
const extension = config.extendProxed(propName);
|
|
12
|
+
if ((0, sat_utils_1.isObject)(extension)) {
|
|
13
|
+
Object.assign(target, extension);
|
|
14
|
+
}
|
|
15
|
+
else if ((0, sat_utils_1.isFunction)(extension)) {
|
|
16
|
+
const result = extension(target);
|
|
17
|
+
Object.assign(target, result);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
console.error(error);
|
|
22
|
+
}
|
|
23
|
+
return target;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* @example
|
|
28
|
+
* const {chainProps} = require('chain-simple');
|
|
29
|
+
* const obj = {
|
|
30
|
+
* async method1() {
|
|
31
|
+
* return Promise.resolve(1).then(value => {
|
|
32
|
+
* console.log('method1', value);
|
|
33
|
+
* return value;
|
|
34
|
+
* });
|
|
35
|
+
* },
|
|
36
|
+
* async method2() {
|
|
37
|
+
* return Promise.resolve(2).then(value => {
|
|
38
|
+
* console.log('method2', value);
|
|
39
|
+
* return value;
|
|
40
|
+
* });
|
|
41
|
+
* },
|
|
42
|
+
* async method3() {
|
|
43
|
+
* return Promise.resolve(3).then(value => {
|
|
44
|
+
* console.log('method3', value);
|
|
45
|
+
* return value;
|
|
46
|
+
* });
|
|
47
|
+
* },
|
|
48
|
+
* };
|
|
49
|
+
* const chainableObj = chainProps(obj);
|
|
50
|
+
* obj.method1().method3().then((val) => console.log(val))
|
|
51
|
+
*
|
|
52
|
+
*
|
|
53
|
+
* @param {!object} item
|
|
54
|
+
* @param {{getEntity: string}} [config] config to describe how to get original not project object
|
|
55
|
+
* @returns {object} object with chainable properties
|
|
56
|
+
*/
|
|
57
|
+
function chainProps(item, config) {
|
|
58
|
+
const promiseCallableProps = ['then', 'catch', 'finally'];
|
|
59
|
+
const propsList = [];
|
|
60
|
+
if ((0, sat_utils_1.isObject)(config) && config.getEntityPropList) {
|
|
61
|
+
if (!(0, sat_utils_1.isObject)(config.getEntityPropList) && !(0, sat_utils_1.isArray)(config.getEntityPropList)) {
|
|
62
|
+
throw new TypeError('config "getEntityPropList" should be an array or an object');
|
|
63
|
+
}
|
|
64
|
+
propsList.push(...((0, sat_utils_1.isObject)(config.getEntityPropList)
|
|
65
|
+
? Object.keys(config.getEntityPropList)
|
|
66
|
+
: config.getEntityPropList));
|
|
67
|
+
}
|
|
68
|
+
if (!(0, sat_utils_1.canBeProxed)(item)) {
|
|
69
|
+
throw new TypeError('chainProps(): first argument should be an entity that can be proxed');
|
|
70
|
+
}
|
|
71
|
+
if (!(0, sat_utils_1.isUndefined)(config) && !(0, sat_utils_1.isObject)(config)) {
|
|
72
|
+
throw new TypeError('chainProps(): second argument should be an object');
|
|
73
|
+
}
|
|
74
|
+
const _config = { ...config };
|
|
75
|
+
let proxifiedResult = item;
|
|
76
|
+
const proxed = new Proxy(item, {
|
|
77
|
+
get(_t, p, r) {
|
|
78
|
+
if (propsList.length && propsList.includes(p)) {
|
|
79
|
+
const propValue = Reflect.getOwnPropertyDescriptor(item, p)?.value;
|
|
80
|
+
if ((0, sat_utils_1.isFunction)(propValue) || (0, sat_utils_1.isAsyncFunction)(propValue)) {
|
|
81
|
+
return item[p].bind(item);
|
|
82
|
+
}
|
|
83
|
+
return item[p];
|
|
84
|
+
}
|
|
85
|
+
if (_config.extendOnly) {
|
|
86
|
+
extendProxed(item, p, r, config);
|
|
87
|
+
return item[p];
|
|
88
|
+
}
|
|
89
|
+
if (_config.getEntity === p) {
|
|
90
|
+
return item;
|
|
91
|
+
}
|
|
92
|
+
if (p === Symbol.toStringTag) {
|
|
93
|
+
return proxifiedResult[Symbol.toStringTag];
|
|
94
|
+
}
|
|
95
|
+
if (p === 'toString') {
|
|
96
|
+
return function (...args) {
|
|
97
|
+
return proxifiedResult.toString(...args);
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
if (p === 'toJSON') {
|
|
101
|
+
return function () {
|
|
102
|
+
return proxifiedResult;
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
if (!promiseCallableProps.includes(p)) {
|
|
106
|
+
extendProxed(item, p, r, config);
|
|
107
|
+
}
|
|
108
|
+
const isCallable = (0, sat_utils_1.isFunction)(Reflect.get(item, p, r)) || (0, sat_utils_1.isAsyncFunction)(Reflect.get(item, p, r));
|
|
109
|
+
if (!isCallable && !(0, sat_utils_1.isPromise)(proxifiedResult) && item[p] && !proxifiedResult[p]) {
|
|
110
|
+
logger_1.logger.chainer(`[CHAIN_SIMPLE]: ${String(p)} is not a callable.`);
|
|
111
|
+
return item[p];
|
|
112
|
+
}
|
|
113
|
+
else if (isCallable) {
|
|
114
|
+
logger_1.logger.chainer(`[CHAIN_SIMPLE]: ${String(p)} is a callable.`);
|
|
115
|
+
return function (...arguments_) {
|
|
116
|
+
logger_1.logger.chainer(`[CHAIN_SIMPLE]: ${String(p)} is called with args: `, ...arguments);
|
|
117
|
+
if ((0, sat_utils_1.isPromise)(proxifiedResult)) {
|
|
118
|
+
logger_1.logger.chainer(`[CHAIN_SIMPLE]: previous call result is a promise`);
|
|
119
|
+
proxifiedResult = proxifiedResult.then(function (r) {
|
|
120
|
+
logger_1.logger.chainer(`[CHAIN_SIMPLE]: previous call result is: `, r);
|
|
121
|
+
return item[p].call(item, ...arguments_);
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
logger_1.logger.chainer(`[CHAIN_SIMPLE]: previous call result is not a promise`);
|
|
126
|
+
logger_1.logger.chainer(`[CHAIN_SIMPLE]: previous call result is: `, proxifiedResult);
|
|
127
|
+
proxifiedResult = item[p].call(item, ...arguments_);
|
|
128
|
+
}
|
|
129
|
+
return proxed;
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
else if (promiseCallableProps.includes(p) && (0, sat_utils_1.isPromise)(proxifiedResult)) {
|
|
133
|
+
logger_1.logger.chainer(`[CHAIN_SIMPLE]: previous call result is a promise and next call is a promise method call`);
|
|
134
|
+
if (!(0, sat_utils_1.isPromise)(proxifiedResult)) {
|
|
135
|
+
return proxifiedResult;
|
|
136
|
+
}
|
|
137
|
+
return function (onRes, onRej) {
|
|
138
|
+
const promised = proxifiedResult;
|
|
139
|
+
proxifiedResult = item;
|
|
140
|
+
return promised[p].call(promised, onRes, onRej);
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
else if (proxifiedResult[p]) {
|
|
144
|
+
return proxifiedResult[p];
|
|
145
|
+
}
|
|
146
|
+
if (!(p in item) && p in proxifiedResult) {
|
|
147
|
+
return proxifiedResult[p];
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
/** @info base */
|
|
151
|
+
getPrototypeOf(_t) {
|
|
152
|
+
return Object.getPrototypeOf(proxifiedResult);
|
|
153
|
+
},
|
|
154
|
+
ownKeys(_t) {
|
|
155
|
+
return Object.getOwnPropertyNames(proxifiedResult);
|
|
156
|
+
},
|
|
157
|
+
getOwnPropertyDescriptor(_t, p) {
|
|
158
|
+
return Object.getOwnPropertyDescriptor(proxifiedResult, p);
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
return proxed;
|
|
162
|
+
}
|
|
163
|
+
function handlerConstructor(config) {
|
|
164
|
+
return {
|
|
165
|
+
construct(target, args) {
|
|
166
|
+
const item = new target(...args);
|
|
167
|
+
return chainProps(item, config);
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
function makeConstructorInstancePropertiesChainable(constructorFunction, config) {
|
|
172
|
+
return new Proxy(constructorFunction, handlerConstructor(config));
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.logger = void 0;
|
|
4
|
+
const sat_utils_1 = require("sat-utils");
|
|
5
|
+
const logger = (0, sat_utils_1.createLogger)().addCustomLevel('chainer', 'CHAIN_LOG', 'CHAIN_LOG', 'info', 'BgBlue', 'BgWhite');
|
|
6
|
+
exports.logger = logger;
|
|
7
|
+
//# sourceMappingURL=logger.js.map
|
package/lib/index.ts
CHANGED
|
@@ -14,13 +14,32 @@ export type TChainable<T extends Record<string, TFn>> = {
|
|
|
14
14
|
|
|
15
15
|
type TConfig = {
|
|
16
16
|
getEntity?: string;
|
|
17
|
+
extendOnly?: boolean;
|
|
17
18
|
extendProxed?: (propName) => { [k: string]: any } | ((item: any) => { [k: string]: any });
|
|
18
19
|
getEntityPropList?: string[] | { [k: string]: any };
|
|
19
20
|
};
|
|
20
21
|
|
|
22
|
+
function extendProxed(target, propName: string | symbol, receiver: any, config: TConfig) {
|
|
23
|
+
if (isObject(config) && isFunction(config.extendProxed) && isUndefined(Reflect.get(target, propName, receiver))) {
|
|
24
|
+
try {
|
|
25
|
+
const extension = config.extendProxed(propName);
|
|
26
|
+
if (isObject(extension)) {
|
|
27
|
+
Object.assign(target, extension);
|
|
28
|
+
} else if (isFunction(extension)) {
|
|
29
|
+
const result = (extension as TConfig['extendProxed'])(target);
|
|
30
|
+
Object.assign(target, result);
|
|
31
|
+
}
|
|
32
|
+
} catch (error) {
|
|
33
|
+
console.error(error);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return target;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
21
40
|
/**
|
|
22
41
|
* @example
|
|
23
|
-
* const {
|
|
42
|
+
* const {chainProps} = require('chain-simple');
|
|
24
43
|
* const obj = {
|
|
25
44
|
* async method1() {
|
|
26
45
|
* return Promise.resolve(1).then(value => {
|
|
@@ -41,7 +60,7 @@ type TConfig = {
|
|
|
41
60
|
* });
|
|
42
61
|
* },
|
|
43
62
|
* };
|
|
44
|
-
* const chainableObj =
|
|
63
|
+
* const chainableObj = chainProps(obj);
|
|
45
64
|
* obj.method1().method3().then((val) => console.log(val))
|
|
46
65
|
*
|
|
47
66
|
*
|
|
@@ -49,7 +68,7 @@ type TConfig = {
|
|
|
49
68
|
* @param {{getEntity: string}} [config] config to describe how to get original not project object
|
|
50
69
|
* @returns {object} object with chainable properties
|
|
51
70
|
*/
|
|
52
|
-
function
|
|
71
|
+
function chainProps(item, config?: TConfig) {
|
|
53
72
|
const promiseCallableProps: any[] = ['then', 'catch', 'finally'];
|
|
54
73
|
const propsList = [];
|
|
55
74
|
|
|
@@ -66,12 +85,13 @@ function makePropertiesChainable(item, config?: TConfig) {
|
|
|
66
85
|
}
|
|
67
86
|
|
|
68
87
|
if (!canBeProxed(item)) {
|
|
69
|
-
throw new TypeError('
|
|
88
|
+
throw new TypeError('chainProps(): first argument should be an entity that can be proxed');
|
|
70
89
|
}
|
|
71
90
|
|
|
72
91
|
if (!isUndefined(config) && !isObject(config)) {
|
|
73
|
-
throw new TypeError('
|
|
92
|
+
throw new TypeError('chainProps(): second argument should be an object');
|
|
74
93
|
}
|
|
94
|
+
const _config = { ...config };
|
|
75
95
|
|
|
76
96
|
let proxifiedResult = item;
|
|
77
97
|
const proxed = new Proxy(item, {
|
|
@@ -84,7 +104,13 @@ function makePropertiesChainable(item, config?: TConfig) {
|
|
|
84
104
|
return item[p];
|
|
85
105
|
}
|
|
86
106
|
|
|
87
|
-
if (
|
|
107
|
+
if (_config.extendOnly) {
|
|
108
|
+
extendProxed(item, p, r, config);
|
|
109
|
+
|
|
110
|
+
return item[p];
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (_config.getEntity === p) {
|
|
88
114
|
return item;
|
|
89
115
|
}
|
|
90
116
|
|
|
@@ -104,24 +130,8 @@ function makePropertiesChainable(item, config?: TConfig) {
|
|
|
104
130
|
};
|
|
105
131
|
}
|
|
106
132
|
|
|
107
|
-
if (
|
|
108
|
-
|
|
109
|
-
isUndefined(Reflect.get(item, p, r)) &&
|
|
110
|
-
isObject(config) &&
|
|
111
|
-
isFunction(config.extendProxed)
|
|
112
|
-
) {
|
|
113
|
-
try {
|
|
114
|
-
const extension = config.extendProxed(p);
|
|
115
|
-
if (isObject(extension)) {
|
|
116
|
-
Object.assign(item, extension);
|
|
117
|
-
} else if (isFunction(extension)) {
|
|
118
|
-
// @ts-ignore
|
|
119
|
-
const result = extension(item);
|
|
120
|
-
Object.assign(item, result);
|
|
121
|
-
}
|
|
122
|
-
} catch (error) {
|
|
123
|
-
console.error(error);
|
|
124
|
-
}
|
|
133
|
+
if (!promiseCallableProps.includes(p)) {
|
|
134
|
+
extendProxed(item, p, r, config);
|
|
125
135
|
}
|
|
126
136
|
|
|
127
137
|
const isCallable = isFunction(Reflect.get(item, p, r)) || isAsyncFunction(Reflect.get(item, p, r));
|
|
@@ -191,7 +201,7 @@ function handlerConstructor(config) {
|
|
|
191
201
|
return {
|
|
192
202
|
construct(target, args) {
|
|
193
203
|
const item = new target(...args);
|
|
194
|
-
return
|
|
204
|
+
return chainProps(item, config);
|
|
195
205
|
},
|
|
196
206
|
};
|
|
197
207
|
}
|
|
@@ -200,4 +210,4 @@ function makeConstructorInstancePropertiesChainable(constructorFunction, config?
|
|
|
200
210
|
return new Proxy(constructorFunction, handlerConstructor(config));
|
|
201
211
|
}
|
|
202
212
|
|
|
203
|
-
export {
|
|
213
|
+
export { chainProps, makeConstructorInstancePropertiesChainable };
|
package/package.json
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chain-simple",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Main purpose of this package is - provide simple way to build chain between any item methods",
|
|
5
|
-
"main": "built/index.js",
|
|
5
|
+
"main": "./built/cjs/index.js",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"require": "./built/cjs/index.js",
|
|
9
|
+
"import": "./built/esm/index.js"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
6
12
|
"directories": {
|
|
7
13
|
"example": "examples",
|
|
8
14
|
"lib": "lib"
|
|
@@ -12,7 +18,9 @@
|
|
|
12
18
|
"test:verbose": "LOG_LEVEL=VERBOSE mocha ./specs/**/*.spec.ts --require ts-node/register --timeout 30000",
|
|
13
19
|
"test:watch": "mocha ./specs/**/*.spec.ts --require ts-node/register --timeout 30000 --watch",
|
|
14
20
|
"lint": "eslint --ext .ts ./",
|
|
15
|
-
"tsc": "
|
|
21
|
+
"tsc:cjs": "tsc -p tsconfig.json",
|
|
22
|
+
"tsc:esm": "tsc -p tsconfig.esm.json",
|
|
23
|
+
"tsc": "rm -rf ./built && npm run tsc:cjs && npm run tsc:esm",
|
|
16
24
|
"prepublish": "npm run tsc"
|
|
17
25
|
},
|
|
18
26
|
"keywords": [
|
|
@@ -38,7 +46,6 @@
|
|
|
38
46
|
"homepage": "https://github.com/Simple-Automation-Testing/chain-simple#readme",
|
|
39
47
|
"devDependencies": {
|
|
40
48
|
"@types/mocha": "^8.2.0",
|
|
41
|
-
"@types/node": "^14.14.17",
|
|
42
49
|
"@typescript-eslint/eslint-plugin": "^4.11.1",
|
|
43
50
|
"@typescript-eslint/parser": "^4.11.1",
|
|
44
51
|
"assertior": "0.0.23",
|
|
@@ -48,13 +55,14 @@
|
|
|
48
55
|
"eslint-plugin-mocha": "^8.0.0",
|
|
49
56
|
"mocha": "^8.2.1",
|
|
50
57
|
"prettier": "^2.6.2",
|
|
51
|
-
"ts-node": "^10.9.
|
|
52
|
-
"typescript": "^
|
|
58
|
+
"ts-node": "^10.9.2",
|
|
59
|
+
"typescript": "^5.8.3"
|
|
53
60
|
},
|
|
54
61
|
"engines": {
|
|
55
|
-
"node": ">=
|
|
62
|
+
"node": ">=20.9.0"
|
|
56
63
|
},
|
|
57
64
|
"dependencies": {
|
|
58
65
|
"sat-utils": "1.9.0"
|
|
59
66
|
}
|
|
60
67
|
}
|
|
68
|
+
|
package/readme.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
The purpose of this library is - build simple and flexible chainable call of the object` methods
|
|
6
6
|
|
|
7
7
|
```ts
|
|
8
|
-
import {
|
|
8
|
+
import { chainProps } from 'chain-simple';
|
|
9
9
|
import type { TChainable } from 'chain-simple';
|
|
10
10
|
|
|
11
11
|
const obj = {
|
|
@@ -29,7 +29,7 @@ const obj = {
|
|
|
29
29
|
},
|
|
30
30
|
};
|
|
31
31
|
|
|
32
|
-
const chainableObj: TChainable<typeof obj> =
|
|
32
|
+
const chainableObj: TChainable<typeof obj> = chainProps(obj);
|
|
33
33
|
|
|
34
34
|
chainableObj
|
|
35
35
|
.method1()
|
|
@@ -38,7 +38,7 @@ chainableObj
|
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
```js
|
|
41
|
-
const {
|
|
41
|
+
const { chainProps } = require('chain-simple');
|
|
42
42
|
|
|
43
43
|
const obj = {
|
|
44
44
|
async method1() {
|
|
@@ -61,10 +61,10 @@ const obj = {
|
|
|
61
61
|
},
|
|
62
62
|
};
|
|
63
63
|
|
|
64
|
-
const chainableObj: TChainable<typeof obj> =
|
|
64
|
+
const chainableObj: TChainable<typeof obj> = chainProps(obj);
|
|
65
65
|
|
|
66
66
|
chainableObj
|
|
67
67
|
.method1()
|
|
68
68
|
.method3()
|
|
69
69
|
.then(val => console.log(val)); // method1 1 \n method3 3 \n 3
|
|
70
|
-
```
|
|
70
|
+
```
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"module": "NodeNext",
|
|
4
|
+
"target": "ESNext",
|
|
5
|
+
"sourceMap": true,
|
|
6
|
+
"outDir": "built/esm",
|
|
7
|
+
"declaration": true,
|
|
8
|
+
"experimentalDecorators": true,
|
|
9
|
+
"allowJs": true
|
|
10
|
+
},
|
|
11
|
+
"exclude": [
|
|
12
|
+
"node_modules",
|
|
13
|
+
"built",
|
|
14
|
+
"specs",
|
|
15
|
+
"example",
|
|
16
|
+
"playground.*"
|
|
17
|
+
]
|
|
18
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
3
|
"module": "commonjs",
|
|
4
|
-
"target": "
|
|
4
|
+
"target": "es2020",
|
|
5
5
|
"sourceMap": true,
|
|
6
|
-
"outDir": "built",
|
|
6
|
+
"outDir": "built/cjs",
|
|
7
7
|
"declaration": true,
|
|
8
|
-
"experimentalDecorators": true
|
|
8
|
+
"experimentalDecorators": true,
|
|
9
|
+
"allowJs": true
|
|
9
10
|
},
|
|
10
|
-
"include": [
|
|
11
|
-
"lib"
|
|
12
|
-
],
|
|
13
11
|
"exclude": [
|
|
14
12
|
"node_modules",
|
|
15
13
|
"built",
|
|
16
14
|
"specs",
|
|
17
|
-
"example"
|
|
15
|
+
"example",
|
|
16
|
+
"playground.*"
|
|
18
17
|
]
|
|
19
18
|
}
|
|
File without changes
|
|
File without changes
|