silentium 0.0.2
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/.husky/pre-commit +1 -0
- package/.husky/pre-push +2 -0
- package/.vscode/settings.json +8 -0
- package/CHANGELOG.md +12 -0
- package/LICENSE.md +7 -0
- package/README.md +3 -0
- package/commitizen.cjs +50 -0
- package/dist/silentium.cjs +771 -0
- package/dist/silentium.cjs.map +1 -0
- package/dist/silentium.d.ts +365 -0
- package/dist/silentium.js +735 -0
- package/dist/silentium.js.map +1 -0
- package/dist/silentium.min.js +1 -0
- package/dist/silentium.min.mjs +2 -0
- package/dist/silentium.min.mjs.map +1 -0
- package/dist/silentium.mjs +735 -0
- package/dist/silentium.mjs.map +1 -0
- package/docs/README.md +3 -0
- package/docs/assets/css/base.css +42 -0
- package/docs/assets/favicon/android-icon-144x144.png +0 -0
- package/docs/assets/favicon/android-icon-192x192.png +0 -0
- package/docs/assets/favicon/android-icon-36x36.png +0 -0
- package/docs/assets/favicon/android-icon-48x48.png +0 -0
- package/docs/assets/favicon/android-icon-72x72.png +0 -0
- package/docs/assets/favicon/android-icon-96x96.png +0 -0
- package/docs/assets/favicon/apple-icon-114x114.png +0 -0
- package/docs/assets/favicon/apple-icon-120x120.png +0 -0
- package/docs/assets/favicon/apple-icon-144x144.png +0 -0
- package/docs/assets/favicon/apple-icon-152x152.png +0 -0
- package/docs/assets/favicon/apple-icon-180x180.png +0 -0
- package/docs/assets/favicon/apple-icon-57x57.png +0 -0
- package/docs/assets/favicon/apple-icon-60x60.png +0 -0
- package/docs/assets/favicon/apple-icon-72x72.png +0 -0
- package/docs/assets/favicon/apple-icon-76x76.png +0 -0
- package/docs/assets/favicon/apple-icon-precomposed.png +0 -0
- package/docs/assets/favicon/apple-icon.png +0 -0
- package/docs/assets/favicon/browserconfig.xml +2 -0
- package/docs/assets/favicon/favicon-16x16.png +0 -0
- package/docs/assets/favicon/favicon-32x32.png +0 -0
- package/docs/assets/favicon/favicon-96x96.png +0 -0
- package/docs/assets/favicon/favicon.ico +0 -0
- package/docs/assets/favicon/manifest.json +41 -0
- package/docs/assets/favicon/ms-icon-144x144.png +0 -0
- package/docs/assets/favicon/ms-icon-150x150.png +0 -0
- package/docs/assets/favicon/ms-icon-310x310.png +0 -0
- package/docs/assets/favicon/ms-icon-70x70.png +0 -0
- package/docs/assets/img/404.jpg +0 -0
- package/docs/assets/img/angular_16.jpg +0 -0
- package/docs/assets/img/angular_32.jpg +0 -0
- package/docs/assets/img/eo_16.jpg +0 -0
- package/docs/assets/img/eo_big.png +0 -0
- package/docs/assets/img/github_16.jpg +0 -0
- package/docs/assets/img/logo.jpg +0 -0
- package/docs/assets/img/philosofy/observable.jpg +0 -0
- package/docs/assets/img/philosofy/responsible.jpg +0 -0
- package/docs/assets/img/philosofy/result.jpg +0 -0
- package/docs/assets/img/philosofy/tell.jpg +0 -0
- package/docs/assets/img/react_16.jpg +0 -0
- package/docs/assets/img/react_32.jpg +0 -0
- package/docs/assets/img/vue_16.jpg +0 -0
- package/docs/assets/img/vue_32.jpg +0 -0
- package/docs/assets/schemes/dip.html +28 -0
- package/docs/build.sh +20 -0
- package/docs/favicon.ico +0 -0
- package/docs/index-dev.html +346 -0
- package/docs/index.html +346 -0
- package/docs/manifest.json +41 -0
- package/docs/pages/404.html +9 -0
- package/docs/pages/common/layout.html +17 -0
- package/docs/pages/compatibility/dip.html +82 -0
- package/docs/pages/compatibility/elegant-objects.html +373 -0
- package/docs/pages/compatibility/layout.html +17 -0
- package/docs/pages/examples/errors.html +167 -0
- package/docs/pages/examples/index.html +10 -0
- package/docs/pages/examples.html +41 -0
- package/docs/pages/factory/index.html +18 -0
- package/docs/pages/factory.html +36 -0
- package/docs/pages/guest/guest-applied.html +51 -0
- package/docs/pages/guest/guest-cast.html +219 -0
- package/docs/pages/guest/guest-disposable.html +147 -0
- package/docs/pages/guest/guest-executor-applied.html +65 -0
- package/docs/pages/guest/guest-object.html +101 -0
- package/docs/pages/guest/guest-pool.html +107 -0
- package/docs/pages/guest/guest-sync.html +66 -0
- package/docs/pages/guest/index.html +115 -0
- package/docs/pages/guest.html +59 -0
- package/docs/pages/index.html +72 -0
- package/docs/pages/integrations/angular.html +5 -0
- package/docs/pages/integrations/layout.html +17 -0
- package/docs/pages/integrations/react.html +7 -0
- package/docs/pages/integrations/vue.html +102 -0
- package/docs/pages/patron/index.html +140 -0
- package/docs/pages/patron/patron-applied.html +66 -0
- package/docs/pages/patron/patron-executor-applied.html +94 -0
- package/docs/pages/patron/patron-once.html +110 -0
- package/docs/pages/patron/patron-pool.html +99 -0
- package/docs/pages/patron.html +50 -0
- package/docs/pages/philosofy.html +210 -0
- package/docs/pages/source/index.html +167 -0
- package/docs/pages/source/source-active.html +120 -0
- package/docs/pages/source/source-all.html +129 -0
- package/docs/pages/source/source-applied.html +73 -0
- package/docs/pages/source/source-dynamic.html +93 -0
- package/docs/pages/source/source-executor-applied.html +64 -0
- package/docs/pages/source/source-map.html +192 -0
- package/docs/pages/source/source-once.html +73 -0
- package/docs/pages/source/source-race.html +171 -0
- package/docs/pages/source/source-sequence.html +160 -0
- package/docs/pages/source/source-with-pool.html +102 -0
- package/docs/pages/source/source.html +167 -0
- package/docs/pages/source.html +68 -0
- package/docs/pages/terminology/guest.html +14 -0
- package/docs/pages/terminology/index.html +6 -0
- package/docs/pages/terminology/introduction.html +25 -0
- package/docs/pages/terminology/patron.html +10 -0
- package/docs/pages/terminology/source.html +55 -0
- package/docs/pages/terminology/visitor.html +19 -0
- package/docs/pages/terminology.html +53 -0
- package/docs/pages/utils/give.html +47 -0
- package/docs/pages/utils/index.html +24 -0
- package/docs/pages/utils/is-guest-aware.html +22 -0
- package/docs/pages/utils/is-guest.html +21 -0
- package/docs/pages/utils/is-patron-in-pools.html +53 -0
- package/docs/pages/utils/is-source.html +21 -0
- package/docs/pages/utils/private.html +44 -0
- package/docs/pages/utils/remove-patron-from-pools.html +57 -0
- package/docs/pages/utils/source-of.html +20 -0
- package/docs/pages/utils/value.html +47 -0
- package/docs/pages/utils.html +64 -0
- package/docs/template.html +346 -0
- package/eslint.config.mjs +47 -0
- package/package.json +57 -0
- package/rollup.config.js +52 -0
- package/src/Guest/Guest.test.ts +15 -0
- package/src/Guest/Guest.ts +53 -0
- package/src/Guest/GuestApplied.test.ts +13 -0
- package/src/Guest/GuestApplied.ts +16 -0
- package/src/Guest/GuestCast.test.ts +30 -0
- package/src/Guest/GuestCast.ts +39 -0
- package/src/Guest/GuestDisposable.test.ts +26 -0
- package/src/Guest/GuestDisposable.ts +33 -0
- package/src/Guest/GuestExecutorApplied.test.ts +27 -0
- package/src/Guest/GuestExecutorApplied.ts +23 -0
- package/src/Guest/GuestObject.test.ts +11 -0
- package/src/Guest/GuestObject.ts +34 -0
- package/src/Guest/GuestPool.test.ts +30 -0
- package/src/Guest/GuestPool.ts +56 -0
- package/src/Guest/GuestSync.test.ts +12 -0
- package/src/Guest/GuestSync.ts +25 -0
- package/src/Patron/Patron.test.ts +16 -0
- package/src/Patron/Patron.ts +35 -0
- package/src/Patron/PatronApplied.ts +22 -0
- package/src/Patron/PatronExecutorApplied.ts +25 -0
- package/src/Patron/PatronOnce.sourceEmpty.test.ts +38 -0
- package/src/Patron/PatronOnce.test.ts +32 -0
- package/src/Patron/PatronOnce.ts +38 -0
- package/src/Patron/PatronPool.test.ts +22 -0
- package/src/Patron/PatronPool.ts +121 -0
- package/src/Private/Private.test.ts +12 -0
- package/src/Private/Private.ts +20 -0
- package/src/Private/PrivateClass.modules.test.ts +36 -0
- package/src/Private/PrivateClass.test.ts +13 -0
- package/src/Private/PrivateClass.ts +29 -0
- package/src/Source/Source.test.ts +14 -0
- package/src/Source/Source.ts +59 -0
- package/src/Source/SourceActive.test.ts +13 -0
- package/src/Source/SourceActive.ts +41 -0
- package/src/Source/SourceAll._asArray.test.ts +22 -0
- package/src/Source/SourceAll._twoValuesAfter.test.ts +19 -0
- package/src/Source/SourceAll._twoValuesBefore.test.ts +19 -0
- package/src/Source/SourceAll._withPatron.test.ts +25 -0
- package/src/Source/SourceAll.ts +86 -0
- package/src/Source/SourceApplied.test.ts +14 -0
- package/src/Source/SourceApplied.ts +23 -0
- package/src/Source/SourceDynamic.ofSource.test.ts +21 -0
- package/src/Source/SourceDynamic.test.ts +26 -0
- package/src/Source/SourceDynamic.ts +35 -0
- package/src/Source/SourceExecutorApplied.test.ts +30 -0
- package/src/Source/SourceExecutorApplied.ts +22 -0
- package/src/Source/SourceMap.defered.test.ts +46 -0
- package/src/Source/SourceMap.fn.test.ts +27 -0
- package/src/Source/SourceMap.test.ts +32 -0
- package/src/Source/SourceMap.ts +48 -0
- package/src/Source/SourceOnce.notcalled.test.ts +13 -0
- package/src/Source/SourceOnce.test.ts +10 -0
- package/src/Source/SourceOnce.ts +31 -0
- package/src/Source/SourceRace.test.ts +46 -0
- package/src/Source/SourceRace.ts +30 -0
- package/src/Source/SourceSequence.defered.test.ts +53 -0
- package/src/Source/SourceSequence.test.ts +30 -0
- package/src/Source/SourceSequence.ts +72 -0
- package/src/Source/SourceWithPool.empty.test.ts +14 -0
- package/src/Source/SourceWithPool.test.ts +10 -0
- package/src/Source/SourceWithPool.ts +58 -0
- package/src/index.ts +26 -0
- package/test-utils/debounce.ts +11 -0
- package/test-utils/id.ts +1 -0
- package/test-utils/wait.ts +6 -0
- package/tsconfig.json +26 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { PrivateClass } from "./PrivateClass";
|
|
2
|
+
import { GuestType } from "../Guest/Guest";
|
|
3
|
+
import { SourceWithPool, SourceWithPoolType } from "../Source/SourceWithPool";
|
|
4
|
+
import { expect, test, vitest } from "vitest";
|
|
5
|
+
import { PrivateType } from "./Private";
|
|
6
|
+
|
|
7
|
+
class TestClass {
|
|
8
|
+
private source: SourceWithPoolType;
|
|
9
|
+
|
|
10
|
+
public constructor(
|
|
11
|
+
baseNum: number,
|
|
12
|
+
modules: { main: PrivateType<SourceWithPoolType> },
|
|
13
|
+
) {
|
|
14
|
+
this.source = modules.main.get(baseNum + 55);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
public value(guest: GuestType) {
|
|
18
|
+
this.source.value(guest);
|
|
19
|
+
return this;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
test("PrivateClass.modules.test", () => {
|
|
24
|
+
const main = new PrivateClass(SourceWithPool);
|
|
25
|
+
const testSource = new PrivateClass(TestClass, {
|
|
26
|
+
main,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const source = testSource.get(42);
|
|
30
|
+
|
|
31
|
+
const guest = vitest.fn();
|
|
32
|
+
source.value(guest);
|
|
33
|
+
|
|
34
|
+
expect(guest).toBeCalled();
|
|
35
|
+
expect(guest).toBeCalledWith(97);
|
|
36
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { expect, test, vitest } from "vitest";
|
|
2
|
+
import { SourceWithPool } from "../Source/SourceWithPool";
|
|
3
|
+
import { PrivateClass } from "./PrivateClass";
|
|
4
|
+
|
|
5
|
+
test("PrivateClass.test", () => {
|
|
6
|
+
const sourcePrivate = new PrivateClass(SourceWithPool);
|
|
7
|
+
const source = sourcePrivate.get(42);
|
|
8
|
+
|
|
9
|
+
const guest = vitest.fn();
|
|
10
|
+
source.value(guest);
|
|
11
|
+
|
|
12
|
+
expect(guest).toBeCalledWith(42);
|
|
13
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { PrivateType } from "./Private";
|
|
2
|
+
|
|
3
|
+
interface Constructable<T> {
|
|
4
|
+
new (...args: unknown[]): T;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
interface Prototyped<T> {
|
|
8
|
+
prototype: T;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class PrivateClass<T> implements PrivateType<T> {
|
|
12
|
+
public constructor(
|
|
13
|
+
private constructorFn: Prototyped<T>,
|
|
14
|
+
private modules: Record<string, unknown> = {},
|
|
15
|
+
) {
|
|
16
|
+
if (constructorFn === undefined) {
|
|
17
|
+
throw new Error("PrivateClass didnt receive constructorFn argument");
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public get<R extends unknown[], CT = null>(
|
|
22
|
+
...args: R
|
|
23
|
+
): CT extends null ? T : CT {
|
|
24
|
+
return new (this.constructorFn as Constructable<T>)(
|
|
25
|
+
...args,
|
|
26
|
+
this.modules,
|
|
27
|
+
) as CT extends null ? T : CT;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { expect, test, vitest } from "vitest";
|
|
2
|
+
import { Source } from "./Source";
|
|
3
|
+
import { give } from "../Guest/Guest";
|
|
4
|
+
|
|
5
|
+
test("Source.test", () => {
|
|
6
|
+
const aware = new Source((guest) => {
|
|
7
|
+
give(111, guest);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
const guest = vitest.fn();
|
|
11
|
+
aware.value(guest);
|
|
12
|
+
|
|
13
|
+
expect(guest).toBeCalledWith(111);
|
|
14
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { give, GuestType } from "../Guest/Guest";
|
|
2
|
+
|
|
3
|
+
export type SourceExecutorType<T> = (guest: GuestType<T>) => unknown;
|
|
4
|
+
|
|
5
|
+
export interface SourceObjectType<T> {
|
|
6
|
+
value: SourceExecutorType<T>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type SourceType<T = any> = SourceExecutorType<T> | SourceObjectType<T>;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @url https://kosukhin.github.io/patron.site/#/utils/value
|
|
13
|
+
*/
|
|
14
|
+
export function value<T>(source: SourceType<T>, guest: GuestType<T>) {
|
|
15
|
+
if (source === undefined) {
|
|
16
|
+
throw new Error("value didnt receive source argument");
|
|
17
|
+
}
|
|
18
|
+
if (guest === undefined) {
|
|
19
|
+
throw new Error("value didnt receive guest argument");
|
|
20
|
+
}
|
|
21
|
+
if (typeof source === "function") {
|
|
22
|
+
return source(guest);
|
|
23
|
+
} else {
|
|
24
|
+
return source.value(guest);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @url https://kosukhin.github.io/patron.site/#/utils/is-source
|
|
30
|
+
*/
|
|
31
|
+
export function isSource(mbSource: any): mbSource is SourceType {
|
|
32
|
+
if (mbSource === undefined) {
|
|
33
|
+
throw new Error("isSource didnt receive mbSource argument");
|
|
34
|
+
}
|
|
35
|
+
return (
|
|
36
|
+
typeof mbSource === "function" || typeof mbSource?.value === "function"
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @url https://kosukhin.github.io/patron.site/#/guest/source
|
|
42
|
+
*/
|
|
43
|
+
export class Source<T = any> implements SourceObjectType<T> {
|
|
44
|
+
public constructor(private source: SourceType<T>) {
|
|
45
|
+
if (source === undefined) {
|
|
46
|
+
throw new Error("Source constructor didnt receive executor function");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
public value(guest: GuestType<T>): GuestType<T> {
|
|
51
|
+
value(this.source, guest);
|
|
52
|
+
return guest;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @url https://kosukhin.github.io/patron.site/#/utils/source-of
|
|
58
|
+
*/
|
|
59
|
+
export const sourceOf = <T>(value: T) => new Source<T>((g) => give(value, g));
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { SourceActive } from "./SourceActive";
|
|
2
|
+
import { expect, test, vitest } from "vitest";
|
|
3
|
+
|
|
4
|
+
test("SourceActive.test", () => {
|
|
5
|
+
const active = new SourceActive<number, number>((config, source) => {
|
|
6
|
+
source.give(config * 3);
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
const guest = vitest.fn();
|
|
10
|
+
active.do(4).value(guest);
|
|
11
|
+
|
|
12
|
+
expect(guest).toBeCalledWith(12);
|
|
13
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { GuestType } from "../Guest/Guest";
|
|
2
|
+
import { SourceObjectType } from "./Source";
|
|
3
|
+
import { SourceWithPool, SourceWithPoolType } from "./SourceWithPool";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @url https://kosukhin.github.io/patron.site/#/utils/action-type
|
|
7
|
+
*/
|
|
8
|
+
export interface ActionType<P = any> {
|
|
9
|
+
do(config: P): this;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface SourceAcitveType<R = unknown, T = unknown>
|
|
13
|
+
extends SourceObjectType<T>,
|
|
14
|
+
ActionType<R> {}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @url https://kosukhin.github.io/patron.site/#/guest/source-active
|
|
18
|
+
*/
|
|
19
|
+
export class SourceActive<R, T> implements SourceAcitveType<R, T> {
|
|
20
|
+
private source = new SourceWithPool<T>();
|
|
21
|
+
|
|
22
|
+
public constructor(
|
|
23
|
+
private configExecutor: (config: R, source: SourceWithPoolType<T>) => void,
|
|
24
|
+
) {
|
|
25
|
+
if (configExecutor === undefined) {
|
|
26
|
+
throw new Error(
|
|
27
|
+
"SourceActive constructor didnt receive executor function",
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public do(config: R): this {
|
|
33
|
+
this.configExecutor(config, this.source);
|
|
34
|
+
return this;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public value(guest: GuestType<T>): this {
|
|
38
|
+
this.source.value(guest);
|
|
39
|
+
return this;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { expect, test, vitest } from "vitest";
|
|
2
|
+
import { SourceAll } from "./SourceAll";
|
|
3
|
+
import { SourceWithPool } from "./SourceWithPool";
|
|
4
|
+
import { Patron } from "../Patron/Patron";
|
|
5
|
+
|
|
6
|
+
test("SourceAll._asArray.test", () => {
|
|
7
|
+
const one = new SourceWithPool(1);
|
|
8
|
+
const two = new SourceWithPool(2);
|
|
9
|
+
const all = new SourceAll<[number, number]>();
|
|
10
|
+
|
|
11
|
+
one.value(new Patron(all.guestKey("0")));
|
|
12
|
+
two.value(new Patron(all.guestKey("1")));
|
|
13
|
+
|
|
14
|
+
const guest = vitest.fn();
|
|
15
|
+
all.valueArray(
|
|
16
|
+
new Patron((value) => {
|
|
17
|
+
guest(JSON.stringify(value));
|
|
18
|
+
}),
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
expect(guest).toBeCalledWith("[1,2]");
|
|
22
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { expect, test, vitest } from "vitest";
|
|
2
|
+
import { SourceWithPool } from "./SourceWithPool";
|
|
3
|
+
import { SourceAll } from "./SourceAll";
|
|
4
|
+
|
|
5
|
+
test("SourceAll._twoValuesAfter.test", () => {
|
|
6
|
+
const one = new SourceWithPool(1);
|
|
7
|
+
const two = new SourceWithPool(2);
|
|
8
|
+
const all = new SourceAll<{ one: number; two: number }>(["one", "two"]);
|
|
9
|
+
|
|
10
|
+
const g = vitest.fn();
|
|
11
|
+
all.value((value) => {
|
|
12
|
+
g(Object.values(value).join());
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
one.value(all.guestKey("one"));
|
|
16
|
+
two.value(all.guestKey("two"));
|
|
17
|
+
|
|
18
|
+
expect(g).toBeCalledWith("1,2");
|
|
19
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { expect, test, vitest } from "vitest";
|
|
2
|
+
import { SourceWithPool } from "./SourceWithPool";
|
|
3
|
+
import { SourceAll } from "./SourceAll";
|
|
4
|
+
|
|
5
|
+
test("SourceAll._twoValuesBefore.test", () => {
|
|
6
|
+
const one = new SourceWithPool(1);
|
|
7
|
+
const two = new SourceWithPool(2);
|
|
8
|
+
const all = new SourceAll<{ one: number; two: number }>();
|
|
9
|
+
|
|
10
|
+
one.value(all.guestKey("one"));
|
|
11
|
+
two.value(all.guestKey("two"));
|
|
12
|
+
|
|
13
|
+
const g = vitest.fn();
|
|
14
|
+
all.value((value) => {
|
|
15
|
+
g(Object.values(value).join());
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
expect(g).toBeCalledWith("1,2");
|
|
19
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { expect, test, vitest } from "vitest";
|
|
2
|
+
import { SourceAll } from "./SourceAll";
|
|
3
|
+
import { SourceWithPool } from "./SourceWithPool";
|
|
4
|
+
import { Patron } from "../Patron/Patron";
|
|
5
|
+
|
|
6
|
+
test("SourceAll._withPatron.test", () => {
|
|
7
|
+
const one = new SourceWithPool(1);
|
|
8
|
+
const two = new SourceWithPool(2);
|
|
9
|
+
const all = new SourceAll<{ one: number; two: number }>();
|
|
10
|
+
|
|
11
|
+
one.value(new Patron(all.guestKey("one")));
|
|
12
|
+
two.value(new Patron(all.guestKey("two")));
|
|
13
|
+
|
|
14
|
+
one.give(3);
|
|
15
|
+
one.give(4);
|
|
16
|
+
|
|
17
|
+
const g = vitest.fn();
|
|
18
|
+
all.value(
|
|
19
|
+
new Patron((value: Record<string, unknown>) => {
|
|
20
|
+
g(Object.values(value).length);
|
|
21
|
+
}),
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
expect(g).toBeCalledWith(2);
|
|
25
|
+
});
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { SourceObjectType } from "./Source";
|
|
2
|
+
import { SourceWithPool } from "./SourceWithPool";
|
|
3
|
+
import { Guest, GuestObjectType, GuestType } from "../Guest/Guest";
|
|
4
|
+
import { GuestCast } from "../Guest/GuestCast";
|
|
5
|
+
import { GuestObject } from "../Guest/GuestObject";
|
|
6
|
+
import { GuestPool } from "../Guest/GuestPool";
|
|
7
|
+
|
|
8
|
+
export interface SourceAllType<T = any> extends SourceObjectType<T> {
|
|
9
|
+
valueArray(guest: GuestObjectType<T>): this;
|
|
10
|
+
guestKey<R>(key: string): GuestObjectType<R>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @url https://kosukhin.github.io/patron.site/#/guest/source-all
|
|
15
|
+
*/
|
|
16
|
+
export class SourceAll<T> implements SourceAllType<T> {
|
|
17
|
+
private theAll: SourceWithPool<Record<string, unknown>>;
|
|
18
|
+
|
|
19
|
+
private keysKnown: Set<string>;
|
|
20
|
+
|
|
21
|
+
private keysFilled = new Set();
|
|
22
|
+
|
|
23
|
+
private filledAllPool = new GuestPool(this);
|
|
24
|
+
|
|
25
|
+
public constructor(initialKnownKeys: string[] = []) {
|
|
26
|
+
this.theAll = new SourceWithPool<Record<string, unknown>>({});
|
|
27
|
+
this.keysKnown = new Set(initialKnownKeys);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public valueArray(guest: GuestType<T>) {
|
|
31
|
+
const guestObject = new GuestObject(guest);
|
|
32
|
+
this.filledAllPool.add(
|
|
33
|
+
new GuestCast(guestObject, (value: Record<string, unknown>) => {
|
|
34
|
+
guestObject.give(Object.values(value) as T);
|
|
35
|
+
}),
|
|
36
|
+
);
|
|
37
|
+
if (this.isAllFilled()) {
|
|
38
|
+
this.theAll.value(
|
|
39
|
+
new Guest((all: Record<string, unknown>) => {
|
|
40
|
+
this.filledAllPool.give(Object.values(all));
|
|
41
|
+
}),
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
return this;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public value(guest: GuestType<T>) {
|
|
48
|
+
const guestObject = new GuestObject(guest);
|
|
49
|
+
if (this.isAllFilled()) {
|
|
50
|
+
this.filledAllPool.add(guestObject);
|
|
51
|
+
this.theAll.value(
|
|
52
|
+
new Guest((all) => {
|
|
53
|
+
this.filledAllPool.give(all);
|
|
54
|
+
}),
|
|
55
|
+
);
|
|
56
|
+
} else {
|
|
57
|
+
this.filledAllPool.add(guestObject);
|
|
58
|
+
}
|
|
59
|
+
return this;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public guestKey<R>(key: string): GuestObjectType<R> {
|
|
63
|
+
this.keysKnown.add(key);
|
|
64
|
+
return new Guest((value) => {
|
|
65
|
+
this.theAll.value(
|
|
66
|
+
new Guest((all: Record<string, unknown>) => {
|
|
67
|
+
this.keysFilled.add(key);
|
|
68
|
+
const lastAll = {
|
|
69
|
+
...all,
|
|
70
|
+
[key]: value,
|
|
71
|
+
};
|
|
72
|
+
this.theAll.give(lastAll);
|
|
73
|
+
if (this.isAllFilled()) {
|
|
74
|
+
this.filledAllPool.give(lastAll);
|
|
75
|
+
}
|
|
76
|
+
}),
|
|
77
|
+
);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private isAllFilled() {
|
|
82
|
+
return (
|
|
83
|
+
this.keysFilled.size > 0 && this.keysFilled.size === this.keysKnown.size
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { GuestSync } from "../Guest/GuestSync";
|
|
2
|
+
import { SourceApplied } from "../Source/SourceApplied";
|
|
3
|
+
import { SourceWithPool } from "../Source/SourceWithPool";
|
|
4
|
+
import { expect, test } from "vitest";
|
|
5
|
+
|
|
6
|
+
test("SourceApplied.test", () => {
|
|
7
|
+
const source = new SourceWithPool(1);
|
|
8
|
+
const sourceDouble = new SourceApplied(source, (x) => x * 2);
|
|
9
|
+
const guest = new GuestSync(0);
|
|
10
|
+
|
|
11
|
+
sourceDouble.value(guest);
|
|
12
|
+
|
|
13
|
+
expect(guest.value()).toBe(2);
|
|
14
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { give, GuestType } from "../Guest/Guest";
|
|
2
|
+
import { GuestCast } from "../Guest/GuestCast";
|
|
3
|
+
import { SourceObjectType, SourceType, value } from "../Source/Source";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @url https://kosukhin.github.io/patron.site/#/source/source-applied
|
|
7
|
+
*/
|
|
8
|
+
export class SourceApplied<T, R> implements SourceObjectType<R> {
|
|
9
|
+
public constructor(
|
|
10
|
+
private baseSource: SourceType<T>,
|
|
11
|
+
private applier: (v: T) => R,
|
|
12
|
+
) {}
|
|
13
|
+
|
|
14
|
+
public value(g: GuestType<R>) {
|
|
15
|
+
value(
|
|
16
|
+
this.baseSource,
|
|
17
|
+
new GuestCast(g, (v) => {
|
|
18
|
+
give(this.applier(v), g);
|
|
19
|
+
}),
|
|
20
|
+
);
|
|
21
|
+
return this;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { SourceDynamic } from "./SourceDynamic";
|
|
2
|
+
import { SourceWithPool } from "./SourceWithPool";
|
|
3
|
+
import { expect, test, vitest } from "vitest";
|
|
4
|
+
|
|
5
|
+
test("SourceDynamic.ofSource.test", () => {
|
|
6
|
+
const source = new SourceWithPool(1);
|
|
7
|
+
const sourceDynamic = new SourceDynamic(source, source);
|
|
8
|
+
|
|
9
|
+
const g1 = vitest.fn();
|
|
10
|
+
sourceDynamic.value(g1);
|
|
11
|
+
expect(g1).toBeCalledWith(1);
|
|
12
|
+
|
|
13
|
+
sourceDynamic.give(2);
|
|
14
|
+
|
|
15
|
+
const g2 = vitest.fn();
|
|
16
|
+
sourceDynamic.value(g2);
|
|
17
|
+
expect(g2).toBeCalledWith(2);
|
|
18
|
+
const g3 = vitest.fn();
|
|
19
|
+
source.value(g3);
|
|
20
|
+
expect(g3).toBeCalledWith(2);
|
|
21
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { SourceDynamic } from "./SourceDynamic";
|
|
2
|
+
import { expect, test, vitest } from "vitest";
|
|
3
|
+
import { give, Guest } from "../Guest/Guest";
|
|
4
|
+
import { Source } from "./Source";
|
|
5
|
+
|
|
6
|
+
test("SourceDynamic", () => {
|
|
7
|
+
let theValue = 1;
|
|
8
|
+
const sourceDynamic = new SourceDynamic(
|
|
9
|
+
new Guest((value: number) => {
|
|
10
|
+
theValue = value;
|
|
11
|
+
}),
|
|
12
|
+
new Source((guest) => {
|
|
13
|
+
give(theValue, guest);
|
|
14
|
+
}),
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
const g1 = vitest.fn();
|
|
18
|
+
sourceDynamic.value(g1);
|
|
19
|
+
expect(g1).toBeCalledWith(1);
|
|
20
|
+
|
|
21
|
+
sourceDynamic.give(2);
|
|
22
|
+
|
|
23
|
+
const g2 = vitest.fn();
|
|
24
|
+
sourceDynamic.value(g2);
|
|
25
|
+
expect(g2).toBeCalledWith(2);
|
|
26
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { give, GuestType } from "../Guest/Guest";
|
|
2
|
+
import { SourceType, value } from "./Source";
|
|
3
|
+
import { PatronPool } from "../Patron/PatronPool";
|
|
4
|
+
import { SourceWithPoolType } from "./SourceWithPool";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @url https://kosukhin.github.io/patron.site/#/source-dynamic
|
|
8
|
+
*/
|
|
9
|
+
export class SourceDynamic<T = unknown> implements SourceWithPoolType<T> {
|
|
10
|
+
public constructor(
|
|
11
|
+
private baseGuest: GuestType<T>,
|
|
12
|
+
private baseSource: SourceType<T>,
|
|
13
|
+
) {
|
|
14
|
+
if (baseGuest === undefined) {
|
|
15
|
+
throw new Error("SourceDynamic didnt receive baseGuest argument");
|
|
16
|
+
}
|
|
17
|
+
if (baseSource === undefined) {
|
|
18
|
+
throw new Error("SourceDynamic didnt receive baseSource argument");
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public value(guest: GuestType<T>) {
|
|
23
|
+
value(this.baseSource, guest);
|
|
24
|
+
return this;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public give(value: T) {
|
|
28
|
+
give(value, this.baseGuest);
|
|
29
|
+
return this;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public pool(): PatronPool<T> {
|
|
33
|
+
throw Error("No pool in SourceDynamic");
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { SourceExecutorApplied } from "../Source/SourceExecutorApplied";
|
|
2
|
+
import { SourceWithPool } from "../Source/SourceWithPool";
|
|
3
|
+
import { debounce } from "../../test-utils/debounce";
|
|
4
|
+
import { expect, test, vi } from "vitest";
|
|
5
|
+
import { Patron } from "../Patron/Patron";
|
|
6
|
+
|
|
7
|
+
test("SourceExecutorApplied.test", () => {
|
|
8
|
+
vi.useFakeTimers({ shouldAdvanceTime: true });
|
|
9
|
+
|
|
10
|
+
const source = new SourceWithPool<number>();
|
|
11
|
+
const sourceDebounced = new SourceExecutorApplied(
|
|
12
|
+
source,
|
|
13
|
+
debounce.bind(null, 100),
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
let counter = 0;
|
|
17
|
+
sourceDebounced.value(
|
|
18
|
+
new Patron((v) => {
|
|
19
|
+
counter += v;
|
|
20
|
+
}),
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
source.give(1);
|
|
24
|
+
source.give(1);
|
|
25
|
+
source.give(1);
|
|
26
|
+
|
|
27
|
+
vi.runOnlyPendingTimers();
|
|
28
|
+
|
|
29
|
+
expect(counter).toBe(1);
|
|
30
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SourceExecutorType,
|
|
3
|
+
SourceObjectType,
|
|
4
|
+
SourceType,
|
|
5
|
+
value,
|
|
6
|
+
} from "../Source/Source";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @url https://kosukhin.github.io/patron.site/#/source/source-executor-applied
|
|
10
|
+
*/
|
|
11
|
+
export class SourceExecutorApplied<T> implements SourceObjectType<T> {
|
|
12
|
+
public value: SourceExecutorType<T>;
|
|
13
|
+
|
|
14
|
+
public constructor(
|
|
15
|
+
source: SourceType<T>,
|
|
16
|
+
applier: (executor: SourceExecutorType<T>) => SourceExecutorType<T>,
|
|
17
|
+
) {
|
|
18
|
+
this.value = applier((g) => {
|
|
19
|
+
value(source, g);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { wait } from "../../test-utils/wait";
|
|
2
|
+
import { Private } from "../Private/Private";
|
|
3
|
+
import { afterEach, beforeEach, expect, test, vi } from "vitest";
|
|
4
|
+
import { SourceWithPool } from "./SourceWithPool";
|
|
5
|
+
import { give, GuestType } from "../Guest/Guest";
|
|
6
|
+
import { Source, SourceType, value } from "./Source";
|
|
7
|
+
import { SourceMap } from "./SourceMap";
|
|
8
|
+
import { GuestCast } from "../Guest/GuestCast";
|
|
9
|
+
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
vi.useFakeTimers({ shouldAdvanceTime: true });
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
afterEach(() => {
|
|
15
|
+
vi.runOnlyPendingTimers();
|
|
16
|
+
vi.useRealTimers();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
function x2(baseNumber: SourceType<number>) {
|
|
20
|
+
return (guest: GuestType<number>) => {
|
|
21
|
+
value(
|
|
22
|
+
baseNumber,
|
|
23
|
+
new GuestCast(guest, (v) => {
|
|
24
|
+
give(v * 2, guest);
|
|
25
|
+
}),
|
|
26
|
+
);
|
|
27
|
+
return guest;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
test("SourceMap.defered.test", async () => {
|
|
32
|
+
const sourceOf = (val: number) =>
|
|
33
|
+
new Source(async (guest) => {
|
|
34
|
+
await wait(5);
|
|
35
|
+
give(val, guest);
|
|
36
|
+
});
|
|
37
|
+
const source = new SourceWithPool([1, 2, 3, 9].map(sourceOf));
|
|
38
|
+
const guestMapped = new SourceMap(source, new Private(x2));
|
|
39
|
+
const callFn = vi.fn();
|
|
40
|
+
guestMapped.value((v) => {
|
|
41
|
+
callFn(v.join());
|
|
42
|
+
});
|
|
43
|
+
await wait(50);
|
|
44
|
+
expect(callFn).toBeCalled();
|
|
45
|
+
expect(callFn).toBeCalledWith("2,4,6,18");
|
|
46
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Private } from "../Private/Private";
|
|
2
|
+
import { expect, test, vitest } from "vitest";
|
|
3
|
+
import { SourceWithPool } from "./SourceWithPool";
|
|
4
|
+
import { give, GuestType } from "../Guest/Guest";
|
|
5
|
+
import { SourceType, value } from "./Source";
|
|
6
|
+
import { SourceMap } from "./SourceMap";
|
|
7
|
+
import { GuestCast } from "../Guest/GuestCast";
|
|
8
|
+
|
|
9
|
+
function x2(baseNumber: SourceType<number>) {
|
|
10
|
+
return (guest: GuestType<number>) => {
|
|
11
|
+
value(
|
|
12
|
+
baseNumber,
|
|
13
|
+
new GuestCast(<GuestType>guest, (v) => {
|
|
14
|
+
give(v * 2, guest);
|
|
15
|
+
}),
|
|
16
|
+
);
|
|
17
|
+
return guest;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
test("SourceMap.test", () => {
|
|
22
|
+
const source = new SourceWithPool([1, 2, 3, 9]);
|
|
23
|
+
const guestMapped = new SourceMap(source, new Private(x2));
|
|
24
|
+
const g = vitest.fn();
|
|
25
|
+
guestMapped.value(g);
|
|
26
|
+
expect(g).toBeCalledWith([2, 4, 6, 18]);
|
|
27
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { expect, test } from "vitest";
|
|
2
|
+
import { give, GuestType } from "../Guest/Guest";
|
|
3
|
+
import { SourceObjectType, SourceType, value } from "./Source";
|
|
4
|
+
import { SourceMap } from "./SourceMap";
|
|
5
|
+
import { GuestCast } from "../Guest/GuestCast";
|
|
6
|
+
import { SourceWithPool } from "./SourceWithPool";
|
|
7
|
+
import { PrivateClass } from "../Private/PrivateClass";
|
|
8
|
+
import { GuestSync } from "../Guest/GuestSync";
|
|
9
|
+
|
|
10
|
+
class X2 implements SourceObjectType<number> {
|
|
11
|
+
public constructor(private baseNumber: SourceType<number>) {}
|
|
12
|
+
|
|
13
|
+
public value(guest: GuestType<number>) {
|
|
14
|
+
value(
|
|
15
|
+
this.baseNumber,
|
|
16
|
+
new GuestCast(<GuestType>guest, (v) => {
|
|
17
|
+
give(v * 2, guest);
|
|
18
|
+
}),
|
|
19
|
+
);
|
|
20
|
+
return this;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
test("SourceMap.test", () => {
|
|
25
|
+
const source = new SourceWithPool([1, 2, 3, 9]);
|
|
26
|
+
const guestMapped = new SourceMap(source, new PrivateClass(X2));
|
|
27
|
+
const guest = new GuestSync([]);
|
|
28
|
+
|
|
29
|
+
guestMapped.value(guest);
|
|
30
|
+
|
|
31
|
+
expect(guest.value().join()).toBe("2,4,6,18");
|
|
32
|
+
});
|