@bemoje/fn 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/index.d.ts +247 -0
- package/index.mjs +282 -0
- package/package.json +35 -0
package/index.d.ts
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { ArraySlice } from 'type-fest';
|
|
2
|
+
import { ArraySplice } from 'type-fest';
|
|
3
|
+
import { Constructor } from 'type-fest';
|
|
4
|
+
import { Subtract } from 'type-fest';
|
|
5
|
+
import { TupleToObject } from 'type-fest';
|
|
6
|
+
import { UnionToTuple } from 'type-fest';
|
|
7
|
+
|
|
8
|
+
type Any = any;
|
|
9
|
+
|
|
10
|
+
type TFunction<R = Any, A extends Any[] = Any[]> = (...args: A) => R;
|
|
11
|
+
|
|
12
|
+
type AnyFunction<Ret = Any, Args extends Any[] = Any[]> = Constructor<Ret, Args> | TFunction<Ret, Args>;
|
|
13
|
+
|
|
14
|
+
type AnyGetter = () => Any;
|
|
15
|
+
|
|
16
|
+
type AnySetter = (value: Any) => Any;
|
|
17
|
+
|
|
18
|
+
type Increment<T extends number> = Subtract<T, -1>;
|
|
19
|
+
|
|
20
|
+
type RemoveArrayElement<T extends any[], Index extends number> = ArraySplice<T, Index, 1, []>;
|
|
21
|
+
|
|
22
|
+
type ParametersWithout<T extends (...args: any[]) => any, Index extends number> = RemoveArrayElement<
|
|
23
|
+
Parameters<T>,
|
|
24
|
+
Index
|
|
25
|
+
>;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Removes elements from an array at specified indices.
|
|
29
|
+
*/
|
|
30
|
+
type RemoveArrayElements<T extends any[], Indices extends number[], Offset extends number = 0> = Indices extends [
|
|
31
|
+
infer First extends number,
|
|
32
|
+
...infer Rest extends number[],
|
|
33
|
+
]
|
|
34
|
+
? RemoveArrayElements<
|
|
35
|
+
RemoveArrayElement<T, Subtract<First, Offset>>,
|
|
36
|
+
Rest,
|
|
37
|
+
Offset extends number ? Increment<Offset> : never
|
|
38
|
+
>
|
|
39
|
+
: T;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Binds a specified argument to the provided function, returning a new function that requires
|
|
43
|
+
* only the remaining arguments at call time.
|
|
44
|
+
*/
|
|
45
|
+
declare function bindArg<
|
|
46
|
+
Ret extends (...args: ParametersWithout<T, Index>) => ReturnType<T>,
|
|
47
|
+
Index extends number = number,
|
|
48
|
+
Value = unknown,
|
|
49
|
+
T extends (...args: any[]) => any = (...args: any[]) => any,
|
|
50
|
+
>(fn: T, boundArgIndex: Index, boundArgValue: Value): Ret;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Binds specified arguments to the provided function, returning a new function that requires
|
|
54
|
+
* only the remaining arguments at call time.
|
|
55
|
+
*
|
|
56
|
+
* @typeParam T - The type of the function to be invoked with bound and unbound arguments.
|
|
57
|
+
* @typeParam BoundArgs - A partial mapping of indices in `Parameters<T>` to their bound values.
|
|
58
|
+
*
|
|
59
|
+
* @param fn - The original function whose arguments need to be partially applied.
|
|
60
|
+
* @param boundArgs - An object mapping argument indices to their respective bound values.
|
|
61
|
+
*
|
|
62
|
+
* @returns A function that, when invoked, applies both bound and unbound arguments in the correct order.
|
|
63
|
+
*/
|
|
64
|
+
declare function bindArgs<
|
|
65
|
+
T extends (...args: Any[]) => Any,
|
|
66
|
+
BoundArgs extends Partial<TupleToObject<Parameters<T>>>,
|
|
67
|
+
>(
|
|
68
|
+
fn: T,
|
|
69
|
+
boundArgs: BoundArgs,
|
|
70
|
+
): (...args: RemoveArrayElements<Parameters<T>, UnionToTuple<Extract<keyof BoundArgs, number>>>) => ReturnType<T>;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Converts a function from a class method by by making the first argument take the place of the 'this' context.
|
|
74
|
+
* The reverse of @see thisify.
|
|
75
|
+
*/
|
|
76
|
+
declare function dethisify<T extends object, Args extends Any[], Ret>(
|
|
77
|
+
fn: (this: T, ...args: Args) => Ret,
|
|
78
|
+
): (target: T, ...args: Args) => Ret;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Wraps a function so that the given @see IFunctionSpyStrategy will be applied.
|
|
82
|
+
* @param func The function to wrap.
|
|
83
|
+
* @param spy The strategy to apply.
|
|
84
|
+
* @param options Options.
|
|
85
|
+
*/
|
|
86
|
+
declare function functionSpy<T, Data>(
|
|
87
|
+
func: TFunction,
|
|
88
|
+
spy: IFunctionSpyStrategy<T, Data>,
|
|
89
|
+
options?: FunctionSpyOptions<T, Data>,
|
|
90
|
+
): TFunction;
|
|
91
|
+
interface FunctionSpyOptions<T, Data> {
|
|
92
|
+
/**
|
|
93
|
+
* Whether the function is async.
|
|
94
|
+
* If provided, execution is a bit faster.
|
|
95
|
+
*/
|
|
96
|
+
async?: boolean;
|
|
97
|
+
/**
|
|
98
|
+
* Predicate function that determines whether to skip the spy's actions for a given function call.
|
|
99
|
+
*/
|
|
100
|
+
ignore?: IgnorePredicate<T, Data>;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* @see functionSpy
|
|
104
|
+
*/
|
|
105
|
+
interface IFunctionSpyStrategy<T, Data> {
|
|
106
|
+
/**
|
|
107
|
+
* Action to perform before the function is invoked.
|
|
108
|
+
* @param thisContext The context in which the function is invoked.
|
|
109
|
+
* @param args The arguments passed to the function. Modify this array to change the arguments passed to the function.
|
|
110
|
+
* @returns Data to be passed to @see onReturn.
|
|
111
|
+
*/
|
|
112
|
+
onInvoke<Args extends Any[]>(thisContext: T, args: Args): Data;
|
|
113
|
+
/**
|
|
114
|
+
* Action to perform before the function returns.
|
|
115
|
+
* @param data The data returned by @see onInvoke.
|
|
116
|
+
* @param retval The return value of the function.
|
|
117
|
+
* @returns The value to be returned by the wrapped function.
|
|
118
|
+
*/
|
|
119
|
+
onReturn<Ret>(data: Data, retval: Ret): Ret;
|
|
120
|
+
}
|
|
121
|
+
type IgnorePredicate<T, Data> = (func: TFunction, spy: IFunctionSpyStrategy<T, Data>, thisContext?: T) => boolean;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Preserves the name and length of a function or class constructor
|
|
125
|
+
*/
|
|
126
|
+
declare function preserveNameAndLength<
|
|
127
|
+
S extends ((...args: Any[]) => Any) | (new (...args: Any[]) => Any),
|
|
128
|
+
F extends ((...args: Any[]) => Any) | (new (...args: Any[]) => Any),
|
|
129
|
+
>(source: S, target: F, adjustLengthBy?: number): F;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Set the length of a function.
|
|
133
|
+
*/
|
|
134
|
+
declare function setLength<T extends object>(
|
|
135
|
+
length:
|
|
136
|
+
| number
|
|
137
|
+
| {
|
|
138
|
+
length: number;
|
|
139
|
+
},
|
|
140
|
+
target: T,
|
|
141
|
+
): T;
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Set the name of a function.
|
|
145
|
+
*/
|
|
146
|
+
declare function setName<T extends object>(
|
|
147
|
+
name:
|
|
148
|
+
| string
|
|
149
|
+
| {
|
|
150
|
+
name: string;
|
|
151
|
+
},
|
|
152
|
+
target: T,
|
|
153
|
+
): T;
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Returns a function that redirects or 'proxies' the 'this' context of the input function
|
|
157
|
+
* to a property of a given key.
|
|
158
|
+
*/
|
|
159
|
+
declare function thisProxy<ThisTarget extends This, This extends object, Args extends AnyArgs, Ret>(
|
|
160
|
+
fn: (this: This, ...args: Args) => Ret,
|
|
161
|
+
proxy: PropertyKey,
|
|
162
|
+
): (this: ThisTarget, ...args: Args) => Ret;
|
|
163
|
+
/**
|
|
164
|
+
* Returns a function that redirects or 'proxies' the 'this' context of the input function
|
|
165
|
+
* to a callback that returns the target object.
|
|
166
|
+
*/
|
|
167
|
+
declare function thisProxy<ThisTarget extends This, This extends object, Args extends AnyArgs, Ret>(
|
|
168
|
+
fn: (this: This, ...args: Args) => Ret,
|
|
169
|
+
proxy: (object: ThisTarget) => This,
|
|
170
|
+
): (this: ThisTarget, ...args: Args) => Ret;
|
|
171
|
+
type AnyArgs = any[];
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Converts a function to a class method by making the 'this' context the first argument.
|
|
175
|
+
*/
|
|
176
|
+
declare function thisify<T, Args extends Any[], Ret>(
|
|
177
|
+
fn: (target: T, ...args: Args) => Ret,
|
|
178
|
+
): (this: T, ...args: Args) => Ret;
|
|
179
|
+
type Thisify<T extends object, F extends (target: T, ...args: any[]) => Any> = (
|
|
180
|
+
this: T,
|
|
181
|
+
...args: ArraySlice<Parameters<F>, 1>
|
|
182
|
+
) => ReturnType<F>;
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Wraps a function to transform its return value using a transform function.
|
|
186
|
+
*/
|
|
187
|
+
declare function transformReturnValue<T, Args extends any[], Ret, NewRet>(
|
|
188
|
+
fn: (this: T, ...args: Args) => Ret,
|
|
189
|
+
transform: (value: Ret) => NewRet,
|
|
190
|
+
): (this: T, ...args: Args) => NewRet;
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Wrap methods, getters and setters of an object with custom logic.
|
|
194
|
+
*/
|
|
195
|
+
declare function wrapMethods<T extends object>(target: T, strat: WrapMethodsStrategy<T>): T;
|
|
196
|
+
type DescriptorMethodType = 'get' | 'set' | 'method';
|
|
197
|
+
type MethodFilter<T extends object = object> = (
|
|
198
|
+
target: T,
|
|
199
|
+
key: string | symbol,
|
|
200
|
+
type: DescriptorMethodType,
|
|
201
|
+
descriptor: PropertyDescriptor,
|
|
202
|
+
) => boolean;
|
|
203
|
+
type MethodWrapper<T extends object = object> = (
|
|
204
|
+
target: T,
|
|
205
|
+
key: string | symbol,
|
|
206
|
+
method: AnyFunction,
|
|
207
|
+
) => AnyFunction | undefined;
|
|
208
|
+
type GetterWrapper<T extends object = object> = (
|
|
209
|
+
target: T,
|
|
210
|
+
key: string | symbol,
|
|
211
|
+
getter: AnyGetter,
|
|
212
|
+
) => AnyGetter | undefined;
|
|
213
|
+
type SetterWrapper<T extends object = object> = (
|
|
214
|
+
target: T,
|
|
215
|
+
key: string | symbol,
|
|
216
|
+
setter: AnySetter,
|
|
217
|
+
) => AnySetter | undefined;
|
|
218
|
+
interface WrapMethodsStrategy<T extends object = object> {
|
|
219
|
+
filter?: MethodFilter<T>;
|
|
220
|
+
onGetter?: GetterWrapper<T>;
|
|
221
|
+
onSetter?: SetterWrapper<T>;
|
|
222
|
+
onMethod?: MethodWrapper<T>;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export {
|
|
226
|
+
type DescriptorMethodType,
|
|
227
|
+
type FunctionSpyOptions,
|
|
228
|
+
type GetterWrapper,
|
|
229
|
+
type IFunctionSpyStrategy,
|
|
230
|
+
type IgnorePredicate,
|
|
231
|
+
type MethodFilter,
|
|
232
|
+
type MethodWrapper,
|
|
233
|
+
type SetterWrapper,
|
|
234
|
+
type Thisify,
|
|
235
|
+
type WrapMethodsStrategy,
|
|
236
|
+
bindArg,
|
|
237
|
+
bindArgs,
|
|
238
|
+
dethisify,
|
|
239
|
+
functionSpy,
|
|
240
|
+
preserveNameAndLength,
|
|
241
|
+
setLength,
|
|
242
|
+
setName,
|
|
243
|
+
thisProxy,
|
|
244
|
+
thisify,
|
|
245
|
+
transformReturnValue,
|
|
246
|
+
wrapMethods,
|
|
247
|
+
};
|
package/index.mjs
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import { isAsyncFunction } from 'util/types';
|
|
2
|
+
import { isFunction } from 'es-toolkit/predicate';
|
|
3
|
+
import { range } from 'es-toolkit/math';
|
|
4
|
+
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __name = (target, value) => {
|
|
7
|
+
return __defProp(target, 'name', { value, configurable: true });
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
// src/preserveNameAndLength.ts
|
|
11
|
+
function preserveNameAndLength(source, target, adjustLengthBy = 0) {
|
|
12
|
+
return Object.defineProperties(target, {
|
|
13
|
+
name: {
|
|
14
|
+
configurable: true,
|
|
15
|
+
value: source.name,
|
|
16
|
+
},
|
|
17
|
+
length: {
|
|
18
|
+
configurable: true,
|
|
19
|
+
value: source.length + adjustLengthBy,
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
__name(preserveNameAndLength, 'preserveNameAndLength');
|
|
24
|
+
|
|
25
|
+
// src/bindArg.ts
|
|
26
|
+
function bindArg(fn, boundArgIndex, boundArgValue) {
|
|
27
|
+
return preserveNameAndLength(
|
|
28
|
+
fn,
|
|
29
|
+
(...args) => {
|
|
30
|
+
return fn(...args.slice(0, boundArgIndex), boundArgValue, ...args.slice(boundArgIndex));
|
|
31
|
+
},
|
|
32
|
+
-1,
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
__name(bindArg, 'bindArg');
|
|
36
|
+
function bindArgs(fn, boundArgs) {
|
|
37
|
+
const boundIndices = Object.keys(boundArgs).map(Number);
|
|
38
|
+
const lastIndex = Math.max(fn.length - 1, ...boundIndices);
|
|
39
|
+
const indices = range(0, lastIndex + 1);
|
|
40
|
+
let offset = 0;
|
|
41
|
+
const argGetters = indices.map((index) => {
|
|
42
|
+
const isBound = Object.hasOwn(boundArgs, index);
|
|
43
|
+
const boundIndex = index;
|
|
44
|
+
const unboundIndex = index - (isBound ? offset++ : offset);
|
|
45
|
+
return isBound
|
|
46
|
+
? () => {
|
|
47
|
+
return boundArgs[boundIndex];
|
|
48
|
+
}
|
|
49
|
+
: (args) => {
|
|
50
|
+
return args[unboundIndex];
|
|
51
|
+
};
|
|
52
|
+
});
|
|
53
|
+
return preserveNameAndLength(
|
|
54
|
+
fn,
|
|
55
|
+
(...args) => {
|
|
56
|
+
return fn(
|
|
57
|
+
...argGetters.map((get) => {
|
|
58
|
+
return get(args);
|
|
59
|
+
}),
|
|
60
|
+
);
|
|
61
|
+
},
|
|
62
|
+
boundIndices.length * -1,
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
__name(bindArgs, 'bindArgs');
|
|
66
|
+
|
|
67
|
+
// src/dethisify.ts
|
|
68
|
+
function dethisify(fn) {
|
|
69
|
+
return preserveNameAndLength(
|
|
70
|
+
fn,
|
|
71
|
+
function (target, ...args) {
|
|
72
|
+
return fn.apply(target, args);
|
|
73
|
+
},
|
|
74
|
+
1,
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
__name(dethisify, 'dethisify');
|
|
78
|
+
function functionSpy(func, spy, options = {}) {
|
|
79
|
+
if (options.async === false) {
|
|
80
|
+
return wrapSync(func, spy, options);
|
|
81
|
+
} else if (options.async || isAsyncFunction(func)) {
|
|
82
|
+
return wrapAsync(func, spy, options);
|
|
83
|
+
} else {
|
|
84
|
+
return wrapMaybeAsync(func, spy, options);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
__name(functionSpy, 'functionSpy');
|
|
88
|
+
function wrapMaybeAsync(func, spy, options = {}) {
|
|
89
|
+
const ignore = options.ignore;
|
|
90
|
+
if (ignore && ignore(func, spy)) {
|
|
91
|
+
return func;
|
|
92
|
+
}
|
|
93
|
+
return preserveNameAndLength(func, function (...args) {
|
|
94
|
+
if (ignore && ignore(func, spy, this)) {
|
|
95
|
+
return func.apply(this, args);
|
|
96
|
+
}
|
|
97
|
+
const data = spy.onInvoke(this, args);
|
|
98
|
+
const retval = func.apply(this, args);
|
|
99
|
+
if (retval instanceof Promise) {
|
|
100
|
+
return retval.then((retval2) => {
|
|
101
|
+
return spy.onReturn(data, retval2);
|
|
102
|
+
});
|
|
103
|
+
} else {
|
|
104
|
+
return spy.onReturn(data, retval);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
__name(wrapMaybeAsync, 'wrapMaybeAsync');
|
|
109
|
+
function wrapSync(func, spy, options = {}) {
|
|
110
|
+
const ignore = options.ignore;
|
|
111
|
+
if (ignore && ignore(func, spy)) {
|
|
112
|
+
return func;
|
|
113
|
+
}
|
|
114
|
+
return preserveNameAndLength(func, function (...args) {
|
|
115
|
+
if (ignore && ignore(func, spy, this)) {
|
|
116
|
+
return func.apply(this, args);
|
|
117
|
+
}
|
|
118
|
+
const data = spy.onInvoke(this, args);
|
|
119
|
+
const retval = func.apply(this, args);
|
|
120
|
+
return spy.onReturn(data, retval);
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
__name(wrapSync, 'wrapSync');
|
|
124
|
+
function wrapAsync(func, spy, options = {}) {
|
|
125
|
+
const ignore = options.ignore;
|
|
126
|
+
if (ignore && ignore(func, spy)) {
|
|
127
|
+
return func;
|
|
128
|
+
}
|
|
129
|
+
return preserveNameAndLength(func, async function (...args) {
|
|
130
|
+
if (ignore && ignore(func, spy, this)) {
|
|
131
|
+
return await func.apply(this, args);
|
|
132
|
+
}
|
|
133
|
+
const data = spy.onInvoke(this, args);
|
|
134
|
+
const retval = await func.apply(this, args);
|
|
135
|
+
return spy.onReturn(data, retval);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
__name(wrapAsync, 'wrapAsync');
|
|
139
|
+
|
|
140
|
+
// src/setLength.ts
|
|
141
|
+
function setLength(length, target) {
|
|
142
|
+
return Object.defineProperty(target, 'length', {
|
|
143
|
+
value: typeof length === 'number' ? length : length.length,
|
|
144
|
+
enumerable: false,
|
|
145
|
+
configurable: true,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
__name(setLength, 'setLength');
|
|
149
|
+
|
|
150
|
+
// src/setName.ts
|
|
151
|
+
function setName(name, target) {
|
|
152
|
+
return Object.defineProperty(target, 'name', {
|
|
153
|
+
value: typeof name === 'string' ? name : name.name,
|
|
154
|
+
configurable: true,
|
|
155
|
+
enumerable: false,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
__name(setName, 'setName');
|
|
159
|
+
function thisProxy(fn, proxy) {
|
|
160
|
+
return isFunction(proxy) ? thisProxyCallback(fn, proxy) : thisProxyKey(fn, proxy);
|
|
161
|
+
}
|
|
162
|
+
__name(thisProxy, 'thisProxy');
|
|
163
|
+
function thisProxyKey(fn, proxy) {
|
|
164
|
+
return preserveNameAndLength(fn, function (...args) {
|
|
165
|
+
const thisArg = this[proxy];
|
|
166
|
+
return fn.apply(thisArg, args);
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
__name(thisProxyKey, 'thisProxyKey');
|
|
170
|
+
function thisProxyCallback(fn, proxy) {
|
|
171
|
+
return preserveNameAndLength(fn, function (...args) {
|
|
172
|
+
const thisArg = proxy(this);
|
|
173
|
+
return fn.apply(thisArg, args);
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
__name(thisProxyCallback, 'thisProxyCallback');
|
|
177
|
+
|
|
178
|
+
// src/thisify.ts
|
|
179
|
+
function thisify(fn) {
|
|
180
|
+
return preserveNameAndLength(
|
|
181
|
+
fn,
|
|
182
|
+
/* @__PURE__ */ __name(function f(...args) {
|
|
183
|
+
return fn(this, ...args);
|
|
184
|
+
}, 'f'),
|
|
185
|
+
-1,
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
__name(thisify, 'thisify');
|
|
189
|
+
|
|
190
|
+
// src/transformReturnValue.ts
|
|
191
|
+
function transformReturnValue(fn, transform) {
|
|
192
|
+
return preserveNameAndLength(fn, function (...args) {
|
|
193
|
+
const result = fn.apply(this, args);
|
|
194
|
+
return transform(result);
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
__name(transformReturnValue, 'transformReturnValue');
|
|
198
|
+
function wrapMethods(target, strat) {
|
|
199
|
+
for (const [key, type, des] of iterateMethods(target)) {
|
|
200
|
+
if (strat.filter && !strat.filter(target, key, type, des)) {
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
if (type === 'method') {
|
|
204
|
+
if (!strat.onMethod) {
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
const orig = des.value;
|
|
208
|
+
const wrapped = strat.onMethod(target, key, orig);
|
|
209
|
+
if (!wrapped) {
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
Object.defineProperty(target, key, {
|
|
213
|
+
value: preserveNameAndLength(orig, wrapped),
|
|
214
|
+
configurable: des.configurable,
|
|
215
|
+
enumerable: des.enumerable,
|
|
216
|
+
});
|
|
217
|
+
} else if (type === 'get') {
|
|
218
|
+
if (!strat.onGetter) {
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
const orig = des.get;
|
|
222
|
+
const wrapped = strat.onGetter(target, key, orig);
|
|
223
|
+
if (!wrapped) {
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
Object.defineProperty(target, key, {
|
|
227
|
+
get: preserveNameAndLength(orig, wrapped),
|
|
228
|
+
configurable: des.configurable,
|
|
229
|
+
enumerable: des.enumerable,
|
|
230
|
+
});
|
|
231
|
+
} else if (type === 'set') {
|
|
232
|
+
if (!strat.onSetter) {
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
const orig = des.set;
|
|
236
|
+
const wrapped = strat.onSetter(target, key, orig);
|
|
237
|
+
if (!wrapped) {
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
Object.defineProperty(target, key, {
|
|
241
|
+
set: preserveNameAndLength(orig, wrapped),
|
|
242
|
+
configurable: des.configurable,
|
|
243
|
+
enumerable: des.enumerable,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return target;
|
|
248
|
+
}
|
|
249
|
+
__name(wrapMethods, 'wrapMethods');
|
|
250
|
+
function* iterateMethods(target) {
|
|
251
|
+
for (const key of Reflect.ownKeys(target)) {
|
|
252
|
+
const des = Object.getOwnPropertyDescriptor(target, key);
|
|
253
|
+
if (!des || des.configurable === false) {
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
if (isFunction(des.value)) {
|
|
257
|
+
yield [key, 'method', des];
|
|
258
|
+
} else {
|
|
259
|
+
if (isFunction(des.get)) {
|
|
260
|
+
yield [key, 'get', des];
|
|
261
|
+
}
|
|
262
|
+
if (isFunction(des.set)) {
|
|
263
|
+
yield [key, 'set', des];
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
__name(iterateMethods, 'iterateMethods');
|
|
269
|
+
|
|
270
|
+
export {
|
|
271
|
+
bindArg,
|
|
272
|
+
bindArgs,
|
|
273
|
+
dethisify,
|
|
274
|
+
functionSpy,
|
|
275
|
+
preserveNameAndLength,
|
|
276
|
+
setLength,
|
|
277
|
+
setName,
|
|
278
|
+
thisProxy,
|
|
279
|
+
thisify,
|
|
280
|
+
transformReturnValue,
|
|
281
|
+
wrapMethods,
|
|
282
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bemoje/fn",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"sideEffects": false,
|
|
6
|
+
"keywords": [
|
|
7
|
+
"function"
|
|
8
|
+
],
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./index.d.ts",
|
|
12
|
+
"import": "./index.mjs",
|
|
13
|
+
"default": "./index.mjs"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"es-toolkit": "^1.44.0",
|
|
18
|
+
"type-fest": "^5.4.4",
|
|
19
|
+
"@types/node": "^24.3.1"
|
|
20
|
+
},
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
23
|
+
},
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"author": {
|
|
26
|
+
"name": "Benjamin Møller Jensen",
|
|
27
|
+
"email": "bemoje@bemoje.net",
|
|
28
|
+
"url": "https://github.com/bemoje/"
|
|
29
|
+
},
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git+https://github.com/bemoje/mono.git",
|
|
33
|
+
"directory": "libs/fn"
|
|
34
|
+
}
|
|
35
|
+
}
|