patron-oop 1.34.0 → 1.36.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 +14 -0
- package/dist/patron.cjs +43 -37
- package/dist/patron.cjs.map +1 -1
- package/dist/patron.d.ts +18 -13
- package/dist/patron.js +43 -37
- package/dist/patron.js.map +1 -1
- package/dist/patron.min.js +1 -1
- package/dist/patron.min.mjs +1 -1
- package/dist/patron.min.mjs.map +1 -1
- package/dist/patron.mjs +43 -37
- package/dist/patron.mjs.map +1 -1
- package/package.json +1 -1
- package/src/Guest/{GuestChain._asArray.test.ts → GuestAwareAll._asArray.test.ts} +6 -6
- package/src/Guest/GuestAwareAll._twoValuesAfter.test.ts +16 -0
- package/src/Guest/GuestAwareAll._twoValuesBefore.test.ts +16 -0
- package/src/Guest/{GuestChain._withPatron.test.ts → GuestAwareAll._withPatron.test.ts} +6 -6
- package/src/Guest/GuestAwareAll.ts +88 -0
- package/src/Guest/GuestAwareMap.ts +4 -4
- package/src/Guest/GuestAwareSequence.ts +4 -4
- package/src/Guest/GuestCast.ts +8 -1
- package/src/Patron/PatronOnce.sourceEmpty.test.ts +35 -0
- package/src/Patron/PatronOnce.test.ts +25 -7
- package/src/Patron/PatronOnce.ts +6 -4
- package/src/Source/SourceEmpty.ts +2 -2
- package/src/index.ts +1 -1
- package/examples/elegant_objects.html +0 -118
- package/examples/reactive.html +0 -65
- package/src/Guest/GuestChain._twoValuesAfter.test.ts +0 -16
- package/src/Guest/GuestChain._twoValuesBefore.test.ts +0 -16
- package/src/Guest/GuestChain.ts +0 -88
package/src/Guest/GuestCast.ts
CHANGED
@@ -3,6 +3,7 @@ import {
|
|
3
3
|
MaybeDisposableType,
|
4
4
|
} from "./GuestDisposable";
|
5
5
|
import { give, GiveOptions, GuestType } from "./Guest";
|
6
|
+
import { PoolAwareOptions } from "../Patron/PatronOnce";
|
6
7
|
|
7
8
|
/**
|
8
9
|
* @url https://kosukhin.github.io/patron.site/#/guest/guest-cast
|
@@ -24,7 +25,13 @@ export class GuestCast<T> implements GuestDisposableType<T> {
|
|
24
25
|
}
|
25
26
|
|
26
27
|
public give(value: T, options?: GiveOptions): this {
|
27
|
-
give(value, this.targetGuest,
|
28
|
+
give(value, this.targetGuest, {
|
29
|
+
...options,
|
30
|
+
data: {
|
31
|
+
...(options?.data ?? {}),
|
32
|
+
castedGuest: (options?.data as PoolAwareOptions)?.castedGuest ?? this,
|
33
|
+
}
|
34
|
+
});
|
28
35
|
return this;
|
29
36
|
}
|
30
37
|
|
@@ -0,0 +1,35 @@
|
|
1
|
+
import { afterEach, beforeEach, expect, test, vi } from "vitest";
|
2
|
+
import { PatronOnce } from "./PatronOnce";
|
3
|
+
import { SourceEmpty } from "../Source/SourceEmpty";
|
4
|
+
|
5
|
+
beforeEach(() => {
|
6
|
+
vi.useFakeTimers({ shouldAdvanceTime: true });
|
7
|
+
});
|
8
|
+
|
9
|
+
afterEach(() => {
|
10
|
+
vi.runOnlyPendingTimers();
|
11
|
+
vi.useRealTimers();
|
12
|
+
});
|
13
|
+
|
14
|
+
const wait = (ms: number) => new Promise(resolve => {
|
15
|
+
setTimeout(() => { resolve(1) }, ms);
|
16
|
+
})
|
17
|
+
|
18
|
+
test("PatronOnce.sourceEmpty.test", async () => {
|
19
|
+
const source = new SourceEmpty();
|
20
|
+
let calls = 0;
|
21
|
+
const patron = new PatronOnce((v) => {
|
22
|
+
calls += 1;
|
23
|
+
});
|
24
|
+
source.value(patron);
|
25
|
+
|
26
|
+
await wait(10);
|
27
|
+
source.give(22);
|
28
|
+
await wait(10);
|
29
|
+
source.give(32);
|
30
|
+
await wait(10);
|
31
|
+
source.give(42);
|
32
|
+
await wait(10);
|
33
|
+
|
34
|
+
expect(calls).toBe(1);
|
35
|
+
});
|
@@ -1,17 +1,35 @@
|
|
1
|
-
import { expect, test } from "vitest";
|
2
|
-
import { PatronOnce } from "./PatronOnce";
|
1
|
+
import { afterEach, beforeEach, expect, test, vi } from "vitest";
|
3
2
|
import { Source } from "../Source/Source";
|
3
|
+
import { PatronOnce } from "./PatronOnce";
|
4
|
+
|
5
|
+
beforeEach(() => {
|
6
|
+
vi.useFakeTimers({ shouldAdvanceTime: true });
|
7
|
+
});
|
8
|
+
|
9
|
+
afterEach(() => {
|
10
|
+
vi.runOnlyPendingTimers();
|
11
|
+
vi.useRealTimers();
|
12
|
+
});
|
13
|
+
|
14
|
+
const wait = (ms: number) => new Promise(resolve => {
|
15
|
+
setTimeout(() => { resolve(1) }, ms);
|
16
|
+
})
|
4
17
|
|
5
|
-
test("PatronOnce.test", () => {
|
6
|
-
const source = new Source(
|
18
|
+
test("PatronOnce.test", async () => {
|
19
|
+
const source = new Source(12);
|
7
20
|
let calls = 0;
|
8
|
-
const patron = new PatronOnce(() => {
|
21
|
+
const patron = new PatronOnce((v) => {
|
9
22
|
calls += 1;
|
10
23
|
});
|
11
24
|
source.value(patron);
|
25
|
+
|
26
|
+
await wait(10);
|
12
27
|
source.give(22);
|
13
|
-
|
14
|
-
source.give(
|
28
|
+
await wait(10);
|
29
|
+
source.give(32);
|
30
|
+
await wait(10);
|
31
|
+
source.give(42);
|
32
|
+
await wait(10);
|
15
33
|
|
16
34
|
expect(calls).toBe(1);
|
17
35
|
});
|
package/src/Patron/PatronOnce.ts
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
import { PoolType } from "./PatronPool";
|
2
|
-
import { give, GuestType, GiveOptions } from "../Guest/Guest";
|
2
|
+
import { give, GuestType, GiveOptions, GuestObjectType } from "../Guest/Guest";
|
3
3
|
import {
|
4
4
|
GuestDisposableType,
|
5
5
|
MaybeDisposableType,
|
6
6
|
} from "../Guest/GuestDisposable";
|
7
7
|
|
8
|
-
type
|
8
|
+
export type PoolAwareOptions = {
|
9
9
|
pool?: PoolType;
|
10
|
+
castedGuest?: GuestObjectType;
|
10
11
|
};
|
11
12
|
|
12
13
|
/**
|
@@ -25,9 +26,10 @@ export class PatronOnce<T> implements GuestDisposableType<T> {
|
|
25
26
|
if (!this.received) {
|
26
27
|
give(value, this.baseGuest, options);
|
27
28
|
}
|
28
|
-
const data = options?.data as
|
29
|
+
const data = options?.data as PoolAwareOptions;
|
30
|
+
|
29
31
|
if (data?.pool) {
|
30
|
-
data.pool.remove(this);
|
32
|
+
data.pool.remove(data?.castedGuest ?? this);
|
31
33
|
}
|
32
34
|
return this;
|
33
35
|
}
|
@@ -11,9 +11,9 @@ export class SourceEmpty<T> implements SourceType<T> {
|
|
11
11
|
|
12
12
|
public value(guest: GuestType<T>) {
|
13
13
|
this.baseSource.value(
|
14
|
-
new GuestCast(guest as GuestType, (value) => {
|
14
|
+
new GuestCast(guest as GuestType, (value, options) => {
|
15
15
|
if (value !== null) {
|
16
|
-
give(value, guest);
|
16
|
+
give(value, guest, options);
|
17
17
|
}
|
18
18
|
}),
|
19
19
|
);
|
package/src/index.ts
CHANGED
@@ -5,7 +5,7 @@ export * from "./Guest/GuestAwareRace";
|
|
5
5
|
export * from "./Guest/GuestAwareActive";
|
6
6
|
export * from "./Guest/Guest";
|
7
7
|
export * from "./Guest/GuestCast";
|
8
|
-
export * from "./Guest/
|
8
|
+
export * from "./Guest/GuestAwareAll";
|
9
9
|
export * from "./Guest/GuestPool";
|
10
10
|
export * from "./Guest/GuestSync";
|
11
11
|
export * from "./Guest/GuestObject";
|
@@ -1,118 +0,0 @@
|
|
1
|
-
<!doctype html>
|
2
|
-
<html lang="en">
|
3
|
-
<head>
|
4
|
-
<meta charset="UTF-8"/>
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
6
|
-
<title>Document</title>
|
7
|
-
</head>
|
8
|
-
<body>
|
9
|
-
<h1>Elegant Objects</h1>
|
10
|
-
<p>Композиция объектов описывает поведение</p>
|
11
|
-
<p>Умножение: num1 * num2 = result</p>
|
12
|
-
<div>
|
13
|
-
<label>
|
14
|
-
num1:
|
15
|
-
<input type="number" class="input-1"/>
|
16
|
-
</label>
|
17
|
-
</div>
|
18
|
-
<div>
|
19
|
-
<label>
|
20
|
-
num2:
|
21
|
-
<input type="number" class="input-2"/>
|
22
|
-
</label>
|
23
|
-
</div>
|
24
|
-
<div>result = <b class="result"></b></div>
|
25
|
-
<script type="module">
|
26
|
-
import 'https://cdn.jsdelivr.net/npm/patron-oop@1.8.0/dist/patron.min.js';
|
27
|
-
|
28
|
-
const {
|
29
|
-
Patron,
|
30
|
-
Source,
|
31
|
-
GuestChain,
|
32
|
-
GuestCast,
|
33
|
-
GuestInTheMiddle,
|
34
|
-
} = window.GUEST_LIBRARY;
|
35
|
-
|
36
|
-
class TextInDocument {
|
37
|
-
constructor(selector) {
|
38
|
-
this.element = document.querySelector(selector);
|
39
|
-
}
|
40
|
-
|
41
|
-
receive(value) {
|
42
|
-
this.element.innerText = value;
|
43
|
-
}
|
44
|
-
}
|
45
|
-
|
46
|
-
class Input {
|
47
|
-
constructor(source, selector) {
|
48
|
-
this.source = source;
|
49
|
-
const el = document.querySelector(selector);
|
50
|
-
this.source.value(
|
51
|
-
new Patron((value) => {
|
52
|
-
el.value = value;
|
53
|
-
}),
|
54
|
-
);
|
55
|
-
el.addEventListener('keyup', (e) => {
|
56
|
-
this.give(e.target.value);
|
57
|
-
});
|
58
|
-
el.addEventListener('change', (e) => {
|
59
|
-
this.give(e.target.value);
|
60
|
-
});
|
61
|
-
}
|
62
|
-
|
63
|
-
receiving(guest) {
|
64
|
-
this.source.value(guest);
|
65
|
-
return this;
|
66
|
-
}
|
67
|
-
|
68
|
-
receive(value) {
|
69
|
-
this.source.give(value);
|
70
|
-
return this;
|
71
|
-
}
|
72
|
-
}
|
73
|
-
|
74
|
-
class NumberOf {
|
75
|
-
constructor(source) {
|
76
|
-
this.source = source;
|
77
|
-
}
|
78
|
-
|
79
|
-
number(guest) {
|
80
|
-
this.source.value(guest);
|
81
|
-
return this;
|
82
|
-
}
|
83
|
-
|
84
|
-
receive(value) {
|
85
|
-
this.source.give(value);
|
86
|
-
}
|
87
|
-
}
|
88
|
-
|
89
|
-
class Mul {
|
90
|
-
constructor(num1, num2) {
|
91
|
-
this.num1 = num1;
|
92
|
-
this.num2 = num2;
|
93
|
-
}
|
94
|
-
|
95
|
-
result(guest) {
|
96
|
-
const chain = new GuestChain();
|
97
|
-
this.num1.number(new GuestCast(guest, chain.receiveKey('num1')));
|
98
|
-
this.num2.number(new GuestCast(guest, chain.receiveKey('num2')));
|
99
|
-
chain.result(
|
100
|
-
new GuestInTheMiddle(guest, ({num1, num2}) => {
|
101
|
-
guest.give(num1 * num2);
|
102
|
-
}),
|
103
|
-
);
|
104
|
-
}
|
105
|
-
}
|
106
|
-
|
107
|
-
const input1 = new Input(new Source(2), '.input-1');
|
108
|
-
const input2 = new Input(new Source(2), '.input-2');
|
109
|
-
const multiplication = new Mul(
|
110
|
-
new NumberOf(input1),
|
111
|
-
new NumberOf(input2),
|
112
|
-
);
|
113
|
-
multiplication.result(
|
114
|
-
new Patron(new TextInDocument('.result')),
|
115
|
-
);
|
116
|
-
</script>
|
117
|
-
</body>
|
118
|
-
</html>
|
package/examples/reactive.html
DELETED
@@ -1,65 +0,0 @@
|
|
1
|
-
<!doctype html>
|
2
|
-
<html lang="en">
|
3
|
-
<head>
|
4
|
-
<meta charset="UTF-8"/>
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
6
|
-
<title>Reactive Patron</title>
|
7
|
-
</head>
|
8
|
-
<body>
|
9
|
-
<h1>Reactive example</h1>
|
10
|
-
<div>
|
11
|
-
<label>
|
12
|
-
Поле ввода:
|
13
|
-
<input class="input-1"/>
|
14
|
-
</label>
|
15
|
-
</div>
|
16
|
-
<div>Результат ввода: <span class="result"></span></div>
|
17
|
-
<script type="module">
|
18
|
-
import 'https://cdn.jsdelivr.net/npm/patron-oop@1.8.0/dist/patron.min.js';
|
19
|
-
|
20
|
-
const {Patron, Source} = window.GUEST_LIBRARY;
|
21
|
-
|
22
|
-
class Input {
|
23
|
-
constructor(source, selector) {
|
24
|
-
this.source = source;
|
25
|
-
const el = document.querySelector(selector);
|
26
|
-
this.source.value(
|
27
|
-
new Patron((value) => {
|
28
|
-
el.value = value;
|
29
|
-
}),
|
30
|
-
);
|
31
|
-
el.addEventListener('keyup', (e) => {
|
32
|
-
this.give(e.target.value);
|
33
|
-
});
|
34
|
-
el.addEventListener('change', (e) => {
|
35
|
-
this.give(e.target.value);
|
36
|
-
});
|
37
|
-
}
|
38
|
-
|
39
|
-
receiving(guest) {
|
40
|
-
this.source.value(guest);
|
41
|
-
return this;
|
42
|
-
}
|
43
|
-
|
44
|
-
receive(value) {
|
45
|
-
this.source.give(value);
|
46
|
-
return this;
|
47
|
-
}
|
48
|
-
}
|
49
|
-
|
50
|
-
class Text {
|
51
|
-
constructor(selector) {
|
52
|
-
this.element = document.querySelector(selector);
|
53
|
-
}
|
54
|
-
|
55
|
-
receive(value) {
|
56
|
-
this.element.innerText = value;
|
57
|
-
}
|
58
|
-
}
|
59
|
-
|
60
|
-
new Input(new Source(2), '.input-1').value(
|
61
|
-
new Patron(new Text('.result')),
|
62
|
-
);
|
63
|
-
</script>
|
64
|
-
</body>
|
65
|
-
</html>
|
@@ -1,16 +0,0 @@
|
|
1
|
-
import { expect, test } from "vitest";
|
2
|
-
import { Source } from "../Source/Source";
|
3
|
-
import { GuestChain } from "./GuestChain";
|
4
|
-
|
5
|
-
test("GuestChain._twoValuesAfter.test", () => {
|
6
|
-
const one = new Source(1);
|
7
|
-
const two = new Source(2);
|
8
|
-
const chain = new GuestChain<{ one: number; two: number }>();
|
9
|
-
|
10
|
-
chain.result((value) => {
|
11
|
-
expect(Object.values(value).join()).toBe("1,2");
|
12
|
-
});
|
13
|
-
|
14
|
-
one.value(chain.receiveKey("one"));
|
15
|
-
two.value(chain.receiveKey("two"));
|
16
|
-
});
|
@@ -1,16 +0,0 @@
|
|
1
|
-
import { expect, test } from "vitest";
|
2
|
-
import { Source } from "../Source/Source";
|
3
|
-
import { GuestChain } from "./GuestChain";
|
4
|
-
|
5
|
-
test("GuestChain._twoValuesBefore.test", () => {
|
6
|
-
const one = new Source(1);
|
7
|
-
const two = new Source(2);
|
8
|
-
const chain = new GuestChain<{ one: number; two: number }>();
|
9
|
-
|
10
|
-
one.value(chain.receiveKey("one"));
|
11
|
-
two.value(chain.receiveKey("two"));
|
12
|
-
|
13
|
-
chain.result((value) => {
|
14
|
-
expect(Object.values(value).join()).toBe("1,2");
|
15
|
-
});
|
16
|
-
});
|
package/src/Guest/GuestChain.ts
DELETED
@@ -1,88 +0,0 @@
|
|
1
|
-
import { GuestCast } from "./GuestCast";
|
2
|
-
import { Source } from "../Source/Source";
|
3
|
-
import { Guest, GuestObjectType, GuestType } from "./Guest";
|
4
|
-
import { GuestObject } from "./GuestObject";
|
5
|
-
import { GuestPool } from "./GuestPool";
|
6
|
-
|
7
|
-
export interface ChainType<T = any> {
|
8
|
-
result(guest: GuestObjectType<T>): this;
|
9
|
-
resultArray(guest: GuestObjectType<T>): this;
|
10
|
-
receiveKey<R>(key: string): GuestObjectType<R>;
|
11
|
-
}
|
12
|
-
|
13
|
-
/**
|
14
|
-
* @url https://kosukhin.github.io/patron.site/#/guest/guest-chain
|
15
|
-
*/
|
16
|
-
export class GuestChain<T> implements ChainType<T> {
|
17
|
-
private theChain: Source<Record<string, unknown>>;
|
18
|
-
|
19
|
-
private keysKnown = new Set();
|
20
|
-
|
21
|
-
private keysFilled = new Set();
|
22
|
-
|
23
|
-
private filledChainPool = new GuestPool(this);
|
24
|
-
|
25
|
-
public constructor() {
|
26
|
-
this.theChain = new Source<Record<string, unknown>>({});
|
27
|
-
}
|
28
|
-
|
29
|
-
public resultArray(guest: GuestType<T>) {
|
30
|
-
const guestObject = new GuestObject(guest);
|
31
|
-
this.filledChainPool.add(
|
32
|
-
new GuestCast(guestObject, (value: Record<string, unknown>) => {
|
33
|
-
guestObject.give(Object.values(value) as T);
|
34
|
-
}),
|
35
|
-
);
|
36
|
-
if (this.isChainFilled()) {
|
37
|
-
this.theChain.value(
|
38
|
-
new Guest((chain: Record<string, unknown>) => {
|
39
|
-
this.filledChainPool.give(Object.values(chain));
|
40
|
-
}),
|
41
|
-
);
|
42
|
-
}
|
43
|
-
return this;
|
44
|
-
}
|
45
|
-
|
46
|
-
public result(guest: GuestType<T>) {
|
47
|
-
const guestObject = new GuestObject(guest);
|
48
|
-
if (this.isChainFilled()) {
|
49
|
-
this.filledChainPool.add(guestObject);
|
50
|
-
this.theChain.value(
|
51
|
-
new Guest((chain) => {
|
52
|
-
this.filledChainPool.give(chain);
|
53
|
-
}),
|
54
|
-
);
|
55
|
-
} else {
|
56
|
-
this.filledChainPool.add(guestObject);
|
57
|
-
}
|
58
|
-
return this;
|
59
|
-
}
|
60
|
-
|
61
|
-
public receiveKey<R>(key: string): GuestObjectType<R> {
|
62
|
-
this.keysKnown.add(key);
|
63
|
-
return new Guest((value) => {
|
64
|
-
// Обернул в очередь чтобы можно было синхронно наполнить очередь известных ключей
|
65
|
-
queueMicrotask(() => {
|
66
|
-
this.theChain.value(
|
67
|
-
new Guest((chain: Record<string, unknown>) => {
|
68
|
-
this.keysFilled.add(key);
|
69
|
-
const lastChain = {
|
70
|
-
...chain,
|
71
|
-
[key]: value,
|
72
|
-
};
|
73
|
-
this.theChain.give(lastChain);
|
74
|
-
if (this.isChainFilled()) {
|
75
|
-
this.filledChainPool.give(lastChain);
|
76
|
-
}
|
77
|
-
}),
|
78
|
-
);
|
79
|
-
});
|
80
|
-
});
|
81
|
-
}
|
82
|
-
|
83
|
-
private isChainFilled() {
|
84
|
-
return (
|
85
|
-
this.keysFilled.size > 0 && this.keysFilled.size === this.keysKnown.size
|
86
|
-
);
|
87
|
-
}
|
88
|
-
}
|