mutts 1.0.9 → 1.0.11
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/README.md +60 -35
- package/dist/browser.cjs +1333 -1760
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.ts +2 -1392
- package/dist/browser.dev.cjs +114 -0
- package/dist/browser.dev.cjs.map +1 -0
- package/dist/browser.dev.d.ts +2 -0
- package/dist/browser.dev.esm.js +5 -0
- package/dist/browser.dev.esm.js.map +1 -0
- package/dist/browser.esm.js +18 -97
- package/dist/browser.esm.js.map +1 -1
- package/dist/chunks/{async-browser-lvzLOCgk.cjs → async-browser-Dgr5CreQ.cjs} +16 -95
- package/dist/chunks/async-browser-Dgr5CreQ.cjs.map +1 -0
- package/dist/chunks/{async-node-C3DeIb0y.cjs → async-node-3PrbVAbB.cjs} +3 -1
- package/dist/chunks/async-node-3PrbVAbB.cjs.map +1 -0
- package/dist/chunks/index-Sf74wXTV.esm.js +2577 -0
- package/dist/chunks/index-Sf74wXTV.esm.js.map +1 -0
- package/dist/chunks/node-Bo7WU5S2.esm.js +96 -0
- package/dist/chunks/node-Bo7WU5S2.esm.js.map +1 -0
- package/dist/chunks/{index-VTO-b2vR.cjs → proxy-Cc79Lrzj.cjs} +2593 -3216
- package/dist/chunks/proxy-Cc79Lrzj.cjs.map +1 -0
- package/dist/chunks/{index-CtA2AWl3.esm.js → proxy-D2C49sXH.esm.js} +2570 -3174
- package/dist/chunks/proxy-D2C49sXH.esm.js.map +1 -0
- package/dist/debug.cjs +987 -28
- package/dist/debug.cjs.map +1 -1
- package/dist/debug.d.ts +37 -38
- package/dist/debug.esm.js +963 -1
- package/dist/debug.esm.js.map +1 -1
- package/dist/devtools/manifest.json +1 -1
- package/dist/devtools/panel.html +1 -1
- package/dist/devtools/panel.js +107 -94
- package/dist/devtools/panel.js.map +1 -1
- package/dist/index.d.ts +1322 -1
- package/dist/mutts.umd.js +6647 -1
- package/dist/mutts.umd.js.map +1 -1
- package/dist/mutts.umd.min.js +1 -1
- package/dist/mutts.umd.min.js.map +1 -1
- package/dist/node.cjs +69 -63
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.ts +2 -2
- package/dist/node.dev.cjs +114 -0
- package/dist/node.dev.cjs.map +1 -0
- package/dist/node.dev.d.ts +2 -0
- package/dist/node.dev.esm.js +6 -0
- package/dist/node.dev.esm.js.map +1 -0
- package/dist/node.esm.js +4 -97
- package/dist/node.esm.js.map +1 -1
- package/dist/{types-DaHFfhlN.d.ts → types-Bx2PhORg.d.ts} +134 -88
- package/docs/ai/api-reference.md +11 -32
- package/docs/ai/manual.md +297 -239
- package/docs/reactive/advanced.md +318 -9
- package/docs/reactive/attend.md +2 -4
- package/docs/reactive/collections.md +22 -187
- package/docs/reactive/core.md +223 -131
- package/docs/reactive/debugging.md +119 -12
- package/docs/reactive/error-handling.md +10 -10
- package/docs/reactive/resource.md +125 -0
- package/docs/reactive.md +3 -4
- package/docs/utils.md +70 -0
- package/docs/zone.md +1 -1
- package/package.json +76 -38
- package/dist/chunks/async-browser-lvzLOCgk.cjs.map +0 -1
- package/dist/chunks/async-node-C3DeIb0y.cjs.map +0 -1
- package/dist/chunks/index-2vea86wD.esm.js +0 -3011
- package/dist/chunks/index-2vea86wD.esm.js.map +0 -1
- package/dist/chunks/index-CtA2AWl3.esm.js.map +0 -1
- package/dist/chunks/index-VTO-b2vR.cjs.map +0 -1
- package/dist/debug/debug.d.ts +0 -122
- package/dist/debug/debug.d.ts.map +0 -1
- package/dist/debug/index.d.ts +0 -4
- package/dist/debug/index.d.ts.map +0 -1
- package/dist/debug/lineage-panel.d.ts +0 -5
- package/dist/debug/lineage-panel.d.ts.map +0 -1
- package/dist/debug/lineage.d.ts +0 -79
- package/dist/debug/lineage.d.ts.map +0 -1
- package/dist/src/async/browser.d.ts +0 -2
- package/dist/src/async/browser.d.ts.map +0 -1
- package/dist/src/async/index.d.ts +0 -19
- package/dist/src/async/index.d.ts.map +0 -1
- package/dist/src/async/node.d.ts +0 -2
- package/dist/src/async/node.d.ts.map +0 -1
- package/dist/src/decorator.d.ts +0 -106
- package/dist/src/decorator.d.ts.map +0 -1
- package/dist/src/destroyable.d.ts +0 -87
- package/dist/src/destroyable.d.ts.map +0 -1
- package/dist/src/entry-browser.d.ts +0 -3
- package/dist/src/entry-browser.d.ts.map +0 -1
- package/dist/src/entry-node.d.ts +0 -3
- package/dist/src/entry-node.d.ts.map +0 -1
- package/dist/src/eventful.d.ts +0 -20
- package/dist/src/eventful.d.ts.map +0 -1
- package/dist/src/flavored.d.ts +0 -33
- package/dist/src/flavored.d.ts.map +0 -1
- package/dist/src/index.d.ts +0 -14
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/indexable.d.ts +0 -243
- package/dist/src/indexable.d.ts.map +0 -1
- package/dist/src/introspection.d.ts +0 -27
- package/dist/src/introspection.d.ts.map +0 -1
- package/dist/src/iterableWeak.d.ts +0 -53
- package/dist/src/iterableWeak.d.ts.map +0 -1
- package/dist/src/mixins.d.ts +0 -25
- package/dist/src/mixins.d.ts.map +0 -1
- package/dist/src/promiseChain.d.ts +0 -20
- package/dist/src/promiseChain.d.ts.map +0 -1
- package/dist/src/reactive/array.d.ts +0 -48
- package/dist/src/reactive/array.d.ts.map +0 -1
- package/dist/src/reactive/buffer.d.ts +0 -120
- package/dist/src/reactive/buffer.d.ts.map +0 -1
- package/dist/src/reactive/change.d.ts +0 -29
- package/dist/src/reactive/change.d.ts.map +0 -1
- package/dist/src/reactive/deep-touch.d.ts +0 -28
- package/dist/src/reactive/deep-touch.d.ts.map +0 -1
- package/dist/src/reactive/deep-watch-state.d.ts +0 -25
- package/dist/src/reactive/deep-watch-state.d.ts.map +0 -1
- package/dist/src/reactive/deep-watch.d.ts +0 -20
- package/dist/src/reactive/deep-watch.d.ts.map +0 -1
- package/dist/src/reactive/describe.d.ts +0 -12
- package/dist/src/reactive/describe.d.ts.map +0 -1
- package/dist/src/reactive/effect-context.d.ts +0 -34
- package/dist/src/reactive/effect-context.d.ts.map +0 -1
- package/dist/src/reactive/effects.d.ts +0 -164
- package/dist/src/reactive/effects.d.ts.map +0 -1
- package/dist/src/reactive/index.d.ts +0 -19
- package/dist/src/reactive/index.d.ts.map +0 -1
- package/dist/src/reactive/map.d.ts +0 -28
- package/dist/src/reactive/map.d.ts.map +0 -1
- package/dist/src/reactive/memoize.d.ts +0 -28
- package/dist/src/reactive/memoize.d.ts.map +0 -1
- package/dist/src/reactive/non-reactive-state.d.ts +0 -9
- package/dist/src/reactive/non-reactive-state.d.ts.map +0 -1
- package/dist/src/reactive/non-reactive.d.ts +0 -11
- package/dist/src/reactive/non-reactive.d.ts.map +0 -1
- package/dist/src/reactive/project.d.ts +0 -40
- package/dist/src/reactive/project.d.ts.map +0 -1
- package/dist/src/reactive/proxy-state.d.ts +0 -8
- package/dist/src/reactive/proxy-state.d.ts.map +0 -1
- package/dist/src/reactive/proxy.d.ts +0 -23
- package/dist/src/reactive/proxy.d.ts.map +0 -1
- package/dist/src/reactive/record.d.ts +0 -115
- package/dist/src/reactive/record.d.ts.map +0 -1
- package/dist/src/reactive/register.d.ts +0 -125
- package/dist/src/reactive/register.d.ts.map +0 -1
- package/dist/src/reactive/registry.d.ts +0 -21
- package/dist/src/reactive/registry.d.ts.map +0 -1
- package/dist/src/reactive/set.d.ts +0 -26
- package/dist/src/reactive/set.d.ts.map +0 -1
- package/dist/src/reactive/tracking.d.ts +0 -7
- package/dist/src/reactive/tracking.d.ts.map +0 -1
- package/dist/src/reactive/types.d.ts +0 -424
- package/dist/src/reactive/types.d.ts.map +0 -1
- package/dist/src/reactive/watch.d.ts +0 -48
- package/dist/src/reactive/watch.d.ts.map +0 -1
- package/dist/src/std-decorators.d.ts +0 -45
- package/dist/src/std-decorators.d.ts.map +0 -1
- package/dist/src/utils.d.ts +0 -49
- package/dist/src/utils.d.ts.map +0 -1
- package/dist/src/zone.d.ts +0 -40
- package/dist/src/zone.d.ts.map +0 -1
- package/docs/reactive/describe.md +0 -85
- package/docs/reactive/project.md +0 -93
- package/docs/reactive/scan.md +0 -293
- package/src/async/browser.ts +0 -323
- package/src/async/index.ts +0 -27
- package/src/async/node.ts +0 -92
- package/src/decorator.ts +0 -272
- package/src/destroyable.ts +0 -199
- package/src/entry-browser.ts +0 -5
- package/src/entry-node.ts +0 -5
- package/src/eventful.ts +0 -110
- package/src/flavored.ts +0 -106
- package/src/index.d.ts +0 -12
- package/src/index.ts +0 -64
- package/src/indexable.ts +0 -526
- package/src/introspection.ts +0 -59
- package/src/iterableWeak.ts +0 -233
- package/src/mixins.ts +0 -123
- package/src/promiseChain.ts +0 -110
- package/src/reactive/array.ts +0 -500
- package/src/reactive/buffer.ts +0 -328
- package/src/reactive/change.ts +0 -131
- package/src/reactive/deep-touch.ts +0 -273
- package/src/reactive/deep-watch-state.ts +0 -82
- package/src/reactive/deep-watch.ts +0 -171
- package/src/reactive/describe.ts +0 -39
- package/src/reactive/effect-context.ts +0 -83
- package/src/reactive/effects.ts +0 -1434
- package/src/reactive/index.ts +0 -72
- package/src/reactive/map.ts +0 -142
- package/src/reactive/memoize.ts +0 -186
- package/src/reactive/non-reactive-state.ts +0 -49
- package/src/reactive/non-reactive.ts +0 -43
- package/src/reactive/project.md +0 -107
- package/src/reactive/project.ts +0 -430
- package/src/reactive/proxy-state.ts +0 -27
- package/src/reactive/proxy.ts +0 -282
- package/src/reactive/record.ts +0 -181
- package/src/reactive/register.ts +0 -538
- package/src/reactive/registry.ts +0 -72
- package/src/reactive/set.ts +0 -117
- package/src/reactive/tracking.ts +0 -41
- package/src/reactive/types.ts +0 -520
- package/src/reactive/watch.ts +0 -180
- package/src/std-decorators.ts +0 -256
- package/src/utils.ts +0 -300
- package/src/zone.ts +0 -142
package/src/decorator.ts
DELETED
|
@@ -1,272 +0,0 @@
|
|
|
1
|
-
// biome-ignore-all lint/suspicious/noConfusingVoidType: We *love* voids
|
|
2
|
-
// Standardized decorator system that works with both Legacy and Modern decorators
|
|
3
|
-
|
|
4
|
-
import { isConstructor } from './utils'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Error thrown when decorator operations fail
|
|
8
|
-
*/
|
|
9
|
-
export class DecoratorError extends Error {
|
|
10
|
-
constructor(message: string) {
|
|
11
|
-
super(message)
|
|
12
|
-
this.name = 'DecoratorException'
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
//#region all decorator types
|
|
16
|
-
|
|
17
|
-
// Used for get/set and method decorators
|
|
18
|
-
/**
|
|
19
|
-
* Legacy property decorator type for methods, getters, and setters
|
|
20
|
-
*/
|
|
21
|
-
export type LegacyPropertyDecorator<T> = (
|
|
22
|
-
target: T,
|
|
23
|
-
name: string | symbol,
|
|
24
|
-
descriptor: PropertyDescriptor
|
|
25
|
-
) => any
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Legacy class decorator type
|
|
29
|
-
*/
|
|
30
|
-
export type LegacyClassDecorator<T> = (target: T) => any
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Modern method decorator type
|
|
34
|
-
*/
|
|
35
|
-
export type ModernMethodDecorator<T> = (target: T, context: ClassMethodDecoratorContext) => any
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Modern getter decorator type
|
|
39
|
-
*/
|
|
40
|
-
export type ModernGetterDecorator<T> = (target: T, context: ClassGetterDecoratorContext) => any
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Modern setter decorator type
|
|
44
|
-
*/
|
|
45
|
-
export type ModernSetterDecorator<T> = (target: T, context: ClassSetterDecoratorContext) => any
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Modern accessor decorator type
|
|
49
|
-
*/
|
|
50
|
-
export type ModernAccessorDecorator<T> = (target: T, context: ClassAccessorDecoratorContext) => any
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Modern class decorator type
|
|
54
|
-
*/
|
|
55
|
-
export type ModernClassDecorator<T> = (target: T, context: ClassDecoratorContext) => any
|
|
56
|
-
|
|
57
|
-
//#endregion
|
|
58
|
-
|
|
59
|
-
type DDMethod<T> = (
|
|
60
|
-
original: (this: T, ...args: any[]) => any,
|
|
61
|
-
target: any,
|
|
62
|
-
name: PropertyKey
|
|
63
|
-
) => ((this: T, ...args: any[]) => any) | void
|
|
64
|
-
|
|
65
|
-
type DDGetter<T> = (
|
|
66
|
-
original: (this: T) => any,
|
|
67
|
-
target: any,
|
|
68
|
-
name: PropertyKey
|
|
69
|
-
) => ((this: T) => any) | void
|
|
70
|
-
|
|
71
|
-
type DDSetter<T> = (
|
|
72
|
-
original: (this: T, value: any) => void,
|
|
73
|
-
target: any,
|
|
74
|
-
name: PropertyKey
|
|
75
|
-
) => ((this: T, value: any) => void) | void
|
|
76
|
-
|
|
77
|
-
type DDClass<T> = <Ctor extends new (...args: any[]) => T = new (...args: any[]) => T>(
|
|
78
|
-
target: Ctor
|
|
79
|
-
) => Ctor | void
|
|
80
|
-
/**
|
|
81
|
-
* Description object for creating decorators that work with both Legacy and Modern decorator proposals
|
|
82
|
-
*/
|
|
83
|
-
export interface DecoratorDescription<T> {
|
|
84
|
-
/** Handler for method decorators */
|
|
85
|
-
method?: DDMethod<T>
|
|
86
|
-
/** Handler for class decorators */
|
|
87
|
-
class?: DDClass<T>
|
|
88
|
-
/** Handler for getter decorators */
|
|
89
|
-
getter?: DDGetter<T>
|
|
90
|
-
/** Handler for setter decorators */
|
|
91
|
-
setter?: DDSetter<T>
|
|
92
|
-
/** Default handler for any decorator type not explicitly defined */
|
|
93
|
-
default?: (...args: any[]) => any
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Type for decorators that work with both Legacy and Modern decorator proposals
|
|
98
|
-
* Automatically infers the correct decorator type based on the description
|
|
99
|
-
*/
|
|
100
|
-
export type Decorator<T, Description extends DecoratorDescription<T>> = (Description extends {
|
|
101
|
-
method: DDMethod<T>
|
|
102
|
-
}
|
|
103
|
-
? LegacyPropertyDecorator<T> & ModernMethodDecorator<T>
|
|
104
|
-
: unknown) &
|
|
105
|
-
(Description extends { class: DDClass<new (...args: any[]) => T> }
|
|
106
|
-
? LegacyClassDecorator<new (...args: any[]) => T> &
|
|
107
|
-
ModernClassDecorator<new (...args: any[]) => T>
|
|
108
|
-
: unknown) &
|
|
109
|
-
(Description extends { getter: DDGetter<T> }
|
|
110
|
-
? LegacyPropertyDecorator<T> & ModernGetterDecorator<T> & ModernAccessorDecorator<T>
|
|
111
|
-
: unknown) &
|
|
112
|
-
(Description extends { setter: DDSetter<T> }
|
|
113
|
-
? LegacyPropertyDecorator<T> & ModernSetterDecorator<T> & ModernAccessorDecorator<T>
|
|
114
|
-
: unknown) &
|
|
115
|
-
(Description extends { default: infer Signature } ? Signature : unknown)
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Factory type for creating decorators that work with both Legacy and Modern decorator proposals
|
|
119
|
-
*/
|
|
120
|
-
export type DecoratorFactory<T> = <Description extends DecoratorDescription<T>>(
|
|
121
|
-
description: Description
|
|
122
|
-
) => (Description extends { method: DDMethod<T> }
|
|
123
|
-
? LegacyPropertyDecorator<T> & ModernMethodDecorator<T>
|
|
124
|
-
: unknown) &
|
|
125
|
-
(Description extends { class: DDClass<new (...args: any[]) => T> }
|
|
126
|
-
? LegacyClassDecorator<new (...args: any[]) => T> &
|
|
127
|
-
ModernClassDecorator<new (...args: any[]) => T>
|
|
128
|
-
: unknown) &
|
|
129
|
-
(Description extends { getter: DDGetter<T> }
|
|
130
|
-
? LegacyPropertyDecorator<T> & ModernGetterDecorator<T> & ModernAccessorDecorator<T>
|
|
131
|
-
: unknown) &
|
|
132
|
-
(Description extends { setter: DDSetter<T> }
|
|
133
|
-
? LegacyPropertyDecorator<T> & ModernSetterDecorator<T> & ModernAccessorDecorator<T>
|
|
134
|
-
: unknown) &
|
|
135
|
-
(Description extends { default: infer Signature } ? Signature : unknown)
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Creates a decorator that works with Legacy decorator proposals
|
|
139
|
-
* @param description - The decorator description object
|
|
140
|
-
* @returns A decorator function compatible with Legacy decorators
|
|
141
|
-
*/
|
|
142
|
-
export function legacyDecorator<T = any>(description: DecoratorDescription<T>): any {
|
|
143
|
-
return function (
|
|
144
|
-
this: any,
|
|
145
|
-
target: any,
|
|
146
|
-
propertyKey?: PropertyKey,
|
|
147
|
-
descriptor?: PropertyDescriptor,
|
|
148
|
-
...args: any[]
|
|
149
|
-
) {
|
|
150
|
-
if (propertyKey === undefined) {
|
|
151
|
-
if (isConstructor(target)) {
|
|
152
|
-
if (!('class' in description)) throw new Error('Decorator cannot be applied to a class')
|
|
153
|
-
return description.class!(target)
|
|
154
|
-
}
|
|
155
|
-
} else if (typeof target === 'object' && ['string', 'symbol'].includes(typeof propertyKey)) {
|
|
156
|
-
if (!descriptor) throw new Error('Decorator cannot be applied to a field')
|
|
157
|
-
else if (typeof descriptor === 'object' && 'configurable' in descriptor) {
|
|
158
|
-
if ('get' in descriptor || 'set' in descriptor) {
|
|
159
|
-
if (!('getter' in description || 'setter' in description))
|
|
160
|
-
throw new Error('Decorator cannot be applied to a getter or setter')
|
|
161
|
-
if ('getter' in description) {
|
|
162
|
-
const newGetter = description.getter!(descriptor.get as any, target, propertyKey)
|
|
163
|
-
if (newGetter) descriptor.get = newGetter
|
|
164
|
-
}
|
|
165
|
-
if ('setter' in description) {
|
|
166
|
-
const newSetter = description.setter!(descriptor.set as any, target, propertyKey)
|
|
167
|
-
if (newSetter) descriptor.set = newSetter
|
|
168
|
-
}
|
|
169
|
-
return descriptor
|
|
170
|
-
} else if (typeof descriptor.value === 'function') {
|
|
171
|
-
if (!('method' in description)) throw new Error('Decorator cannot be applied to a method')
|
|
172
|
-
const newMethod = description.method!(descriptor.value, target, propertyKey)
|
|
173
|
-
if (newMethod) descriptor.value = newMethod
|
|
174
|
-
return descriptor
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
if (!('default' in description))
|
|
179
|
-
throw new Error('Decorator do not have a default implementation')
|
|
180
|
-
return description.default!.call(this, target, propertyKey, descriptor, ...args)
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Creates a decorator that works with Modern decorator proposals
|
|
186
|
-
* @param description - The decorator description object
|
|
187
|
-
* @returns A decorator function compatible with Modern decorators
|
|
188
|
-
*/
|
|
189
|
-
export function modernDecorator<T = any>(description: DecoratorDescription<T>): any {
|
|
190
|
-
/*return function (target: any, context?: DecoratorContext, ...args: any[]) {*/
|
|
191
|
-
return function (this: any, target: any, context?: DecoratorContext, ...args: any[]) {
|
|
192
|
-
if (!context?.kind || typeof context.kind !== 'string') {
|
|
193
|
-
if (!('default' in description))
|
|
194
|
-
throw new Error('Decorator do not have a default implementation')
|
|
195
|
-
return description.default!.call(this, target, context, ...args)
|
|
196
|
-
}
|
|
197
|
-
switch (context.kind) {
|
|
198
|
-
case 'class':
|
|
199
|
-
if (!('class' in description)) throw new Error('Decorator cannot be applied to a class')
|
|
200
|
-
return description.class!(target)
|
|
201
|
-
case 'field':
|
|
202
|
-
throw new Error('Decorator cannot be applied to a field')
|
|
203
|
-
case 'getter':
|
|
204
|
-
if (!('getter' in description)) throw new Error('Decorator cannot be applied to a getter')
|
|
205
|
-
return description.getter!(target, target, context.name)
|
|
206
|
-
case 'setter':
|
|
207
|
-
if (!('setter' in description)) throw new Error('Decorator cannot be applied to a setter')
|
|
208
|
-
return description.setter!(target, target, context.name)
|
|
209
|
-
case 'method':
|
|
210
|
-
if (!('method' in description)) throw new Error('Decorator cannot be applied to a method')
|
|
211
|
-
return description.method!(target, target, context.name)
|
|
212
|
-
case 'accessor': {
|
|
213
|
-
if (!('getter' in description || 'setter' in description))
|
|
214
|
-
throw new Error('Decorator cannot be applied to a getter or setter')
|
|
215
|
-
const rv: Partial<ClassAccessorDecoratorResult<any, any>> = {}
|
|
216
|
-
if ('getter' in description) {
|
|
217
|
-
const newGetter = description.getter!(target.get, target, context.name)
|
|
218
|
-
if (newGetter) rv.get = newGetter
|
|
219
|
-
}
|
|
220
|
-
if ('setter' in description) {
|
|
221
|
-
const newSetter = description.setter!(target.set, target, context.name)
|
|
222
|
-
if (newSetter) rv.set = newSetter
|
|
223
|
-
}
|
|
224
|
-
return rv
|
|
225
|
-
}
|
|
226
|
-
//return description.accessor?.(target, context.name, target)
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
/**
|
|
232
|
-
* Detects if the decorator is being called in modern (Modern) or legacy (Legacy) mode
|
|
233
|
-
* based on the arguments passed to the decorator function
|
|
234
|
-
*/
|
|
235
|
-
function detectDecoratorMode(
|
|
236
|
-
_target: any,
|
|
237
|
-
contextOrKey?: any,
|
|
238
|
-
_descriptor?: any
|
|
239
|
-
): 'modern' | 'legacy' {
|
|
240
|
-
// Modern decorators have a context object as the second parameter
|
|
241
|
-
// Legacy decorators have a string/symbol key as the second parameter
|
|
242
|
-
if (
|
|
243
|
-
typeof contextOrKey === 'object' &&
|
|
244
|
-
contextOrKey !== null &&
|
|
245
|
-
typeof contextOrKey.kind === 'string'
|
|
246
|
-
) {
|
|
247
|
-
return 'modern'
|
|
248
|
-
}
|
|
249
|
-
return 'legacy'
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
/**
|
|
253
|
-
* Main decorator factory that automatically detects and works with both Legacy and Modern decorator proposals
|
|
254
|
-
* @param description - The decorator description object
|
|
255
|
-
* @returns A decorator that works in both Legacy and Modern environments
|
|
256
|
-
*/
|
|
257
|
-
export const decorator: DecoratorFactory<any> = (description: DecoratorDescription<any>) => {
|
|
258
|
-
const modern = modernDecorator(description)
|
|
259
|
-
const legacy = legacyDecorator(description)
|
|
260
|
-
return ((target: any, contextOrKey?: any, ...args: any[]) => {
|
|
261
|
-
const mode = detectDecoratorMode(target, contextOrKey, args[0])
|
|
262
|
-
return mode === 'modern'
|
|
263
|
-
? modern(target, contextOrKey, ...args)
|
|
264
|
-
: legacy(target, contextOrKey, ...args)
|
|
265
|
-
}) as any
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
/**
|
|
269
|
-
* Generic class decorator type that works with both Legacy and Modern decorator proposals
|
|
270
|
-
*/
|
|
271
|
-
export type GenericClassDecorator<T> = LegacyClassDecorator<abstract new (...args: any[]) => T> &
|
|
272
|
-
ModernClassDecorator<abstract new (...args: any[]) => T>
|
package/src/destroyable.ts
DELETED
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
import { decorator } from './decorator'
|
|
2
|
-
|
|
3
|
-
// Integrated with `using` statement via Symbol.dispose
|
|
4
|
-
const fr = new FinalizationRegistry<() => void>((f) => f())
|
|
5
|
-
/**
|
|
6
|
-
* Symbol for marking destructor methods
|
|
7
|
-
*/
|
|
8
|
-
export const destructor = Symbol('destructor')
|
|
9
|
-
/**
|
|
10
|
-
* Symbol for accessing allocated values in destroyable objects
|
|
11
|
-
*/
|
|
12
|
-
export const allocatedValues = Symbol('allocated')
|
|
13
|
-
/**
|
|
14
|
-
* Error thrown when attempting to access a destroyed object
|
|
15
|
-
*/
|
|
16
|
-
export class DestructionError extends Error {
|
|
17
|
-
static throw<_T = void>(msg: string) {
|
|
18
|
-
return () => {
|
|
19
|
-
throw new DestructionError(msg)
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
constructor(msg: string) {
|
|
23
|
-
super(`Object is destroyed. ${msg}`)
|
|
24
|
-
this.name = 'DestroyedAccessError'
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
const destroyedHandler = {
|
|
28
|
-
[Symbol.toStringTag]: 'MutTs Destroyable',
|
|
29
|
-
get: DestructionError.throw('Cannot access destroyed object'),
|
|
30
|
-
set: DestructionError.throw('Cannot access destroyed object'),
|
|
31
|
-
} as const
|
|
32
|
-
|
|
33
|
-
abstract class AbstractDestroyable<Allocated> {
|
|
34
|
-
abstract [destructor](allocated: Allocated): void
|
|
35
|
-
[Symbol.dispose](): void {
|
|
36
|
-
this[destructor](this as unknown as Allocated)
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
interface Destructor<Allocated> {
|
|
41
|
-
destructor(allocated: Allocated): void
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Creates a destroyable class with a base class and destructor object
|
|
46
|
-
* @param base - The base class to extend
|
|
47
|
-
* @param destructorObj - Object containing the destructor method
|
|
48
|
-
* @returns A destroyable class with static destroy and isDestroyable methods
|
|
49
|
-
*/
|
|
50
|
-
export function Destroyable<
|
|
51
|
-
T extends new (
|
|
52
|
-
...args: any[]
|
|
53
|
-
) => any,
|
|
54
|
-
Allocated extends Partial<InstanceType<T>>,
|
|
55
|
-
>(
|
|
56
|
-
base: T,
|
|
57
|
-
destructorObj: Destructor<Allocated>
|
|
58
|
-
): (new (
|
|
59
|
-
...args: ConstructorParameters<T>
|
|
60
|
-
) => InstanceType<T> & { [allocatedValues]: Allocated }) & {
|
|
61
|
-
destroy(obj: InstanceType<T>): boolean
|
|
62
|
-
isDestroyable(obj: InstanceType<T>): boolean
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Creates a destroyable class with only a destructor object (no base class)
|
|
67
|
-
* @param destructorObj - Object containing the destructor method
|
|
68
|
-
* @returns A destroyable class with static destroy and isDestroyable methods
|
|
69
|
-
*/
|
|
70
|
-
export function Destroyable<Allocated extends Record<PropertyKey, any> = Record<PropertyKey, any>>(
|
|
71
|
-
destructorObj: Destructor<Allocated>
|
|
72
|
-
): (new () => { [allocatedValues]: Allocated }) & {
|
|
73
|
-
destroy(obj: any): boolean
|
|
74
|
-
isDestroyable(obj: any): boolean
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Creates a destroyable class with a base class (requires [destructor] method)
|
|
79
|
-
* @param base - The base class to extend
|
|
80
|
-
* @returns A destroyable class with static destroy and isDestroyable methods
|
|
81
|
-
*/
|
|
82
|
-
export function Destroyable<
|
|
83
|
-
T extends new (
|
|
84
|
-
...args: any[]
|
|
85
|
-
) => any,
|
|
86
|
-
Allocated extends Record<PropertyKey, any> = Record<PropertyKey, any>,
|
|
87
|
-
>(
|
|
88
|
-
base: T
|
|
89
|
-
): (new (
|
|
90
|
-
...args: ConstructorParameters<T>
|
|
91
|
-
) => AbstractDestroyable<Allocated> & InstanceType<T> & { [allocatedValues]: Allocated }) & {
|
|
92
|
-
destroy(obj: InstanceType<T>): boolean
|
|
93
|
-
isDestroyable(obj: InstanceType<T>): boolean
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Creates an abstract destroyable base class
|
|
98
|
-
* @returns An abstract destroyable class with static destroy and isDestroyable methods
|
|
99
|
-
*/
|
|
100
|
-
export function Destroyable<
|
|
101
|
-
Allocated extends Record<PropertyKey, any> = Record<PropertyKey, any>,
|
|
102
|
-
>(): abstract new () => (AbstractDestroyable<Allocated> & {
|
|
103
|
-
[allocatedValues]: Allocated
|
|
104
|
-
}) & {
|
|
105
|
-
destroy(obj: any): boolean
|
|
106
|
-
isDestroyable(obj: any): boolean
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export function Destroyable<
|
|
110
|
-
T extends new (
|
|
111
|
-
...args: any[]
|
|
112
|
-
) => any,
|
|
113
|
-
Allocated extends Record<PropertyKey, any> = Record<PropertyKey, any>,
|
|
114
|
-
>(base?: T | Destructor<Allocated>, destructorObj?: Destructor<Allocated>) {
|
|
115
|
-
if (base && typeof base !== 'function') {
|
|
116
|
-
destructorObj = base as Destructor<Allocated>
|
|
117
|
-
base = undefined
|
|
118
|
-
}
|
|
119
|
-
if (!base) {
|
|
120
|
-
base = class {} as T
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
return class Destroyable extends (base as T) {
|
|
124
|
-
static readonly destructors = new WeakMap<any, () => void>()
|
|
125
|
-
static destroy(obj: Destroyable) {
|
|
126
|
-
const destructor = Destroyable.destructors.get(obj)
|
|
127
|
-
if (!destructor) return false
|
|
128
|
-
fr.unregister(obj[allocatedValues])
|
|
129
|
-
Destroyable.destructors.delete(obj)
|
|
130
|
-
Object.setPrototypeOf(obj, new Proxy({}, destroyedHandler))
|
|
131
|
-
// Clear all own properties
|
|
132
|
-
for (const key of Object.getOwnPropertyNames(obj)) {
|
|
133
|
-
delete (obj as any)[key]
|
|
134
|
-
}
|
|
135
|
-
destructor()
|
|
136
|
-
return true
|
|
137
|
-
}
|
|
138
|
-
static isDestroyable(obj: Destroyable) {
|
|
139
|
-
return Destroyable.destructors.has(obj)
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
[forwardProperties]!: PropertyKey[]
|
|
143
|
-
readonly [allocatedValues]: Allocated
|
|
144
|
-
constructor(...args: any[]) {
|
|
145
|
-
super(...args)
|
|
146
|
-
const allocated = {} as Allocated
|
|
147
|
-
this[allocatedValues] = allocated
|
|
148
|
-
// @ts-expect-error `this` is an AbstractDestroyable
|
|
149
|
-
const myDestructor = destructorObj?.destructor ?? this[destructor]
|
|
150
|
-
if (!myDestructor) {
|
|
151
|
-
throw new DestructionError('Destructor is not defined')
|
|
152
|
-
}
|
|
153
|
-
function destruction() {
|
|
154
|
-
myDestructor(allocated)
|
|
155
|
-
}
|
|
156
|
-
Destroyable.destructors.set(this, destruction)
|
|
157
|
-
fr.register(this, destruction, allocated)
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const forwardProperties = Symbol('forwardProperties')
|
|
163
|
-
/**
|
|
164
|
-
* Decorator that marks properties to be stored in the allocated object and passed to the destructor
|
|
165
|
-
* Use with accessor properties or explicit get/set pairs
|
|
166
|
-
*/
|
|
167
|
-
export const allocated = decorator({
|
|
168
|
-
setter(original, _target, propertyKey) {
|
|
169
|
-
return function (value) {
|
|
170
|
-
this[allocatedValues][propertyKey] = value
|
|
171
|
-
return original.call(this, value)
|
|
172
|
-
}
|
|
173
|
-
},
|
|
174
|
-
})
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Registers a callback to be called when an object is garbage collected
|
|
178
|
-
* @param cb - The callback function to execute on garbage collection
|
|
179
|
-
* @returns The object whose reference can be collected
|
|
180
|
-
*/
|
|
181
|
-
export function callOnGC(cb: () => void) {
|
|
182
|
-
let called = false
|
|
183
|
-
const forward = () => {
|
|
184
|
-
if (called) return
|
|
185
|
-
called = true
|
|
186
|
-
cb()
|
|
187
|
-
}
|
|
188
|
-
fr.register(forward, cb, cb)
|
|
189
|
-
return forward
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Context Manager Protocol for `using` statement integration
|
|
194
|
-
* Provides automatic resource cleanup when used with the `using` statement
|
|
195
|
-
*/
|
|
196
|
-
export interface ContextManager<T = any> {
|
|
197
|
-
[Symbol.dispose](): void
|
|
198
|
-
value?: T
|
|
199
|
-
}
|
package/src/entry-browser.ts
DELETED
package/src/entry-node.ts
DELETED
package/src/eventful.ts
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Base type for event maps - all event handlers must be functions
|
|
3
|
-
*/
|
|
4
|
-
export type EventsBase = Record<string, (...args: any[]) => void>
|
|
5
|
-
|
|
6
|
-
const events = Symbol('events')
|
|
7
|
-
const hooks = Symbol('hooks')
|
|
8
|
-
|
|
9
|
-
const eventBehavior = {
|
|
10
|
-
on<EventType extends keyof EventsBase>(
|
|
11
|
-
eventOrEvents: EventType | Partial<EventsBase>,
|
|
12
|
-
cb?: EventsBase[EventType]
|
|
13
|
-
): () => void {
|
|
14
|
-
if (typeof eventOrEvents === 'object') {
|
|
15
|
-
for (const e of Object.keys(eventOrEvents) as (keyof EventsBase)[]) {
|
|
16
|
-
this.on(e, eventOrEvents[e]!)
|
|
17
|
-
}
|
|
18
|
-
} else if (cb !== undefined) {
|
|
19
|
-
const callbacks = this[events].get(eventOrEvents) ?? new Set<EventsBase[EventType]>()
|
|
20
|
-
if (!callbacks.has(cb)) callbacks.add(cb)
|
|
21
|
-
this[events].set(eventOrEvents, callbacks)
|
|
22
|
-
}
|
|
23
|
-
return () => this.off(eventOrEvents, cb)
|
|
24
|
-
},
|
|
25
|
-
off<EventType extends keyof EventsBase>(
|
|
26
|
-
eventOrEvents: EventType | Partial<EventsBase>,
|
|
27
|
-
cb?: EventsBase[EventType]
|
|
28
|
-
): void {
|
|
29
|
-
if (typeof eventOrEvents === 'object') {
|
|
30
|
-
for (const e of Object.keys(eventOrEvents) as (keyof EventsBase)[]) {
|
|
31
|
-
this.off(e, eventOrEvents[e])
|
|
32
|
-
}
|
|
33
|
-
} else if (cb !== null && cb !== undefined) {
|
|
34
|
-
const callbacks = this[events].get(eventOrEvents)
|
|
35
|
-
if (callbacks) {
|
|
36
|
-
callbacks.delete(cb)
|
|
37
|
-
if (!callbacks.size) this[events].delete(eventOrEvents)
|
|
38
|
-
}
|
|
39
|
-
} else {
|
|
40
|
-
// Remove all listeners for this event
|
|
41
|
-
this[events].delete(eventOrEvents)
|
|
42
|
-
}
|
|
43
|
-
},
|
|
44
|
-
emit<EventType extends keyof EventsBase>(
|
|
45
|
-
event: EventType,
|
|
46
|
-
...args: Parameters<EventsBase[EventType]>
|
|
47
|
-
) {
|
|
48
|
-
const callbacks = this[events].get(event)
|
|
49
|
-
if (callbacks) for (const cb of callbacks) cb.apply(this, args)
|
|
50
|
-
for (const cb of this[hooks]) cb.call(this, event, ...args)
|
|
51
|
-
},
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function perEvent(
|
|
55
|
-
eventful: Eventful<any>,
|
|
56
|
-
fct: (event: string, ...args: any[]) => void,
|
|
57
|
-
use?: 'use'
|
|
58
|
-
) {
|
|
59
|
-
const cache = new Map<string, (...args: any[]) => any>()
|
|
60
|
-
return new Proxy(fct, {
|
|
61
|
-
get(target, prop: PropertyKey) {
|
|
62
|
-
if (typeof prop !== 'string') return target[prop]
|
|
63
|
-
if (use && !eventful[events].has(prop) && !eventful[hooks].size) return () => {}
|
|
64
|
-
|
|
65
|
-
// Return cached function or create and cache
|
|
66
|
-
let cached = cache.get(prop)
|
|
67
|
-
if (!cached) {
|
|
68
|
-
cached = (...args: any[]) => fct.apply(eventful, [prop, ...args])
|
|
69
|
-
cache.set(prop, cached)
|
|
70
|
-
}
|
|
71
|
-
return cached
|
|
72
|
-
},
|
|
73
|
-
})
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* A type-safe event system that provides a clean API for event handling
|
|
78
|
-
* @template Events - The event map defining event names and their handler signatures
|
|
79
|
-
*/
|
|
80
|
-
export class Eventful<Events extends EventsBase> {
|
|
81
|
-
private readonly [events] = new Map<keyof Events, Set<(...args: any[]) => void>>()
|
|
82
|
-
private readonly [hooks] = new Set<(...args: any[]) => void>()
|
|
83
|
-
|
|
84
|
-
public hook(
|
|
85
|
-
cb: <EventType extends keyof Events>(
|
|
86
|
-
event: EventType,
|
|
87
|
-
...args: Parameters<Events[EventType]>
|
|
88
|
-
) => void
|
|
89
|
-
): () => void {
|
|
90
|
-
this[hooks].add(cb)
|
|
91
|
-
return () => {
|
|
92
|
-
this[hooks].delete(cb)
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
public on = perEvent(this, eventBehavior.on) as ((events: Partial<Events>) => void) &
|
|
97
|
-
(<EventType extends keyof Events>(event: EventType, cb: Events[EventType]) => () => void) & {
|
|
98
|
-
[event in keyof Events]: (cb: Events[event]) => () => void
|
|
99
|
-
}
|
|
100
|
-
public off = perEvent(this, eventBehavior.off) as ((events: Partial<Events>) => void) &
|
|
101
|
-
(<EventType extends keyof Events>(event: EventType, cb?: Events[EventType]) => void) & {
|
|
102
|
-
[event in keyof Events]: (cb?: Events[event]) => void
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
public emit = perEvent(this, eventBehavior.emit, 'use') as (<EventType extends keyof Events>(
|
|
106
|
-
event: EventType,
|
|
107
|
-
...args: Parameters<Events[EventType]>
|
|
108
|
-
) => void) &
|
|
109
|
-
Events
|
|
110
|
-
}
|
package/src/flavored.ts
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Creates a flavored (extensible) version of a function with chainable property modifiers.
|
|
3
|
-
*
|
|
4
|
-
* Each property defined in `flavors` returns a new flavored function that transforms
|
|
5
|
-
* how the original function is called. This enables a fluent API where properties
|
|
6
|
-
* create specialized variants of the base function.
|
|
7
|
-
*
|
|
8
|
-
* @param fn - The base function to flavor
|
|
9
|
-
* @param flavors - Object defining the flavor properties (getters or methods)
|
|
10
|
-
* @returns A proxy of the function with the flavor properties attached
|
|
11
|
-
*
|
|
12
|
-
* @example
|
|
13
|
-
* ```typescript
|
|
14
|
-
* function greet(name: string, options?: { loud?: boolean }) {
|
|
15
|
-
* const greeting = `Hello, ${name}!`
|
|
16
|
-
* return options?.loud ? greeting.toUpperCase() : greeting
|
|
17
|
-
* }
|
|
18
|
-
*
|
|
19
|
-
* const flavoredGreet = flavored(greet, {
|
|
20
|
-
* get loud() {
|
|
21
|
-
* return createFlavor(this, (name, opts) => [name, { ...opts, loud: true }])
|
|
22
|
-
* }
|
|
23
|
-
* })
|
|
24
|
-
*
|
|
25
|
-
* flavoredGreet('World') // "Hello, World!"
|
|
26
|
-
* flavoredGreet.loud('World') // "HELLO, WORLD!"
|
|
27
|
-
* ```
|
|
28
|
-
*/
|
|
29
|
-
import { named } from './utils'
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Creates a flavored (extensible) version of a function with chainable property modifiers.
|
|
33
|
-
*/
|
|
34
|
-
export function flavored<T extends (...args: any[]) => any, F extends Record<string, any>>(
|
|
35
|
-
fn: T,
|
|
36
|
-
flavors: F
|
|
37
|
-
): T & F {
|
|
38
|
-
// Store flavors for recursive flavoring
|
|
39
|
-
;(fn as any).flavors = flavors
|
|
40
|
-
|
|
41
|
-
return new Proxy(fn, {
|
|
42
|
-
get(target, prop, receiver) {
|
|
43
|
-
if (prop in flavors) {
|
|
44
|
-
return Reflect.get(flavors, prop, receiver)
|
|
45
|
-
}
|
|
46
|
-
return (target as any)[prop]
|
|
47
|
-
},
|
|
48
|
-
}) as T & F
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Creates a new flavored function that transforms arguments before calling the base.
|
|
53
|
-
*
|
|
54
|
-
* @param fn - The base flavored function
|
|
55
|
-
* @param transform - Function that receives the original arguments and returns transformed arguments
|
|
56
|
-
* @returns A new flavored function with the transformation applied
|
|
57
|
-
*
|
|
58
|
-
* @example
|
|
59
|
-
* ```typescript
|
|
60
|
-
* const loudGreet = createFlavor(greet, (name, opts) => [name, { ...opts, loud: true }])
|
|
61
|
-
* ```
|
|
62
|
-
*/
|
|
63
|
-
export function createFlavor<T extends (...args: any[]) => any>(
|
|
64
|
-
fn: T,
|
|
65
|
-
transform: (...args: Parameters<T>) => Parameters<T>,
|
|
66
|
-
name?: string
|
|
67
|
-
): T {
|
|
68
|
-
const fct = function flavorWrapper(this: any, ...args: Parameters<T>) {
|
|
69
|
-
return fn.apply(this, transform(...args))
|
|
70
|
-
}
|
|
71
|
-
if (name) named(name, fct)
|
|
72
|
-
|
|
73
|
-
return flavored(fct as any as T, (fn as any).flavors || {})
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Creates a new flavored function that merges options objects.
|
|
78
|
-
* Useful when the last argument is an options object that should be merged.
|
|
79
|
-
*
|
|
80
|
-
* @param fn - The base flavored function
|
|
81
|
-
* @param defaultOptions - Options to merge with the provided options
|
|
82
|
-
* @returns A new flavored function with merged options
|
|
83
|
-
*
|
|
84
|
-
* @example
|
|
85
|
-
* ```typescript
|
|
86
|
-
* const opaqueEffect = flavorOptions(effect, { opaque: true })
|
|
87
|
-
* const namedEffect = flavorOptions(effect, { name: 'myEffect' })
|
|
88
|
-
* ```
|
|
89
|
-
*/
|
|
90
|
-
export function flavorOptions<T extends (...args: any[]) => any>(
|
|
91
|
-
fn: T,
|
|
92
|
-
defaultOptions: Record<string, any>,
|
|
93
|
-
name?: string
|
|
94
|
-
): T {
|
|
95
|
-
const fct = function flavorOptionsWrapper(this: any, ...args: any[]) {
|
|
96
|
-
const lastArg = args[args.length - 1]
|
|
97
|
-
const mergedArgs =
|
|
98
|
-
lastArg !== undefined && typeof lastArg === 'object'
|
|
99
|
-
? [...args.slice(0, -1), { ...defaultOptions, ...lastArg }]
|
|
100
|
-
: [...args, defaultOptions]
|
|
101
|
-
return fn.apply(this, mergedArgs)
|
|
102
|
-
}
|
|
103
|
-
if (name) named(name, fct)
|
|
104
|
-
|
|
105
|
-
return flavored(fct as any as T, (fn as any).flavors || {})
|
|
106
|
-
}
|