@praxisjs/decorators 0.4.2 → 0.5.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/CHANGELOG.md +43 -0
- package/dist/__tests__/component.test.d.ts +2 -0
- package/dist/__tests__/component.test.d.ts.map +1 -0
- package/dist/__tests__/component.test.js +146 -0
- package/dist/__tests__/component.test.js.map +1 -0
- package/dist/__tests__/compose.test.d.ts +2 -0
- package/dist/__tests__/compose.test.d.ts.map +1 -0
- package/dist/__tests__/compose.test.js +171 -0
- package/dist/__tests__/compose.test.js.map +1 -0
- package/dist/__tests__/events.test.d.ts +2 -0
- package/dist/__tests__/events.test.d.ts.map +1 -0
- package/dist/__tests__/events.test.js +216 -0
- package/dist/__tests__/events.test.js.map +1 -0
- package/dist/__tests__/functions.test.js +283 -31
- package/dist/__tests__/functions.test.js.map +1 -1
- package/dist/__tests__/lazy.test.d.ts +2 -0
- package/dist/__tests__/lazy.test.d.ts.map +1 -0
- package/dist/__tests__/lazy.test.js +163 -0
- package/dist/__tests__/lazy.test.js.map +1 -0
- package/dist/__tests__/memo.test.js +71 -22
- package/dist/__tests__/memo.test.js.map +1 -1
- package/dist/__tests__/properties.test.js +191 -1
- package/dist/__tests__/properties.test.js.map +1 -1
- package/dist/__tests__/resource.test.d.ts +2 -0
- package/dist/__tests__/resource.test.d.ts.map +1 -0
- package/dist/__tests__/resource.test.js +103 -0
- package/dist/__tests__/resource.test.js.map +1 -0
- package/dist/__tests__/slot.test.d.ts +2 -0
- package/dist/__tests__/slot.test.d.ts.map +1 -0
- package/dist/__tests__/slot.test.js +147 -0
- package/dist/__tests__/slot.test.js.map +1 -0
- package/dist/__tests__/virtual.test.d.ts +2 -0
- package/dist/__tests__/virtual.test.d.ts.map +1 -0
- package/dist/__tests__/virtual.test.js +242 -0
- package/dist/__tests__/virtual.test.js.map +1 -0
- package/dist/component/component.d.ts +1 -1
- package/dist/component/component.d.ts.map +1 -1
- package/dist/component/component.js +15 -10
- package/dist/component/component.js.map +1 -1
- package/dist/component/lazy.d.ts +1 -1
- package/dist/component/lazy.d.ts.map +1 -1
- package/dist/component/lazy.js +29 -27
- package/dist/component/lazy.js.map +1 -1
- package/dist/component/virtual.d.ts +1 -1
- package/dist/component/virtual.d.ts.map +1 -1
- package/dist/component/virtual.js +46 -50
- package/dist/component/virtual.js.map +1 -1
- package/dist/create-class-decorator.d.ts +16 -0
- package/dist/create-class-decorator.d.ts.map +1 -0
- package/dist/create-class-decorator.js +35 -0
- package/dist/create-class-decorator.js.map +1 -0
- package/dist/create-field-decorator.d.ts +14 -0
- package/dist/create-field-decorator.d.ts.map +1 -0
- package/dist/create-field-decorator.js +37 -0
- package/dist/create-field-decorator.js.map +1 -0
- package/dist/create-getter-decorator.d.ts +18 -0
- package/dist/create-getter-decorator.d.ts.map +1 -0
- package/dist/create-getter-decorator.js +15 -0
- package/dist/create-getter-decorator.js.map +1 -0
- package/dist/create-lifecycle-method-decorator.d.ts +6 -0
- package/dist/create-lifecycle-method-decorator.d.ts.map +1 -0
- package/dist/create-lifecycle-method-decorator.js +22 -0
- package/dist/create-lifecycle-method-decorator.js.map +1 -0
- package/dist/create-method-decorator.d.ts +6 -0
- package/dist/create-method-decorator.d.ts.map +1 -0
- package/dist/create-method-decorator.js +14 -0
- package/dist/create-method-decorator.js.map +1 -0
- package/dist/events/emit.d.ts +1 -1
- package/dist/events/emit.d.ts.map +1 -1
- package/dist/events/emit.js +24 -29
- package/dist/events/emit.js.map +1 -1
- package/dist/events/on-command.d.ts +1 -2
- package/dist/events/on-command.d.ts.map +1 -1
- package/dist/events/on-command.js +15 -32
- package/dist/events/on-command.js.map +1 -1
- package/dist/functions/bind.d.ts +1 -2
- package/dist/functions/bind.d.ts.map +1 -1
- package/dist/functions/bind.js +4 -11
- package/dist/functions/bind.js.map +1 -1
- package/dist/functions/debounce.d.ts +1 -2
- package/dist/functions/debounce.d.ts.map +1 -1
- package/dist/functions/debounce.js +12 -20
- package/dist/functions/debounce.js.map +1 -1
- package/dist/functions/log.d.ts +1 -2
- package/dist/functions/log.d.ts.map +1 -1
- package/dist/functions/log.js +40 -38
- package/dist/functions/log.js.map +1 -1
- package/dist/functions/memo.d.ts +1 -2
- package/dist/functions/memo.d.ts.map +1 -1
- package/dist/functions/memo.js +15 -27
- package/dist/functions/memo.js.map +1 -1
- package/dist/functions/once.d.ts +1 -2
- package/dist/functions/once.d.ts.map +1 -1
- package/dist/functions/once.js +14 -12
- package/dist/functions/once.js.map +1 -1
- package/dist/functions/retry.d.ts +1 -2
- package/dist/functions/retry.d.ts.map +1 -1
- package/dist/functions/retry.js +23 -20
- package/dist/functions/retry.js.map +1 -1
- package/dist/functions/throttle.d.ts +1 -2
- package/dist/functions/throttle.d.ts.map +1 -1
- package/dist/functions/throttle.js +9 -16
- package/dist/functions/throttle.js.map +1 -1
- package/dist/functions/watch.d.ts +1 -1
- package/dist/functions/watch.d.ts.map +1 -1
- package/dist/functions/watch.js +25 -31
- package/dist/functions/watch.js.map +1 -1
- package/dist/functions/when.d.ts +1 -2
- package/dist/functions/when.d.ts.map +1 -1
- package/dist/functions/when.js +10 -26
- package/dist/functions/when.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/properties/compose.d.ts +3 -0
- package/dist/properties/compose.d.ts.map +1 -0
- package/dist/properties/compose.js +40 -0
- package/dist/properties/compose.js.map +1 -0
- package/dist/properties/computed.d.ts +1 -2
- package/dist/properties/computed.d.ts.map +1 -1
- package/dist/properties/computed.js +10 -9
- package/dist/properties/computed.js.map +1 -1
- package/dist/properties/history.d.ts.map +1 -1
- package/dist/properties/history.js +37 -32
- package/dist/properties/history.js.map +1 -1
- package/dist/properties/index.d.ts +2 -0
- package/dist/properties/index.d.ts.map +1 -1
- package/dist/properties/index.js +2 -0
- package/dist/properties/index.js.map +1 -1
- package/dist/properties/persisted.d.ts +1 -2
- package/dist/properties/persisted.d.ts.map +1 -1
- package/dist/properties/persisted.js +13 -29
- package/dist/properties/persisted.js.map +1 -1
- package/dist/properties/prop.d.ts +1 -2
- package/dist/properties/prop.d.ts.map +1 -1
- package/dist/properties/prop.js +21 -25
- package/dist/properties/prop.js.map +1 -1
- package/dist/properties/resource.d.ts +14 -0
- package/dist/properties/resource.d.ts.map +1 -0
- package/dist/properties/resource.js +27 -0
- package/dist/properties/resource.js.map +1 -0
- package/dist/properties/slot.d.ts +1 -2
- package/dist/properties/slot.d.ts.map +1 -1
- package/dist/properties/slot.js +15 -20
- package/dist/properties/slot.js.map +1 -1
- package/dist/properties/state.d.ts +1 -2
- package/dist/properties/state.d.ts.map +1 -1
- package/dist/properties/state.js +13 -18
- package/dist/properties/state.js.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/component.test.ts +166 -0
- package/src/__tests__/compose.test.ts +202 -0
- package/src/__tests__/events.test.ts +268 -0
- package/src/__tests__/functions.test.ts +368 -30
- package/src/__tests__/lazy.test.ts +218 -0
- package/src/__tests__/memo.test.ts +89 -22
- package/src/__tests__/properties.test.ts +249 -1
- package/src/__tests__/resource.test.ts +113 -0
- package/src/__tests__/slot.test.ts +179 -0
- package/src/__tests__/virtual.test.ts +260 -0
- package/src/component/component.ts +27 -12
- package/src/component/lazy.ts +33 -35
- package/src/component/virtual.tsx +62 -75
- package/src/create-class-decorator.ts +61 -0
- package/src/create-field-decorator.ts +66 -0
- package/src/create-getter-decorator.ts +52 -0
- package/src/create-lifecycle-method-decorator.ts +38 -0
- package/src/create-method-decorator.ts +26 -0
- package/src/events/emit.ts +22 -33
- package/src/events/on-command.ts +22 -47
- package/src/functions/bind.ts +4 -15
- package/src/functions/debounce.ts +11 -26
- package/src/functions/log.ts +40 -43
- package/src/functions/memo.ts +15 -45
- package/src/functions/once.ts +13 -16
- package/src/functions/retry.ts +21 -22
- package/src/functions/throttle.ts +9 -23
- package/src/functions/watch.ts +27 -34
- package/src/functions/when.ts +11 -36
- package/src/index.ts +28 -0
- package/src/properties/compose.ts +53 -0
- package/src/properties/computed.ts +11 -13
- package/src/properties/history.ts +42 -41
- package/src/properties/index.ts +2 -0
- package/src/properties/persisted.ts +17 -58
- package/src/properties/prop.ts +21 -31
- package/src/properties/resource.ts +34 -0
- package/src/properties/slot.ts +17 -30
- package/src/properties/state.ts +14 -24
package/src/events/on-command.ts
CHANGED
|
@@ -1,54 +1,29 @@
|
|
|
1
|
-
import type { StatefulComponent } from "@praxisjs/core";
|
|
2
1
|
|
|
2
|
+
import { createLifecycleMethodDecorator } from "../create-lifecycle-method-decorator";
|
|
3
3
|
import { readProp } from "./helper";
|
|
4
4
|
|
|
5
5
|
import type { Command } from "./command";
|
|
6
6
|
|
|
7
7
|
export function OnCommand(propName: string) {
|
|
8
|
-
return
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
);
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if (typeof command.subscribe !== "function") {
|
|
34
|
-
console.warn(
|
|
35
|
-
`[OnCommand] prop "${propName}" is not a valid Command in ${this.constructor.name}`,
|
|
36
|
-
);
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const bound = value.bind(this);
|
|
41
|
-
const unsub = command.subscribe((...args: unknown[]) => {
|
|
42
|
-
bound(...args);
|
|
43
|
-
});
|
|
44
|
-
cleanups.set(this, unsub);
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
instance.onUnmount = function (this: StatefulComponent) {
|
|
48
|
-
originalOnUnmount?.call(this);
|
|
49
|
-
cleanups.get(this)?.();
|
|
50
|
-
cleanups.delete(this);
|
|
51
|
-
};
|
|
52
|
-
});
|
|
53
|
-
};
|
|
8
|
+
return createLifecycleMethodDecorator({
|
|
9
|
+
register(callback, instance) {
|
|
10
|
+
const command = readProp(instance, propName) as Command<unknown> | undefined;
|
|
11
|
+
|
|
12
|
+
if (!command) {
|
|
13
|
+
console.warn(
|
|
14
|
+
`[OnCommand] prop "${propName}" was not provided to ${(instance.constructor as { name?: string }).name ?? "unknown"}`,
|
|
15
|
+
);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (typeof command.subscribe !== "function") {
|
|
20
|
+
console.warn(
|
|
21
|
+
`[OnCommand] prop "${propName}" is not a valid Command in ${(instance.constructor as { name?: string }).name ?? "unknown"}`,
|
|
22
|
+
);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return command.subscribe((...args: unknown[]) => { callback(...args); });
|
|
27
|
+
},
|
|
28
|
+
});
|
|
54
29
|
}
|
package/src/functions/bind.ts
CHANGED
|
@@ -1,18 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { createMethodDecorator } from "../create-method-decorator";
|
|
2
2
|
|
|
3
3
|
export function Bind() {
|
|
4
|
-
return
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
): void {
|
|
8
|
-
context.addInitializer(function (this: unknown) {
|
|
9
|
-
const name = context.name as string;
|
|
10
|
-
const bound = value.bind(this as object);
|
|
11
|
-
Object.defineProperty(this as object, name, {
|
|
12
|
-
value: bound,
|
|
13
|
-
configurable: true,
|
|
14
|
-
writable: true,
|
|
15
|
-
});
|
|
16
|
-
});
|
|
17
|
-
};
|
|
4
|
+
return createMethodDecorator({
|
|
5
|
+
wrap: (original, instance) => original.bind(instance),
|
|
6
|
+
});
|
|
18
7
|
}
|
|
@@ -1,31 +1,16 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { createMethodDecorator } from "../create-method-decorator";
|
|
2
2
|
|
|
3
3
|
export function Debounce(ms: number) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const name = context.name as string;
|
|
13
|
-
const bound = (...args: unknown[]) => {
|
|
14
|
-
const existing = timers.get(instance);
|
|
15
|
-
if (existing !== undefined) clearTimeout(existing);
|
|
16
|
-
|
|
17
|
-
const timer = setTimeout(() => {
|
|
18
|
-
timers.delete(instance);
|
|
19
|
-
value.apply(instance, args);
|
|
4
|
+
return createMethodDecorator({
|
|
5
|
+
wrap(original, instance) {
|
|
6
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
7
|
+
return (...args: unknown[]) => {
|
|
8
|
+
if (timer !== undefined) clearTimeout(timer);
|
|
9
|
+
timer = setTimeout(() => {
|
|
10
|
+
timer = undefined;
|
|
11
|
+
original.apply(instance, args);
|
|
20
12
|
}, ms);
|
|
21
|
-
|
|
22
|
-
timers.set(instance, timer);
|
|
23
13
|
};
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
configurable: true,
|
|
27
|
-
writable: true,
|
|
28
|
-
});
|
|
29
|
-
});
|
|
30
|
-
};
|
|
14
|
+
},
|
|
15
|
+
});
|
|
31
16
|
}
|
package/src/functions/log.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { createMethodDecorator } from "../create-method-decorator";
|
|
2
2
|
|
|
3
3
|
export interface LogOptions {
|
|
4
4
|
level?: "log" | "warn" | "error" | "debug";
|
|
@@ -17,52 +17,49 @@ export function Log(options: LogOptions = {}) {
|
|
|
17
17
|
devOnly = true,
|
|
18
18
|
} = options;
|
|
19
19
|
|
|
20
|
-
return
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
return createMethodDecorator({
|
|
21
|
+
wrap(original, instance, name) {
|
|
22
|
+
return (...args: unknown[]) => {
|
|
23
|
+
if (
|
|
24
|
+
devOnly &&
|
|
25
|
+
typeof process !== "undefined" &&
|
|
26
|
+
process.env.NODE_ENV === "production"
|
|
27
|
+
) {
|
|
28
|
+
return original.apply(instance, args);
|
|
29
|
+
}
|
|
25
30
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
process.env.NODE_ENV === "production"
|
|
31
|
-
) {
|
|
32
|
-
return value.apply(this, args);
|
|
33
|
-
}
|
|
31
|
+
const className =
|
|
32
|
+
(instance.constructor as { name?: string }).name ?? "Unknown";
|
|
33
|
+
const label = `[${className}.${name}]`;
|
|
34
|
+
const logger = console[level].bind(console);
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
(this.constructor as { name?: string }).name ?? "Unknown";
|
|
37
|
-
const label = `[${className}.${methodKey}]`;
|
|
38
|
-
const logger = console[level].bind(console);
|
|
36
|
+
if (logArgs) logger(`${label} args:`, args);
|
|
39
37
|
|
|
40
|
-
|
|
38
|
+
const start = time ? performance.now() : 0;
|
|
39
|
+
const output = original.apply(instance, args);
|
|
41
40
|
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
if (output instanceof Promise) {
|
|
42
|
+
return (output as Promise<unknown>)
|
|
43
|
+
.then((resolved) => {
|
|
44
|
+
const elapsed = time
|
|
45
|
+
? ` (${(performance.now() - start).toFixed(2)}ms)`
|
|
46
|
+
: "";
|
|
47
|
+
if (result) logger(`${label} resolved:`, resolved, elapsed);
|
|
48
|
+
return resolved;
|
|
49
|
+
})
|
|
50
|
+
.catch((e: unknown) => {
|
|
51
|
+
logger(`${label} rejected:`, e);
|
|
52
|
+
throw e;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
44
55
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
? ` (${(performance.now() - start).toFixed(2)}ms)`
|
|
50
|
-
: "";
|
|
51
|
-
if (result) logger(`${label} resolved:`, resolved, elapsed);
|
|
52
|
-
return resolved;
|
|
53
|
-
})
|
|
54
|
-
.catch((e: unknown) => {
|
|
55
|
-
logger(`${label} rejected:`, e);
|
|
56
|
-
throw e;
|
|
57
|
-
});
|
|
58
|
-
}
|
|
56
|
+
const elapsed = time
|
|
57
|
+
? ` (${(performance.now() - start).toFixed(2)}ms)`
|
|
58
|
+
: "";
|
|
59
|
+
if (result) logger(`${label} returned:`, output, elapsed);
|
|
59
60
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
return output;
|
|
66
|
-
};
|
|
67
|
-
};
|
|
61
|
+
return output;
|
|
62
|
+
};
|
|
63
|
+
},
|
|
64
|
+
});
|
|
68
65
|
}
|
package/src/functions/memo.ts
CHANGED
|
@@ -1,38 +1,7 @@
|
|
|
1
|
-
import type { StatefulComponent } from "@praxisjs/core";
|
|
2
1
|
import { computed } from "@praxisjs/core/internal";
|
|
3
2
|
import type { Computed } from "@praxisjs/shared";
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
object,
|
|
7
|
-
Map<string, Map<string, Computed<unknown>>>
|
|
8
|
-
>();
|
|
9
|
-
|
|
10
|
-
function getCache(
|
|
11
|
-
instance: object,
|
|
12
|
-
methodName: string,
|
|
13
|
-
argKey: string,
|
|
14
|
-
factory: () => unknown,
|
|
15
|
-
): Computed<unknown> {
|
|
16
|
-
let methodMap = instanceCache.get(instance);
|
|
17
|
-
if (!methodMap) {
|
|
18
|
-
methodMap = new Map();
|
|
19
|
-
instanceCache.set(instance, methodMap);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
let argMap = methodMap.get(methodName);
|
|
23
|
-
if (!argMap) {
|
|
24
|
-
argMap = new Map();
|
|
25
|
-
methodMap.set(methodName, argMap);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
let cached = argMap.get(argKey);
|
|
29
|
-
if (!cached) {
|
|
30
|
-
cached = computed(factory);
|
|
31
|
-
argMap.set(argKey, cached);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return cached;
|
|
35
|
-
}
|
|
4
|
+
import { createMethodDecorator } from "../create-method-decorator";
|
|
36
5
|
|
|
37
6
|
function serializeArgs(args: unknown[]) {
|
|
38
7
|
if (args.length === 0) return "__no_args__";
|
|
@@ -46,17 +15,18 @@ function serializeArgs(args: unknown[]) {
|
|
|
46
15
|
}
|
|
47
16
|
|
|
48
17
|
export function Memo() {
|
|
49
|
-
return
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
18
|
+
return createMethodDecorator({
|
|
19
|
+
wrap(original, instance, _name) {
|
|
20
|
+
const cache = new Map<string, Computed<unknown>>();
|
|
21
|
+
return (...args: unknown[]) => {
|
|
22
|
+
const key = serializeArgs(args);
|
|
23
|
+
let memoized = cache.get(key);
|
|
24
|
+
if (!memoized) {
|
|
25
|
+
memoized = computed(() => original.apply(instance, args));
|
|
26
|
+
cache.set(key, memoized);
|
|
27
|
+
}
|
|
28
|
+
return memoized();
|
|
29
|
+
};
|
|
30
|
+
},
|
|
31
|
+
});
|
|
62
32
|
}
|
package/src/functions/once.ts
CHANGED
|
@@ -1,19 +1,16 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { createMethodDecorator } from "../create-method-decorator";
|
|
2
2
|
|
|
3
3
|
export function Once() {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
return result;
|
|
17
|
-
};
|
|
18
|
-
};
|
|
4
|
+
return createMethodDecorator({
|
|
5
|
+
wrap(original, instance) {
|
|
6
|
+
let called = false;
|
|
7
|
+
let result: unknown;
|
|
8
|
+
return (...args: unknown[]) => {
|
|
9
|
+
if (called) return result;
|
|
10
|
+
result = original.apply(instance, args);
|
|
11
|
+
called = true;
|
|
12
|
+
return result;
|
|
13
|
+
};
|
|
14
|
+
},
|
|
15
|
+
});
|
|
19
16
|
}
|
package/src/functions/retry.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { createMethodDecorator } from "../create-method-decorator";
|
|
2
2
|
|
|
3
3
|
export interface RetryOptions {
|
|
4
4
|
delay?: number;
|
|
@@ -9,30 +9,29 @@ export interface RetryOptions {
|
|
|
9
9
|
export function Retry(maxAttempts: number, options: RetryOptions = {}) {
|
|
10
10
|
const { delay = 0, backoff = 1, onRetry } = options;
|
|
11
11
|
|
|
12
|
-
return
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
let lastError: Error = new Error("Unknown error");
|
|
18
|
-
let currentDelay = delay;
|
|
12
|
+
return createMethodDecorator({
|
|
13
|
+
wrap(original, instance) {
|
|
14
|
+
return async (...args: unknown[]) => {
|
|
15
|
+
let lastError: Error = new Error("Unknown error");
|
|
16
|
+
let currentDelay = delay;
|
|
19
17
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
18
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
19
|
+
try {
|
|
20
|
+
return await (original.apply(instance, args) as Promise<unknown>);
|
|
21
|
+
} catch (e: unknown) {
|
|
22
|
+
lastError = e instanceof Error ? e : new Error(String(e));
|
|
23
|
+
if (attempt === maxAttempts) break;
|
|
24
|
+
onRetry?.(lastError, attempt);
|
|
27
25
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
if (currentDelay > 0) {
|
|
27
|
+
await new Promise((res) => setTimeout(res, currentDelay));
|
|
28
|
+
currentDelay = Math.round(currentDelay * backoff);
|
|
29
|
+
}
|
|
31
30
|
}
|
|
32
31
|
}
|
|
33
|
-
}
|
|
34
32
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
throw lastError;
|
|
34
|
+
};
|
|
35
|
+
},
|
|
36
|
+
});
|
|
38
37
|
}
|
|
@@ -1,29 +1,15 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { createMethodDecorator } from "../create-method-decorator";
|
|
2
2
|
|
|
3
3
|
export function Throttle(ms: number) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
context: ClassMethodDecoratorContext<StatefulComponent>,
|
|
9
|
-
): void {
|
|
10
|
-
context.addInitializer(function (this: unknown) {
|
|
11
|
-
const instance = this as object;
|
|
12
|
-
const name = context.name as string;
|
|
13
|
-
const bound = (...args: unknown[]) => {
|
|
4
|
+
return createMethodDecorator({
|
|
5
|
+
wrap(original, instance) {
|
|
6
|
+
let last = 0;
|
|
7
|
+
return (...args: unknown[]) => {
|
|
14
8
|
const now = Date.now();
|
|
15
|
-
const last = lastRun.get(instance) ?? 0;
|
|
16
|
-
|
|
17
9
|
if (now - last < ms) return;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
return value.apply(instance, args);
|
|
10
|
+
last = now;
|
|
11
|
+
return original.apply(instance, args);
|
|
21
12
|
};
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
configurable: true,
|
|
25
|
-
writable: true,
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
};
|
|
13
|
+
},
|
|
14
|
+
});
|
|
29
15
|
}
|
package/src/functions/watch.ts
CHANGED
|
@@ -3,6 +3,8 @@ import { effect } from "@praxisjs/core/internal";
|
|
|
3
3
|
import type { Computed } from "@praxisjs/shared";
|
|
4
4
|
import { isComputed } from "@praxisjs/shared/internal";
|
|
5
5
|
|
|
6
|
+
import { createLifecycleMethodDecorator } from "../create-lifecycle-method-decorator";
|
|
7
|
+
|
|
6
8
|
type BaseComponentKeys = keyof StatefulComponent;
|
|
7
9
|
|
|
8
10
|
type WatchableKeys<T> = {
|
|
@@ -54,42 +56,33 @@ export function Watch<
|
|
|
54
56
|
T extends StatefulComponent,
|
|
55
57
|
const Keys extends ReadonlyArray<WatchableKeys<T>>,
|
|
56
58
|
>(...propNames: ValidateKeys<T, Keys>) {
|
|
57
|
-
|
|
58
|
-
value: (this: T, ...args: unknown[]) => void,
|
|
59
|
-
context: ClassMethodDecoratorContext<T>,
|
|
60
|
-
): void {
|
|
61
|
-
const props = propNames as unknown as string[];
|
|
59
|
+
const props = propNames as unknown as string[];
|
|
62
60
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const originalOnMount = instance.onMount;
|
|
61
|
+
return createLifecycleMethodDecorator<T>({
|
|
62
|
+
register(callback, instance) {
|
|
63
|
+
const inst = instance as T & Record<string, unknown>;
|
|
67
64
|
|
|
68
|
-
|
|
69
|
-
|
|
65
|
+
if (props.length === 1) {
|
|
66
|
+
let oldVal = readValue(inst, props[0]);
|
|
67
|
+
return effect(() => {
|
|
68
|
+
const newVal = readValue(inst, props[0]);
|
|
69
|
+
if (!Object.is(newVal, oldVal)) {
|
|
70
|
+
callback(newVal, oldVal);
|
|
71
|
+
oldVal = newVal;
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
70
75
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
});
|
|
80
|
-
} else {
|
|
81
|
-
const read = () =>
|
|
82
|
-
Object.fromEntries(props.map((p) => [p, readValue(this, p)]));
|
|
83
|
-
let oldVals = read();
|
|
84
|
-
effect(() => {
|
|
85
|
-
const newVals = read();
|
|
86
|
-
if (props.some((p) => !Object.is(newVals[p], oldVals[p]))) {
|
|
87
|
-
value.call(this as T, newVals, oldVals);
|
|
88
|
-
oldVals = newVals;
|
|
89
|
-
}
|
|
90
|
-
});
|
|
76
|
+
const read = () =>
|
|
77
|
+
Object.fromEntries(props.map((p) => [p, readValue(inst, p)]));
|
|
78
|
+
let oldVals = read();
|
|
79
|
+
return effect(() => {
|
|
80
|
+
const newVals = read();
|
|
81
|
+
if (props.some((p) => !Object.is(newVals[p], oldVals[p]))) {
|
|
82
|
+
callback(newVals, oldVals);
|
|
83
|
+
oldVals = newVals;
|
|
91
84
|
}
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
};
|
|
85
|
+
});
|
|
86
|
+
},
|
|
87
|
+
});
|
|
95
88
|
}
|
package/src/functions/when.ts
CHANGED
|
@@ -1,42 +1,17 @@
|
|
|
1
|
-
import type { StatefulComponent } from "@praxisjs/core";
|
|
2
1
|
import { when } from "@praxisjs/core/internal";
|
|
3
2
|
import type { Computed, Signal } from "@praxisjs/shared";
|
|
4
3
|
import { isComputed } from "@praxisjs/shared/internal";
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
return function (
|
|
8
|
-
value: (this: StatefulComponent, val: unknown) => void,
|
|
9
|
-
context: ClassMethodDecoratorContext<StatefulComponent>,
|
|
10
|
-
): void {
|
|
11
|
-
const cancels = new WeakMap<object, () => void>();
|
|
12
|
-
|
|
13
|
-
context.addInitializer(function (this: unknown) {
|
|
14
|
-
const instance = this as StatefulComponent;
|
|
15
|
-
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
16
|
-
const originalOnMount = instance.onMount;
|
|
17
|
-
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
18
|
-
const originalOnUnmount = instance.onUnmount;
|
|
19
|
-
|
|
20
|
-
instance.onMount = function (this: StatefulComponent) {
|
|
21
|
-
originalOnMount?.call(this);
|
|
22
|
-
|
|
23
|
-
const raw = (this as unknown as Record<string, unknown>)[propName];
|
|
24
|
-
const source = isComputed(raw)
|
|
25
|
-
? (raw as Computed<unknown>)
|
|
26
|
-
: (raw as Signal<unknown>);
|
|
5
|
+
import { createLifecycleMethodDecorator } from "../create-lifecycle-method-decorator";
|
|
27
6
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
cancels.delete(this);
|
|
39
|
-
};
|
|
40
|
-
});
|
|
41
|
-
};
|
|
7
|
+
export function When(propName: string) {
|
|
8
|
+
return createLifecycleMethodDecorator({
|
|
9
|
+
register(callback, instance) {
|
|
10
|
+
const raw = (instance as unknown as Record<string, unknown>)[propName];
|
|
11
|
+
const source = isComputed(raw)
|
|
12
|
+
? (raw as Computed<unknown>)
|
|
13
|
+
: (raw as Signal<unknown>);
|
|
14
|
+
return when(source, (val) => { callback(val); });
|
|
15
|
+
},
|
|
16
|
+
});
|
|
42
17
|
}
|
package/src/index.ts
CHANGED
|
@@ -21,5 +21,33 @@ export {
|
|
|
21
21
|
initSlots,
|
|
22
22
|
History,
|
|
23
23
|
type WithHistory,
|
|
24
|
+
Compose,
|
|
25
|
+
Resource,
|
|
26
|
+
type ResourceInstance,
|
|
27
|
+
type ResourceOptions,
|
|
24
28
|
} from "./properties";
|
|
25
29
|
export { type Command, createCommand, Emit, OnCommand } from "./events";
|
|
30
|
+
export {
|
|
31
|
+
createFieldDecorator,
|
|
32
|
+
type FieldBehavior,
|
|
33
|
+
type FieldBinding,
|
|
34
|
+
} from "./create-field-decorator";
|
|
35
|
+
export {
|
|
36
|
+
createClassDecorator,
|
|
37
|
+
ClassBehavior,
|
|
38
|
+
type ClassEnhancement,
|
|
39
|
+
} from "./create-class-decorator";
|
|
40
|
+
export {
|
|
41
|
+
createMethodDecorator,
|
|
42
|
+
type MethodBehavior,
|
|
43
|
+
} from "./create-method-decorator";
|
|
44
|
+
export {
|
|
45
|
+
createLifecycleMethodDecorator,
|
|
46
|
+
type LifecycleMethodBehavior,
|
|
47
|
+
} from "./create-lifecycle-method-decorator";
|
|
48
|
+
export {
|
|
49
|
+
createGetterDecorator,
|
|
50
|
+
type GetterBehavior,
|
|
51
|
+
createGetterObserverDecorator,
|
|
52
|
+
type GetterObserverBehavior,
|
|
53
|
+
} from "./create-getter-decorator";
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { StatefulComponent, Composable } from "@praxisjs/core";
|
|
2
|
+
|
|
3
|
+
import { createFieldDecorator } from "../create-field-decorator";
|
|
4
|
+
|
|
5
|
+
function isReactive(
|
|
6
|
+
value: unknown,
|
|
7
|
+
): value is () => unknown {
|
|
8
|
+
return (
|
|
9
|
+
typeof value === "function" &&
|
|
10
|
+
("__isSignal" in (value as object) || "__isComputed" in (value as object))
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function buildView(bindings: Record<string, unknown>): object {
|
|
15
|
+
const view: Record<string, unknown> = {};
|
|
16
|
+
for (const [key, value] of Object.entries(bindings)) {
|
|
17
|
+
if (isReactive(value)) {
|
|
18
|
+
Object.defineProperty(view, key, {
|
|
19
|
+
get: () => (value as () => unknown)(),
|
|
20
|
+
enumerable: true,
|
|
21
|
+
configurable: true,
|
|
22
|
+
});
|
|
23
|
+
} else {
|
|
24
|
+
view[key] = value;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return view;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function Compose(
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
32
|
+
ComposableClass: new (...args: any[]) => Composable,
|
|
33
|
+
...ctorArgs: unknown[]
|
|
34
|
+
) {
|
|
35
|
+
return createFieldDecorator({
|
|
36
|
+
bind(instance: StatefulComponent, _name: string, _initialValue: unknown) {
|
|
37
|
+
const resolvedArgs = ctorArgs.map((arg) =>
|
|
38
|
+
typeof arg === "string"
|
|
39
|
+
? (instance as unknown as Record<string, unknown>)[arg]
|
|
40
|
+
: arg,
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const composable = new ComposableClass(...resolvedArgs);
|
|
44
|
+
const view = buildView(composable.setup());
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
descriptor: { get: () => view },
|
|
48
|
+
onMount: composable.onMount?.bind(composable),
|
|
49
|
+
onUnmount: composable.onUnmount?.bind(composable),
|
|
50
|
+
};
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
}
|