From 3095e01422c4c8e6ad4c09acca520530691b3369 Mon Sep 17 00:00:00 2001 From: Tomoe <4.artem.0@gmail.com> Date: Wed, 26 Mar 2025 22:33:35 +0300 Subject: [PATCH 01/12] feat(store): type tests for store.set() --- .../branch/branch-from-memory.store.ts | 8 ++ .../branch/branch-from-storage.store.ts | 22 +++++ .../store/_common/branch/branch.entity.ts | 6 ++ .../_common/leaf/leaf-from-memory.store.ts | 6 ++ .../_common/leaf/leaf-from-storage.store.ts | 20 ++++ test/types/store/_common/leaf/leaf.entity.ts | 3 + .../singleton/singleton-from-memory.store.ts | 7 ++ .../singleton/singleton-from-storage.store.ts | 16 ++++ .../_common/singleton/singleton.entity.ts | 9 ++ .../_common/wood/wood-from-memory.store.ts | 8 ++ .../_common/wood/wood-from-storage.store.ts | 22 +++++ test/types/store/_common/wood/wood.entity.ts | 6 ++ test/types/store/set.ts | 96 +++++++++++++++++++ 13 files changed, 229 insertions(+) create mode 100644 test/types/store/_common/branch/branch-from-memory.store.ts create mode 100644 test/types/store/_common/branch/branch-from-storage.store.ts create mode 100644 test/types/store/_common/branch/branch.entity.ts create mode 100644 test/types/store/_common/leaf/leaf-from-memory.store.ts create mode 100644 test/types/store/_common/leaf/leaf-from-storage.store.ts create mode 100644 test/types/store/_common/leaf/leaf.entity.ts create mode 100644 test/types/store/_common/singleton/singleton-from-memory.store.ts create mode 100644 test/types/store/_common/singleton/singleton-from-storage.store.ts create mode 100644 test/types/store/_common/singleton/singleton.entity.ts create mode 100644 test/types/store/_common/wood/wood-from-memory.store.ts create mode 100644 test/types/store/_common/wood/wood-from-storage.store.ts create mode 100644 test/types/store/_common/wood/wood.entity.ts create mode 100644 test/types/store/set.ts diff --git a/test/types/store/_common/branch/branch-from-memory.store.ts b/test/types/store/_common/branch/branch-from-memory.store.ts new file mode 100644 index 00000000..ae609b38 --- /dev/null +++ b/test/types/store/_common/branch/branch-from-memory.store.ts @@ -0,0 +1,8 @@ +import { LeafFromMemory } from "../leaf/leaf-from-memory.store"; +import { IBranch } from "./branch.entity"; +import { Model } from "/types"; + +export const BranchFromMemory: Model = { + id: true, + leaf: LeafFromMemory, +} \ No newline at end of file diff --git a/test/types/store/_common/branch/branch-from-storage.store.ts b/test/types/store/_common/branch/branch-from-storage.store.ts new file mode 100644 index 00000000..febdd276 --- /dev/null +++ b/test/types/store/_common/branch/branch-from-storage.store.ts @@ -0,0 +1,22 @@ +import { LeafFromStorage } from "../leaf/leaf-from-storage.store"; +import { IBranch } from "./branch.entity"; +import { Model, ModelIdentifier, store } from "/types"; + +const storage = new Map() + +export const BranchFromStorage: Model = { + id: true, + leaf: LeafFromStorage, + [store.connect]: { + get: async (id) => storage.get(id), + set: async (id, values) => { + if (values) { + if (typeof id !== "string") throw new TypeError() + return storage.set(id, { ...values, id}).get(id) + } else { + storage.delete(id) + return undefined + } + }, + } +} \ No newline at end of file diff --git a/test/types/store/_common/branch/branch.entity.ts b/test/types/store/_common/branch/branch.entity.ts new file mode 100644 index 00000000..a63aeb90 --- /dev/null +++ b/test/types/store/_common/branch/branch.entity.ts @@ -0,0 +1,6 @@ +import { ILeaf } from "../leaf/leaf.entity" + +export interface IBranch { + id: string + leaf: ILeaf +} \ No newline at end of file diff --git a/test/types/store/_common/leaf/leaf-from-memory.store.ts b/test/types/store/_common/leaf/leaf-from-memory.store.ts new file mode 100644 index 00000000..2c5b2a3f --- /dev/null +++ b/test/types/store/_common/leaf/leaf-from-memory.store.ts @@ -0,0 +1,6 @@ +import { ILeaf } from "./leaf.entity"; +import { Model } from "/types"; + +export const LeafFromMemory: Model = { + id: true, +} \ No newline at end of file diff --git a/test/types/store/_common/leaf/leaf-from-storage.store.ts b/test/types/store/_common/leaf/leaf-from-storage.store.ts new file mode 100644 index 00000000..6caf9dad --- /dev/null +++ b/test/types/store/_common/leaf/leaf-from-storage.store.ts @@ -0,0 +1,20 @@ +import { ILeaf } from "./leaf.entity"; +import { Model, ModelIdentifier, store } from "/types"; + +const storage = new Map() + +export const LeafFromStorage: Model = { + id: true, + [store.connect]: { + get: async (id) => storage.get(id), + set: async (id, values) => { + if (values) { + if (typeof id !== "string") throw new TypeError() + return storage.set(id, { ...values, id}).get(id) + } else { + storage.delete(id) + return undefined + } + }, + } +} \ No newline at end of file diff --git a/test/types/store/_common/leaf/leaf.entity.ts b/test/types/store/_common/leaf/leaf.entity.ts new file mode 100644 index 00000000..8fed301c --- /dev/null +++ b/test/types/store/_common/leaf/leaf.entity.ts @@ -0,0 +1,3 @@ +export interface ILeaf { + id: string +} \ No newline at end of file diff --git a/test/types/store/_common/singleton/singleton-from-memory.store.ts b/test/types/store/_common/singleton/singleton-from-memory.store.ts new file mode 100644 index 00000000..8c964df1 --- /dev/null +++ b/test/types/store/_common/singleton/singleton-from-memory.store.ts @@ -0,0 +1,7 @@ +import { WoodFromMemory } from "../wood/wood-from-memory.store"; +import { ISingleton } from "./singleton.entity"; +import { Model } from "/types"; + +export const SingletonFromMemory: Model = { + wood: WoodFromMemory +} \ No newline at end of file diff --git a/test/types/store/_common/singleton/singleton-from-storage.store.ts b/test/types/store/_common/singleton/singleton-from-storage.store.ts new file mode 100644 index 00000000..40375287 --- /dev/null +++ b/test/types/store/_common/singleton/singleton-from-storage.store.ts @@ -0,0 +1,16 @@ +import { WoodFromStorage } from "../wood/wood-from-storage.store"; +import { ISingleton } from "./singleton.entity"; +import { Model, store } from "/types"; + +let storage: ISingleton = {} + +export const SingletonFromStorage: Model = { + wood: WoodFromStorage, + [store.connect]: { + get: async () => storage, + set: async (_, values) => { + storage = Object.assign(storage, values) + return storage + }, + } +} \ No newline at end of file diff --git a/test/types/store/_common/singleton/singleton.entity.ts b/test/types/store/_common/singleton/singleton.entity.ts new file mode 100644 index 00000000..da54f459 --- /dev/null +++ b/test/types/store/_common/singleton/singleton.entity.ts @@ -0,0 +1,9 @@ +import { IWood } from "../wood/wood.entity" +import { SingletonFromMemory } from "./singleton-from-memory.store" +import { store } from "/types" + +export interface ISingleton { + wood?: IWood +} + +export const singleton = store.sync(SingletonFromMemory, {}) diff --git a/test/types/store/_common/wood/wood-from-memory.store.ts b/test/types/store/_common/wood/wood-from-memory.store.ts new file mode 100644 index 00000000..5cae4312 --- /dev/null +++ b/test/types/store/_common/wood/wood-from-memory.store.ts @@ -0,0 +1,8 @@ +import { BranchFromMemory } from "../branch/branch-from-memory.store"; +import { IWood } from "./wood.entity"; +import { Model } from "/types"; + +export const WoodFromMemory: Model = { + id: true, + branch: BranchFromMemory, +} \ No newline at end of file diff --git a/test/types/store/_common/wood/wood-from-storage.store.ts b/test/types/store/_common/wood/wood-from-storage.store.ts new file mode 100644 index 00000000..e28937e5 --- /dev/null +++ b/test/types/store/_common/wood/wood-from-storage.store.ts @@ -0,0 +1,22 @@ +import { BranchFromStorage } from "../branch/branch-from-storage.store"; +import { IWood } from "./wood.entity"; +import { Model, ModelIdentifier, store } from "/types"; + +const storage = new Map() + +export const WoodFromStorage: Model = { + id: true, + branch: BranchFromStorage, + [store.connect]: { + get: async (id) => storage.get(id), + set: async (id, values) => { + if (values) { + if (typeof id !== "string") throw new TypeError() + return storage.set(id, { ...values, id}).get(id) + } else { + storage.delete(id) + return undefined + } + }, + } +} \ No newline at end of file diff --git a/test/types/store/_common/wood/wood.entity.ts b/test/types/store/_common/wood/wood.entity.ts new file mode 100644 index 00000000..4c2fd406 --- /dev/null +++ b/test/types/store/_common/wood/wood.entity.ts @@ -0,0 +1,6 @@ +import { IBranch } from "../branch/branch.entity" + +export interface IWood { + id: string + branch: IBranch +} \ No newline at end of file diff --git a/test/types/store/set.ts b/test/types/store/set.ts new file mode 100644 index 00000000..85aff6b6 --- /dev/null +++ b/test/types/store/set.ts @@ -0,0 +1,96 @@ +import { LeafFromMemory } from "./_common/leaf/leaf-from-memory.store" +import { BranchFromMemory } from "./_common/branch/branch-from-memory.store" +import { WoodFromMemory } from "./_common/wood/wood-from-memory.store" +import { SingletonFromMemory } from "./_common/singleton/singleton-from-memory.store" +import { store } from "/types" +import { IWood } from "./_common/wood/wood.entity" +import { ISingleton, singleton } from "./_common/singleton/singleton.entity" + +const leaf = store.sync(LeafFromMemory, { id: "1" }) +const branch = store.sync(BranchFromMemory, { id: "1" }) +const wood = store.sync(WoodFromMemory, { id: "1" }) + +// ##################################################### +// Overload for working with Definition + +let woodInput: Promise +let singletonInput: Promise + +{ + // Create... + + // Create model via Definition + + woodInput = store.set(WoodFromMemory, { branch: branch }) + woodInput = store.set(WoodFromMemory, { branch: "1" }) + + // Create model & nested via Definition + + woodInput = store.set(WoodFromMemory, { branch: { leaf: leaf } }) + singletonInput = store.set(SingletonFromMemory, { wood: { leaf: leaf } }) + + // Update... + + // Update model via Definition + + woodInput = store.set(WoodFromMemory, { id: "1", branch: branch }) + woodInput = store.set(WoodFromMemory, { id: "1", branch: "1" }) + singletonInput = store.set(SingletonFromMemory, { wood: branch }) + singletonInput = store.set(SingletonFromMemory, { wood: "1" }) + + // Update model & nested via Definition + + woodInput = store.set(WoodFromMemory, { id: "1", branch: { id: "1", leaf: leaf } }) + woodInput = store.set(WoodFromMemory, { id: "1", branch: { id: "1", leaf: "1" } }) + singletonInput = store.set(SingletonFromMemory, { wood: { id: "1", leaf: leaf } }) + singletonInput = store.set(SingletonFromMemory, { wood: { id: "1", leaf: "1" } }) + + // Delete... + + /// @ts-expect-error + woodInput = store.set(WoodFromMemory, null) + + singletonInput = store.set(SingletonFromMemory, null) + + // Mixed... + + // Create model and Update nested via Definition + + woodInput = store.set(WoodFromMemory, { branch: { id: "1", leaf: leaf } }) + woodInput = store.set(WoodFromMemory, { branch: { id: "1", leaf: "1" } }) + + // Update model and Create nested via Definition + + woodInput = store.set(WoodFromMemory, { id: "1", branch: { leaf: leaf } }) + woodInput = store.set(WoodFromMemory, { id: "1", branch: { leaf: "1" } }) +} + +// ##################################################### +// Overload for working with instance + +{ + // Create... x + + // Update... + + // Update model via instance + + store.set(wood, { branch: branch }) + store.set(wood, { branch: "1" }) + store.set(singleton, { wood: wood }) + store.set(singleton, { wood: "1" }) + + // Update model & nested via instance + + store.set(wood, { branch: { id: "1", leaf: leaf }}) + store.set(wood, { branch: { id: "1", leaf: "1" }}) + store.set(singleton, { wood: { id: "1", branch: branch }}) + store.set(singleton, { wood: { id: "1", branch: "1" }}) + + // Delete... + + // delete model via instance + + store.set(wood, null) + store.set(singleton, null) // this is a cleansing of the model +} From fefae12759ca6347a0beaf63122bf1e3595bc9e1 Mon Sep 17 00:00:00 2001 From: Tomoe <4.artem.0@gmail.com> Date: Thu, 3 Apr 2025 22:38:43 +0300 Subject: [PATCH 02/12] feat(store): helper entities for type testing --- .../deep-nested-enumerable.entity.ts | 3 ++ .../deep-nested-enumerable.store.ts | 6 ++++ .../enumerable/enumerable.entity.ts | 14 +++++++++ .../.internals/enumerable/enumerable.store.ts | 28 +++++++++++++++++ .../nested-enumerable.entity.ts | 14 +++++++++ .../nested-enumerable.store.ts | 16 ++++++++++ .../.internals/singleton/singleton.entity.ts | 12 +++++++ .../.internals/singleton/singleton.store.ts | 27 ++++++++++++++++ .../branch/branch-from-memory.store.ts | 8 ----- .../branch/branch-from-storage.store.ts | 22 ------------- .../store/_common/branch/branch.entity.ts | 6 ---- .../_common/leaf/leaf-from-memory.store.ts | 6 ---- .../_common/leaf/leaf-from-storage.store.ts | 20 ------------ test/types/store/_common/leaf/leaf.entity.ts | 3 -- .../singleton/singleton-from-memory.store.ts | 7 ----- .../singleton/singleton-from-storage.store.ts | 16 ---------- .../_common/singleton/singleton.entity.ts | 9 ------ .../_common/wood/wood-from-memory.store.ts | 8 ----- .../_common/wood/wood-from-storage.store.ts | 22 ------------- test/types/store/_common/wood/wood.entity.ts | 6 ---- .../store/enumerable-definition.store.ts | 31 ------------------- test/types/store/model-definition.ts | 29 ++++++++--------- .../types/store/singleton-definition.store.ts | 30 ------------------ test/types/store/storage-external.ts | 11 ++++--- 24 files changed, 141 insertions(+), 213 deletions(-) create mode 100644 test/types/store/.internals/deep-nested-enumerable/deep-nested-enumerable.entity.ts create mode 100644 test/types/store/.internals/deep-nested-enumerable/deep-nested-enumerable.store.ts create mode 100644 test/types/store/.internals/enumerable/enumerable.entity.ts create mode 100644 test/types/store/.internals/enumerable/enumerable.store.ts create mode 100644 test/types/store/.internals/nested-enumerable/nested-enumerable.entity.ts create mode 100644 test/types/store/.internals/nested-enumerable/nested-enumerable.store.ts create mode 100644 test/types/store/.internals/singleton/singleton.entity.ts create mode 100644 test/types/store/.internals/singleton/singleton.store.ts delete mode 100644 test/types/store/_common/branch/branch-from-memory.store.ts delete mode 100644 test/types/store/_common/branch/branch-from-storage.store.ts delete mode 100644 test/types/store/_common/branch/branch.entity.ts delete mode 100644 test/types/store/_common/leaf/leaf-from-memory.store.ts delete mode 100644 test/types/store/_common/leaf/leaf-from-storage.store.ts delete mode 100644 test/types/store/_common/leaf/leaf.entity.ts delete mode 100644 test/types/store/_common/singleton/singleton-from-memory.store.ts delete mode 100644 test/types/store/_common/singleton/singleton-from-storage.store.ts delete mode 100644 test/types/store/_common/singleton/singleton.entity.ts delete mode 100644 test/types/store/_common/wood/wood-from-memory.store.ts delete mode 100644 test/types/store/_common/wood/wood-from-storage.store.ts delete mode 100644 test/types/store/_common/wood/wood.entity.ts delete mode 100644 test/types/store/enumerable-definition.store.ts delete mode 100644 test/types/store/singleton-definition.store.ts diff --git a/test/types/store/.internals/deep-nested-enumerable/deep-nested-enumerable.entity.ts b/test/types/store/.internals/deep-nested-enumerable/deep-nested-enumerable.entity.ts new file mode 100644 index 00000000..ddbf6fe3 --- /dev/null +++ b/test/types/store/.internals/deep-nested-enumerable/deep-nested-enumerable.entity.ts @@ -0,0 +1,3 @@ +export interface IDeepNestedEnumerable { + id: string +} \ No newline at end of file diff --git a/test/types/store/.internals/deep-nested-enumerable/deep-nested-enumerable.store.ts b/test/types/store/.internals/deep-nested-enumerable/deep-nested-enumerable.store.ts new file mode 100644 index 00000000..ad267a42 --- /dev/null +++ b/test/types/store/.internals/deep-nested-enumerable/deep-nested-enumerable.store.ts @@ -0,0 +1,6 @@ +import { IDeepNestedEnumerable } from "./deep-nested-enumerable.entity"; +import { Model } from "/types"; + +export const DeepNestedEnumerable: Model = { + id: true, +} \ No newline at end of file diff --git a/test/types/store/.internals/enumerable/enumerable.entity.ts b/test/types/store/.internals/enumerable/enumerable.entity.ts new file mode 100644 index 00000000..30e7117c --- /dev/null +++ b/test/types/store/.internals/enumerable/enumerable.entity.ts @@ -0,0 +1,14 @@ +import { INestedEnumerable } from "../nested-enumerable/nested-enumerable.entity" +import { ISingleton } from "../singleton/singleton.entity"; + +export interface IEnumerable { + id: string; + stringProperty: string; + numberProperty: number; + self: IEnumerable + nestedSingleton: ISingleton; + optionalNestedSingleton?: ISingleton; + nestedEnumerable: INestedEnumerable; + optionalNestedEnumerable?: INestedEnumerable; + nestedEnumerables: INestedEnumerable[]; +} \ No newline at end of file diff --git a/test/types/store/.internals/enumerable/enumerable.store.ts b/test/types/store/.internals/enumerable/enumerable.store.ts new file mode 100644 index 00000000..e20342a3 --- /dev/null +++ b/test/types/store/.internals/enumerable/enumerable.store.ts @@ -0,0 +1,28 @@ +import { NestedEnumerable } from "../nested-enumerable/nested-enumerable.store"; +import { Singleton } from "../singleton/singleton.store"; +import { IEnumerable } from "./enumerable.entity"; +import { Model, store } from "/types"; + +export const Enumerable: Model = { + id: true, + stringProperty: "", + numberProperty: 0, + self: store.ref(() => Enumerable), + nestedSingleton: store.ref(() => Singleton), + optionalNestedSingleton: store.ref(() => Singleton), + nestedEnumerable: store.ref(() => NestedEnumerable), + optionalNestedEnumerable: store.ref(() => NestedEnumerable), + nestedEnumerables: store.ref(() => [NestedEnumerable]), +} + +/// @ts-expect-error +const BrokenEnumerable: Model = { + stringProperty: "", + numberProperty: 0, + self: store.ref(() => Enumerable), + nestedSingleton: store.ref(() => Singleton), + optionalNestedSingleton: store.ref(() => Singleton), + nestedEnumerable: store.ref(() => NestedEnumerable), + optionalNestedEnumerable: store.ref(() => NestedEnumerable), + nestedEnumerables: store.ref(() => [NestedEnumerable]), +}; \ No newline at end of file diff --git a/test/types/store/.internals/nested-enumerable/nested-enumerable.entity.ts b/test/types/store/.internals/nested-enumerable/nested-enumerable.entity.ts new file mode 100644 index 00000000..7ed71d20 --- /dev/null +++ b/test/types/store/.internals/nested-enumerable/nested-enumerable.entity.ts @@ -0,0 +1,14 @@ +import { IDeepNestedEnumerable } from "../deep-nested-enumerable/deep-nested-enumerable.entity" +import { ISingleton } from "../singleton/singleton.entity"; + +export interface INestedEnumerable { + id: string + stringProperty: string; + numberProperty: number; + self: INestedEnumerable + nestedSingleton: ISingleton; + optionalNestedSingleton?: ISingleton; + nestedEnumerable: IDeepNestedEnumerable; + optionalNestedEnumerable?: IDeepNestedEnumerable; + nestedEnumerables: IDeepNestedEnumerable[]; +} \ No newline at end of file diff --git a/test/types/store/.internals/nested-enumerable/nested-enumerable.store.ts b/test/types/store/.internals/nested-enumerable/nested-enumerable.store.ts new file mode 100644 index 00000000..f0184f89 --- /dev/null +++ b/test/types/store/.internals/nested-enumerable/nested-enumerable.store.ts @@ -0,0 +1,16 @@ +import { DeepNestedEnumerable } from "../deep-nested-enumerable/deep-nested-enumerable.store"; +import { Singleton } from "../singleton/singleton.store"; +import { INestedEnumerable } from "./nested-enumerable.entity"; +import { Model, store } from "/types"; + +export const NestedEnumerable: Model = { + id: true, + stringProperty: "", + numberProperty: 0, + self: store.ref(() => NestedEnumerable), + nestedSingleton: store.ref(() => Singleton), + optionalNestedSingleton: store.ref(() => Singleton), + nestedEnumerable: store.ref(() => DeepNestedEnumerable), + optionalNestedEnumerable: store.ref(() => DeepNestedEnumerable), + nestedEnumerables: store.ref(() => [DeepNestedEnumerable]), +} \ No newline at end of file diff --git a/test/types/store/.internals/singleton/singleton.entity.ts b/test/types/store/.internals/singleton/singleton.entity.ts new file mode 100644 index 00000000..66d4b997 --- /dev/null +++ b/test/types/store/.internals/singleton/singleton.entity.ts @@ -0,0 +1,12 @@ +import { INestedEnumerable } from "../nested-enumerable/nested-enumerable.entity"; + +export interface ISingleton { + stringProperty: string; + numberProperty: number; + self: ISingleton + nestedSingleton: ISingleton; + optionalNestedSingleton?: ISingleton; + nestedEnumerable: INestedEnumerable; + optionalNestedEnumerable?: INestedEnumerable; + nestedEnumerables: INestedEnumerable[] +} diff --git a/test/types/store/.internals/singleton/singleton.store.ts b/test/types/store/.internals/singleton/singleton.store.ts new file mode 100644 index 00000000..977749ae --- /dev/null +++ b/test/types/store/.internals/singleton/singleton.store.ts @@ -0,0 +1,27 @@ +import { NestedEnumerable } from "../nested-enumerable/nested-enumerable.store"; +import { ISingleton } from "./singleton.entity"; +import { Model, store } from "/types"; + +export const Singleton: Model = { + stringProperty: "", + numberProperty: 0, + self: store.ref(() => Singleton), + nestedSingleton: store.ref(() => Singleton), + optionalNestedSingleton: store.ref(() => Singleton), + nestedEnumerable: store.ref(() => NestedEnumerable), + optionalNestedEnumerable: store.ref(() => NestedEnumerable), + nestedEnumerables: store.ref(() => [NestedEnumerable]), +} + +const BrokenSingleton: Model = { + /// @ts-expect-error + id: true, + stringProperty: "", + numberProperty: 0, + self: store.ref(() => Singleton), + nestedSingleton: store.ref(() => Singleton), + optionalNestedSingleton: store.ref(() => Singleton), + nestedEnumerable: store.ref(() => NestedEnumerable), + optionalNestedEnumerable: store.ref(() => NestedEnumerable), + nestedEnumerables: store.ref(() => [NestedEnumerable]), +}; \ No newline at end of file diff --git a/test/types/store/_common/branch/branch-from-memory.store.ts b/test/types/store/_common/branch/branch-from-memory.store.ts deleted file mode 100644 index ae609b38..00000000 --- a/test/types/store/_common/branch/branch-from-memory.store.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { LeafFromMemory } from "../leaf/leaf-from-memory.store"; -import { IBranch } from "./branch.entity"; -import { Model } from "/types"; - -export const BranchFromMemory: Model = { - id: true, - leaf: LeafFromMemory, -} \ No newline at end of file diff --git a/test/types/store/_common/branch/branch-from-storage.store.ts b/test/types/store/_common/branch/branch-from-storage.store.ts deleted file mode 100644 index febdd276..00000000 --- a/test/types/store/_common/branch/branch-from-storage.store.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { LeafFromStorage } from "../leaf/leaf-from-storage.store"; -import { IBranch } from "./branch.entity"; -import { Model, ModelIdentifier, store } from "/types"; - -const storage = new Map() - -export const BranchFromStorage: Model = { - id: true, - leaf: LeafFromStorage, - [store.connect]: { - get: async (id) => storage.get(id), - set: async (id, values) => { - if (values) { - if (typeof id !== "string") throw new TypeError() - return storage.set(id, { ...values, id}).get(id) - } else { - storage.delete(id) - return undefined - } - }, - } -} \ No newline at end of file diff --git a/test/types/store/_common/branch/branch.entity.ts b/test/types/store/_common/branch/branch.entity.ts deleted file mode 100644 index a63aeb90..00000000 --- a/test/types/store/_common/branch/branch.entity.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { ILeaf } from "../leaf/leaf.entity" - -export interface IBranch { - id: string - leaf: ILeaf -} \ No newline at end of file diff --git a/test/types/store/_common/leaf/leaf-from-memory.store.ts b/test/types/store/_common/leaf/leaf-from-memory.store.ts deleted file mode 100644 index 2c5b2a3f..00000000 --- a/test/types/store/_common/leaf/leaf-from-memory.store.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { ILeaf } from "./leaf.entity"; -import { Model } from "/types"; - -export const LeafFromMemory: Model = { - id: true, -} \ No newline at end of file diff --git a/test/types/store/_common/leaf/leaf-from-storage.store.ts b/test/types/store/_common/leaf/leaf-from-storage.store.ts deleted file mode 100644 index 6caf9dad..00000000 --- a/test/types/store/_common/leaf/leaf-from-storage.store.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { ILeaf } from "./leaf.entity"; -import { Model, ModelIdentifier, store } from "/types"; - -const storage = new Map() - -export const LeafFromStorage: Model = { - id: true, - [store.connect]: { - get: async (id) => storage.get(id), - set: async (id, values) => { - if (values) { - if (typeof id !== "string") throw new TypeError() - return storage.set(id, { ...values, id}).get(id) - } else { - storage.delete(id) - return undefined - } - }, - } -} \ No newline at end of file diff --git a/test/types/store/_common/leaf/leaf.entity.ts b/test/types/store/_common/leaf/leaf.entity.ts deleted file mode 100644 index 8fed301c..00000000 --- a/test/types/store/_common/leaf/leaf.entity.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface ILeaf { - id: string -} \ No newline at end of file diff --git a/test/types/store/_common/singleton/singleton-from-memory.store.ts b/test/types/store/_common/singleton/singleton-from-memory.store.ts deleted file mode 100644 index 8c964df1..00000000 --- a/test/types/store/_common/singleton/singleton-from-memory.store.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { WoodFromMemory } from "../wood/wood-from-memory.store"; -import { ISingleton } from "./singleton.entity"; -import { Model } from "/types"; - -export const SingletonFromMemory: Model = { - wood: WoodFromMemory -} \ No newline at end of file diff --git a/test/types/store/_common/singleton/singleton-from-storage.store.ts b/test/types/store/_common/singleton/singleton-from-storage.store.ts deleted file mode 100644 index 40375287..00000000 --- a/test/types/store/_common/singleton/singleton-from-storage.store.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { WoodFromStorage } from "../wood/wood-from-storage.store"; -import { ISingleton } from "./singleton.entity"; -import { Model, store } from "/types"; - -let storage: ISingleton = {} - -export const SingletonFromStorage: Model = { - wood: WoodFromStorage, - [store.connect]: { - get: async () => storage, - set: async (_, values) => { - storage = Object.assign(storage, values) - return storage - }, - } -} \ No newline at end of file diff --git a/test/types/store/_common/singleton/singleton.entity.ts b/test/types/store/_common/singleton/singleton.entity.ts deleted file mode 100644 index da54f459..00000000 --- a/test/types/store/_common/singleton/singleton.entity.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { IWood } from "../wood/wood.entity" -import { SingletonFromMemory } from "./singleton-from-memory.store" -import { store } from "/types" - -export interface ISingleton { - wood?: IWood -} - -export const singleton = store.sync(SingletonFromMemory, {}) diff --git a/test/types/store/_common/wood/wood-from-memory.store.ts b/test/types/store/_common/wood/wood-from-memory.store.ts deleted file mode 100644 index 5cae4312..00000000 --- a/test/types/store/_common/wood/wood-from-memory.store.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { BranchFromMemory } from "../branch/branch-from-memory.store"; -import { IWood } from "./wood.entity"; -import { Model } from "/types"; - -export const WoodFromMemory: Model = { - id: true, - branch: BranchFromMemory, -} \ No newline at end of file diff --git a/test/types/store/_common/wood/wood-from-storage.store.ts b/test/types/store/_common/wood/wood-from-storage.store.ts deleted file mode 100644 index e28937e5..00000000 --- a/test/types/store/_common/wood/wood-from-storage.store.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { BranchFromStorage } from "../branch/branch-from-storage.store"; -import { IWood } from "./wood.entity"; -import { Model, ModelIdentifier, store } from "/types"; - -const storage = new Map() - -export const WoodFromStorage: Model = { - id: true, - branch: BranchFromStorage, - [store.connect]: { - get: async (id) => storage.get(id), - set: async (id, values) => { - if (values) { - if (typeof id !== "string") throw new TypeError() - return storage.set(id, { ...values, id}).get(id) - } else { - storage.delete(id) - return undefined - } - }, - } -} \ No newline at end of file diff --git a/test/types/store/_common/wood/wood.entity.ts b/test/types/store/_common/wood/wood.entity.ts deleted file mode 100644 index 4c2fd406..00000000 --- a/test/types/store/_common/wood/wood.entity.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { IBranch } from "../branch/branch.entity" - -export interface IWood { - id: string - branch: IBranch -} \ No newline at end of file diff --git a/test/types/store/enumerable-definition.store.ts b/test/types/store/enumerable-definition.store.ts deleted file mode 100644 index 68aecfab..00000000 --- a/test/types/store/enumerable-definition.store.ts +++ /dev/null @@ -1,31 +0,0 @@ -import SingletonStore, { ISingleton } from "./singleton-definition.store"; -import { Model, store } from "/types/index"; - -export interface IEnumerable { - id: string; - prop: string; - length: number; - relatedSingleton?: ISingleton; - relatedEnumerable?: IEnumerable; - relatedEnumerables: IEnumerable[]; -} - -const EnumerableStore: Model = { - id: true, - prop: "", - length: 0, - relatedSingleton: store.ref(() => SingletonStore), - relatedEnumerable: store.ref(() => EnumerableStore), - relatedEnumerables: store.ref(() => [EnumerableStore]), -}; - -export default EnumerableStore; - -/// @ts-expect-error -const BrokenEnumerableStore: Model = { - prop: "", - length: 0, - relatedSingleton: store.ref(() => SingletonStore), - relatedEnumerable: store.ref(() => EnumerableStore), - relatedEnumerables: store.ref(() => [EnumerableStore]), -}; diff --git a/test/types/store/model-definition.ts b/test/types/store/model-definition.ts index 5e6e1498..99d180df 100644 --- a/test/types/store/model-definition.ts +++ b/test/types/store/model-definition.ts @@ -1,6 +1,7 @@ +import { IEnumerable } from "./.internals/enumerable/enumerable.entity"; +import { ISingleton } from "./.internals/singleton/singleton.entity"; +import { Singleton } from "./.internals/singleton/singleton.store"; import { Model } from "/types/index"; -import SingletonStore, { ISingleton } from "./singleton-definition.store"; -import EnumerableStore, { IEnumerable } from "./enumerable-definition.store"; interface ISomeObject { prop: string; @@ -357,40 +358,40 @@ const ModelStore: Model = { // Singleton Model - singletonModel: SingletonStore, - optionalSingletonModel: SingletonStore, + singletonModel: Singleton, + optionalSingletonModel: Singleton, /// @ts-expect-error undefinedOptionalSingletonModel: undefined, - calculatedSingletonModel: () => SingletonStore, + calculatedSingletonModel: () => Singleton, /// @ts-expect-error undefinedCalculatedSingletonModel: () => undefined, - calculatedOptionalSingletonModel: () => SingletonStore, + calculatedOptionalSingletonModel: () => Singleton, undefinedCalculatedOptionalSingletonModel: () => - condition ? undefined : SingletonStore, + condition ? undefined : Singleton, // Singleton Model List /// @ts-expect-error - singletonModelList: [SingletonStore], + singletonModelList: [Singleton], /// @ts-expect-error - looseSingletonModelList: [SingletonStore, { loose: true }], + looseSingletonModelList: [Singleton, { loose: true }], /// @ts-expect-error - optionalSingletonModelList: [SingletonStore], + optionalSingletonModelList: [Singleton], /// @ts-expect-error undefinedOptionalSingletonModelList: undefined, /// @ts-expect-error - calculatedSingletonModelList: () => [SingletonStore], + calculatedSingletonModelList: () => [Singleton], /// @ts-expect-error undefinedCalculatedSingletonModelList: () => undefined, /// @ts-expect-error - looseCalculatedSingletonModelList: () => [SingletonStore, { loose: true }], + looseCalculatedSingletonModelList: () => [Singleton, { loose: true }], /// @ts-expect-error - calculatedOptionalSingletonModelList: () => [SingletonStore], + calculatedOptionalSingletonModelList: () => [Singleton], /// @ts-expect-error undefinedCalculatedOptionalSingletonModelList: () => - condition ? undefined : [SingletonStore], + condition ? undefined : [Singleton], }; export default ModelStore; diff --git a/test/types/store/singleton-definition.store.ts b/test/types/store/singleton-definition.store.ts deleted file mode 100644 index d9c6283f..00000000 --- a/test/types/store/singleton-definition.store.ts +++ /dev/null @@ -1,30 +0,0 @@ -import EnumerableStore, { IEnumerable } from "./enumerable-definition.store"; -import { Model, store } from "/types/index"; - -export interface ISingleton { - prop: string; - length: number; - relatedSingleton?: ISingleton; - relatedEnumerable?: IEnumerable; - relatedEnumerables: IEnumerable[]; -} - -const SingletonStore: Model = { - prop: "", - length: 0, - relatedSingleton: store.ref(() => SingletonStore), - relatedEnumerable: store.ref(() => EnumerableStore), - relatedEnumerables: store.ref(() => [EnumerableStore]), -}; - -export default SingletonStore; - -const BrokenSingletonStore: Model = { - /// @ts-expect-error - id: true, - prop: "", - length: 0, - relatedSingleton: store.ref(() => SingletonStore), - relatedEnumerable: store.ref(() => EnumerableStore), - relatedEnumerables: store.ref(() => [EnumerableStore]), -}; diff --git a/test/types/store/storage-external.ts b/test/types/store/storage-external.ts index f295c3dd..6dabeac4 100644 --- a/test/types/store/storage-external.ts +++ b/test/types/store/storage-external.ts @@ -1,17 +1,18 @@ +import { IEnumerable } from "./.internals/enumerable/enumerable.entity"; +import { Enumerable } from "./.internals/enumerable/enumerable.store"; import { Model, ModelIdentifier, StorageValues, store } from "/types/index"; -import EnumerableStore, { IEnumerable } from "./enumerable-definition.store"; const EnumerableModelsSource = new Map< ModelIdentifier, StorageValues >([ - ["0", { id: "0", prop: "qweqwe", length: 5, relatedEnumerable: "2" }], - ["1", { id: "1", length: 1711014651455, relatedEnumerables: ["1", "2"] }], - ["2", { id: "2", prop: "swswswsws" }], + ["0", { id: "0", stringProperty: "qweqwe", numberProperty: 5, nestedEnumerable: "2" }], + ["1", { id: "1", numberProperty: 1711014651455, nestedEnumerables: ["1", "2"] }], + ["2", { id: "2", stringProperty: "swswswsws" }], ]); const EnumerableModelStore: Model = { - ...EnumerableStore, + ...Enumerable, [store.connect]: { list: (id) => [...Object.values(EnumerableModelsSource)], get: (id) => EnumerableModelsSource.get(id) ?? null, From 7d87fcf2ea484f959d233b77d0cc8a75ff35f21b Mon Sep 17 00:00:00 2001 From: Tomoe <4.artem.0@gmail.com> Date: Thu, 3 Apr 2025 22:42:19 +0300 Subject: [PATCH 03/12] fix(store): type tests for direct set/sync methods --- test/types/store/direct-methods.ts | 94 ---- .../store/direct-methods/set-and-sync.ts | 524 ++++++++++++++++++ test/types/store/set.ts | 96 ---- 3 files changed, 524 insertions(+), 190 deletions(-) create mode 100644 test/types/store/direct-methods/set-and-sync.ts delete mode 100644 test/types/store/set.ts diff --git a/test/types/store/direct-methods.ts b/test/types/store/direct-methods.ts index 5ee13944..db1d1f8b 100644 --- a/test/types/store/direct-methods.ts +++ b/test/types/store/direct-methods.ts @@ -21,97 +21,3 @@ store.get([SingletonStore]); store.get(EnumerableStore); store.get([EnumerableStore]); -// ############################################### Create Singleton ############################################### - -store.set(SingletonStore, { - prop: "qweqwe", -}); - -store.set(SingletonStore, { - relatedEnumerable: {}, - relatedSingleton: {}, - relatedEnumerables: [{}, {}], -}); - -store.set(SingletonStore, { - // an error is expected, but I couldn't type it( - relatedEnumerable: [{}, {}], - // an error is expected, but I couldn't type it( - relatedSingleton: [{}, {}], - /// @ts-expect-error - relatedEnumerables: {}, -}); - -// ############################################### Update Singleton ############################################### - -store.set(SingletonModel, { - prop: "qweqwe", -}); - -store.set(SingletonModel, { - relatedEnumerable: {}, - relatedSingleton: {}, - relatedEnumerables: [{}, {}], -}); - -store.set(SingletonModel, { - // an error is expected, but I couldn't type it( - relatedEnumerable: [{}, {}], - // an error is expected, but I couldn't type it( - relatedSingleton: [{}, {}], - /// @ts-expect-error - relatedEnumerables: {}, -}); - -// ############################################### Delete Singleton ############################################### - -// an error is expected, but when determining overload, the display of errors for incorrect values ​​in Model Update breaks -store.set(SingletonModel, null); -store.set(EnumerableModel, null); - -// ############################################### Create Enumerable ############################################### - -store.set(EnumerableStore, { - prop: "qweqwe", -}); - -store.set(EnumerableStore, { - relatedEnumerable: {}, - relatedSingleton: {}, - relatedEnumerables: [{}, {}], -}); - -store.set(EnumerableStore, { - // an error is expected, but I couldn't type it( - relatedEnumerable: [{}, {}], - // an error is expected, but I couldn't type it( - relatedSingleton: [{}, {}], - /// @ts-expect-error - relatedEnumerables: {}, -}); - -// ############################################### Update Enumerable ############################################### - -store.set(EnumerableModel, { - prop: "qweqwe", -}); - -store.set(EnumerableModel, { - relatedEnumerable: {}, - relatedSingleton: {}, - relatedEnumerables: [{}, {}], -}); - -store.set(EnumerableModel, { - // an error is expected, but I couldn't type it( - relatedEnumerable: [{}, {}], - // an error is expected, but I couldn't type it( - relatedSingleton: [{}, {}], - /// @ts-expect-error - relatedEnumerables: {}, -}); - -// ############################################### Delete Enumerable ############################################### -// an error is expected, but when determining overload, the display of errors for incorrect values ​​in Model Update breaks -store.set(EnumerableStore, null); -store.set(EnumerableModel, null); diff --git a/test/types/store/direct-methods/set-and-sync.ts b/test/types/store/direct-methods/set-and-sync.ts new file mode 100644 index 00000000..94b78f60 --- /dev/null +++ b/test/types/store/direct-methods/set-and-sync.ts @@ -0,0 +1,524 @@ +import { NestedEnumerable } from "../.internals/nested-enumerable/nested-enumerable.store" +import { Enumerable } from "../.internals/enumerable/enumerable.store" +import { Singleton } from "../.internals/singleton/singleton.store" +import { store } from "/types" +import { IEnumerable } from "../.internals/enumerable/enumerable.entity" +import { ISingleton } from "../.internals/singleton/singleton.entity" + +const nestedEnumerable = store.sync(NestedEnumerable, { id: "1" }) +const enumerable = store.sync(Enumerable, { id: "1" }) +const singleton = store.get(Singleton) + +let enumerablePromiseInput: Promise +let singletonPromiseInput: Promise +let enumerableInput: IEnumerable +let singletonInput: ISingleton + +const primitives = { + stringProperty: "qweqwe", + numberProperty: 123456789, +} +const primitivesInCreateNestedModels = { + nestedEnumerable: primitives, + optionalNestedEnumerable: primitives, + nestedSingleton: primitives, + optionalNestedSingleton: primitives, + nestedEnumerables: [primitives, primitives] +} +const primitivesInUpdateNestedModels = { + nestedEnumerable: { id: "1", ...primitives }, + optionalNestedEnumerable: { id: "1", ...primitives }, + nestedSingleton: { ...primitives }, + optionalNestedSingleton: { ...primitives }, + nestedEnumerables: [{ id: "1", ...primitives }, { id: "1", ...primitives }] +} + +const empty = {} +const emptyInCreateNestedModels = { + nestedEnumerable: empty, + optionalNestedEnumerable: empty, + nestedSingleton: empty, + optionalNestedSingleton: empty, + nestedEnumerables: [empty, empty] +} +const emptyInUpdateNestedModels = { + nestedEnumerable: { id: "1", ...empty }, + optionalNestedEnumerable: { id: "1", ...empty }, + nestedSingleton: { ...empty }, + optionalNestedSingleton: { ...empty }, + nestedEnumerables: [{ id: "1", ...empty }, { id: "1", ...empty }] +} + +const refs = { + nestedSingleton: singleton, + optionalNestedSingleton: singleton, + nestedEnumerable: nestedEnumerable, + optionalNestedEnumerable: nestedEnumerable, + nestedEnumerables: [nestedEnumerable, nestedEnumerable], +} +const refsInCreateNestedModels = { + nestedEnumerable: refs, + optionalNestedEnumerable: refs, + nestedSingleton: refs, + optionalNestedSingleton: refs, + nestedEnumerables: [refs, refs] +} +const refsInUpdateNestedModels = { + nestedEnumerable: { id: "1", ...refs }, + optionalNestedEnumerable: { id: "1", ...refs }, + nestedSingleton: { ...refs }, + optionalNestedSingleton: { ...refs }, + nestedEnumerables: [{ id: "1", ...refs }, { id: "1", ...refs }] +} + +const identifiers = { + nestedSingleton: "1", + optionalNestedSingleton: "1", + nestedEnumerable: "1", + optionalNestedEnumerable: "1", + nestedEnumerables: ["1", "2"], +} +const identifiersInCreateNestedModels = { + nestedEnumerable: identifiers, + optionalNestedEnumerable: identifiers, + nestedSingleton: identifiers, + optionalNestedSingleton: identifiers, + nestedEnumerables: [identifiers, identifiers] +} +const identifiersInUpdateNestedModels = { + nestedEnumerable: { id: "1", ...identifiers }, + optionalNestedEnumerable: { id: "1", ...identifiers }, + nestedSingleton: { ...identifiers }, + optionalNestedSingleton: { ...identifiers }, + nestedEnumerables: [{ id: "1", ...identifiers }, { id: "1", ...identifiers }] +} + +const unrefs = { + nestedSingleton: undefined, + optionalNestedSingleton: undefined, + nestedEnumerable: undefined, + optionalNestedEnumerable: undefined, + nestedEnumerables: [], +} +const unrefsInCreateNestedModels = { + nestedEnumerable: unrefs, + optionalNestedEnumerable: unrefs, + nestedSingleton: unrefs, + optionalNestedSingleton: unrefs, + nestedEnumerables: [unrefs, unrefs] +} +const unrefsInUpdateNestedModels = { + nestedEnumerable: { id: "1", ...unrefs }, + optionalNestedEnumerable: { id: "1", ...unrefs }, + nestedSingleton: { ...unrefs }, + optionalNestedSingleton: { ...unrefs }, + nestedEnumerables: [{ id: "1", ...unrefs }, { id: "1", ...unrefs }] +} + +const collisions = { + nestedSingleton: [{}], + optionalNestedSingleton: [{}], + nestedEnumerable: [{}], + optionalNestedEnumerable: [{}], + nestedEnumerables: {}, +} +const collisionsInCreateNestedModels = { + nestedEnumerable: collisions, + optionalNestedEnumerable: collisions, + nestedSingleton: collisions, + optionalNestedSingleton: collisions, + nestedEnumerables: [collisions, collisions] +} +const collisionsInUpdateNestedModels = { + nestedEnumerable: { id: "1", ...collisions }, + optionalNestedEnumerable: { id: "1", ...collisions }, + nestedSingleton: { ...collisions }, + optionalNestedSingleton: { ...collisions }, + nestedEnumerables: [{ id: "1", ...collisions }, { id: "1", ...collisions }] +} + +// Overload via Definition +{ + // Create... + { + // Create model via Definition + { + // ...set primitive propertiers + enumerablePromiseInput = store.set(Enumerable, primitives) + enumerableInput = store.sync(Enumerable, primitives) + + // ...use default values + enumerablePromiseInput = store.set(Enumerable, empty) + enumerableInput = store.sync(Enumerable, empty) + + // ...binding through refs + enumerablePromiseInput = store.set(Enumerable, refs) + enumerableInput = store.sync(Enumerable, refs) + + // ...binding through identifiers + enumerablePromiseInput = store.set(Enumerable, identifiers) + enumerableInput = store.sync(Enumerable, identifiers) + + // ...unbinding + enumerablePromiseInput = store.set(Enumerable, unrefs) + enumerableInput = store.sync(Enumerable, unrefs) + + // ...check collisions + /// @ts-expect-error + store.set(Enumerable, collisions); + /// @ts-expect-error + store.sync(Enumerable, collisions); + } + + // Create model & nested via Definition + { + // ...set primitive propertiers + enumerablePromiseInput = store.set(Enumerable, primitivesInCreateNestedModels) + enumerableInput = store.sync(Enumerable, primitivesInCreateNestedModels) + + // ...use default values + enumerablePromiseInput = store.set(Enumerable, emptyInCreateNestedModels) + enumerableInput = store.sync(Enumerable, emptyInCreateNestedModels) + + // ...binding through refs + enumerablePromiseInput = store.set(Enumerable, refsInCreateNestedModels) + enumerableInput = store.sync(Enumerable, refsInCreateNestedModels) + + // ...binding through identifiers + enumerablePromiseInput = store.set(Enumerable, identifiersInCreateNestedModels) + enumerableInput = store.sync(Enumerable, identifiersInCreateNestedModels) + + // ...unbinding + enumerablePromiseInput = store.set(Enumerable, unrefsInCreateNestedModels) + enumerableInput = store.sync(Enumerable, unrefsInCreateNestedModels) + + // ...check collisions + /// @ts-expect-error + enumerablePromiseInput = store.set(Enumerable, collisionsInCreateNestedModels) + /// @ts-expect-error + enumerableInput = store.sync(Enumerable, collisionsInCreateNestedModels) + } + } + + // Update... + { + // Update model via Definition + { + // ...set primitive propertiers + singletonPromiseInput = store.set(Singleton, primitives) + singletonInput = store.sync(Singleton, primitives) + enumerablePromiseInput = store.set(Enumerable, { id: "1", ...primitives }) + enumerableInput = store.sync(Enumerable, { id: "1", ...primitives }) + + // ...use default values + singletonPromiseInput = store.set(Singleton, empty) + singletonInput = store.sync(Singleton, empty) + enumerablePromiseInput = store.set(Enumerable, { id: "1", ...empty }) + enumerableInput = store.sync(Enumerable, { id: "1", ...empty }) + + // ...binding through refs + singletonPromiseInput = store.set(Singleton, refs) + singletonInput = store.sync(Singleton, refs) + enumerablePromiseInput = store.set(Enumerable, { id: "1", ...refs }) + enumerableInput = store.sync(Enumerable, { id: "1", ...refs }) + + // ...binding through identifiers + singletonPromiseInput = store.set(Singleton, identifiers) + singletonInput = store.sync(Singleton, identifiers) + enumerablePromiseInput = store.set(Enumerable, { id: "1", ...identifiers }) + enumerableInput = store.sync(Enumerable, { id: "1", ...identifiers }) + + // ...unbinding + singletonPromiseInput = store.set(Singleton, unrefs) + singletonInput = store.sync(Singleton, unrefs) + enumerablePromiseInput = store.set(Enumerable, { id: "1", ...unrefs }) + enumerableInput = store.sync(Enumerable, { id: "1", ...unrefs }) + + // ...check collisions + /// @ts-expect-error + singletonPromiseInput = store.set(Singleton, collisions) + /// @ts-expect-error + singletonInput = store.sync(Singleton, collisions) + /// @ts-expect-error + enumerablePromiseInput = store.set(Enumerable, { id: "1", ...collisions }) + /// @ts-expect-error + enumerableInput = store.sync(Enumerable, { id: "1", ...collisions }) + } + + // Update model & nested via Definition + { + // ...set primitive propertiers + singletonPromiseInput = store.set(Singleton, primitivesInUpdateNestedModels) + singletonInput = store.sync(Singleton, primitivesInUpdateNestedModels) + enumerablePromiseInput = store.set(Enumerable, { id: "1", ...primitivesInUpdateNestedModels }) + enumerableInput = store.sync(Enumerable, { id: "1", ...primitivesInUpdateNestedModels }) + + // ...use default values + singletonPromiseInput = store.set(Singleton, emptyInUpdateNestedModels) + singletonInput = store.sync(Singleton, emptyInUpdateNestedModels) + enumerablePromiseInput = store.set(Enumerable, { id: "1", ...emptyInUpdateNestedModels }) + enumerableInput = store.sync(Enumerable, { id: "1", ...emptyInUpdateNestedModels }) + + // ...binding through refs + singletonPromiseInput = store.set(Singleton, refsInUpdateNestedModels) + singletonInput = store.sync(Singleton, refsInUpdateNestedModels) + enumerablePromiseInput = store.set(Enumerable, { id: "1", ...refsInUpdateNestedModels }) + enumerableInput = store.sync(Enumerable, { id: "1", ...refsInUpdateNestedModels }) + + // ...binding through identifiers + singletonPromiseInput = store.set(Singleton, identifiersInUpdateNestedModels) + singletonInput = store.sync(Singleton, identifiersInUpdateNestedModels) + enumerablePromiseInput = store.set(Enumerable, { id: "1", ...identifiersInUpdateNestedModels }) + enumerableInput = store.sync(Enumerable, { id: "1", ...identifiersInUpdateNestedModels }) + + // ...unbinding + singletonPromiseInput = store.set(Singleton, unrefsInUpdateNestedModels) + singletonInput = store.sync(Singleton, unrefsInUpdateNestedModels) + enumerablePromiseInput = store.set(Enumerable, { id: "1", ...unrefsInUpdateNestedModels }) + enumerableInput = store.sync(Enumerable, { id: "1", ...unrefsInUpdateNestedModels }) + + // ...check collisions + /// @ts-expect-error + singletonPromiseInput = store.set(Singleton, collisionsInUpdateNestedModels) + /// @ts-expect-error + singletonInput = store.sync(Singleton, collisionsInUpdateNestedModels) + /// @ts-expect-error + enumerablePromiseInput = store.set(Enumerable, { id: "1", ...collisionsInUpdateNestedModels }) + /// @ts-expect-error + enumerableInput = store.sync(Enumerable, { id: "1", ...collisionsInUpdateNestedModels }) + } + } + + // Delete... + { + // Delete model via Definition + + /// @ts-expect-error + enumerablePromiseInput = store.set(Enumerable, null) + /// @ts-expect-error + enumerableInput = store.sync(Enumerable, null) + + singletonPromiseInput = store.set(Singleton, null) + singletonInput = store.sync(Singleton, null) + } + + // Mixed... + { + // Create model and Update nested via Definition + { + // ...set primitive propertiers + enumerablePromiseInput = store.set(Enumerable, primitivesInUpdateNestedModels) + enumerableInput = store.sync(Enumerable, primitivesInUpdateNestedModels) + + // ...use default values + enumerablePromiseInput = store.set(Enumerable, emptyInUpdateNestedModels) + enumerableInput = store.sync(Enumerable, emptyInUpdateNestedModels) + + // ...binding through refs + enumerablePromiseInput = store.set(Enumerable, refsInUpdateNestedModels) + enumerableInput = store.sync(Enumerable, refsInUpdateNestedModels) + + // ...binding through identifiers + enumerablePromiseInput = store.set(Enumerable, identifiersInUpdateNestedModels) + enumerableInput = store.sync(Enumerable, identifiersInUpdateNestedModels) + + // ...unbinding + enumerablePromiseInput = store.set(Enumerable, unrefsInUpdateNestedModels) + enumerableInput = store.sync(Enumerable, unrefsInUpdateNestedModels) + + // ...check collisions + /// @ts-expect-error + enumerablePromiseInput = store.set(Enumerable, collisionsInUpdateNestedModels) + /// @ts-expect-error + enumerableInput = store.sync(Enumerable, collisionsInUpdateNestedModels) + } + + // Update model and Create nested via Definition + { + // ...set primitive propertiers + singletonPromiseInput = store.set(Singleton, primitivesInCreateNestedModels) + singletonInput = store.sync(Singleton, primitivesInCreateNestedModels) + enumerablePromiseInput = store.set(Enumerable, { id: "1", ...primitivesInCreateNestedModels }) + enumerableInput = store.sync(Enumerable, { id: "1", ...primitivesInCreateNestedModels }) + + // ...use default values + singletonPromiseInput = store.set(Singleton, emptyInCreateNestedModels) + singletonInput = store.sync(Singleton, emptyInCreateNestedModels) + enumerablePromiseInput = store.set(Enumerable, { id: "1", ...emptyInCreateNestedModels }) + enumerableInput = store.sync(Enumerable, { id: "1", ...emptyInCreateNestedModels }) + + // ...binding through refs + singletonPromiseInput = store.set(Singleton, refsInCreateNestedModels) + singletonInput = store.sync(Singleton, refsInCreateNestedModels) + enumerablePromiseInput = store.set(Enumerable, { id: "1", ...refsInCreateNestedModels }) + enumerableInput = store.sync(Enumerable, { id: "1", ...refsInCreateNestedModels }) + + // ...binding through identifiers + singletonPromiseInput = store.set(Singleton, identifiersInCreateNestedModels) + singletonInput = store.sync(Singleton, identifiersInCreateNestedModels) + enumerablePromiseInput = store.set(Enumerable, { id: "1", ...identifiersInCreateNestedModels }) + enumerableInput = store.sync(Enumerable, { id: "1", ...identifiersInCreateNestedModels }) + + // ...unbinding + singletonPromiseInput = store.set(Singleton, unrefsInCreateNestedModels) + singletonInput = store.sync(Singleton, unrefsInCreateNestedModels) + enumerablePromiseInput = store.set(Enumerable, { id: "1", ...unrefsInCreateNestedModels }) + enumerableInput = store.sync(Enumerable, { id: "1", ...unrefsInCreateNestedModels }) + + // ...check collisions + /// @ts-expect-error + singletonPromiseInput = store.set(Singleton, collisionsInCreateNestedModels) + /// @ts-expect-error + singletonInput = store.sync(Singleton, collisionsInCreateNestedModels) + /// @ts-expect-error + enumerablePromiseInput = store.set(Enumerable, { id: "1", ...collisionsInCreateNestedModels }) + /// @ts-expect-error + enumerableInput = store.sync(Enumerable, { id: "1", ...collisionsInCreateNestedModels }) + } + } +} + +// Overload via instance +{ + // Update model via instance + { + // ...set primitive propertiers + singletonPromiseInput = store.set(singleton, primitives) + singletonInput = store.sync(singleton, primitives) + enumerablePromiseInput = store.set(enumerable, { id: "1", ...primitives }) + enumerableInput = store.sync(enumerable, { id: "1", ...primitives }) + + // ...use default values + singletonPromiseInput = store.set(singleton, empty) + singletonInput = store.sync(singleton, empty) + enumerablePromiseInput = store.set(enumerable, { id: "1", ...empty }) + enumerableInput = store.sync(enumerable, { id: "1", ...empty }) + + // ...binding through refs + singletonPromiseInput = store.set(singleton, refs) + singletonInput = store.sync(singleton, refs) + enumerablePromiseInput = store.set(enumerable, { id: "1", ...refs }) + enumerableInput = store.sync(enumerable, { id: "1", ...refs }) + + // ...binding through identifiers + singletonPromiseInput = store.set(singleton, identifiers) + singletonInput = store.sync(singleton, identifiers) + enumerablePromiseInput = store.set(enumerable, { id: "1", ...identifiers }) + enumerableInput = store.sync(enumerable, { id: "1", ...identifiers }) + + // ...unbinding + singletonPromiseInput = store.set(singleton, unrefs) + singletonInput = store.sync(singleton, unrefs) + enumerablePromiseInput = store.set(enumerable, { id: "1", ...unrefs }) + enumerableInput = store.sync(enumerable, { id: "1", ...unrefs }) + + // ...check collisions + /// @ts-expect-error + singletonPromiseInput = store.set(singleton, collisions) + singletonInput = store.sync(singleton, collisions) + /// @ts-expect-error + enumerablePromiseInput = store.set(enumerable, { id: "1", ...collisions }) + enumerableInput = store.sync(enumerable, { id: "1", ...collisions }) + } + + // Update model & nested via instance + { + // ...set primitive propertiers + singletonPromiseInput = store.set(singleton, primitivesInUpdateNestedModels) + singletonInput = store.sync(singleton, primitivesInUpdateNestedModels) + enumerablePromiseInput = store.set(enumerable, { id: "1", ...primitivesInUpdateNestedModels }) + enumerableInput = store.sync(enumerable, { id: "1", ...primitivesInUpdateNestedModels }) + + // ...use default values + singletonPromiseInput = store.set(singleton, emptyInUpdateNestedModels) + singletonInput = store.sync(singleton, emptyInUpdateNestedModels) + enumerablePromiseInput = store.set(enumerable, { id: "1", ...emptyInUpdateNestedModels }) + enumerableInput = store.sync(enumerable, { id: "1", ...emptyInUpdateNestedModels }) + + // ...binding through refs + singletonPromiseInput = store.set(singleton, refsInUpdateNestedModels) + singletonInput = store.sync(singleton, refsInUpdateNestedModels) + enumerablePromiseInput = store.set(enumerable, { id: "1", ...refsInUpdateNestedModels }) + enumerableInput = store.sync(enumerable, { id: "1", ...refsInUpdateNestedModels }) + + // ...binding through identifiers + singletonPromiseInput = store.set(singleton, identifiersInUpdateNestedModels) + singletonInput = store.sync(singleton, identifiersInUpdateNestedModels) + enumerablePromiseInput = store.set(enumerable, { id: "1", ...identifiersInUpdateNestedModels }) + enumerableInput = store.sync(enumerable, { id: "1", ...identifiersInUpdateNestedModels }) + + // ...unbinding + singletonPromiseInput = store.set(singleton, unrefsInUpdateNestedModels) + singletonInput = store.sync(singleton, unrefsInUpdateNestedModels) + enumerablePromiseInput = store.set(enumerable, { id: "1", ...unrefsInUpdateNestedModels }) + enumerableInput = store.sync(enumerable, { id: "1", ...unrefsInUpdateNestedModels }) + + // ...check collisions + /// @ts-expect-error + singletonPromiseInput = store.set(singleton, collisionsInUpdateNestedModels) + /// @ts-expect-error + singletonInput = store.sync(singleton, collisionsInUpdateNestedModels) + /// @ts-expect-error + enumerablePromiseInput = store.set(enumerable, { id: "1", ...collisionsInUpdateNestedModels }) + /// @ts-expect-error + enumerableInput = store.sync(enumerable, { id: "1", ...collisionsInUpdateNestedModels }) + } + + // Mixed... + { + // Update model and Create nested via Definition + { + // ...set primitive propertiers + singletonPromiseInput = store.set(singleton, primitivesInCreateNestedModels) + singletonInput = store.sync(singleton, primitivesInCreateNestedModels) + enumerablePromiseInput = store.set(enumerable, { id: "1", ...primitivesInCreateNestedModels }) + enumerableInput = store.sync(enumerable, { id: "1", ...primitivesInCreateNestedModels }) + + // ...use default values + singletonPromiseInput = store.set(singleton, emptyInCreateNestedModels) + singletonInput = store.sync(singleton, emptyInCreateNestedModels) + enumerablePromiseInput = store.set(enumerable, { id: "1", ...emptyInCreateNestedModels }) + enumerableInput = store.sync(enumerable, { id: "1", ...emptyInCreateNestedModels }) + + // ...binding through refs + singletonPromiseInput = store.set(singleton, refsInCreateNestedModels) + singletonInput = store.sync(singleton, refsInCreateNestedModels) + enumerablePromiseInput = store.set(enumerable, { id: "1", ...refsInCreateNestedModels }) + enumerableInput = store.sync(enumerable, { id: "1", ...refsInCreateNestedModels }) + + // ...binding through identifiers + singletonPromiseInput = store.set(singleton, identifiersInCreateNestedModels) + singletonInput = store.sync(singleton, identifiersInCreateNestedModels) + enumerablePromiseInput = store.set(enumerable, { id: "1", ...identifiersInCreateNestedModels }) + enumerableInput = store.sync(enumerable, { id: "1", ...identifiersInCreateNestedModels }) + + // ...unbinding + singletonPromiseInput = store.set(singleton, unrefsInCreateNestedModels) + singletonInput = store.sync(singleton, unrefsInCreateNestedModels) + enumerablePromiseInput = store.set(enumerable, { id: "1", ...unrefsInCreateNestedModels }) + enumerableInput = store.sync(enumerable, { id: "1", ...unrefsInCreateNestedModels }) + + // ...check collisions + /// @ts-expect-error + singletonPromiseInput = store.set(singleton, collisionsInCreateNestedModels) + /// @ts-expect-error + singletonInput = store.sync(singleton, collisionsInCreateNestedModels) + /// @ts-expect-error + enumerablePromiseInput = store.set(enumerable, { id: "1", ...collisionsInCreateNestedModels }) + /// @ts-expect-error + enumerableInput = store.sync(enumerable, { id: "1", ...collisionsInCreateNestedModels }) + } + } +} + +// Delete... +{ + // delete model via instance + { + enumerablePromiseInput = store.set(enumerable, null) + enumerableInput = store.sync(enumerable, null) + singletonPromiseInput = store.set(singleton, null) // is may be cleaning of the model values or draft values + singletonInput = store.sync(singleton, null) // is may be cleaning of the model values or draft values + } +} + diff --git a/test/types/store/set.ts b/test/types/store/set.ts deleted file mode 100644 index 85aff6b6..00000000 --- a/test/types/store/set.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { LeafFromMemory } from "./_common/leaf/leaf-from-memory.store" -import { BranchFromMemory } from "./_common/branch/branch-from-memory.store" -import { WoodFromMemory } from "./_common/wood/wood-from-memory.store" -import { SingletonFromMemory } from "./_common/singleton/singleton-from-memory.store" -import { store } from "/types" -import { IWood } from "./_common/wood/wood.entity" -import { ISingleton, singleton } from "./_common/singleton/singleton.entity" - -const leaf = store.sync(LeafFromMemory, { id: "1" }) -const branch = store.sync(BranchFromMemory, { id: "1" }) -const wood = store.sync(WoodFromMemory, { id: "1" }) - -// ##################################################### -// Overload for working with Definition - -let woodInput: Promise -let singletonInput: Promise - -{ - // Create... - - // Create model via Definition - - woodInput = store.set(WoodFromMemory, { branch: branch }) - woodInput = store.set(WoodFromMemory, { branch: "1" }) - - // Create model & nested via Definition - - woodInput = store.set(WoodFromMemory, { branch: { leaf: leaf } }) - singletonInput = store.set(SingletonFromMemory, { wood: { leaf: leaf } }) - - // Update... - - // Update model via Definition - - woodInput = store.set(WoodFromMemory, { id: "1", branch: branch }) - woodInput = store.set(WoodFromMemory, { id: "1", branch: "1" }) - singletonInput = store.set(SingletonFromMemory, { wood: branch }) - singletonInput = store.set(SingletonFromMemory, { wood: "1" }) - - // Update model & nested via Definition - - woodInput = store.set(WoodFromMemory, { id: "1", branch: { id: "1", leaf: leaf } }) - woodInput = store.set(WoodFromMemory, { id: "1", branch: { id: "1", leaf: "1" } }) - singletonInput = store.set(SingletonFromMemory, { wood: { id: "1", leaf: leaf } }) - singletonInput = store.set(SingletonFromMemory, { wood: { id: "1", leaf: "1" } }) - - // Delete... - - /// @ts-expect-error - woodInput = store.set(WoodFromMemory, null) - - singletonInput = store.set(SingletonFromMemory, null) - - // Mixed... - - // Create model and Update nested via Definition - - woodInput = store.set(WoodFromMemory, { branch: { id: "1", leaf: leaf } }) - woodInput = store.set(WoodFromMemory, { branch: { id: "1", leaf: "1" } }) - - // Update model and Create nested via Definition - - woodInput = store.set(WoodFromMemory, { id: "1", branch: { leaf: leaf } }) - woodInput = store.set(WoodFromMemory, { id: "1", branch: { leaf: "1" } }) -} - -// ##################################################### -// Overload for working with instance - -{ - // Create... x - - // Update... - - // Update model via instance - - store.set(wood, { branch: branch }) - store.set(wood, { branch: "1" }) - store.set(singleton, { wood: wood }) - store.set(singleton, { wood: "1" }) - - // Update model & nested via instance - - store.set(wood, { branch: { id: "1", leaf: leaf }}) - store.set(wood, { branch: { id: "1", leaf: "1" }}) - store.set(singleton, { wood: { id: "1", branch: branch }}) - store.set(singleton, { wood: { id: "1", branch: "1" }}) - - // Delete... - - // delete model via instance - - store.set(wood, null) - store.set(singleton, null) // this is a cleansing of the model -} From c42661a611b9ce5bb8fe1866065f7053551ef085 Mon Sep 17 00:00:00 2001 From: Tomoe <4.artem.0@gmail.com> Date: Thu, 3 Apr 2025 22:43:34 +0300 Subject: [PATCH 04/12] update(store): type tests for store factory --- test/types/store/descriptor.ts | 122 ---------------------------- test/types/store/factory/factory.ts | 115 ++++++++++++++++++++++++++ 2 files changed, 115 insertions(+), 122 deletions(-) delete mode 100644 test/types/store/descriptor.ts create mode 100644 test/types/store/factory/factory.ts diff --git a/test/types/store/descriptor.ts b/test/types/store/descriptor.ts deleted file mode 100644 index cec7356d..00000000 --- a/test/types/store/descriptor.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { Model, define, store } from "/types/index"; - -interface IEnumerableModel { - id: string; - prop: number; -} -interface ISingletonModel { - prop: number; -} - -const EnumerableDefinition: Model = { id: true, prop: 0 }; -const SingletonDefinition: Model = { prop: 0 }; - -interface IAComponent extends HTMLElement { - modelId: undefined | string; - - singleton: ISingletonModel; - singletonDraft: ISingletonModel; - model: undefined | IEnumerableModel; - modelDraft: IEnumerableModel; - - singletonById: ISingletonModel; - singletonDraftById: ISingletonModel; - modelById: undefined | IEnumerableModel; - modelDraftById: IEnumerableModel; - - singletonList: ISingletonModel[]; - singletonDraftList: ISingletonModel[]; - modelList: IEnumerableModel[]; - modelDraftList: IEnumerableModel[]; - - singletonListById: ISingletonModel[]; - singletonDraftListById: ISingletonModel[]; - modelListById: IEnumerableModel[]; - modelDraftListById: IEnumerableModel[]; - - looseSingletonList: ISingletonModel[]; - looseSingletonDraftList: ISingletonModel[]; - looseModelList: IEnumerableModel[]; - looseModelDraftList: IEnumerableModel[]; - - looseSingletonListById: ISingletonModel[]; - looseSingletonDraftListById: ISingletonModel[]; - looseModelListById: IEnumerableModel[]; - looseModelDraftListById: IEnumerableModel[]; -} - -const Component = define({ - tag: "a-component", - modelId: undefined, - - singleton: store(SingletonDefinition), - singletonDraft: store(SingletonDefinition, { draft: true }), - model: store(EnumerableDefinition), - modelDraft: store(EnumerableDefinition, { draft: true }), - - singletonById: store(SingletonDefinition, { id: "modelId" }), - singletonDraftById: store(SingletonDefinition, { - id: "modelId", - draft: true, - }), - modelById: store(EnumerableDefinition, { id: "modelId" }), - modelDraftById: store(EnumerableDefinition, { draft: true, id: "modelId" }), - - /// @ts-expect-error - singletonList: store([SingletonDefinition]), - /// @ts-expect-error - singletonDraftList: store([SingletonDefinition], { draft: true }), - modelList: store([EnumerableDefinition]), - /// @ts-expect-error - modelDraftList: store([EnumerableDefinition], { draft: true }), - - /// @ts-expect-error - singletonListById: store([SingletonDefinition], { id: "modelId" }), - /// @ts-expect-error - singletonDraftListById: store([SingletonDefinition], { - id: "modelId", - draft: true, - }), - modelListById: store([EnumerableDefinition], { id: "modelId" }), - /// @ts-expect-error - modelDraftListById: store([EnumerableDefinition], { - id: "modelId", - draft: true, - }), - - /// @ts-expect-error - looseSingletonList: store([SingletonDefinition], { loose: true }), - /// @ts-expect-error - looseSingletonDraftList: store([SingletonDefinition], { - draft: true, - loose: true, - }), - looseModelList: store([EnumerableDefinition], { loose: true }), - /// @ts-expect-error - looseModelDraftList: store([EnumerableDefinition], { - draft: true, - loose: true, - }), - - /// @ts-expect-error - looseSingletonListById: store([SingletonDefinition], { - id: "modelId", - loose: true, - }), - /// @ts-expect-error - looseSingletonDraftListById: store([SingletonDefinition], { - id: "modelId", - draft: true, - loose: true, - }), - looseModelListById: store([EnumerableDefinition], { - id: "modelId", - loose: true, - }), - /// @ts-expect-error - looseModelDraftListById: store([EnumerableDefinition], { - id: "modelId", - draft: true, - loose: true, - }), -}); diff --git a/test/types/store/factory/factory.ts b/test/types/store/factory/factory.ts new file mode 100644 index 00000000..34b32b57 --- /dev/null +++ b/test/types/store/factory/factory.ts @@ -0,0 +1,115 @@ +import { Enumerable } from "../.internals/enumerable/enumerable.store"; +import { IEnumerable } from "../.internals/enumerable/enumerable.entity"; +import { Singleton } from "../.internals/singleton/singleton.store"; +import { ISingleton } from "../.internals/singleton/singleton.entity"; +import { define, store } from "/types/index"; + +interface IComponent extends HTMLElement { + modelId: undefined | string; + + singleton: ISingleton; + singletonDraft: ISingleton; + model: undefined | IEnumerable; + modelDraft: IEnumerable; + + singletonById: ISingleton; + singletonDraftById: ISingleton; + modelById: undefined | IEnumerable; + modelDraftById: IEnumerable; + + singletonList: ISingleton[]; + singletonDraftList: ISingleton[]; + modelList: IEnumerable[]; + modelDraftList: IEnumerable[]; + + singletonListById: ISingleton[]; + singletonDraftListById: ISingleton[]; + modelListById: IEnumerable[]; + modelDraftListById: IEnumerable[]; + + looseSingletonList: ISingleton[]; + looseSingletonDraftList: ISingleton[]; + looseModelList: IEnumerable[]; + looseModelDraftList: IEnumerable[]; + + looseSingletonListById: ISingleton[]; + looseSingletonDraftListById: ISingleton[]; + looseModelListById: IEnumerable[]; + looseModelDraftListById: IEnumerable[]; +} + +const Component = define({ + tag: "a-component", + modelId: undefined, + + singleton: store(Singleton), + singletonDraft: store(Singleton, { draft: true }), + model: store(Enumerable), + modelDraft: store(Enumerable, { draft: true }), + + singletonById: store(Singleton, { id: "modelId" }), + singletonDraftById: store(Singleton, { + id: "modelId", + draft: true, + }), + modelById: store(Enumerable, { id: "modelId" }), + modelDraftById: store(Enumerable, { draft: true, id: "modelId" }), + + /// @ts-expect-error + singletonList: store([Singleton]), + /// @ts-expect-error + singletonDraftList: store([Singleton], { draft: true }), + modelList: store([Enumerable]), + /// @ts-expect-error + modelDraftList: store([Enumerable], { draft: true }), + + /// @ts-expect-error + singletonListById: store([Singleton], { id: "modelId" }), + /// @ts-expect-error + singletonDraftListById: store([Singleton], { + id: "modelId", + draft: true, + }), + modelListById: store([Enumerable], { id: "modelId" }), + /// @ts-expect-error + modelDraftListById: store([Enumerable], { + id: "modelId", + draft: true, + }), + + /// @ts-expect-error + looseSingletonList: store([Singleton], { loose: true }), + /// @ts-expect-error + looseSingletonDraftList: store([Singleton], { + draft: true, + loose: true, + }), + looseModelList: store([Enumerable], { loose: true }), + /// @ts-expect-error + looseModelDraftList: store([Enumerable], { + draft: true, + loose: true, + }), + + /// @ts-expect-error + looseSingletonListById: store([Singleton], { + id: "modelId", + loose: true, + }), + /// @ts-expect-error + looseSingletonDraftListById: store([Singleton], { + id: "modelId", + draft: true, + loose: true, + }), + looseModelListById: store([Enumerable], { + id: "modelId", + loose: true, + }), + /// @ts-expect-error + looseModelDraftListById: store([Enumerable], { + id: "modelId", + draft: true, + loose: true, + }), +}); From 91a3d13f3d512547563d0c4e442766670a7fd54e Mon Sep 17 00:00:00 2001 From: Tomoe <4.artem.0@gmail.com> Date: Thu, 3 Apr 2025 22:44:10 +0300 Subject: [PATCH 05/12] fix(store): type tests for direct get/resolve methods --- test/types/store/direct-methods.ts | 23 ---------- test/types/store/direct-methods/get.ts | 41 ++++++++++++++++++ test/types/store/direct-methods/resolve.ts | 50 ++++++++++++++++++++++ 3 files changed, 91 insertions(+), 23 deletions(-) delete mode 100644 test/types/store/direct-methods.ts create mode 100644 test/types/store/direct-methods/get.ts create mode 100644 test/types/store/direct-methods/resolve.ts diff --git a/test/types/store/direct-methods.ts b/test/types/store/direct-methods.ts deleted file mode 100644 index db1d1f8b..00000000 --- a/test/types/store/direct-methods.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { store } from "/types/index"; -import SingletonStore, { ISingleton } from "./singleton-definition.store"; -import EnumerableStore, { IEnumerable } from "./enumerable-definition.store"; - -const SingletonModelPromise: Promise = - store.resolve(SingletonStore); -const SingletonModel = await SingletonModelPromise; - -const EnumerableModelPromise: Promise = - store.resolve(EnumerableStore); -const EnumerableModel = await EnumerableModelPromise; - -const EnumerableModelListPromise: Promise = store.resolve([ - EnumerableStore, -]); -const EnumerableModelList = await EnumerableModelListPromise; - -store.get(SingletonStore); -store.get([SingletonStore]); - -store.get(EnumerableStore); -store.get([EnumerableStore]); - diff --git a/test/types/store/direct-methods/get.ts b/test/types/store/direct-methods/get.ts new file mode 100644 index 00000000..4166d688 --- /dev/null +++ b/test/types/store/direct-methods/get.ts @@ -0,0 +1,41 @@ +import { IEnumerable } from "../.internals/enumerable/enumerable.entity"; +import { Enumerable } from "../.internals/enumerable/enumerable.store"; +import { ISingleton } from "../.internals/singleton/singleton.entity"; +import { Singleton } from "../.internals/singleton/singleton.store"; +import { store } from "/types"; + +let singletonInput: ISingleton +let singletonListInput: ISingleton[] +let enumerableInput: IEnumerable +let enumerableListInput: IEnumerable[] + +// Overload via Definition +{ + // ...read singleton + singletonInput = store.get(Singleton); + // ...read unidentified model + enumerableInput = store.get(Enumerable); // looks strange + + // read identified model + singletonInput = store.get(Singleton, "1"); // looks strange + enumerableInput = store.get(Enumerable, "1"); + + // read queried model + singletonInput = store.get(Singleton, { a: 1, b: 2 }); // looks strange + enumerableInput = store.get(Enumerable, { a: 1, b: 2 }); +} + +// Overload via [Definition] +{ + // ...read unidentified list + singletonListInput = store.get([Singleton]); // looks strange + enumerableListInput = store.get([Enumerable]); + + // ...read identified list + singletonListInput = store.get([Singleton], "1"); // looks strange + enumerableListInput = store.get([Enumerable], "1"); + + // ...read queried list + singletonListInput = store.get([Singleton], { a: 1, b: 2 }); // looks strange + enumerableListInput = store.get([Enumerable], { a: 1, b: 2 }); +} \ No newline at end of file diff --git a/test/types/store/direct-methods/resolve.ts b/test/types/store/direct-methods/resolve.ts new file mode 100644 index 00000000..650ca7e4 --- /dev/null +++ b/test/types/store/direct-methods/resolve.ts @@ -0,0 +1,50 @@ +import { Enumerable } from "../.internals/enumerable/enumerable.store"; +import { IEnumerable } from "../.internals/enumerable/enumerable.entity"; +import { Singleton } from "../.internals/singleton/singleton.store"; +import { ISingleton } from "../.internals/singleton/singleton.entity"; +import { store } from "/types"; + +const singleton = store.get(Singleton) +const enumerable = store.sync(Enumerable, { id: "1" }) + +let singletonPromiseInput: Promise +let enumerablePromiseInput: Promise +let singletonListPromiseInput: Promise +let enumerableListPromiseInput: Promise + +// Overload via Definition +{ + // ...read singleton + singletonPromiseInput = store.resolve(Singleton); + // ...read unidentified model + enumerablePromiseInput = store.resolve(Enumerable); // looks strange + + // read identified model + singletonPromiseInput = store.resolve(Singleton, "1"); // looks strange + enumerablePromiseInput = store.resolve(Enumerable, "1"); + + // read queried model + singletonPromiseInput = store.resolve(Singleton, { a: 1, b: 2 }); // looks strange + enumerablePromiseInput = store.resolve(Enumerable, { a: 1, b: 2 }); +} + +// Overload via [Definition] +{ + // ...read unidentified list + singletonListPromiseInput = store.resolve([Singleton]); // looks strange + enumerableListPromiseInput = store.resolve([Enumerable]); + + // ...read identified list + singletonListPromiseInput = store.resolve([Singleton], "1"); // looks strange + enumerableListPromiseInput = store.resolve([Enumerable], "1"); + + // ...read queried list + singletonListPromiseInput = store.resolve([Singleton], { a: 1, b: 2 }); // looks strange + enumerableListPromiseInput = store.resolve([Enumerable], { a: 1, b: 2 }); +} + +// Overload via instance +{ + singletonPromiseInput = store.resolve(singleton); + enumerablePromiseInput = store.resolve(enumerable); +} \ No newline at end of file From 4bab3396bc0bcb70054c16f6e66eefeedd752798 Mon Sep 17 00:00:00 2001 From: Tomoe <4.artem.0@gmail.com> Date: Fri, 4 Apr 2025 22:11:37 +0300 Subject: [PATCH 06/12] fix(store): types test of collisions in set and sync direct methods --- test/types/store/direct-methods/set-and-sync.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/types/store/direct-methods/set-and-sync.ts b/test/types/store/direct-methods/set-and-sync.ts index 94b78f60..8a4fec30 100644 --- a/test/types/store/direct-methods/set-and-sync.ts +++ b/test/types/store/direct-methods/set-and-sync.ts @@ -415,9 +415,11 @@ const collisionsInUpdateNestedModels = { // ...check collisions /// @ts-expect-error singletonPromiseInput = store.set(singleton, collisions) + /// @ts-expect-error singletonInput = store.sync(singleton, collisions) /// @ts-expect-error enumerablePromiseInput = store.set(enumerable, { id: "1", ...collisions }) + /// @ts-expect-error enumerableInput = store.sync(enumerable, { id: "1", ...collisions }) } From b6a6f1252a2bf0848182927bc4991e79c82a3ddc Mon Sep 17 00:00:00 2001 From: Tomoe <4.artem.0@gmail.com> Date: Fri, 4 Apr 2025 22:13:34 +0300 Subject: [PATCH 07/12] fix(store): typo in definition test --- test/types/store/model-definition.ts | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/test/types/store/model-definition.ts b/test/types/store/model-definition.ts index 99d180df..43c6b6a1 100644 --- a/test/types/store/model-definition.ts +++ b/test/types/store/model-definition.ts @@ -1,4 +1,5 @@ import { IEnumerable } from "./.internals/enumerable/enumerable.entity"; +import { Enumerable } from "./.internals/enumerable/enumerable.store"; import { ISingleton } from "./.internals/singleton/singleton.entity"; import { Singleton } from "./.internals/singleton/singleton.store"; import { Model } from "/types/index"; @@ -328,33 +329,33 @@ const ModelStore: Model = { // Enumerable Model - enumerableModel: EnumerableStore, - optionalEnumerableModel: EnumerableStore, + enumerableModel: Enumerable, + optionalEnumerableModel: Enumerable, /// @ts-expect-error undefinedOptionalEnumerableModel: undefined, - calculatedEnumerableModel: () => EnumerableStore, + calculatedEnumerableModel: () => Enumerable, /// @ts-expect-error undefinedCalculatedEnumerableModel: () => undefined, - calculatedOptionalEnumerableModel: () => EnumerableStore, + calculatedOptionalEnumerableModel: () => Enumerable, undefinedCalculatedOptionalEnumerableModel: () => - condition ? undefined : EnumerableStore, + condition ? undefined : Enumerable, // Enumerable Model List - enumerableModelList: [EnumerableStore], - looseEnumerableModelList: [EnumerableStore, { loose: true }], - optionalEnumerableModelList: [EnumerableStore], + enumerableModelList: [Enumerable], + looseEnumerableModelList: [Enumerable, { loose: true }], + optionalEnumerableModelList: [Enumerable], /// @ts-expect-error undefinedOptionalEnumerableModelList: undefined, - calculatedEnumerableModelList: () => [EnumerableStore], + calculatedEnumerableModelList: () => [Enumerable], /// @ts-expect-error undefinedCalculatedEnumerableModelList: () => undefined, - looseCalculatedEnumerableModelList: () => [EnumerableStore, { loose: true }], - calculatedOptionalEnumerableModelList: () => [EnumerableStore], + looseCalculatedEnumerableModelList: () => [Enumerable, { loose: true }], + calculatedOptionalEnumerableModelList: () => [Enumerable], undefinedCalculatedOptionalEnumerableModelList: () => - condition ? undefined : [EnumerableStore], + condition ? undefined : [Enumerable], // Singleton Model From a03d2af68af2c593d005577ce48dc37890d82d46 Mon Sep 17 00:00:00 2001 From: Tomoe <4.artem.0@gmail.com> Date: Fri, 4 Apr 2025 22:41:30 +0300 Subject: [PATCH 08/12] clear(store): something useless in internals --- .../.internals/enumerable/enumerable.store.ts | 14 +------------- .../nested-enumerable/nested-enumerable.entity.ts | 1 - .../nested-enumerable/nested-enumerable.store.ts | 1 - 3 files changed, 1 insertion(+), 15 deletions(-) diff --git a/test/types/store/.internals/enumerable/enumerable.store.ts b/test/types/store/.internals/enumerable/enumerable.store.ts index e20342a3..e8d00507 100644 --- a/test/types/store/.internals/enumerable/enumerable.store.ts +++ b/test/types/store/.internals/enumerable/enumerable.store.ts @@ -13,16 +13,4 @@ export const Enumerable: Model = { nestedEnumerable: store.ref(() => NestedEnumerable), optionalNestedEnumerable: store.ref(() => NestedEnumerable), nestedEnumerables: store.ref(() => [NestedEnumerable]), -} - -/// @ts-expect-error -const BrokenEnumerable: Model = { - stringProperty: "", - numberProperty: 0, - self: store.ref(() => Enumerable), - nestedSingleton: store.ref(() => Singleton), - optionalNestedSingleton: store.ref(() => Singleton), - nestedEnumerable: store.ref(() => NestedEnumerable), - optionalNestedEnumerable: store.ref(() => NestedEnumerable), - nestedEnumerables: store.ref(() => [NestedEnumerable]), -}; \ No newline at end of file +} \ No newline at end of file diff --git a/test/types/store/.internals/nested-enumerable/nested-enumerable.entity.ts b/test/types/store/.internals/nested-enumerable/nested-enumerable.entity.ts index 7ed71d20..c8498da5 100644 --- a/test/types/store/.internals/nested-enumerable/nested-enumerable.entity.ts +++ b/test/types/store/.internals/nested-enumerable/nested-enumerable.entity.ts @@ -5,7 +5,6 @@ export interface INestedEnumerable { id: string stringProperty: string; numberProperty: number; - self: INestedEnumerable nestedSingleton: ISingleton; optionalNestedSingleton?: ISingleton; nestedEnumerable: IDeepNestedEnumerable; diff --git a/test/types/store/.internals/nested-enumerable/nested-enumerable.store.ts b/test/types/store/.internals/nested-enumerable/nested-enumerable.store.ts index f0184f89..b74f7144 100644 --- a/test/types/store/.internals/nested-enumerable/nested-enumerable.store.ts +++ b/test/types/store/.internals/nested-enumerable/nested-enumerable.store.ts @@ -7,7 +7,6 @@ export const NestedEnumerable: Model = { id: true, stringProperty: "", numberProperty: 0, - self: store.ref(() => NestedEnumerable), nestedSingleton: store.ref(() => Singleton), optionalNestedSingleton: store.ref(() => Singleton), nestedEnumerable: store.ref(() => DeepNestedEnumerable), From 88640f6db5caeb209e7d4788dde565e98b7884e2 Mon Sep 17 00:00:00 2001 From: Tomoe <4.artem.0@gmail.com> Date: Fri, 4 Apr 2025 22:42:47 +0300 Subject: [PATCH 09/12] feat(store): type tests for direct clear method --- test/types/store/direct-methods/clear.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 test/types/store/direct-methods/clear.ts diff --git a/test/types/store/direct-methods/clear.ts b/test/types/store/direct-methods/clear.ts new file mode 100644 index 00000000..2fec6eec --- /dev/null +++ b/test/types/store/direct-methods/clear.ts @@ -0,0 +1,22 @@ +import { Enumerable } from "../.internals/enumerable/enumerable.store"; +import { Singleton } from "../.internals/singleton/singleton.store"; +import { store } from "/types"; + +const singleton = store.get(Singleton) +const enumerable = store.sync(Enumerable, { id: "1" }) + +// Overload via Definition +{ + store.clear(Singleton); + store.clear(Enumerable); + store.clear(Singleton, true); + store.clear(Enumerable, true); +} + +// Overload via instance +{ + store.clear(singleton); + store.clear(enumerable); + store.clear(singleton, true); + store.clear(enumerable, true); +} \ No newline at end of file From 79f789cfa84efb7fab185b7ce4caacc1b8958719 Mon Sep 17 00:00:00 2001 From: Tomoe <4.artem.0@gmail.com> Date: Fri, 4 Apr 2025 22:44:03 +0300 Subject: [PATCH 10/12] fix(store): types of values in direct methods --- types/index.d.ts | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/types/index.d.ts b/types/index.d.ts index 3ebecb8d..a0bf9f19 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -154,23 +154,16 @@ export type ModelIdentifier = | undefined; export type ModelValues = { - [property in keyof M]?: NonNullable extends Array - ? Array>>> + [property in keyof M]?: + NonNullable extends Array + ? Array>> | string | undefined> : NonNullable extends ModelInstance - ? ModelValues> - : M[property]; -}; - -export type StorageValues = { - [property in keyof M]?: NonNullable extends EnumerableInstance - ? NonNullable | M["id"] - : NonNullable extends EnumerableInstance[] - ? (NonNullable> | M["id"])[] + ? ModelValues> | string | undefined : M[property]; }; export type StorageResult = - | StorageValues + | ModelValues | null | undefined; @@ -241,13 +234,31 @@ export namespace store { ): M[]; function set( - model: Model | M, - values: ModelValues | null, + model: Model, + values: NoInfer>, + ): Promise; + function set( + model: Model, + values: null, + ): Promise; + function set( + model: M, + values: NoInfer | null>, ): Promise; + + function sync( + model: Model, + values: NoInfer>, + ): M; + function sync( + model: Model, + values: null, + ): M; function sync( - model: Model | M, - values: ModelValues | null, + model: M, + values: NoInfer | null>, ): M; + function clear( model: Model | [Model] | M, clearValue?: boolean, From 86f743c1026a0d6d12944162527b0160e2713c65 Mon Sep 17 00:00:00 2001 From: Tomoe <4.artem.0@gmail.com> Date: Wed, 9 Apr 2025 22:39:17 +0300 Subject: [PATCH 11/12] fix(store): types tests of model definition --- test/types/store/model-definition.ts | 610 ++++++++++++--------------- 1 file changed, 276 insertions(+), 334 deletions(-) diff --git a/test/types/store/model-definition.ts b/test/types/store/model-definition.ts index 43c6b6a1..2fa84805 100644 --- a/test/types/store/model-definition.ts +++ b/test/types/store/model-definition.ts @@ -2,403 +2,345 @@ import { IEnumerable } from "./.internals/enumerable/enumerable.entity"; import { Enumerable } from "./.internals/enumerable/enumerable.store"; import { ISingleton } from "./.internals/singleton/singleton.entity"; import { Singleton } from "./.internals/singleton/singleton.store"; -import { Model } from "/types/index"; +import { Model, store } from "/types/index"; + +interface ICasesOfFieldsWithValues { + // value = value + fieldWithDefaultValue: T; + fieldCalculatedAsValue: T; + optionalFieldWithDefaultValue?: T; + optionalFieldCalculatedAsValue?: T; +} -interface ISomeObject { - prop: string; - length: number; +interface ICasesOfListedFieldsWithValues { + // value[] = value[] + listedFieldWithDefaultValues: T[]; + listedFieldCalculatedAsValues: T[]; + listedOptionalFieldWithDefaultValues?: T[]; + listedOptionalFieldCalculatedAsValues?: T[]; +} + +interface ICasesOfFieldsWithEmptyValues { + // value = Empty + fieldWithDefaultEmptyValue: T; + fieldCalculatedAsEmptyValue: T; + optionalFieldWithDefaultEmptyValue?: T; + optionalFieldCalculatedAsEmptyValue?: T; +} + +interface ICasesOfListedFieldsWithEmptyValues { + // value[] = [Empty] + listedFieldWithDefaultEmptyValues: T[]; + listedFieldCalculatedAsEmptyValues: T[]; + listedOptionalFieldWithDefaultEmptyValues?: T[]; + listedOptionalFieldCalculatedAsEmptyValues?: T[]; } -let condition = false; - -interface IModel { - id: string; - - // boolean - - emptyBoolean: boolean; - boolean: boolean; - looseBoolean: boolean; - undefinedOptionalBoolean?: boolean; - optionalBoolean?: boolean; - - emptyCalculatedBoolean: boolean; - calculatedBoolean: boolean; - undefinedCalculatedBoolean: boolean; - looseCalculatedBoolean: boolean; - calculatedOptionalBoolean?: boolean; - undefinedCalculatedOptionalBoolean?: boolean; - - // boolean List - - emptyBooleanList: boolean[]; - booleanList: boolean[]; - looseBooleanList: boolean[]; - undefinedOptionalBooleanList?: boolean[]; - optionalBooleanList?: boolean[]; - - emptyCalculatedBooleanList: boolean[]; - calculatedBooleanList: boolean[]; - undefinedCalculatedBooleanList: boolean[]; - looseCalculatedBooleanList: boolean[]; - calculatedOptionalBooleanList?: boolean[]; - undefinedCalculatedOptionalBooleanList?: boolean[]; - - // number - - emptyNumber: number; - number: number; - looseNumber: number; - undefinedOptionalNumber?: number; - optionalNumber?: number; - - emptyCalculatedNumber: number; - calculatedNumber: number; - undefinedCalculatedNumber: number; - looseCalculatedNumber: number; - calculatedOptionalNumber?: number; - undefinedCalculatedOptionalNumber?: number; - - // number List - - emptyNumberList: number[]; - numberList: number[]; - looseNumberList: number[]; - undefinedOptionalNumberList?: number[]; - optionalNumberList?: number[]; - - emptyCalculatedNumberList: number[]; - calculatedNumberList: number[]; - undefinedCalculatedNumberList: number[]; - looseCalculatedNumberList: number[]; - calculatedOptionalNumberList?: number[]; - undefinedCalculatedOptionalNumberList?: number[]; - - // string - - emptyString: string; - string: string; - looseString: string; - undefinedOptionalString?: string; - optionalString?: string; - - emptyCalculatedString: string; - calculatedString: string; - undefinedCalculatedString: string; - looseCalculatedString: string; - calculatedOptionalString?: string; - undefinedCalculatedOptionalString?: string; - - // string List - - emptyStringList: string[]; - stringList: string[]; - looseStringList: string[]; - undefinedOptionalStringList?: string[]; - optionalStringList?: string[]; - - emptyCalculatedStringList: string[]; - calculatedStringList: string[]; - undefinedCalculatedStringList: string[]; - looseCalculatedStringList: string[]; - calculatedOptionalStringList?: string[]; - undefinedCalculatedOptionalStringList?: string[]; - - // Object - - object: ISomeObject; - looseObject: ISomeObject; - undefinedOptionalObject?: ISomeObject; - optionalObject?: ISomeObject; - - calculatedObject: ISomeObject; - undefinedCalculatedObject: ISomeObject; - looseCalculatedObject: ISomeObject; - calculatedOptionalObject?: ISomeObject; - undefinedCalculatedOptionalObject?: ISomeObject; - - // Object List - - objectList: ISomeObject[]; - looseObjectList: ISomeObject[]; - undefinedOptionalObjectList?: ISomeObject[]; - optionalObjectList?: ISomeObject[]; - - calculatedObjectList: ISomeObject[]; - undefinedCalculatedObjectList: ISomeObject[]; - looseCalculatedObjectList: ISomeObject[]; - calculatedOptionalObjectList?: ISomeObject[]; - undefinedCalculatedOptionalObjectList?: ISomeObject[]; - - // Enumerable Model - - enumerableModel: IEnumerable; - looseEnumerableModel: IEnumerable; - undefinedOptionalEnumerableModel?: IEnumerable; - optionalEnumerableModel?: IEnumerable; - - calculatedEnumerableModel: IEnumerable; - undefinedCalculatedEnumerableModel: IEnumerable; - looseCalculatedEnumerableModel: IEnumerable; - calculatedOptionalEnumerableModel?: IEnumerable; - undefinedCalculatedOptionalEnumerableModel?: IEnumerable; - - // Enumerable Model List - - enumerableModelList: IEnumerable[]; - looseEnumerableModelList: IEnumerable[]; - undefinedOptionalEnumerableModelList?: IEnumerable[]; - optionalEnumerableModelList?: IEnumerable[]; - - calculatedEnumerableModelList: IEnumerable[]; - undefinedCalculatedEnumerableModelList: IEnumerable[]; - looseCalculatedEnumerableModelList: IEnumerable[]; - calculatedOptionalEnumerableModelList?: IEnumerable[]; - undefinedCalculatedOptionalEnumerableModelList?: IEnumerable[]; - - // Singleton Model - - singletonModel: ISingleton; - looseSingletonModel: ISingleton; - undefinedOptionalSingletonModel?: ISingleton; - optionalSingletonModel?: ISingleton; - - calculatedSingletonModel: ISingleton; - undefinedCalculatedSingletonModel: ISingleton; - looseCalculatedSingletonModel: ISingleton; - calculatedOptionalSingletonModel?: ISingleton; - undefinedCalculatedOptionalSingletonModel?: ISingleton; - - // Singleton Model List - - singletonModelList: ISingleton[]; - looseSingletonModelList: ISingleton[]; - undefinedOptionalSingletonModelList?: ISingleton[]; - optionalSingletonModelList?: ISingleton[]; - - calculatedSingletonModelList: ISingleton[]; - undefinedCalculatedSingletonModelList: ISingleton[]; - looseCalculatedSingletonModelList: ISingleton[]; - calculatedOptionalSingletonModelList?: ISingleton[]; - undefinedCalculatedOptionalSingletonModelList?: ISingleton[]; +interface ICasesOfListedFieldsWithLoosedValues { + // value[] = [value, { loose }] + loosedListedFieldWithDefaultEmptyValue: T[] + loosedListedFieldCalculatedAsEmptyValue?: T[] + loosedListedOptionalFieldWithDefaultEmptyValue: T[] + loosedListedOptionalFieldCalculatedAsEmptyValue?: T[] } -const ModelStore: Model = { - id: true, +interface ICasesOfFieldsWithUndefinedValues { + // value = undefined + fieldWithDefaultUndefinedValue: T; + fieldCalculatedAsUndefinedValue: T; + optionalFieldWithDefaultUndefinedValue?: T; + optionalFieldCalculatedAsUndefinedValue?: T; +} - // boolean +interface ICasesOfListedFieldsWithUndefinedValues { + // value[] = undefined[] + listedFieldWithDefaultUndefinedValues: T[]; + listedFieldCalculatedAsUndefinedValues: T[]; + listedOptionalFieldWithDefaultUndefinedValues?: T[]; + listedOptionalFieldCalculatedAsUndefinedValues?: T[]; +} + +interface IPrimitivePositiveCases extends ICasesOfFieldsWithValues, ICasesOfListedFieldsWithValues, ICasesOfListedFieldsWithEmptyValues {} +interface IPrimitiveNegativeCases extends ICasesOfFieldsWithEmptyValues, ICasesOfListedFieldsWithLoosedValues, ICasesOfFieldsWithUndefinedValues, ICasesOfListedFieldsWithUndefinedValues {} + +const PrimitivePositiveCases: Model = { + // boolean = boolean + fieldWithDefaultValue: false, + fieldCalculatedAsValue: ({ fieldWithDefaultValue }) => fieldWithDefaultValue, + optionalFieldWithDefaultValue: false, + optionalFieldCalculatedAsValue: ({ optionalFieldWithDefaultValue }) => optionalFieldWithDefaultValue, + + // boolean[] = boolean[] + listedFieldWithDefaultValues: [false], + listedFieldCalculatedAsValues: ({ listedFieldWithDefaultValues }) => listedFieldWithDefaultValues, + listedOptionalFieldWithDefaultValues: [false], + listedOptionalFieldCalculatedAsValues: ({ listedOptionalFieldWithDefaultValues }) => listedOptionalFieldWithDefaultValues, + + // boolean[] = [Boolean] + listedFieldWithDefaultEmptyValues: [Boolean], + listedFieldCalculatedAsEmptyValues: ({ listedFieldWithDefaultEmptyValues }) => listedFieldWithDefaultEmptyValues && [Boolean], + listedOptionalFieldWithDefaultEmptyValues: [Boolean], + listedOptionalFieldCalculatedAsEmptyValues: ({ listedOptionalFieldWithDefaultEmptyValues }) => listedOptionalFieldWithDefaultEmptyValues && [Boolean], +} - boolean: false, +const PrimitiveNegativeCases: Model = { + // boolean = Boolean /// @ts-expect-error - emptyBoolean: Boolean, - optionalBoolean: false, + fieldWithDefaultEmptyValue: Boolean, /// @ts-expect-error - undefinedOptionalBoolean: undefined, - - calculatedBoolean: () => false, + fieldCalculatedAsEmptyValue: ({ fieldWithDefaultEmptyValue }) => fieldWithDefaultEmptyValue && Boolean, /// @ts-expect-error - undefinedCalculatedBoolean: () => undefined, + optionalFieldWithDefaultEmptyValue: Boolean, /// @ts-expect-error - emptyCalculatedBoolean: () => Boolean, - calculatedOptionalBoolean: () => false, - undefinedCalculatedOptionalBoolean: () => (condition ? undefined : false), - - // boolean List - - booleanList: [false], - emptyBooleanList: [Boolean], + optionalFieldCalculatedAsEmptyValue: ({ optionalFieldWithDefaultEmptyValue }) => optionalFieldWithDefaultEmptyValue && Boolean, + + // boolean[] = [Boolean, { loose }] /// @ts-expect-error - looseBooleanList: [false, { loose: true }], - optionalBooleanList: [false], + loosedListedFieldWithDefaultEmptyValue: [Boolean, { loose: true }], /// @ts-expect-error - undefinedOptionalBooleanList: undefined, - - calculatedBooleanList: () => [false], + loosedListedFieldCalculatedAsEmptyValue: ({ loosedListedFieldWithDefaultEmptyValue: loosedListedFieldWithDefaultUndefinedValues }) => loosedListedFieldWithDefaultUndefinedValues && [Boolean, { loose: true }], /// @ts-expect-error - undefinedCalculatedBooleanList: () => undefined, - emptyCalculatedBooleanList: () => [Boolean], + loosedListedOptionalFieldWithDefaultEmptyValue: [Boolean, { loose: true }], /// @ts-expect-error - looseCalculatedBooleanList: () => [false, { loose: true }], - calculatedOptionalBooleanList: () => [false], - undefinedCalculatedOptionalBooleanList: () => - condition ? undefined : [false], - - // number - - number: 0, + loosedListedOptionalFieldCalculatedAsEmptyValue: ({ loosedListedOptionalFieldWithDefaultEmptyValue: loosedListedOptionalFieldWithDefaultUndefinedValues }) => loosedListedOptionalFieldWithDefaultUndefinedValues && [Boolean, { loose: true }], + + // boolean = undefined /// @ts-expect-error - emptyNumber: Number, - optionalNumber: 0, + fieldWithDefaultUndefinedValue: undefined, /// @ts-expect-error - undefinedOptionalNumber: undefined, - - calculatedNumber: () => 0, + fieldCalculatedAsUndefinedValue: ({ fieldWithDefaultUndefinedValue }) => fieldWithDefaultUndefinedValue && undefined, /// @ts-expect-error - undefinedCalculatedNumber: () => undefined, + optionalFieldWithDefaultUndefinedValue: undefined, /// @ts-expect-error - emptyCalculatedNumber: () => Number, - calculatedOptionalNumber: () => 0, - undefinedCalculatedOptionalNumber: () => (condition ? undefined : 0), - - // number List + optionalFieldCalculatedAsUndefinedValue: ({ optionalFieldWithDefaultUndefinedValue }) => optionalFieldWithDefaultUndefinedValue && undefined, - numberList: [0], - emptyNumberList: [Number], + // boolean[] = undefined[] /// @ts-expect-error - looseNumberList: [0, { loose: true }], - optionalNumberList: [0], + listedFieldWithDefaultUndefinedValues: [undefined], /// @ts-expect-error - undefinedOptionalNumberList: undefined, - - calculatedNumberList: () => [0], + listedFieldCalculatedAsUndefinedValues: ({ listedFieldWithDefaultUndefinedValues }) => listedFieldWithDefaultUndefinedValues && [undefined], /// @ts-expect-error - undefinedCalculatedNumberList: () => undefined, - emptyCalculatedNumberList: () => [Number], + listedOptionalFieldWithDefaultUndefinedValues: [undefined], /// @ts-expect-error - looseCalculatedNumberList: () => [0, { loose: true }], - calculatedOptionalNumberList: () => [0], - undefinedCalculatedOptionalNumberList: () => (condition ? undefined : [0]), + listedOptionalFieldCalculatedAsUndefinedValues: ({ listedOptionalFieldWithDefaultUndefinedValues }) => listedOptionalFieldWithDefaultUndefinedValues && [undefined], +} - // string +interface ISomeObject { + stringProperty: string, + numberProperty: number, +} +interface IObjectPositiveCases extends ICasesOfFieldsWithValues, ICasesOfListedFieldsWithValues {} +interface IObjectNegativeCases extends ICasesOfFieldsWithEmptyValues, ICasesOfListedFieldsWithEmptyValues, ICasesOfListedFieldsWithLoosedValues, ICasesOfFieldsWithUndefinedValues, ICasesOfListedFieldsWithUndefinedValues {} + +const someObject: ISomeObject = { + stringProperty: "", + numberProperty: 1, +} + +const ObjectPositiveCases: Model = { + // ISomeObject = someObject + fieldWithDefaultValue: someObject, + fieldCalculatedAsValue: ({ fieldWithDefaultValue }) => fieldWithDefaultValue, + optionalFieldWithDefaultValue: someObject, + optionalFieldCalculatedAsValue: ({ optionalFieldWithDefaultValue }) => optionalFieldWithDefaultValue, + + // ISomeObject[] = someObject[] + listedFieldWithDefaultValues: [someObject, someObject], + listedFieldCalculatedAsValues: ({ listedFieldWithDefaultValues }) => listedFieldWithDefaultValues, + listedOptionalFieldWithDefaultValues: [someObject, someObject], + listedOptionalFieldCalculatedAsValues: ({ listedOptionalFieldWithDefaultValues }) => listedOptionalFieldWithDefaultValues, +} - string: "", +const ObjectNegativeCases: Model = { + // ISomeObject = Object /// @ts-expect-error - emptyString: String, - optionalString: "", + fieldWithDefaultEmptyValue: Object, /// @ts-expect-error - undefinedOptionalString: undefined, - - calculatedString: () => "", + fieldCalculatedAsEmptyValue: ({ fieldWithDefaultEmptyValue }) => fieldWithDefaultEmptyValue && Object, /// @ts-expect-error - undefinedCalculatedString: () => undefined, + optionalFieldWithDefaultEmptyValue: Object, /// @ts-expect-error - emptyCalculatedString: () => String, - calculatedOptionalString: () => "", - undefinedCalculatedOptionalString: () => (condition ? undefined : ""), - - // string List + optionalFieldCalculatedAsEmptyValue: ({ optionalFieldWithDefaultEmptyValue }) => optionalFieldWithDefaultEmptyValue && Object, - stringList: [""], - emptyStringList: [String], + // ISomeObject[] = [Object] /// @ts-expect-error - looseStringList: ["", { loose: true }], - optionalStringList: [""], + listedFieldWithDefaultEmptyValues: [Object], /// @ts-expect-error - undefinedOptionalStringList: undefined, - - calculatedStringList: () => [""], + listedFieldCalculatedAsEmptyValues: ({ listedFieldWithDefaultEmptyValues }) => listedFieldWithDefaultEmptyValues && [Object], /// @ts-expect-error - undefinedCalculatedStringList: () => undefined, - emptyCalculatedStringList: () => [String], + listedOptionalFieldWithDefaultEmptyValues: [Object], /// @ts-expect-error - looseCalculatedStringList: () => ["", { loose: true }], - calculatedOptionalStringList: () => [""], - undefinedCalculatedOptionalStringList: () => (condition ? undefined : [""]), - - // Object - - object: { prop: "", length: 0 }, - optionalObject: { prop: "", length: 0 }, + listedOptionalFieldCalculatedAsEmptyValues: ({ listedOptionalFieldWithDefaultEmptyValues }) => listedOptionalFieldWithDefaultEmptyValues && [Object], + + // ISomeObject[] = [Object, { loose }] /// @ts-expect-error - undefinedOptionalObject: undefined, - - calculatedObject: () => ({ prop: "", length: 0 }), + loosedListedFieldWithDefaultEmptyValue: [Object, { loose: true }], /// @ts-expect-error - undefinedCalculatedObject: () => undefined, - calculatedOptionalObject: () => ({ prop: "", length: 0 }), - undefinedCalculatedOptionalObject: () => - condition ? undefined : { prop: "", length: 0 }, - - // Object List - - objectList: [{ prop: "", length: 0 }], + loosedListedFieldCalculatedAsEmptyValue: ({ loosedListedFieldWithDefaultEmptyValue }) => loosedListedFieldWithDefaultEmptyValue && [Object, { loose: true }], /// @ts-expect-error - looseObjectList: [{ prop: "", length: 0 }, { loose: true }], - optionalObjectList: [{ prop: "", length: 0 }], + loosedListedOptionalFieldWithDefaultEmptyValue: [Object, { loose: true }], /// @ts-expect-error - undefinedOptionalObjectList: undefined, - - calculatedObjectList: () => [{ prop: "", length: 0 }], + loosedListedOptionalFieldCalculatedAsEmptyValue: ({ loosedListedOptionalFieldWithDefaultEmptyValue }) => loosedListedOptionalFieldWithDefaultEmptyValue && [Object, { loose: true }], + + // ISomeObject = undefined /// @ts-expect-error - undefinedCalculatedObjectList: () => undefined, + fieldWithDefaultUndefinedValue: undefined, /// @ts-expect-error - looseCalculatedObjectList: () => [{ prop: "", length: 0 }, { loose: true }], - calculatedOptionalObjectList: () => [{ prop: "", length: 0 }], - undefinedCalculatedOptionalObjectList: () => - condition ? undefined : [{ prop: "", length: 0 }], - - // Enumerable Model - - enumerableModel: Enumerable, - optionalEnumerableModel: Enumerable, + fieldCalculatedAsUndefinedValue: ({ fieldWithDefaultUndefinedValue }) => fieldWithDefaultUndefinedValue && undefined, /// @ts-expect-error - undefinedOptionalEnumerableModel: undefined, + optionalFieldWithDefaultUndefinedValue: undefined, + /// @ts-expect-error + optionalFieldCalculatedAsUndefinedValue: ({ optionalFieldWithDefaultUndefinedValue }) => optionalFieldWithDefaultUndefinedValue && undefined, - calculatedEnumerableModel: () => Enumerable, + // ISomeObject[] = undefined[] + /// @ts-expect-error + listedFieldWithDefaultUndefinedValues: [undefined], /// @ts-expect-error - undefinedCalculatedEnumerableModel: () => undefined, - calculatedOptionalEnumerableModel: () => Enumerable, - undefinedCalculatedOptionalEnumerableModel: () => - condition ? undefined : Enumerable, + listedFieldCalculatedAsUndefinedValues: ({ listedFieldWithDefaultUndefinedValues }) => listedFieldWithDefaultUndefinedValues && [undefined], + /// @ts-expect-error + listedOptionalFieldWithDefaultUndefinedValues: [undefined], + /// @ts-expect-error + listedOptionalFieldCalculatedAsUndefinedValues: ({ listedOptionalFieldWithDefaultUndefinedValues }) => listedOptionalFieldWithDefaultUndefinedValues && [undefined], +} - // Enumerable Model List +interface ISingletonPositiveCases extends ICasesOfFieldsWithEmptyValues {} +interface ISingletonNegativeCases extends ICasesOfFieldsWithValues, ICasesOfListedFieldsWithValues, ICasesOfListedFieldsWithEmptyValues, ICasesOfListedFieldsWithLoosedValues, ICasesOfFieldsWithUndefinedValues, ICasesOfListedFieldsWithUndefinedValues {} - enumerableModelList: [Enumerable], - looseEnumerableModelList: [Enumerable, { loose: true }], - optionalEnumerableModelList: [Enumerable], - /// @ts-expect-error - undefinedOptionalEnumerableModelList: undefined, +const singleton = store.sync(Singleton, {}) + +const SingletonPositiveCases: Model = { + // ISingleton = Singleton + fieldWithDefaultEmptyValue: Singleton, + fieldCalculatedAsEmptyValue: ({ fieldWithDefaultEmptyValue }) => fieldWithDefaultEmptyValue && Singleton, + optionalFieldWithDefaultEmptyValue: Singleton, + optionalFieldCalculatedAsEmptyValue: ({ optionalFieldWithDefaultEmptyValue }) => optionalFieldWithDefaultEmptyValue && Singleton, +} - calculatedEnumerableModelList: () => [Enumerable], +const SingletonNegativeCases: Model = { + // ISingleton = singleton + /// @ts-expect-error + fieldWithDefaultValue: singleton, + /// @ts-expect-error + fieldCalculatedAsValue: ({ fieldWithDefaultValue }) => fieldWithDefaultValue, /// @ts-expect-error - undefinedCalculatedEnumerableModelList: () => undefined, - looseCalculatedEnumerableModelList: () => [Enumerable, { loose: true }], - calculatedOptionalEnumerableModelList: () => [Enumerable], - undefinedCalculatedOptionalEnumerableModelList: () => - condition ? undefined : [Enumerable], + optionalFieldWithDefaultValue: singleton, + /// @ts-expect-error + optionalFieldCalculatedAsValue: ({ optionalFieldWithDefaultValue }) => optionalFieldWithDefaultValue, - // Singleton Model + // ISingleton[] = singleton[] + /// @ts-expect-error + listedFieldWithDefaultValues: [singleton, singleton], + /// @ts-expect-error + listedFieldCalculatedAsValues: ({ listedFieldWithDefaultValues }) => listedFieldWithDefaultValues, + /// @ts-expect-error + listedOptionalFieldWithDefaultValues: [singleton, singleton], + /// @ts-expect-error + listedOptionalFieldCalculatedAsValues: ({ listedOptionalFieldWithDefaultValues }) => listedOptionalFieldWithDefaultValues, - singletonModel: Singleton, - optionalSingletonModel: Singleton, + // ISingleton[] = [Singleton] + /// @ts-expect-error + listedFieldWithDefaultEmptyValues: [Singleton], + /// @ts-expect-error + listedFieldCalculatedAsEmptyValues: ({ listedFieldWithDefaultEmptyValues }) => listedFieldWithDefaultEmptyValues && [Singleton], + /// @ts-expect-error + listedOptionalFieldWithDefaultEmptyValues: [Singleton], + /// @ts-expect-error + listedOptionalFieldCalculatedAsEmptyValues: ({ listedOptionalFieldWithDefaultEmptyValues }) => listedOptionalFieldWithDefaultEmptyValues && [Singleton], + + // ISingleton[] = [Singleton, { loose }] + /// @ts-expect-error + loosedListedFieldWithDefaultEmptyValue: [Singleton, { loose: true }], + /// @ts-expect-error + loosedListedFieldCalculatedAsEmptyValue: ({ loosedListedFieldWithDefaultEmptyValue }) => loosedListedFieldWithDefaultEmptyValue && [Singleton, { loose: true }], /// @ts-expect-error - undefinedOptionalSingletonModel: undefined, + loosedListedOptionalFieldWithDefaultEmptyValue: [Singleton, { loose: true }], + /// @ts-expect-error + loosedListedOptionalFieldCalculatedAsEmptyValue: ({ loosedListedOptionalFieldWithDefaultEmptyValue }) => loosedListedOptionalFieldWithDefaultEmptyValue && [Singleton, { loose: true }], + + // ISingleton = undefined + /// @ts-expect-error + fieldWithDefaultUndefinedValue: undefined, + /// @ts-expect-error + fieldCalculatedAsUndefinedValue: ({ fieldWithDefaultUndefinedValue }) => fieldWithDefaultUndefinedValue && undefined, + /// @ts-expect-error + optionalFieldWithDefaultUndefinedValue: undefined, + /// @ts-expect-error + optionalFieldCalculatedAsUndefinedValue: ({ optionalFieldWithDefaultUndefinedValue }) => optionalFieldWithDefaultUndefinedValue && undefined, - calculatedSingletonModel: () => Singleton, + // ISingleton[] = undefined[] /// @ts-expect-error - undefinedCalculatedSingletonModel: () => undefined, - calculatedOptionalSingletonModel: () => Singleton, - undefinedCalculatedOptionalSingletonModel: () => - condition ? undefined : Singleton, + listedFieldWithDefaultUndefinedValues: [undefined], + /// @ts-expect-error + listedFieldCalculatedAsUndefinedValues: ({ listedFieldWithDefaultUndefinedValues }) => listedFieldWithDefaultUndefinedValues && [undefined], + /// @ts-expect-error + listedOptionalFieldWithDefaultUndefinedValues: [undefined], + /// @ts-expect-error + listedOptionalFieldCalculatedAsUndefinedValues: ({ listedOptionalFieldWithDefaultUndefinedValues }) => listedOptionalFieldWithDefaultUndefinedValues && [undefined], +} - // Singleton Model List +interface IEnumerablePositiveCases extends ICasesOfFieldsWithEmptyValues, ICasesOfListedFieldsWithEmptyValues, ICasesOfListedFieldsWithLoosedValues {} +interface IEnumerableNegativeCases extends ICasesOfFieldsWithValues, ICasesOfListedFieldsWithValues, ICasesOfFieldsWithUndefinedValues, ICasesOfListedFieldsWithUndefinedValues {} + +const enumerable = store.sync(Enumerable, {}) + +const EnumerablePositiveCases: Model = { + // IEnumerable = Enumerable + fieldWithDefaultEmptyValue: Enumerable, + fieldCalculatedAsEmptyValue: ({ fieldWithDefaultEmptyValue }) => fieldWithDefaultEmptyValue && Enumerable, + optionalFieldWithDefaultEmptyValue: Enumerable, + optionalFieldCalculatedAsEmptyValue: ({ optionalFieldWithDefaultEmptyValue }) => optionalFieldWithDefaultEmptyValue && Enumerable, + + // IEnumerable[] = [Enumerable] + listedFieldWithDefaultEmptyValues: [Enumerable], + listedFieldCalculatedAsEmptyValues: ({ listedFieldWithDefaultEmptyValues }) => listedFieldWithDefaultEmptyValues && [Enumerable], + listedOptionalFieldWithDefaultEmptyValues: [Enumerable], + listedOptionalFieldCalculatedAsEmptyValues: ({ listedOptionalFieldWithDefaultEmptyValues }) => listedOptionalFieldWithDefaultEmptyValues && [Enumerable], + + // IEnumerable[] = [Enumerable, { loose }] + loosedListedFieldWithDefaultEmptyValue: [Enumerable, { loose: true }], + loosedListedFieldCalculatedAsEmptyValue: ({ loosedListedFieldWithDefaultEmptyValue }) => loosedListedFieldWithDefaultEmptyValue && [Enumerable, { loose: true }], + loosedListedOptionalFieldWithDefaultEmptyValue: [Enumerable, { loose: true }], + loosedListedOptionalFieldCalculatedAsEmptyValue: ({ loosedListedOptionalFieldWithDefaultEmptyValue }) => loosedListedOptionalFieldWithDefaultEmptyValue && [Enumerable, { loose: true }], +} +const EnumerableNegativeCases: Model = { + // IEnumerable = enumerable /// @ts-expect-error - singletonModelList: [Singleton], + fieldWithDefaultValue: enumerable, /// @ts-expect-error - looseSingletonModelList: [Singleton, { loose: true }], + fieldCalculatedAsValue: ({ fieldWithDefaultValue }) => fieldWithDefaultValue, /// @ts-expect-error - optionalSingletonModelList: [Singleton], + optionalFieldWithDefaultValue: enumerable, /// @ts-expect-error - undefinedOptionalSingletonModelList: undefined, + optionalFieldCalculatedAsValue: ({ optionalFieldWithDefaultValue }) => optionalFieldWithDefaultValue, + // IEnumerable[] = enumerable[] /// @ts-expect-error - calculatedSingletonModelList: () => [Singleton], + listedFieldWithDefaultValues: [enumerable, enumerable], /// @ts-expect-error - undefinedCalculatedSingletonModelList: () => undefined, + listedFieldCalculatedAsValues: ({ listedFieldWithDefaultValues }) => listedFieldWithDefaultValues, /// @ts-expect-error - looseCalculatedSingletonModelList: () => [Singleton, { loose: true }], + listedOptionalFieldWithDefaultValues: [enumerable, enumerable], /// @ts-expect-error - calculatedOptionalSingletonModelList: () => [Singleton], + listedOptionalFieldCalculatedAsValues: ({ listedOptionalFieldWithDefaultValues }) => listedOptionalFieldWithDefaultValues, + + // IEnumerable = undefined /// @ts-expect-error - undefinedCalculatedOptionalSingletonModelList: () => - condition ? undefined : [Singleton], -}; - -export default ModelStore; + fieldWithDefaultUndefinedValue: undefined, + /// @ts-expect-error + fieldCalculatedAsUndefinedValue: ({ fieldWithDefaultUndefinedValue }) => fieldWithDefaultUndefinedValue && undefined, + /// @ts-expect-error + optionalFieldWithDefaultUndefinedValue: undefined, + /// @ts-expect-error + optionalFieldCalculatedAsUndefinedValue: ({ optionalFieldWithDefaultUndefinedValue }) => optionalFieldWithDefaultUndefinedValue && undefined, -/// @ts-expect-error -const EmptyStore: Model = { - id: true, - boolean: false, -}; + // IEnumerable[] = undefined[] + /// @ts-expect-error + listedFieldWithDefaultUndefinedValues: [undefined], + /// @ts-expect-error + listedFieldCalculatedAsUndefinedValues: ({ listedFieldWithDefaultUndefinedValues }) => listedFieldWithDefaultUndefinedValues && [undefined], + /// @ts-expect-error + listedOptionalFieldWithDefaultUndefinedValues: [undefined], + /// @ts-expect-error + listedOptionalFieldCalculatedAsUndefinedValues: ({ listedOptionalFieldWithDefaultUndefinedValues }) => listedOptionalFieldWithDefaultUndefinedValues && [undefined], +} From bb8b11c04c1f2b74fc53eec6eda6fbafaec26ce2 Mon Sep 17 00:00:00 2001 From: Tomoe <4.artem.0@gmail.com> Date: Wed, 18 Jun 2025 00:30:47 +0300 Subject: [PATCH 12/12] draft refactor(store): ModelDefinition --- .../deep-nested-enumerable.entity.ts | 6 +- .../deep-nested-enumerable.store.ts | 12 +- .../enumerable/enumerable.entity.ts | 28 +- .../.internals/enumerable/enumerable.store.ts | 32 +- .../nested-enumerable.entity.ts | 26 +- .../nested-enumerable.store.ts | 30 +- .../.internals/singleton/singleton.entity.ts | 24 +- .../.internals/singleton/singleton.store.ts | 54 +- test/types/store/direct-methods/clear.ts | 44 +- test/types/store/direct-methods/get.ts | 82 +- test/types/store/direct-methods/resolve.ts | 100 +- .../store/direct-methods/set-and-sync.ts | 1282 ++++++++++------- test/types/store/model-definition.ts | 327 +++-- test/types/store/record.ts | 17 +- test/types/store/ref.ts | 6 +- test/types/store/storage-external.ts | 15 +- types/index.d.ts | 619 ++++++-- 17 files changed, 1724 insertions(+), 980 deletions(-) diff --git a/test/types/store/.internals/deep-nested-enumerable/deep-nested-enumerable.entity.ts b/test/types/store/.internals/deep-nested-enumerable/deep-nested-enumerable.entity.ts index ddbf6fe3..ae29805c 100644 --- a/test/types/store/.internals/deep-nested-enumerable/deep-nested-enumerable.entity.ts +++ b/test/types/store/.internals/deep-nested-enumerable/deep-nested-enumerable.entity.ts @@ -1,3 +1,3 @@ -export interface IDeepNestedEnumerable { - id: string -} \ No newline at end of file +export interface IDeepNestedEnumerable { + id: string; +} diff --git a/test/types/store/.internals/deep-nested-enumerable/deep-nested-enumerable.store.ts b/test/types/store/.internals/deep-nested-enumerable/deep-nested-enumerable.store.ts index ad267a42..c9c01c6b 100644 --- a/test/types/store/.internals/deep-nested-enumerable/deep-nested-enumerable.store.ts +++ b/test/types/store/.internals/deep-nested-enumerable/deep-nested-enumerable.store.ts @@ -1,6 +1,6 @@ -import { IDeepNestedEnumerable } from "./deep-nested-enumerable.entity"; -import { Model } from "/types"; - -export const DeepNestedEnumerable: Model = { - id: true, -} \ No newline at end of file +import { IDeepNestedEnumerable } from "./deep-nested-enumerable.entity"; +import { Model } from "/types"; + +export const DeepNestedEnumerable: Model = { + id: true, +}; diff --git a/test/types/store/.internals/enumerable/enumerable.entity.ts b/test/types/store/.internals/enumerable/enumerable.entity.ts index 30e7117c..25ab3f3a 100644 --- a/test/types/store/.internals/enumerable/enumerable.entity.ts +++ b/test/types/store/.internals/enumerable/enumerable.entity.ts @@ -1,14 +1,14 @@ -import { INestedEnumerable } from "../nested-enumerable/nested-enumerable.entity" -import { ISingleton } from "../singleton/singleton.entity"; - -export interface IEnumerable { - id: string; - stringProperty: string; - numberProperty: number; - self: IEnumerable - nestedSingleton: ISingleton; - optionalNestedSingleton?: ISingleton; - nestedEnumerable: INestedEnumerable; - optionalNestedEnumerable?: INestedEnumerable; - nestedEnumerables: INestedEnumerable[]; -} \ No newline at end of file +import { INestedEnumerable } from "../nested-enumerable/nested-enumerable.entity"; +import { ISingleton } from "../singleton/singleton.entity"; + +export interface IEnumerable { + id: string; + stringProperty: string; + numberProperty: number; + self: IEnumerable; + nestedSingleton: ISingleton; + optionalNestedSingleton?: ISingleton; + nestedEnumerable: INestedEnumerable; + optionalNestedEnumerable?: INestedEnumerable; + nestedEnumerables: INestedEnumerable[]; +} diff --git a/test/types/store/.internals/enumerable/enumerable.store.ts b/test/types/store/.internals/enumerable/enumerable.store.ts index e8d00507..4e2f5220 100644 --- a/test/types/store/.internals/enumerable/enumerable.store.ts +++ b/test/types/store/.internals/enumerable/enumerable.store.ts @@ -1,16 +1,16 @@ -import { NestedEnumerable } from "../nested-enumerable/nested-enumerable.store"; -import { Singleton } from "../singleton/singleton.store"; -import { IEnumerable } from "./enumerable.entity"; -import { Model, store } from "/types"; - -export const Enumerable: Model = { - id: true, - stringProperty: "", - numberProperty: 0, - self: store.ref(() => Enumerable), - nestedSingleton: store.ref(() => Singleton), - optionalNestedSingleton: store.ref(() => Singleton), - nestedEnumerable: store.ref(() => NestedEnumerable), - optionalNestedEnumerable: store.ref(() => NestedEnumerable), - nestedEnumerables: store.ref(() => [NestedEnumerable]), -} \ No newline at end of file +import { NestedEnumerable } from "../nested-enumerable/nested-enumerable.store"; +import { Singleton } from "../singleton/singleton.store"; +import { IEnumerable } from "./enumerable.entity"; +import { ModelDefinition, store } from "/types"; + +export const Enumerable: ModelDefinition = { + id: true, + stringProperty: "", + numberProperty: 0, + self: store.ref(() => Enumerable), + nestedSingleton: store.ref(() => Singleton), + optionalNestedSingleton: store.ref(() => Singleton), + nestedEnumerable: store.ref(() => NestedEnumerable), + optionalNestedEnumerable: store.ref(() => NestedEnumerable), + nestedEnumerables: store.ref(() => [NestedEnumerable]), +}; diff --git a/test/types/store/.internals/nested-enumerable/nested-enumerable.entity.ts b/test/types/store/.internals/nested-enumerable/nested-enumerable.entity.ts index c8498da5..8720b1e6 100644 --- a/test/types/store/.internals/nested-enumerable/nested-enumerable.entity.ts +++ b/test/types/store/.internals/nested-enumerable/nested-enumerable.entity.ts @@ -1,13 +1,13 @@ -import { IDeepNestedEnumerable } from "../deep-nested-enumerable/deep-nested-enumerable.entity" -import { ISingleton } from "../singleton/singleton.entity"; - -export interface INestedEnumerable { - id: string - stringProperty: string; - numberProperty: number; - nestedSingleton: ISingleton; - optionalNestedSingleton?: ISingleton; - nestedEnumerable: IDeepNestedEnumerable; - optionalNestedEnumerable?: IDeepNestedEnumerable; - nestedEnumerables: IDeepNestedEnumerable[]; -} \ No newline at end of file +import { IDeepNestedEnumerable } from "../deep-nested-enumerable/deep-nested-enumerable.entity"; +import { ISingleton } from "../singleton/singleton.entity"; + +export interface INestedEnumerable { + id: string; + stringProperty: string; + numberProperty: number; + nestedSingleton: ISingleton; + optionalNestedSingleton?: ISingleton; + nestedEnumerable: IDeepNestedEnumerable; + optionalNestedEnumerable?: IDeepNestedEnumerable; + nestedEnumerables: IDeepNestedEnumerable[]; +} diff --git a/test/types/store/.internals/nested-enumerable/nested-enumerable.store.ts b/test/types/store/.internals/nested-enumerable/nested-enumerable.store.ts index b74f7144..4105528b 100644 --- a/test/types/store/.internals/nested-enumerable/nested-enumerable.store.ts +++ b/test/types/store/.internals/nested-enumerable/nested-enumerable.store.ts @@ -1,15 +1,15 @@ -import { DeepNestedEnumerable } from "../deep-nested-enumerable/deep-nested-enumerable.store"; -import { Singleton } from "../singleton/singleton.store"; -import { INestedEnumerable } from "./nested-enumerable.entity"; -import { Model, store } from "/types"; - -export const NestedEnumerable: Model = { - id: true, - stringProperty: "", - numberProperty: 0, - nestedSingleton: store.ref(() => Singleton), - optionalNestedSingleton: store.ref(() => Singleton), - nestedEnumerable: store.ref(() => DeepNestedEnumerable), - optionalNestedEnumerable: store.ref(() => DeepNestedEnumerable), - nestedEnumerables: store.ref(() => [DeepNestedEnumerable]), -} \ No newline at end of file +import { DeepNestedEnumerable } from "../deep-nested-enumerable/deep-nested-enumerable.store"; +import { Singleton } from "../singleton/singleton.store"; +import { INestedEnumerable } from "./nested-enumerable.entity"; +import { Model, store } from "/types"; + +export const NestedEnumerable: Model = { + id: true, + stringProperty: "", + numberProperty: 0, + nestedSingleton: store.ref(() => Singleton), + optionalNestedSingleton: store.ref(() => Singleton), + nestedEnumerable: store.ref(() => DeepNestedEnumerable), + optionalNestedEnumerable: store.ref(() => DeepNestedEnumerable), + nestedEnumerables: store.ref(() => [DeepNestedEnumerable]), +}; diff --git a/test/types/store/.internals/singleton/singleton.entity.ts b/test/types/store/.internals/singleton/singleton.entity.ts index 66d4b997..6eb9b323 100644 --- a/test/types/store/.internals/singleton/singleton.entity.ts +++ b/test/types/store/.internals/singleton/singleton.entity.ts @@ -1,12 +1,12 @@ -import { INestedEnumerable } from "../nested-enumerable/nested-enumerable.entity"; - -export interface ISingleton { - stringProperty: string; - numberProperty: number; - self: ISingleton - nestedSingleton: ISingleton; - optionalNestedSingleton?: ISingleton; - nestedEnumerable: INestedEnumerable; - optionalNestedEnumerable?: INestedEnumerable; - nestedEnumerables: INestedEnumerable[] -} +import { INestedEnumerable } from "../nested-enumerable/nested-enumerable.entity"; + +export interface ISingleton { + stringProperty: string; + numberProperty: number; + self: ISingleton; + nestedSingleton: ISingleton; + optionalNestedSingleton?: ISingleton; + nestedEnumerable: INestedEnumerable; + optionalNestedEnumerable?: INestedEnumerable; + nestedEnumerables: INestedEnumerable[]; +} diff --git a/test/types/store/.internals/singleton/singleton.store.ts b/test/types/store/.internals/singleton/singleton.store.ts index 977749ae..e515db2f 100644 --- a/test/types/store/.internals/singleton/singleton.store.ts +++ b/test/types/store/.internals/singleton/singleton.store.ts @@ -1,27 +1,27 @@ -import { NestedEnumerable } from "../nested-enumerable/nested-enumerable.store"; -import { ISingleton } from "./singleton.entity"; -import { Model, store } from "/types"; - -export const Singleton: Model = { - stringProperty: "", - numberProperty: 0, - self: store.ref(() => Singleton), - nestedSingleton: store.ref(() => Singleton), - optionalNestedSingleton: store.ref(() => Singleton), - nestedEnumerable: store.ref(() => NestedEnumerable), - optionalNestedEnumerable: store.ref(() => NestedEnumerable), - nestedEnumerables: store.ref(() => [NestedEnumerable]), -} - -const BrokenSingleton: Model = { - /// @ts-expect-error - id: true, - stringProperty: "", - numberProperty: 0, - self: store.ref(() => Singleton), - nestedSingleton: store.ref(() => Singleton), - optionalNestedSingleton: store.ref(() => Singleton), - nestedEnumerable: store.ref(() => NestedEnumerable), - optionalNestedEnumerable: store.ref(() => NestedEnumerable), - nestedEnumerables: store.ref(() => [NestedEnumerable]), -}; \ No newline at end of file +import { NestedEnumerable } from "../nested-enumerable/nested-enumerable.store"; +import { ISingleton } from "./singleton.entity"; +import { ModelDefinition, store } from "/types"; + +export const Singleton: ModelDefinition = { + stringProperty: "", + numberProperty: 0, + self: store.ref(() => Singleton), + nestedSingleton: store.ref(() => Singleton), + optionalNestedSingleton: store.ref(() => Singleton), + nestedEnumerable: store.ref(() => NestedEnumerable), + optionalNestedEnumerable: store.ref(() => NestedEnumerable), + nestedEnumerables: store.ref(() => [NestedEnumerable]), +}; + +const BrokenSingleton: ModelDefinition = { + /// @ts-expect-error + id: true, + stringProperty: "", + numberProperty: 0, + self: store.ref(() => Singleton), + nestedSingleton: store.ref(() => Singleton), + optionalNestedSingleton: store.ref(() => Singleton), + nestedEnumerable: store.ref(() => NestedEnumerable), + optionalNestedEnumerable: store.ref(() => NestedEnumerable), + nestedEnumerables: store.ref(() => [NestedEnumerable]), +}; diff --git a/test/types/store/direct-methods/clear.ts b/test/types/store/direct-methods/clear.ts index 2fec6eec..923757d4 100644 --- a/test/types/store/direct-methods/clear.ts +++ b/test/types/store/direct-methods/clear.ts @@ -1,22 +1,22 @@ -import { Enumerable } from "../.internals/enumerable/enumerable.store"; -import { Singleton } from "../.internals/singleton/singleton.store"; -import { store } from "/types"; - -const singleton = store.get(Singleton) -const enumerable = store.sync(Enumerable, { id: "1" }) - -// Overload via Definition -{ - store.clear(Singleton); - store.clear(Enumerable); - store.clear(Singleton, true); - store.clear(Enumerable, true); -} - -// Overload via instance -{ - store.clear(singleton); - store.clear(enumerable); - store.clear(singleton, true); - store.clear(enumerable, true); -} \ No newline at end of file +import { Enumerable } from "../.internals/enumerable/enumerable.store"; +import { Singleton } from "../.internals/singleton/singleton.store"; +import { store } from "/types"; + +const singleton = store.get(Singleton); +const enumerable = store.sync(Enumerable, { id: "1" }); + +// Overload via Definition +{ + store.clear(Singleton); + store.clear(Enumerable); + store.clear(Singleton, true); + store.clear(Enumerable, true); +} + +// Overload via instance +{ + store.clear(singleton); + store.clear(enumerable); + store.clear(singleton, true); + store.clear(enumerable, true); +} diff --git a/test/types/store/direct-methods/get.ts b/test/types/store/direct-methods/get.ts index 4166d688..7988479f 100644 --- a/test/types/store/direct-methods/get.ts +++ b/test/types/store/direct-methods/get.ts @@ -1,41 +1,41 @@ -import { IEnumerable } from "../.internals/enumerable/enumerable.entity"; -import { Enumerable } from "../.internals/enumerable/enumerable.store"; -import { ISingleton } from "../.internals/singleton/singleton.entity"; -import { Singleton } from "../.internals/singleton/singleton.store"; -import { store } from "/types"; - -let singletonInput: ISingleton -let singletonListInput: ISingleton[] -let enumerableInput: IEnumerable -let enumerableListInput: IEnumerable[] - -// Overload via Definition -{ - // ...read singleton - singletonInput = store.get(Singleton); - // ...read unidentified model - enumerableInput = store.get(Enumerable); // looks strange - - // read identified model - singletonInput = store.get(Singleton, "1"); // looks strange - enumerableInput = store.get(Enumerable, "1"); - - // read queried model - singletonInput = store.get(Singleton, { a: 1, b: 2 }); // looks strange - enumerableInput = store.get(Enumerable, { a: 1, b: 2 }); -} - -// Overload via [Definition] -{ - // ...read unidentified list - singletonListInput = store.get([Singleton]); // looks strange - enumerableListInput = store.get([Enumerable]); - - // ...read identified list - singletonListInput = store.get([Singleton], "1"); // looks strange - enumerableListInput = store.get([Enumerable], "1"); - - // ...read queried list - singletonListInput = store.get([Singleton], { a: 1, b: 2 }); // looks strange - enumerableListInput = store.get([Enumerable], { a: 1, b: 2 }); -} \ No newline at end of file +import { IEnumerable } from "../.internals/enumerable/enumerable.entity"; +import { Enumerable } from "../.internals/enumerable/enumerable.store"; +import { ISingleton } from "../.internals/singleton/singleton.entity"; +import { Singleton } from "../.internals/singleton/singleton.store"; +import { store } from "/types"; + +let singletonInput: ISingleton; +let singletonListInput: ISingleton[]; +let enumerableInput: IEnumerable; +let enumerableListInput: IEnumerable[]; + +// Overload via Definition +{ + // ...read singleton + singletonInput = store.get(Singleton); + // ...read unidentified model + enumerableInput = store.get(Enumerable); // looks strange + + // read identified model + singletonInput = store.get(Singleton, "1"); // looks strange + enumerableInput = store.get(Enumerable, "1"); + + // read queried model + singletonInput = store.get(Singleton, { a: 1, b: 2 }); // looks strange + enumerableInput = store.get(Enumerable, { a: 1, b: 2 }); +} + +// Overload via [Definition] +{ + // ...read unidentified list + singletonListInput = store.get([Singleton]); // looks strange + enumerableListInput = store.get([Enumerable]); + + // ...read identified list + singletonListInput = store.get([Singleton], "1"); // looks strange + enumerableListInput = store.get([Enumerable], "1"); + + // ...read queried list + singletonListInput = store.get([Singleton], { a: 1, b: 2 }); // looks strange + enumerableListInput = store.get([Enumerable], { a: 1, b: 2 }); +} diff --git a/test/types/store/direct-methods/resolve.ts b/test/types/store/direct-methods/resolve.ts index 650ca7e4..93107a26 100644 --- a/test/types/store/direct-methods/resolve.ts +++ b/test/types/store/direct-methods/resolve.ts @@ -1,50 +1,50 @@ -import { Enumerable } from "../.internals/enumerable/enumerable.store"; -import { IEnumerable } from "../.internals/enumerable/enumerable.entity"; -import { Singleton } from "../.internals/singleton/singleton.store"; -import { ISingleton } from "../.internals/singleton/singleton.entity"; -import { store } from "/types"; - -const singleton = store.get(Singleton) -const enumerable = store.sync(Enumerable, { id: "1" }) - -let singletonPromiseInput: Promise -let enumerablePromiseInput: Promise -let singletonListPromiseInput: Promise -let enumerableListPromiseInput: Promise - -// Overload via Definition -{ - // ...read singleton - singletonPromiseInput = store.resolve(Singleton); - // ...read unidentified model - enumerablePromiseInput = store.resolve(Enumerable); // looks strange - - // read identified model - singletonPromiseInput = store.resolve(Singleton, "1"); // looks strange - enumerablePromiseInput = store.resolve(Enumerable, "1"); - - // read queried model - singletonPromiseInput = store.resolve(Singleton, { a: 1, b: 2 }); // looks strange - enumerablePromiseInput = store.resolve(Enumerable, { a: 1, b: 2 }); -} - -// Overload via [Definition] -{ - // ...read unidentified list - singletonListPromiseInput = store.resolve([Singleton]); // looks strange - enumerableListPromiseInput = store.resolve([Enumerable]); - - // ...read identified list - singletonListPromiseInput = store.resolve([Singleton], "1"); // looks strange - enumerableListPromiseInput = store.resolve([Enumerable], "1"); - - // ...read queried list - singletonListPromiseInput = store.resolve([Singleton], { a: 1, b: 2 }); // looks strange - enumerableListPromiseInput = store.resolve([Enumerable], { a: 1, b: 2 }); -} - -// Overload via instance -{ - singletonPromiseInput = store.resolve(singleton); - enumerablePromiseInput = store.resolve(enumerable); -} \ No newline at end of file +import { Enumerable } from "../.internals/enumerable/enumerable.store"; +import { IEnumerable } from "../.internals/enumerable/enumerable.entity"; +import { Singleton } from "../.internals/singleton/singleton.store"; +import { ISingleton } from "../.internals/singleton/singleton.entity"; +import { store } from "/types"; + +const singleton = store.get(Singleton); +const enumerable = store.sync(Enumerable, { id: "1" }); + +let singletonPromiseInput: Promise; +let enumerablePromiseInput: Promise; +let singletonListPromiseInput: Promise; +let enumerableListPromiseInput: Promise; + +// Overload via Definition +{ + // ...read singleton + singletonPromiseInput = store.resolve(Singleton); + // ...read unidentified model + enumerablePromiseInput = store.resolve(Enumerable); // looks strange + + // read identified model + singletonPromiseInput = store.resolve(Singleton, "1"); // looks strange + enumerablePromiseInput = store.resolve(Enumerable, "1"); + + // read queried model + singletonPromiseInput = store.resolve(Singleton, { a: 1, b: 2 }); // looks strange + enumerablePromiseInput = store.resolve(Enumerable, { a: 1, b: 2 }); +} + +// Overload via [Definition] +{ + // ...read unidentified list + singletonListPromiseInput = store.resolve([Singleton]); // looks strange + enumerableListPromiseInput = store.resolve([Enumerable]); + + // ...read identified list + singletonListPromiseInput = store.resolve([Singleton], "1"); // looks strange + enumerableListPromiseInput = store.resolve([Enumerable], "1"); + + // ...read queried list + singletonListPromiseInput = store.resolve([Singleton], { a: 1, b: 2 }); // looks strange + enumerableListPromiseInput = store.resolve([Enumerable], { a: 1, b: 2 }); +} + +// Overload via instance +{ + singletonPromiseInput = store.resolve(singleton); + enumerablePromiseInput = store.resolve(enumerable); +} diff --git a/test/types/store/direct-methods/set-and-sync.ts b/test/types/store/direct-methods/set-and-sync.ts index 8a4fec30..0453e712 100644 --- a/test/types/store/direct-methods/set-and-sync.ts +++ b/test/types/store/direct-methods/set-and-sync.ts @@ -1,526 +1,756 @@ -import { NestedEnumerable } from "../.internals/nested-enumerable/nested-enumerable.store" -import { Enumerable } from "../.internals/enumerable/enumerable.store" -import { Singleton } from "../.internals/singleton/singleton.store" -import { store } from "/types" -import { IEnumerable } from "../.internals/enumerable/enumerable.entity" -import { ISingleton } from "../.internals/singleton/singleton.entity" - -const nestedEnumerable = store.sync(NestedEnumerable, { id: "1" }) -const enumerable = store.sync(Enumerable, { id: "1" }) -const singleton = store.get(Singleton) - -let enumerablePromiseInput: Promise -let singletonPromiseInput: Promise -let enumerableInput: IEnumerable -let singletonInput: ISingleton - -const primitives = { - stringProperty: "qweqwe", - numberProperty: 123456789, -} -const primitivesInCreateNestedModels = { - nestedEnumerable: primitives, - optionalNestedEnumerable: primitives, - nestedSingleton: primitives, - optionalNestedSingleton: primitives, - nestedEnumerables: [primitives, primitives] -} -const primitivesInUpdateNestedModels = { - nestedEnumerable: { id: "1", ...primitives }, - optionalNestedEnumerable: { id: "1", ...primitives }, - nestedSingleton: { ...primitives }, - optionalNestedSingleton: { ...primitives }, - nestedEnumerables: [{ id: "1", ...primitives }, { id: "1", ...primitives }] -} - -const empty = {} -const emptyInCreateNestedModels = { - nestedEnumerable: empty, - optionalNestedEnumerable: empty, - nestedSingleton: empty, - optionalNestedSingleton: empty, - nestedEnumerables: [empty, empty] -} -const emptyInUpdateNestedModels = { - nestedEnumerable: { id: "1", ...empty }, - optionalNestedEnumerable: { id: "1", ...empty }, - nestedSingleton: { ...empty }, - optionalNestedSingleton: { ...empty }, - nestedEnumerables: [{ id: "1", ...empty }, { id: "1", ...empty }] -} - -const refs = { - nestedSingleton: singleton, - optionalNestedSingleton: singleton, - nestedEnumerable: nestedEnumerable, - optionalNestedEnumerable: nestedEnumerable, - nestedEnumerables: [nestedEnumerable, nestedEnumerable], -} -const refsInCreateNestedModels = { - nestedEnumerable: refs, - optionalNestedEnumerable: refs, - nestedSingleton: refs, - optionalNestedSingleton: refs, - nestedEnumerables: [refs, refs] -} -const refsInUpdateNestedModels = { - nestedEnumerable: { id: "1", ...refs }, - optionalNestedEnumerable: { id: "1", ...refs }, - nestedSingleton: { ...refs }, - optionalNestedSingleton: { ...refs }, - nestedEnumerables: [{ id: "1", ...refs }, { id: "1", ...refs }] -} - -const identifiers = { - nestedSingleton: "1", - optionalNestedSingleton: "1", - nestedEnumerable: "1", - optionalNestedEnumerable: "1", - nestedEnumerables: ["1", "2"], -} -const identifiersInCreateNestedModels = { - nestedEnumerable: identifiers, - optionalNestedEnumerable: identifiers, - nestedSingleton: identifiers, - optionalNestedSingleton: identifiers, - nestedEnumerables: [identifiers, identifiers] -} -const identifiersInUpdateNestedModels = { - nestedEnumerable: { id: "1", ...identifiers }, - optionalNestedEnumerable: { id: "1", ...identifiers }, - nestedSingleton: { ...identifiers }, - optionalNestedSingleton: { ...identifiers }, - nestedEnumerables: [{ id: "1", ...identifiers }, { id: "1", ...identifiers }] -} - -const unrefs = { - nestedSingleton: undefined, - optionalNestedSingleton: undefined, - nestedEnumerable: undefined, - optionalNestedEnumerable: undefined, - nestedEnumerables: [], -} -const unrefsInCreateNestedModels = { - nestedEnumerable: unrefs, - optionalNestedEnumerable: unrefs, - nestedSingleton: unrefs, - optionalNestedSingleton: unrefs, - nestedEnumerables: [unrefs, unrefs] -} -const unrefsInUpdateNestedModels = { - nestedEnumerable: { id: "1", ...unrefs }, - optionalNestedEnumerable: { id: "1", ...unrefs }, - nestedSingleton: { ...unrefs }, - optionalNestedSingleton: { ...unrefs }, - nestedEnumerables: [{ id: "1", ...unrefs }, { id: "1", ...unrefs }] -} - -const collisions = { - nestedSingleton: [{}], - optionalNestedSingleton: [{}], - nestedEnumerable: [{}], - optionalNestedEnumerable: [{}], - nestedEnumerables: {}, -} -const collisionsInCreateNestedModels = { - nestedEnumerable: collisions, - optionalNestedEnumerable: collisions, - nestedSingleton: collisions, - optionalNestedSingleton: collisions, - nestedEnumerables: [collisions, collisions] -} -const collisionsInUpdateNestedModels = { - nestedEnumerable: { id: "1", ...collisions }, - optionalNestedEnumerable: { id: "1", ...collisions }, - nestedSingleton: { ...collisions }, - optionalNestedSingleton: { ...collisions }, - nestedEnumerables: [{ id: "1", ...collisions }, { id: "1", ...collisions }] -} - -// Overload via Definition -{ - // Create... - { - // Create model via Definition - { - // ...set primitive propertiers - enumerablePromiseInput = store.set(Enumerable, primitives) - enumerableInput = store.sync(Enumerable, primitives) - - // ...use default values - enumerablePromiseInput = store.set(Enumerable, empty) - enumerableInput = store.sync(Enumerable, empty) - - // ...binding through refs - enumerablePromiseInput = store.set(Enumerable, refs) - enumerableInput = store.sync(Enumerable, refs) - - // ...binding through identifiers - enumerablePromiseInput = store.set(Enumerable, identifiers) - enumerableInput = store.sync(Enumerable, identifiers) - - // ...unbinding - enumerablePromiseInput = store.set(Enumerable, unrefs) - enumerableInput = store.sync(Enumerable, unrefs) - - // ...check collisions - /// @ts-expect-error - store.set(Enumerable, collisions); - /// @ts-expect-error - store.sync(Enumerable, collisions); - } - - // Create model & nested via Definition - { - // ...set primitive propertiers - enumerablePromiseInput = store.set(Enumerable, primitivesInCreateNestedModels) - enumerableInput = store.sync(Enumerable, primitivesInCreateNestedModels) - - // ...use default values - enumerablePromiseInput = store.set(Enumerable, emptyInCreateNestedModels) - enumerableInput = store.sync(Enumerable, emptyInCreateNestedModels) - - // ...binding through refs - enumerablePromiseInput = store.set(Enumerable, refsInCreateNestedModels) - enumerableInput = store.sync(Enumerable, refsInCreateNestedModels) - - // ...binding through identifiers - enumerablePromiseInput = store.set(Enumerable, identifiersInCreateNestedModels) - enumerableInput = store.sync(Enumerable, identifiersInCreateNestedModels) - - // ...unbinding - enumerablePromiseInput = store.set(Enumerable, unrefsInCreateNestedModels) - enumerableInput = store.sync(Enumerable, unrefsInCreateNestedModels) - - // ...check collisions - /// @ts-expect-error - enumerablePromiseInput = store.set(Enumerable, collisionsInCreateNestedModels) - /// @ts-expect-error - enumerableInput = store.sync(Enumerable, collisionsInCreateNestedModels) - } - } - - // Update... - { - // Update model via Definition - { - // ...set primitive propertiers - singletonPromiseInput = store.set(Singleton, primitives) - singletonInput = store.sync(Singleton, primitives) - enumerablePromiseInput = store.set(Enumerable, { id: "1", ...primitives }) - enumerableInput = store.sync(Enumerable, { id: "1", ...primitives }) - - // ...use default values - singletonPromiseInput = store.set(Singleton, empty) - singletonInput = store.sync(Singleton, empty) - enumerablePromiseInput = store.set(Enumerable, { id: "1", ...empty }) - enumerableInput = store.sync(Enumerable, { id: "1", ...empty }) - - // ...binding through refs - singletonPromiseInput = store.set(Singleton, refs) - singletonInput = store.sync(Singleton, refs) - enumerablePromiseInput = store.set(Enumerable, { id: "1", ...refs }) - enumerableInput = store.sync(Enumerable, { id: "1", ...refs }) - - // ...binding through identifiers - singletonPromiseInput = store.set(Singleton, identifiers) - singletonInput = store.sync(Singleton, identifiers) - enumerablePromiseInput = store.set(Enumerable, { id: "1", ...identifiers }) - enumerableInput = store.sync(Enumerable, { id: "1", ...identifiers }) - - // ...unbinding - singletonPromiseInput = store.set(Singleton, unrefs) - singletonInput = store.sync(Singleton, unrefs) - enumerablePromiseInput = store.set(Enumerable, { id: "1", ...unrefs }) - enumerableInput = store.sync(Enumerable, { id: "1", ...unrefs }) - - // ...check collisions - /// @ts-expect-error - singletonPromiseInput = store.set(Singleton, collisions) - /// @ts-expect-error - singletonInput = store.sync(Singleton, collisions) - /// @ts-expect-error - enumerablePromiseInput = store.set(Enumerable, { id: "1", ...collisions }) - /// @ts-expect-error - enumerableInput = store.sync(Enumerable, { id: "1", ...collisions }) - } - - // Update model & nested via Definition - { - // ...set primitive propertiers - singletonPromiseInput = store.set(Singleton, primitivesInUpdateNestedModels) - singletonInput = store.sync(Singleton, primitivesInUpdateNestedModels) - enumerablePromiseInput = store.set(Enumerable, { id: "1", ...primitivesInUpdateNestedModels }) - enumerableInput = store.sync(Enumerable, { id: "1", ...primitivesInUpdateNestedModels }) - - // ...use default values - singletonPromiseInput = store.set(Singleton, emptyInUpdateNestedModels) - singletonInput = store.sync(Singleton, emptyInUpdateNestedModels) - enumerablePromiseInput = store.set(Enumerable, { id: "1", ...emptyInUpdateNestedModels }) - enumerableInput = store.sync(Enumerable, { id: "1", ...emptyInUpdateNestedModels }) - - // ...binding through refs - singletonPromiseInput = store.set(Singleton, refsInUpdateNestedModels) - singletonInput = store.sync(Singleton, refsInUpdateNestedModels) - enumerablePromiseInput = store.set(Enumerable, { id: "1", ...refsInUpdateNestedModels }) - enumerableInput = store.sync(Enumerable, { id: "1", ...refsInUpdateNestedModels }) - - // ...binding through identifiers - singletonPromiseInput = store.set(Singleton, identifiersInUpdateNestedModels) - singletonInput = store.sync(Singleton, identifiersInUpdateNestedModels) - enumerablePromiseInput = store.set(Enumerable, { id: "1", ...identifiersInUpdateNestedModels }) - enumerableInput = store.sync(Enumerable, { id: "1", ...identifiersInUpdateNestedModels }) - - // ...unbinding - singletonPromiseInput = store.set(Singleton, unrefsInUpdateNestedModels) - singletonInput = store.sync(Singleton, unrefsInUpdateNestedModels) - enumerablePromiseInput = store.set(Enumerable, { id: "1", ...unrefsInUpdateNestedModels }) - enumerableInput = store.sync(Enumerable, { id: "1", ...unrefsInUpdateNestedModels }) - - // ...check collisions - /// @ts-expect-error - singletonPromiseInput = store.set(Singleton, collisionsInUpdateNestedModels) - /// @ts-expect-error - singletonInput = store.sync(Singleton, collisionsInUpdateNestedModels) - /// @ts-expect-error - enumerablePromiseInput = store.set(Enumerable, { id: "1", ...collisionsInUpdateNestedModels }) - /// @ts-expect-error - enumerableInput = store.sync(Enumerable, { id: "1", ...collisionsInUpdateNestedModels }) - } - } - - // Delete... - { - // Delete model via Definition - - /// @ts-expect-error - enumerablePromiseInput = store.set(Enumerable, null) - /// @ts-expect-error - enumerableInput = store.sync(Enumerable, null) - - singletonPromiseInput = store.set(Singleton, null) - singletonInput = store.sync(Singleton, null) - } - - // Mixed... - { - // Create model and Update nested via Definition - { - // ...set primitive propertiers - enumerablePromiseInput = store.set(Enumerable, primitivesInUpdateNestedModels) - enumerableInput = store.sync(Enumerable, primitivesInUpdateNestedModels) - - // ...use default values - enumerablePromiseInput = store.set(Enumerable, emptyInUpdateNestedModels) - enumerableInput = store.sync(Enumerable, emptyInUpdateNestedModels) - - // ...binding through refs - enumerablePromiseInput = store.set(Enumerable, refsInUpdateNestedModels) - enumerableInput = store.sync(Enumerable, refsInUpdateNestedModels) - - // ...binding through identifiers - enumerablePromiseInput = store.set(Enumerable, identifiersInUpdateNestedModels) - enumerableInput = store.sync(Enumerable, identifiersInUpdateNestedModels) - - // ...unbinding - enumerablePromiseInput = store.set(Enumerable, unrefsInUpdateNestedModels) - enumerableInput = store.sync(Enumerable, unrefsInUpdateNestedModels) - - // ...check collisions - /// @ts-expect-error - enumerablePromiseInput = store.set(Enumerable, collisionsInUpdateNestedModels) - /// @ts-expect-error - enumerableInput = store.sync(Enumerable, collisionsInUpdateNestedModels) - } - - // Update model and Create nested via Definition - { - // ...set primitive propertiers - singletonPromiseInput = store.set(Singleton, primitivesInCreateNestedModels) - singletonInput = store.sync(Singleton, primitivesInCreateNestedModels) - enumerablePromiseInput = store.set(Enumerable, { id: "1", ...primitivesInCreateNestedModels }) - enumerableInput = store.sync(Enumerable, { id: "1", ...primitivesInCreateNestedModels }) - - // ...use default values - singletonPromiseInput = store.set(Singleton, emptyInCreateNestedModels) - singletonInput = store.sync(Singleton, emptyInCreateNestedModels) - enumerablePromiseInput = store.set(Enumerable, { id: "1", ...emptyInCreateNestedModels }) - enumerableInput = store.sync(Enumerable, { id: "1", ...emptyInCreateNestedModels }) - - // ...binding through refs - singletonPromiseInput = store.set(Singleton, refsInCreateNestedModels) - singletonInput = store.sync(Singleton, refsInCreateNestedModels) - enumerablePromiseInput = store.set(Enumerable, { id: "1", ...refsInCreateNestedModels }) - enumerableInput = store.sync(Enumerable, { id: "1", ...refsInCreateNestedModels }) - - // ...binding through identifiers - singletonPromiseInput = store.set(Singleton, identifiersInCreateNestedModels) - singletonInput = store.sync(Singleton, identifiersInCreateNestedModels) - enumerablePromiseInput = store.set(Enumerable, { id: "1", ...identifiersInCreateNestedModels }) - enumerableInput = store.sync(Enumerable, { id: "1", ...identifiersInCreateNestedModels }) - - // ...unbinding - singletonPromiseInput = store.set(Singleton, unrefsInCreateNestedModels) - singletonInput = store.sync(Singleton, unrefsInCreateNestedModels) - enumerablePromiseInput = store.set(Enumerable, { id: "1", ...unrefsInCreateNestedModels }) - enumerableInput = store.sync(Enumerable, { id: "1", ...unrefsInCreateNestedModels }) - - // ...check collisions - /// @ts-expect-error - singletonPromiseInput = store.set(Singleton, collisionsInCreateNestedModels) - /// @ts-expect-error - singletonInput = store.sync(Singleton, collisionsInCreateNestedModels) - /// @ts-expect-error - enumerablePromiseInput = store.set(Enumerable, { id: "1", ...collisionsInCreateNestedModels }) - /// @ts-expect-error - enumerableInput = store.sync(Enumerable, { id: "1", ...collisionsInCreateNestedModels }) - } - } -} - -// Overload via instance -{ - // Update model via instance - { - // ...set primitive propertiers - singletonPromiseInput = store.set(singleton, primitives) - singletonInput = store.sync(singleton, primitives) - enumerablePromiseInput = store.set(enumerable, { id: "1", ...primitives }) - enumerableInput = store.sync(enumerable, { id: "1", ...primitives }) - - // ...use default values - singletonPromiseInput = store.set(singleton, empty) - singletonInput = store.sync(singleton, empty) - enumerablePromiseInput = store.set(enumerable, { id: "1", ...empty }) - enumerableInput = store.sync(enumerable, { id: "1", ...empty }) - - // ...binding through refs - singletonPromiseInput = store.set(singleton, refs) - singletonInput = store.sync(singleton, refs) - enumerablePromiseInput = store.set(enumerable, { id: "1", ...refs }) - enumerableInput = store.sync(enumerable, { id: "1", ...refs }) - - // ...binding through identifiers - singletonPromiseInput = store.set(singleton, identifiers) - singletonInput = store.sync(singleton, identifiers) - enumerablePromiseInput = store.set(enumerable, { id: "1", ...identifiers }) - enumerableInput = store.sync(enumerable, { id: "1", ...identifiers }) - - // ...unbinding - singletonPromiseInput = store.set(singleton, unrefs) - singletonInput = store.sync(singleton, unrefs) - enumerablePromiseInput = store.set(enumerable, { id: "1", ...unrefs }) - enumerableInput = store.sync(enumerable, { id: "1", ...unrefs }) - - // ...check collisions - /// @ts-expect-error - singletonPromiseInput = store.set(singleton, collisions) - /// @ts-expect-error - singletonInput = store.sync(singleton, collisions) - /// @ts-expect-error - enumerablePromiseInput = store.set(enumerable, { id: "1", ...collisions }) - /// @ts-expect-error - enumerableInput = store.sync(enumerable, { id: "1", ...collisions }) - } - - // Update model & nested via instance - { - // ...set primitive propertiers - singletonPromiseInput = store.set(singleton, primitivesInUpdateNestedModels) - singletonInput = store.sync(singleton, primitivesInUpdateNestedModels) - enumerablePromiseInput = store.set(enumerable, { id: "1", ...primitivesInUpdateNestedModels }) - enumerableInput = store.sync(enumerable, { id: "1", ...primitivesInUpdateNestedModels }) - - // ...use default values - singletonPromiseInput = store.set(singleton, emptyInUpdateNestedModels) - singletonInput = store.sync(singleton, emptyInUpdateNestedModels) - enumerablePromiseInput = store.set(enumerable, { id: "1", ...emptyInUpdateNestedModels }) - enumerableInput = store.sync(enumerable, { id: "1", ...emptyInUpdateNestedModels }) - - // ...binding through refs - singletonPromiseInput = store.set(singleton, refsInUpdateNestedModels) - singletonInput = store.sync(singleton, refsInUpdateNestedModels) - enumerablePromiseInput = store.set(enumerable, { id: "1", ...refsInUpdateNestedModels }) - enumerableInput = store.sync(enumerable, { id: "1", ...refsInUpdateNestedModels }) - - // ...binding through identifiers - singletonPromiseInput = store.set(singleton, identifiersInUpdateNestedModels) - singletonInput = store.sync(singleton, identifiersInUpdateNestedModels) - enumerablePromiseInput = store.set(enumerable, { id: "1", ...identifiersInUpdateNestedModels }) - enumerableInput = store.sync(enumerable, { id: "1", ...identifiersInUpdateNestedModels }) - - // ...unbinding - singletonPromiseInput = store.set(singleton, unrefsInUpdateNestedModels) - singletonInput = store.sync(singleton, unrefsInUpdateNestedModels) - enumerablePromiseInput = store.set(enumerable, { id: "1", ...unrefsInUpdateNestedModels }) - enumerableInput = store.sync(enumerable, { id: "1", ...unrefsInUpdateNestedModels }) - - // ...check collisions - /// @ts-expect-error - singletonPromiseInput = store.set(singleton, collisionsInUpdateNestedModels) - /// @ts-expect-error - singletonInput = store.sync(singleton, collisionsInUpdateNestedModels) - /// @ts-expect-error - enumerablePromiseInput = store.set(enumerable, { id: "1", ...collisionsInUpdateNestedModels }) - /// @ts-expect-error - enumerableInput = store.sync(enumerable, { id: "1", ...collisionsInUpdateNestedModels }) - } - - // Mixed... - { - // Update model and Create nested via Definition - { - // ...set primitive propertiers - singletonPromiseInput = store.set(singleton, primitivesInCreateNestedModels) - singletonInput = store.sync(singleton, primitivesInCreateNestedModels) - enumerablePromiseInput = store.set(enumerable, { id: "1", ...primitivesInCreateNestedModels }) - enumerableInput = store.sync(enumerable, { id: "1", ...primitivesInCreateNestedModels }) - - // ...use default values - singletonPromiseInput = store.set(singleton, emptyInCreateNestedModels) - singletonInput = store.sync(singleton, emptyInCreateNestedModels) - enumerablePromiseInput = store.set(enumerable, { id: "1", ...emptyInCreateNestedModels }) - enumerableInput = store.sync(enumerable, { id: "1", ...emptyInCreateNestedModels }) - - // ...binding through refs - singletonPromiseInput = store.set(singleton, refsInCreateNestedModels) - singletonInput = store.sync(singleton, refsInCreateNestedModels) - enumerablePromiseInput = store.set(enumerable, { id: "1", ...refsInCreateNestedModels }) - enumerableInput = store.sync(enumerable, { id: "1", ...refsInCreateNestedModels }) - - // ...binding through identifiers - singletonPromiseInput = store.set(singleton, identifiersInCreateNestedModels) - singletonInput = store.sync(singleton, identifiersInCreateNestedModels) - enumerablePromiseInput = store.set(enumerable, { id: "1", ...identifiersInCreateNestedModels }) - enumerableInput = store.sync(enumerable, { id: "1", ...identifiersInCreateNestedModels }) - - // ...unbinding - singletonPromiseInput = store.set(singleton, unrefsInCreateNestedModels) - singletonInput = store.sync(singleton, unrefsInCreateNestedModels) - enumerablePromiseInput = store.set(enumerable, { id: "1", ...unrefsInCreateNestedModels }) - enumerableInput = store.sync(enumerable, { id: "1", ...unrefsInCreateNestedModels }) - - // ...check collisions - /// @ts-expect-error - singletonPromiseInput = store.set(singleton, collisionsInCreateNestedModels) - /// @ts-expect-error - singletonInput = store.sync(singleton, collisionsInCreateNestedModels) - /// @ts-expect-error - enumerablePromiseInput = store.set(enumerable, { id: "1", ...collisionsInCreateNestedModels }) - /// @ts-expect-error - enumerableInput = store.sync(enumerable, { id: "1", ...collisionsInCreateNestedModels }) - } - } -} - -// Delete... -{ - // delete model via instance - { - enumerablePromiseInput = store.set(enumerable, null) - enumerableInput = store.sync(enumerable, null) - singletonPromiseInput = store.set(singleton, null) // is may be cleaning of the model values or draft values - singletonInput = store.sync(singleton, null) // is may be cleaning of the model values or draft values - } -} - +import { NestedEnumerable } from "../.internals/nested-enumerable/nested-enumerable.store"; +import { Enumerable } from "../.internals/enumerable/enumerable.store"; +import { Singleton } from "../.internals/singleton/singleton.store"; +import { store } from "/types"; +import { IEnumerable } from "../.internals/enumerable/enumerable.entity"; +import { ISingleton } from "../.internals/singleton/singleton.entity"; + +const nestedEnumerable = store.sync(NestedEnumerable, { id: "1" }); +const enumerable = store.sync(Enumerable, { id: "1" }); +const singleton = store.get(Singleton); + +let enumerablePromiseInput: Promise; +let singletonPromiseInput: Promise; +let enumerableInput: IEnumerable; +let singletonInput: ISingleton; + +const primitives = { + stringProperty: "qweqwe", + numberProperty: 123456789, +}; +const primitivesInCreateNestedModels = { + nestedEnumerable: primitives, + optionalNestedEnumerable: primitives, + nestedSingleton: primitives, + optionalNestedSingleton: primitives, + nestedEnumerables: [primitives, primitives], +}; +const primitivesInUpdateNestedModels = { + nestedEnumerable: { id: "1", ...primitives }, + optionalNestedEnumerable: { id: "1", ...primitives }, + nestedSingleton: { ...primitives }, + optionalNestedSingleton: { ...primitives }, + nestedEnumerables: [ + { id: "1", ...primitives }, + { id: "1", ...primitives }, + ], +}; + +const empty = {}; +const emptyInCreateNestedModels = { + nestedEnumerable: empty, + optionalNestedEnumerable: empty, + nestedSingleton: empty, + optionalNestedSingleton: empty, + nestedEnumerables: [empty, empty], +}; +const emptyInUpdateNestedModels = { + nestedEnumerable: { id: "1", ...empty }, + optionalNestedEnumerable: { id: "1", ...empty }, + nestedSingleton: { ...empty }, + optionalNestedSingleton: { ...empty }, + nestedEnumerables: [ + { id: "1", ...empty }, + { id: "1", ...empty }, + ], +}; + +const refs = { + nestedSingleton: singleton, + optionalNestedSingleton: singleton, + nestedEnumerable: nestedEnumerable, + optionalNestedEnumerable: nestedEnumerable, + nestedEnumerables: [nestedEnumerable, nestedEnumerable], +}; +const refsInCreateNestedModels = { + nestedEnumerable: refs, + optionalNestedEnumerable: refs, + nestedSingleton: refs, + optionalNestedSingleton: refs, + nestedEnumerables: [refs, refs], +}; +const refsInUpdateNestedModels = { + nestedEnumerable: { id: "1", ...refs }, + optionalNestedEnumerable: { id: "1", ...refs }, + nestedSingleton: { ...refs }, + optionalNestedSingleton: { ...refs }, + nestedEnumerables: [ + { id: "1", ...refs }, + { id: "1", ...refs }, + ], +}; + +const identifiers = { + nestedSingleton: "1", + optionalNestedSingleton: "1", + nestedEnumerable: "1", + optionalNestedEnumerable: "1", + nestedEnumerables: ["1", "2"], +}; +const identifiersInCreateNestedModels = { + nestedEnumerable: identifiers, + optionalNestedEnumerable: identifiers, + nestedSingleton: identifiers, + optionalNestedSingleton: identifiers, + nestedEnumerables: [identifiers, identifiers], +}; +const identifiersInUpdateNestedModels = { + nestedEnumerable: { id: "1", ...identifiers }, + optionalNestedEnumerable: { id: "1", ...identifiers }, + nestedSingleton: { ...identifiers }, + optionalNestedSingleton: { ...identifiers }, + nestedEnumerables: [ + { id: "1", ...identifiers }, + { id: "1", ...identifiers }, + ], +}; + +const unrefs = { + nestedSingleton: undefined, + optionalNestedSingleton: undefined, + nestedEnumerable: undefined, + optionalNestedEnumerable: undefined, + nestedEnumerables: [], +}; +const unrefsInCreateNestedModels = { + nestedEnumerable: unrefs, + optionalNestedEnumerable: unrefs, + nestedSingleton: unrefs, + optionalNestedSingleton: unrefs, + nestedEnumerables: [unrefs, unrefs], +}; +const unrefsInUpdateNestedModels = { + nestedEnumerable: { id: "1", ...unrefs }, + optionalNestedEnumerable: { id: "1", ...unrefs }, + nestedSingleton: { ...unrefs }, + optionalNestedSingleton: { ...unrefs }, + nestedEnumerables: [ + { id: "1", ...unrefs }, + { id: "1", ...unrefs }, + ], +}; + +const collisions = { + nestedSingleton: [{}], + optionalNestedSingleton: [{}], + nestedEnumerable: [{}], + optionalNestedEnumerable: [{}], + nestedEnumerables: {}, +}; +const collisionsInCreateNestedModels = { + nestedEnumerable: collisions, + optionalNestedEnumerable: collisions, + nestedSingleton: collisions, + optionalNestedSingleton: collisions, + nestedEnumerables: [collisions, collisions], +}; +const collisionsInUpdateNestedModels = { + nestedEnumerable: { id: "1", ...collisions }, + optionalNestedEnumerable: { id: "1", ...collisions }, + nestedSingleton: { ...collisions }, + optionalNestedSingleton: { ...collisions }, + nestedEnumerables: [ + { id: "1", ...collisions }, + { id: "1", ...collisions }, + ], +}; + +// Overload via Definition +{ + // Create... + { + // Create model via Definition + { + // ...set primitive propertiers + enumerablePromiseInput = store.set(Enumerable, primitives); + enumerableInput = store.sync(Enumerable, primitives); + + // ...use default values + enumerablePromiseInput = store.set(Enumerable, empty); + enumerableInput = store.sync(Enumerable, empty); + + // ...binding through refs + enumerablePromiseInput = store.set(Enumerable, refs); + enumerableInput = store.sync(Enumerable, refs); + + // ...binding through identifiers + enumerablePromiseInput = store.set(Enumerable, identifiers); + enumerableInput = store.sync(Enumerable, identifiers); + + // ...unbinding + enumerablePromiseInput = store.set(Enumerable, unrefs); + enumerableInput = store.sync(Enumerable, unrefs); + + // ...check collisions + /// @ts-expect-error + store.set(Enumerable, collisions); + /// @ts-expect-error + store.sync(Enumerable, collisions); + } + + // Create model & nested via Definition + { + // ...set primitive propertiers + enumerablePromiseInput = store.set( + Enumerable, + primitivesInCreateNestedModels, + ); + enumerableInput = store.sync(Enumerable, primitivesInCreateNestedModels); + + // ...use default values + enumerablePromiseInput = store.set(Enumerable, emptyInCreateNestedModels); + enumerableInput = store.sync(Enumerable, emptyInCreateNestedModels); + + // ...binding through refs + enumerablePromiseInput = store.set(Enumerable, refsInCreateNestedModels); + enumerableInput = store.sync(Enumerable, refsInCreateNestedModels); + + // ...binding through identifiers + enumerablePromiseInput = store.set( + Enumerable, + identifiersInCreateNestedModels, + ); + enumerableInput = store.sync(Enumerable, identifiersInCreateNestedModels); + + // ...unbinding + enumerablePromiseInput = store.set( + Enumerable, + unrefsInCreateNestedModels, + ); + enumerableInput = store.sync(Enumerable, unrefsInCreateNestedModels); + + // ...check collisions + /// @ts-expect-error + enumerablePromiseInput = store.set( + Enumerable, + collisionsInCreateNestedModels, + ); + /// @ts-expect-error + enumerableInput = store.sync(Enumerable, collisionsInCreateNestedModels); + } + } + + // Update... + { + // Update model via Definition + { + // ...set primitive propertiers + singletonPromiseInput = store.set(Singleton, primitives); + singletonInput = store.sync(Singleton, primitives); + enumerablePromiseInput = store.set(Enumerable, { + id: "1", + ...primitives, + }); + enumerableInput = store.sync(Enumerable, { id: "1", ...primitives }); + + // ...use default values + singletonPromiseInput = store.set(Singleton, empty); + singletonInput = store.sync(Singleton, empty); + enumerablePromiseInput = store.set(Enumerable, { id: "1", ...empty }); + enumerableInput = store.sync(Enumerable, { id: "1", ...empty }); + + // ...binding through refs + singletonPromiseInput = store.set(Singleton, refs); + singletonInput = store.sync(Singleton, refs); + enumerablePromiseInput = store.set(Enumerable, { id: "1", ...refs }); + enumerableInput = store.sync(Enumerable, { id: "1", ...refs }); + + // ...binding through identifiers + singletonPromiseInput = store.set(Singleton, identifiers); + singletonInput = store.sync(Singleton, identifiers); + enumerablePromiseInput = store.set(Enumerable, { + id: "1", + ...identifiers, + }); + enumerableInput = store.sync(Enumerable, { id: "1", ...identifiers }); + + // ...unbinding + singletonPromiseInput = store.set(Singleton, unrefs); + singletonInput = store.sync(Singleton, unrefs); + enumerablePromiseInput = store.set(Enumerable, { id: "1", ...unrefs }); + enumerableInput = store.sync(Enumerable, { id: "1", ...unrefs }); + + // ...check collisions + /// @ts-expect-error + singletonPromiseInput = store.set(Singleton, collisions); + /// @ts-expect-error + singletonInput = store.sync(Singleton, collisions); + /// @ts-expect-error + enumerablePromiseInput = store.set(Enumerable, { + id: "1", + ...collisions, + }); + /// @ts-expect-error + enumerableInput = store.sync(Enumerable, { id: "1", ...collisions }); + } + + // Update model & nested via Definition + { + // ...set primitive propertiers + singletonPromiseInput = store.set( + Singleton, + primitivesInUpdateNestedModels, + ); + singletonInput = store.sync(Singleton, primitivesInUpdateNestedModels); + enumerablePromiseInput = store.set(Enumerable, { + id: "1", + ...primitivesInUpdateNestedModels, + }); + enumerableInput = store.sync(Enumerable, { + id: "1", + ...primitivesInUpdateNestedModels, + }); + + // ...use default values + singletonPromiseInput = store.set(Singleton, emptyInUpdateNestedModels); + singletonInput = store.sync(Singleton, emptyInUpdateNestedModels); + enumerablePromiseInput = store.set(Enumerable, { + id: "1", + ...emptyInUpdateNestedModels, + }); + enumerableInput = store.sync(Enumerable, { + id: "1", + ...emptyInUpdateNestedModels, + }); + + // ...binding through refs + singletonPromiseInput = store.set(Singleton, refsInUpdateNestedModels); + singletonInput = store.sync(Singleton, refsInUpdateNestedModels); + enumerablePromiseInput = store.set(Enumerable, { + id: "1", + ...refsInUpdateNestedModels, + }); + enumerableInput = store.sync(Enumerable, { + id: "1", + ...refsInUpdateNestedModels, + }); + + // ...binding through identifiers + singletonPromiseInput = store.set( + Singleton, + identifiersInUpdateNestedModels, + ); + singletonInput = store.sync(Singleton, identifiersInUpdateNestedModels); + enumerablePromiseInput = store.set(Enumerable, { + id: "1", + ...identifiersInUpdateNestedModels, + }); + enumerableInput = store.sync(Enumerable, { + id: "1", + ...identifiersInUpdateNestedModels, + }); + + // ...unbinding + singletonPromiseInput = store.set(Singleton, unrefsInUpdateNestedModels); + singletonInput = store.sync(Singleton, unrefsInUpdateNestedModels); + enumerablePromiseInput = store.set(Enumerable, { + id: "1", + ...unrefsInUpdateNestedModels, + }); + enumerableInput = store.sync(Enumerable, { + id: "1", + ...unrefsInUpdateNestedModels, + }); + + // ...check collisions + /// @ts-expect-error + singletonPromiseInput = store.set( + Singleton, + collisionsInUpdateNestedModels, + ); + /// @ts-expect-error + singletonInput = store.sync(Singleton, collisionsInUpdateNestedModels); + /// @ts-expect-error + enumerablePromiseInput = store.set(Enumerable, { + id: "1", + ...collisionsInUpdateNestedModels, + }); + /// @ts-expect-error + enumerableInput = store.sync(Enumerable, { + id: "1", + ...collisionsInUpdateNestedModels, + }); + } + } + + // Delete... + { + // Delete model via Definition + + /// @ts-expect-error + enumerablePromiseInput = store.set(Enumerable, null); + /// @ts-expect-error + enumerableInput = store.sync(Enumerable, null); + + singletonPromiseInput = store.set(Singleton, null); + singletonInput = store.sync(Singleton, null); + } + + // Mixed... + { + // Create model and Update nested via Definition + { + // ...set primitive propertiers + enumerablePromiseInput = store.set( + Enumerable, + primitivesInUpdateNestedModels, + ); + enumerableInput = store.sync(Enumerable, primitivesInUpdateNestedModels); + + // ...use default values + enumerablePromiseInput = store.set(Enumerable, emptyInUpdateNestedModels); + enumerableInput = store.sync(Enumerable, emptyInUpdateNestedModels); + + // ...binding through refs + enumerablePromiseInput = store.set(Enumerable, refsInUpdateNestedModels); + enumerableInput = store.sync(Enumerable, refsInUpdateNestedModels); + + // ...binding through identifiers + enumerablePromiseInput = store.set( + Enumerable, + identifiersInUpdateNestedModels, + ); + enumerableInput = store.sync(Enumerable, identifiersInUpdateNestedModels); + + // ...unbinding + enumerablePromiseInput = store.set( + Enumerable, + unrefsInUpdateNestedModels, + ); + enumerableInput = store.sync(Enumerable, unrefsInUpdateNestedModels); + + // ...check collisions + /// @ts-expect-error + enumerablePromiseInput = store.set( + Enumerable, + collisionsInUpdateNestedModels, + ); + /// @ts-expect-error + enumerableInput = store.sync(Enumerable, collisionsInUpdateNestedModels); + } + + // Update model and Create nested via Definition + { + // ...set primitive propertiers + singletonPromiseInput = store.set( + Singleton, + primitivesInCreateNestedModels, + ); + singletonInput = store.sync(Singleton, primitivesInCreateNestedModels); + enumerablePromiseInput = store.set(Enumerable, { + id: "1", + ...primitivesInCreateNestedModels, + }); + enumerableInput = store.sync(Enumerable, { + id: "1", + ...primitivesInCreateNestedModels, + }); + + // ...use default values + singletonPromiseInput = store.set(Singleton, emptyInCreateNestedModels); + singletonInput = store.sync(Singleton, emptyInCreateNestedModels); + enumerablePromiseInput = store.set(Enumerable, { + id: "1", + ...emptyInCreateNestedModels, + }); + enumerableInput = store.sync(Enumerable, { + id: "1", + ...emptyInCreateNestedModels, + }); + + // ...binding through refs + singletonPromiseInput = store.set(Singleton, refsInCreateNestedModels); + singletonInput = store.sync(Singleton, refsInCreateNestedModels); + enumerablePromiseInput = store.set(Enumerable, { + id: "1", + ...refsInCreateNestedModels, + }); + enumerableInput = store.sync(Enumerable, { + id: "1", + ...refsInCreateNestedModels, + }); + + // ...binding through identifiers + singletonPromiseInput = store.set( + Singleton, + identifiersInCreateNestedModels, + ); + singletonInput = store.sync(Singleton, identifiersInCreateNestedModels); + enumerablePromiseInput = store.set(Enumerable, { + id: "1", + ...identifiersInCreateNestedModels, + }); + enumerableInput = store.sync(Enumerable, { + id: "1", + ...identifiersInCreateNestedModels, + }); + + // ...unbinding + singletonPromiseInput = store.set(Singleton, unrefsInCreateNestedModels); + singletonInput = store.sync(Singleton, unrefsInCreateNestedModels); + enumerablePromiseInput = store.set(Enumerable, { + id: "1", + ...unrefsInCreateNestedModels, + }); + enumerableInput = store.sync(Enumerable, { + id: "1", + ...unrefsInCreateNestedModels, + }); + + // ...check collisions + /// @ts-expect-error + singletonPromiseInput = store.set( + Singleton, + collisionsInCreateNestedModels, + ); + /// @ts-expect-error + singletonInput = store.sync(Singleton, collisionsInCreateNestedModels); + /// @ts-expect-error + enumerablePromiseInput = store.set(Enumerable, { + id: "1", + ...collisionsInCreateNestedModels, + }); + /// @ts-expect-error + enumerableInput = store.sync(Enumerable, { + id: "1", + ...collisionsInCreateNestedModels, + }); + } + } +} + +// Overload via instance +{ + // Update model via instance + { + // ...set primitive propertiers + singletonPromiseInput = store.set(singleton, primitives); + singletonInput = store.sync(singleton, primitives); + enumerablePromiseInput = store.set(enumerable, { id: "1", ...primitives }); + enumerableInput = store.sync(enumerable, { id: "1", ...primitives }); + + // ...use default values + singletonPromiseInput = store.set(singleton, empty); + singletonInput = store.sync(singleton, empty); + enumerablePromiseInput = store.set(enumerable, { id: "1", ...empty }); + enumerableInput = store.sync(enumerable, { id: "1", ...empty }); + + // ...binding through refs + singletonPromiseInput = store.set(singleton, refs); + singletonInput = store.sync(singleton, refs); + enumerablePromiseInput = store.set(enumerable, { id: "1", ...refs }); + enumerableInput = store.sync(enumerable, { id: "1", ...refs }); + + // ...binding through identifiers + singletonPromiseInput = store.set(singleton, identifiers); + singletonInput = store.sync(singleton, identifiers); + enumerablePromiseInput = store.set(enumerable, { id: "1", ...identifiers }); + enumerableInput = store.sync(enumerable, { id: "1", ...identifiers }); + + // ...unbinding + singletonPromiseInput = store.set(singleton, unrefs); + singletonInput = store.sync(singleton, unrefs); + enumerablePromiseInput = store.set(enumerable, { id: "1", ...unrefs }); + enumerableInput = store.sync(enumerable, { id: "1", ...unrefs }); + + // ...check collisions + /// @ts-expect-error + singletonPromiseInput = store.set(singleton, collisions); + /// @ts-expect-error + singletonInput = store.sync(singleton, collisions); + /// @ts-expect-error + enumerablePromiseInput = store.set(enumerable, { id: "1", ...collisions }); + /// @ts-expect-error + enumerableInput = store.sync(enumerable, { id: "1", ...collisions }); + } + + // Update model & nested via instance + { + // ...set primitive propertiers + singletonPromiseInput = store.set( + singleton, + primitivesInUpdateNestedModels, + ); + singletonInput = store.sync(singleton, primitivesInUpdateNestedModels); + enumerablePromiseInput = store.set(enumerable, { + id: "1", + ...primitivesInUpdateNestedModels, + }); + enumerableInput = store.sync(enumerable, { + id: "1", + ...primitivesInUpdateNestedModels, + }); + + // ...use default values + singletonPromiseInput = store.set(singleton, emptyInUpdateNestedModels); + singletonInput = store.sync(singleton, emptyInUpdateNestedModels); + enumerablePromiseInput = store.set(enumerable, { + id: "1", + ...emptyInUpdateNestedModels, + }); + enumerableInput = store.sync(enumerable, { + id: "1", + ...emptyInUpdateNestedModels, + }); + + // ...binding through refs + singletonPromiseInput = store.set(singleton, refsInUpdateNestedModels); + singletonInput = store.sync(singleton, refsInUpdateNestedModels); + enumerablePromiseInput = store.set(enumerable, { + id: "1", + ...refsInUpdateNestedModels, + }); + enumerableInput = store.sync(enumerable, { + id: "1", + ...refsInUpdateNestedModels, + }); + + // ...binding through identifiers + singletonPromiseInput = store.set( + singleton, + identifiersInUpdateNestedModels, + ); + singletonInput = store.sync(singleton, identifiersInUpdateNestedModels); + enumerablePromiseInput = store.set(enumerable, { + id: "1", + ...identifiersInUpdateNestedModels, + }); + enumerableInput = store.sync(enumerable, { + id: "1", + ...identifiersInUpdateNestedModels, + }); + + // ...unbinding + singletonPromiseInput = store.set(singleton, unrefsInUpdateNestedModels); + singletonInput = store.sync(singleton, unrefsInUpdateNestedModels); + enumerablePromiseInput = store.set(enumerable, { + id: "1", + ...unrefsInUpdateNestedModels, + }); + enumerableInput = store.sync(enumerable, { + id: "1", + ...unrefsInUpdateNestedModels, + }); + + // ...check collisions + /// @ts-expect-error + singletonPromiseInput = store.set( + singleton, + collisionsInUpdateNestedModels, + ); + /// @ts-expect-error + singletonInput = store.sync(singleton, collisionsInUpdateNestedModels); + /// @ts-expect-error + enumerablePromiseInput = store.set(enumerable, { + id: "1", + ...collisionsInUpdateNestedModels, + }); + /// @ts-expect-error + enumerableInput = store.sync(enumerable, { + id: "1", + ...collisionsInUpdateNestedModels, + }); + } + + // Mixed... + { + // Update model and Create nested via Definition + { + // ...set primitive propertiers + singletonPromiseInput = store.set( + singleton, + primitivesInCreateNestedModels, + ); + singletonInput = store.sync(singleton, primitivesInCreateNestedModels); + enumerablePromiseInput = store.set(enumerable, { + id: "1", + ...primitivesInCreateNestedModels, + }); + enumerableInput = store.sync(enumerable, { + id: "1", + ...primitivesInCreateNestedModels, + }); + + // ...use default values + singletonPromiseInput = store.set(singleton, emptyInCreateNestedModels); + singletonInput = store.sync(singleton, emptyInCreateNestedModels); + enumerablePromiseInput = store.set(enumerable, { + id: "1", + ...emptyInCreateNestedModels, + }); + enumerableInput = store.sync(enumerable, { + id: "1", + ...emptyInCreateNestedModels, + }); + + // ...binding through refs + singletonPromiseInput = store.set(singleton, refsInCreateNestedModels); + singletonInput = store.sync(singleton, refsInCreateNestedModels); + enumerablePromiseInput = store.set(enumerable, { + id: "1", + ...refsInCreateNestedModels, + }); + enumerableInput = store.sync(enumerable, { + id: "1", + ...refsInCreateNestedModels, + }); + + // ...binding through identifiers + singletonPromiseInput = store.set( + singleton, + identifiersInCreateNestedModels, + ); + singletonInput = store.sync(singleton, identifiersInCreateNestedModels); + enumerablePromiseInput = store.set(enumerable, { + id: "1", + ...identifiersInCreateNestedModels, + }); + enumerableInput = store.sync(enumerable, { + id: "1", + ...identifiersInCreateNestedModels, + }); + + // ...unbinding + singletonPromiseInput = store.set(singleton, unrefsInCreateNestedModels); + singletonInput = store.sync(singleton, unrefsInCreateNestedModels); + enumerablePromiseInput = store.set(enumerable, { + id: "1", + ...unrefsInCreateNestedModels, + }); + enumerableInput = store.sync(enumerable, { + id: "1", + ...unrefsInCreateNestedModels, + }); + + // ...check collisions + /// @ts-expect-error + singletonPromiseInput = store.set( + singleton, + collisionsInCreateNestedModels, + ); + /// @ts-expect-error + singletonInput = store.sync(singleton, collisionsInCreateNestedModels); + /// @ts-expect-error + enumerablePromiseInput = store.set(enumerable, { + id: "1", + ...collisionsInCreateNestedModels, + }); + /// @ts-expect-error + enumerableInput = store.sync(enumerable, { + id: "1", + ...collisionsInCreateNestedModels, + }); + } + } +} + +// Delete... +{ + // delete model via instance + { + enumerablePromiseInput = store.set(enumerable, null); + enumerableInput = store.sync(enumerable, null); + singletonPromiseInput = store.set(singleton, null); // is may be cleaning of the model values or draft values + singletonInput = store.sync(singleton, null); // is may be cleaning of the model values or draft values + } +} diff --git a/test/types/store/model-definition.ts b/test/types/store/model-definition.ts index 2fa84805..56622de5 100644 --- a/test/types/store/model-definition.ts +++ b/test/types/store/model-definition.ts @@ -2,7 +2,10 @@ import { IEnumerable } from "./.internals/enumerable/enumerable.entity"; import { Enumerable } from "./.internals/enumerable/enumerable.store"; import { ISingleton } from "./.internals/singleton/singleton.entity"; import { Singleton } from "./.internals/singleton/singleton.store"; -import { Model, store } from "/types/index"; +import { + ModelDefinition, + store, +} from "/types/index"; interface ICasesOfFieldsWithValues { // value = value @@ -38,10 +41,10 @@ interface ICasesOfListedFieldsWithEmptyValues { interface ICasesOfListedFieldsWithLoosedValues { // value[] = [value, { loose }] - loosedListedFieldWithDefaultEmptyValue: T[] - loosedListedFieldCalculatedAsEmptyValue?: T[] - loosedListedOptionalFieldWithDefaultEmptyValue: T[] - loosedListedOptionalFieldCalculatedAsEmptyValue?: T[] + loosedListedFieldWithDefaultEmptyValue: T[]; + loosedListedFieldCalculatedAsEmptyValue?: T[]; + loosedListedOptionalFieldWithDefaultEmptyValue: T[]; + loosedListedOptionalFieldCalculatedAsEmptyValue?: T[]; } interface ICasesOfFieldsWithUndefinedValues { @@ -60,163 +63,239 @@ interface ICasesOfListedFieldsWithUndefinedValues { listedOptionalFieldCalculatedAsUndefinedValues?: T[]; } -interface IPrimitivePositiveCases extends ICasesOfFieldsWithValues, ICasesOfListedFieldsWithValues, ICasesOfListedFieldsWithEmptyValues {} -interface IPrimitiveNegativeCases extends ICasesOfFieldsWithEmptyValues, ICasesOfListedFieldsWithLoosedValues, ICasesOfFieldsWithUndefinedValues, ICasesOfListedFieldsWithUndefinedValues {} - -const PrimitivePositiveCases: Model = { +interface IPrimitivePositiveCases + extends ICasesOfFieldsWithValues, + ICasesOfListedFieldsWithValues, + ICasesOfListedFieldsWithEmptyValues { } +interface IPrimitiveNegativeCases + extends ICasesOfFieldsWithEmptyValues, + ICasesOfListedFieldsWithLoosedValues, + ICasesOfFieldsWithUndefinedValues, + ICasesOfListedFieldsWithUndefinedValues { } + +const PrimitivePositiveCases: ModelDefinition = { // boolean = boolean fieldWithDefaultValue: false, - fieldCalculatedAsValue: ({ fieldWithDefaultValue }) => fieldWithDefaultValue, + fieldCalculatedAsValue: ({ fieldWithDefaultValue }) => + fieldWithDefaultValue, optionalFieldWithDefaultValue: false, - optionalFieldCalculatedAsValue: ({ optionalFieldWithDefaultValue }) => optionalFieldWithDefaultValue, + optionalFieldCalculatedAsValue: ({ optionalFieldWithDefaultValue }) => + optionalFieldWithDefaultValue || false, // boolean[] = boolean[] listedFieldWithDefaultValues: [false], - listedFieldCalculatedAsValues: ({ listedFieldWithDefaultValues }) => listedFieldWithDefaultValues, + listedFieldCalculatedAsValues: ({ listedFieldWithDefaultValues }) => + listedFieldWithDefaultValues, listedOptionalFieldWithDefaultValues: [false], - listedOptionalFieldCalculatedAsValues: ({ listedOptionalFieldWithDefaultValues }) => listedOptionalFieldWithDefaultValues, + listedOptionalFieldCalculatedAsValues: ({ + listedOptionalFieldWithDefaultValues, + }) => listedOptionalFieldWithDefaultValues, // boolean[] = [Boolean] listedFieldWithDefaultEmptyValues: [Boolean], - listedFieldCalculatedAsEmptyValues: ({ listedFieldWithDefaultEmptyValues }) => listedFieldWithDefaultEmptyValues && [Boolean], + listedFieldCalculatedAsEmptyValues: ({ + listedFieldWithDefaultEmptyValues, + }) => listedFieldWithDefaultEmptyValues, listedOptionalFieldWithDefaultEmptyValues: [Boolean], - listedOptionalFieldCalculatedAsEmptyValues: ({ listedOptionalFieldWithDefaultEmptyValues }) => listedOptionalFieldWithDefaultEmptyValues && [Boolean], -} + listedOptionalFieldCalculatedAsEmptyValues: ({ + listedOptionalFieldWithDefaultEmptyValues, + }) => listedOptionalFieldWithDefaultEmptyValues, +}; -const PrimitiveNegativeCases: Model = { +const PrimitiveNegativeCases: ModelDefinition = { // boolean = Boolean /// @ts-expect-error fieldWithDefaultEmptyValue: Boolean, /// @ts-expect-error - fieldCalculatedAsEmptyValue: ({ fieldWithDefaultEmptyValue }) => fieldWithDefaultEmptyValue && Boolean, + fieldCalculatedAsEmptyValue: ({ fieldWithDefaultEmptyValue }) => + fieldWithDefaultEmptyValue && Boolean, /// @ts-expect-error optionalFieldWithDefaultEmptyValue: Boolean, /// @ts-expect-error - optionalFieldCalculatedAsEmptyValue: ({ optionalFieldWithDefaultEmptyValue }) => optionalFieldWithDefaultEmptyValue && Boolean, - + optionalFieldCalculatedAsEmptyValue: ({ + optionalFieldWithDefaultEmptyValue, + }) => optionalFieldWithDefaultEmptyValue && Boolean, + // boolean[] = [Boolean, { loose }] /// @ts-expect-error loosedListedFieldWithDefaultEmptyValue: [Boolean, { loose: true }], /// @ts-expect-error - loosedListedFieldCalculatedAsEmptyValue: ({ loosedListedFieldWithDefaultEmptyValue: loosedListedFieldWithDefaultUndefinedValues }) => loosedListedFieldWithDefaultUndefinedValues && [Boolean, { loose: true }], + loosedListedFieldCalculatedAsEmptyValue: ({ + loosedListedFieldWithDefaultEmptyValue: + loosedListedFieldWithDefaultUndefinedValues, + }) => + loosedListedFieldWithDefaultUndefinedValues && [Boolean, { loose: true }], /// @ts-expect-error loosedListedOptionalFieldWithDefaultEmptyValue: [Boolean, { loose: true }], /// @ts-expect-error - loosedListedOptionalFieldCalculatedAsEmptyValue: ({ loosedListedOptionalFieldWithDefaultEmptyValue: loosedListedOptionalFieldWithDefaultUndefinedValues }) => loosedListedOptionalFieldWithDefaultUndefinedValues && [Boolean, { loose: true }], - + loosedListedOptionalFieldCalculatedAsEmptyValue: ({ + loosedListedOptionalFieldWithDefaultEmptyValue: + loosedListedOptionalFieldWithDefaultUndefinedValues, + }) => + loosedListedOptionalFieldWithDefaultUndefinedValues && [ + Boolean, + { loose: true }, + ], + // boolean = undefined /// @ts-expect-error fieldWithDefaultUndefinedValue: undefined, /// @ts-expect-error - fieldCalculatedAsUndefinedValue: ({ fieldWithDefaultUndefinedValue }) => fieldWithDefaultUndefinedValue && undefined, + fieldCalculatedAsUndefinedValue: ({ fieldWithDefaultUndefinedValue }) => + fieldWithDefaultUndefinedValue && undefined, /// @ts-expect-error optionalFieldWithDefaultUndefinedValue: undefined, /// @ts-expect-error - optionalFieldCalculatedAsUndefinedValue: ({ optionalFieldWithDefaultUndefinedValue }) => optionalFieldWithDefaultUndefinedValue && undefined, + optionalFieldCalculatedAsUndefinedValue: ({ + optionalFieldWithDefaultUndefinedValue, + }) => optionalFieldWithDefaultUndefinedValue && undefined, // boolean[] = undefined[] /// @ts-expect-error listedFieldWithDefaultUndefinedValues: [undefined], /// @ts-expect-error - listedFieldCalculatedAsUndefinedValues: ({ listedFieldWithDefaultUndefinedValues }) => listedFieldWithDefaultUndefinedValues && [undefined], + listedFieldCalculatedAsUndefinedValues: ({ + listedFieldWithDefaultUndefinedValues, + }) => listedFieldWithDefaultUndefinedValues && [undefined], /// @ts-expect-error listedOptionalFieldWithDefaultUndefinedValues: [undefined], /// @ts-expect-error - listedOptionalFieldCalculatedAsUndefinedValues: ({ listedOptionalFieldWithDefaultUndefinedValues }) => listedOptionalFieldWithDefaultUndefinedValues && [undefined], -} + listedOptionalFieldCalculatedAsUndefinedValues: ({ + listedOptionalFieldWithDefaultUndefinedValues, + }) => listedOptionalFieldWithDefaultUndefinedValues && [undefined], +}; interface ISomeObject { - stringProperty: string, - numberProperty: number, + stringProperty: string; + numberProperty: number; } -interface IObjectPositiveCases extends ICasesOfFieldsWithValues, ICasesOfListedFieldsWithValues {} -interface IObjectNegativeCases extends ICasesOfFieldsWithEmptyValues, ICasesOfListedFieldsWithEmptyValues, ICasesOfListedFieldsWithLoosedValues, ICasesOfFieldsWithUndefinedValues, ICasesOfListedFieldsWithUndefinedValues {} +interface IObjectPositiveCases + extends ICasesOfFieldsWithValues, + ICasesOfListedFieldsWithValues { } +interface IObjectNegativeCases + extends ICasesOfFieldsWithEmptyValues, + ICasesOfListedFieldsWithEmptyValues, + ICasesOfListedFieldsWithLoosedValues, + ICasesOfFieldsWithUndefinedValues, + ICasesOfListedFieldsWithUndefinedValues { } const someObject: ISomeObject = { stringProperty: "", numberProperty: 1, -} +}; -const ObjectPositiveCases: Model = { +const ObjectPositiveCases: ModelDefinition = { // ISomeObject = someObject fieldWithDefaultValue: someObject, fieldCalculatedAsValue: ({ fieldWithDefaultValue }) => fieldWithDefaultValue, optionalFieldWithDefaultValue: someObject, - optionalFieldCalculatedAsValue: ({ optionalFieldWithDefaultValue }) => optionalFieldWithDefaultValue, + optionalFieldCalculatedAsValue: ({ optionalFieldWithDefaultValue }) => + optionalFieldWithDefaultValue, // ISomeObject[] = someObject[] listedFieldWithDefaultValues: [someObject, someObject], - listedFieldCalculatedAsValues: ({ listedFieldWithDefaultValues }) => listedFieldWithDefaultValues, + listedFieldCalculatedAsValues: ({ listedFieldWithDefaultValues }) => + listedFieldWithDefaultValues, listedOptionalFieldWithDefaultValues: [someObject, someObject], - listedOptionalFieldCalculatedAsValues: ({ listedOptionalFieldWithDefaultValues }) => listedOptionalFieldWithDefaultValues, -} + listedOptionalFieldCalculatedAsValues: ({ + listedOptionalFieldWithDefaultValues, + }) => listedOptionalFieldWithDefaultValues, +}; -const ObjectNegativeCases: Model = { +const ObjectNegativeCases: ModelDefinition = { // ISomeObject = Object /// @ts-expect-error fieldWithDefaultEmptyValue: Object, /// @ts-expect-error - fieldCalculatedAsEmptyValue: ({ fieldWithDefaultEmptyValue }) => fieldWithDefaultEmptyValue && Object, + fieldCalculatedAsEmptyValue: ({ fieldWithDefaultEmptyValue }) => + fieldWithDefaultEmptyValue && Object, /// @ts-expect-error optionalFieldWithDefaultEmptyValue: Object, /// @ts-expect-error - optionalFieldCalculatedAsEmptyValue: ({ optionalFieldWithDefaultEmptyValue }) => optionalFieldWithDefaultEmptyValue && Object, + optionalFieldCalculatedAsEmptyValue: ({ + optionalFieldWithDefaultEmptyValue, + }) => optionalFieldWithDefaultEmptyValue && Object, // ISomeObject[] = [Object] /// @ts-expect-error listedFieldWithDefaultEmptyValues: [Object], /// @ts-expect-error - listedFieldCalculatedAsEmptyValues: ({ listedFieldWithDefaultEmptyValues }) => listedFieldWithDefaultEmptyValues && [Object], + listedFieldCalculatedAsEmptyValues: ({ listedFieldWithDefaultEmptyValues }) => + listedFieldWithDefaultEmptyValues && [Object], /// @ts-expect-error listedOptionalFieldWithDefaultEmptyValues: [Object], /// @ts-expect-error - listedOptionalFieldCalculatedAsEmptyValues: ({ listedOptionalFieldWithDefaultEmptyValues }) => listedOptionalFieldWithDefaultEmptyValues && [Object], - + listedOptionalFieldCalculatedAsEmptyValues: ({ + listedOptionalFieldWithDefaultEmptyValues, + }) => listedOptionalFieldWithDefaultEmptyValues && [Object], + // ISomeObject[] = [Object, { loose }] /// @ts-expect-error loosedListedFieldWithDefaultEmptyValue: [Object, { loose: true }], /// @ts-expect-error - loosedListedFieldCalculatedAsEmptyValue: ({ loosedListedFieldWithDefaultEmptyValue }) => loosedListedFieldWithDefaultEmptyValue && [Object, { loose: true }], + loosedListedFieldCalculatedAsEmptyValue: ({ + loosedListedFieldWithDefaultEmptyValue, + }) => loosedListedFieldWithDefaultEmptyValue && [Object, { loose: true }], /// @ts-expect-error loosedListedOptionalFieldWithDefaultEmptyValue: [Object, { loose: true }], /// @ts-expect-error - loosedListedOptionalFieldCalculatedAsEmptyValue: ({ loosedListedOptionalFieldWithDefaultEmptyValue }) => loosedListedOptionalFieldWithDefaultEmptyValue && [Object, { loose: true }], - + loosedListedOptionalFieldCalculatedAsEmptyValue: ({ + loosedListedOptionalFieldWithDefaultEmptyValue, + }) => + loosedListedOptionalFieldWithDefaultEmptyValue && [Object, { loose: true }], + // ISomeObject = undefined /// @ts-expect-error fieldWithDefaultUndefinedValue: undefined, /// @ts-expect-error - fieldCalculatedAsUndefinedValue: ({ fieldWithDefaultUndefinedValue }) => fieldWithDefaultUndefinedValue && undefined, + fieldCalculatedAsUndefinedValue: ({ fieldWithDefaultUndefinedValue }) => + fieldWithDefaultUndefinedValue && undefined, /// @ts-expect-error optionalFieldWithDefaultUndefinedValue: undefined, /// @ts-expect-error - optionalFieldCalculatedAsUndefinedValue: ({ optionalFieldWithDefaultUndefinedValue }) => optionalFieldWithDefaultUndefinedValue && undefined, + optionalFieldCalculatedAsUndefinedValue: ({ + optionalFieldWithDefaultUndefinedValue, + }) => optionalFieldWithDefaultUndefinedValue && undefined, // ISomeObject[] = undefined[] /// @ts-expect-error listedFieldWithDefaultUndefinedValues: [undefined], /// @ts-expect-error - listedFieldCalculatedAsUndefinedValues: ({ listedFieldWithDefaultUndefinedValues }) => listedFieldWithDefaultUndefinedValues && [undefined], + listedFieldCalculatedAsUndefinedValues: ({ + listedFieldWithDefaultUndefinedValues, + }) => listedFieldWithDefaultUndefinedValues && [undefined], /// @ts-expect-error listedOptionalFieldWithDefaultUndefinedValues: [undefined], /// @ts-expect-error - listedOptionalFieldCalculatedAsUndefinedValues: ({ listedOptionalFieldWithDefaultUndefinedValues }) => listedOptionalFieldWithDefaultUndefinedValues && [undefined], -} + listedOptionalFieldCalculatedAsUndefinedValues: ({ + listedOptionalFieldWithDefaultUndefinedValues, + }) => listedOptionalFieldWithDefaultUndefinedValues && [undefined], +}; -interface ISingletonPositiveCases extends ICasesOfFieldsWithEmptyValues {} -interface ISingletonNegativeCases extends ICasesOfFieldsWithValues, ICasesOfListedFieldsWithValues, ICasesOfListedFieldsWithEmptyValues, ICasesOfListedFieldsWithLoosedValues, ICasesOfFieldsWithUndefinedValues, ICasesOfListedFieldsWithUndefinedValues {} +interface ISingletonPositiveCases + extends ICasesOfFieldsWithEmptyValues { } +interface ISingletonNegativeCases + extends ICasesOfFieldsWithValues, + ICasesOfListedFieldsWithValues, + ICasesOfListedFieldsWithEmptyValues, + ICasesOfListedFieldsWithLoosedValues, + ICasesOfFieldsWithUndefinedValues, + ICasesOfListedFieldsWithUndefinedValues { } -const singleton = store.sync(Singleton, {}) +const singleton = store.sync(Singleton, {}); -const SingletonPositiveCases: Model = { +const SingletonPositiveCases: ModelDefinition = { // ISingleton = Singleton fieldWithDefaultEmptyValue: Singleton, - fieldCalculatedAsEmptyValue: ({ fieldWithDefaultEmptyValue }) => fieldWithDefaultEmptyValue && Singleton, + fieldCalculatedAsEmptyValue: ({ fieldWithDefaultEmptyValue }) => + fieldWithDefaultEmptyValue && Singleton, optionalFieldWithDefaultEmptyValue: Singleton, - optionalFieldCalculatedAsEmptyValue: ({ optionalFieldWithDefaultEmptyValue }) => optionalFieldWithDefaultEmptyValue && Singleton, -} + optionalFieldCalculatedAsEmptyValue: ({ + optionalFieldWithDefaultEmptyValue, + }) => optionalFieldWithDefaultEmptyValue && Singleton, +}; -const SingletonNegativeCases: Model = { +const SingletonNegativeCases: ModelDefinition = { // ISingleton = singleton /// @ts-expect-error fieldWithDefaultValue: singleton, @@ -225,85 +304,128 @@ const SingletonNegativeCases: Model = { /// @ts-expect-error optionalFieldWithDefaultValue: singleton, /// @ts-expect-error - optionalFieldCalculatedAsValue: ({ optionalFieldWithDefaultValue }) => optionalFieldWithDefaultValue, + optionalFieldCalculatedAsValue: ({ optionalFieldWithDefaultValue }) => + optionalFieldWithDefaultValue, // ISingleton[] = singleton[] /// @ts-expect-error listedFieldWithDefaultValues: [singleton, singleton], /// @ts-expect-error - listedFieldCalculatedAsValues: ({ listedFieldWithDefaultValues }) => listedFieldWithDefaultValues, + listedFieldCalculatedAsValues: ({ listedFieldWithDefaultValues }) => + listedFieldWithDefaultValues, /// @ts-expect-error listedOptionalFieldWithDefaultValues: [singleton, singleton], /// @ts-expect-error - listedOptionalFieldCalculatedAsValues: ({ listedOptionalFieldWithDefaultValues }) => listedOptionalFieldWithDefaultValues, + listedOptionalFieldCalculatedAsValues: ({ + listedOptionalFieldWithDefaultValues, + }) => listedOptionalFieldWithDefaultValues, // ISingleton[] = [Singleton] /// @ts-expect-error listedFieldWithDefaultEmptyValues: [Singleton], /// @ts-expect-error - listedFieldCalculatedAsEmptyValues: ({ listedFieldWithDefaultEmptyValues }) => listedFieldWithDefaultEmptyValues && [Singleton], + listedFieldCalculatedAsEmptyValues: ({ listedFieldWithDefaultEmptyValues }) => + listedFieldWithDefaultEmptyValues && [Singleton], /// @ts-expect-error listedOptionalFieldWithDefaultEmptyValues: [Singleton], /// @ts-expect-error - listedOptionalFieldCalculatedAsEmptyValues: ({ listedOptionalFieldWithDefaultEmptyValues }) => listedOptionalFieldWithDefaultEmptyValues && [Singleton], - + listedOptionalFieldCalculatedAsEmptyValues: ({ + listedOptionalFieldWithDefaultEmptyValues, + }) => listedOptionalFieldWithDefaultEmptyValues && [Singleton], + // ISingleton[] = [Singleton, { loose }] /// @ts-expect-error loosedListedFieldWithDefaultEmptyValue: [Singleton, { loose: true }], /// @ts-expect-error - loosedListedFieldCalculatedAsEmptyValue: ({ loosedListedFieldWithDefaultEmptyValue }) => loosedListedFieldWithDefaultEmptyValue && [Singleton, { loose: true }], + loosedListedFieldCalculatedAsEmptyValue: ({ + loosedListedFieldWithDefaultEmptyValue, + }) => loosedListedFieldWithDefaultEmptyValue && [Singleton, { loose: true }], /// @ts-expect-error loosedListedOptionalFieldWithDefaultEmptyValue: [Singleton, { loose: true }], /// @ts-expect-error - loosedListedOptionalFieldCalculatedAsEmptyValue: ({ loosedListedOptionalFieldWithDefaultEmptyValue }) => loosedListedOptionalFieldWithDefaultEmptyValue && [Singleton, { loose: true }], - + loosedListedOptionalFieldCalculatedAsEmptyValue: ({ + loosedListedOptionalFieldWithDefaultEmptyValue, + }) => + loosedListedOptionalFieldWithDefaultEmptyValue && [ + Singleton, + { loose: true }, + ], + // ISingleton = undefined /// @ts-expect-error fieldWithDefaultUndefinedValue: undefined, /// @ts-expect-error - fieldCalculatedAsUndefinedValue: ({ fieldWithDefaultUndefinedValue }) => fieldWithDefaultUndefinedValue && undefined, + fieldCalculatedAsUndefinedValue: ({ fieldWithDefaultUndefinedValue }) => + fieldWithDefaultUndefinedValue && undefined, /// @ts-expect-error optionalFieldWithDefaultUndefinedValue: undefined, /// @ts-expect-error - optionalFieldCalculatedAsUndefinedValue: ({ optionalFieldWithDefaultUndefinedValue }) => optionalFieldWithDefaultUndefinedValue && undefined, + optionalFieldCalculatedAsUndefinedValue: ({ + optionalFieldWithDefaultUndefinedValue, + }) => optionalFieldWithDefaultUndefinedValue && undefined, // ISingleton[] = undefined[] /// @ts-expect-error listedFieldWithDefaultUndefinedValues: [undefined], /// @ts-expect-error - listedFieldCalculatedAsUndefinedValues: ({ listedFieldWithDefaultUndefinedValues }) => listedFieldWithDefaultUndefinedValues && [undefined], + listedFieldCalculatedAsUndefinedValues: ({ + listedFieldWithDefaultUndefinedValues, + }) => listedFieldWithDefaultUndefinedValues && [undefined], /// @ts-expect-error listedOptionalFieldWithDefaultUndefinedValues: [undefined], /// @ts-expect-error - listedOptionalFieldCalculatedAsUndefinedValues: ({ listedOptionalFieldWithDefaultUndefinedValues }) => listedOptionalFieldWithDefaultUndefinedValues && [undefined], -} + listedOptionalFieldCalculatedAsUndefinedValues: ({ + listedOptionalFieldWithDefaultUndefinedValues, + }) => listedOptionalFieldWithDefaultUndefinedValues && [undefined], +}; -interface IEnumerablePositiveCases extends ICasesOfFieldsWithEmptyValues, ICasesOfListedFieldsWithEmptyValues, ICasesOfListedFieldsWithLoosedValues {} -interface IEnumerableNegativeCases extends ICasesOfFieldsWithValues, ICasesOfListedFieldsWithValues, ICasesOfFieldsWithUndefinedValues, ICasesOfListedFieldsWithUndefinedValues {} +interface IEnumerablePositiveCases + extends ICasesOfFieldsWithEmptyValues, + ICasesOfListedFieldsWithEmptyValues, + ICasesOfListedFieldsWithLoosedValues { } +interface IEnumerableNegativeCases + extends ICasesOfFieldsWithValues, + ICasesOfListedFieldsWithValues, + ICasesOfFieldsWithUndefinedValues, + ICasesOfListedFieldsWithUndefinedValues { } -const enumerable = store.sync(Enumerable, {}) +const enumerable = store.sync(Enumerable, {}); -const EnumerablePositiveCases: Model = { +const EnumerablePositiveCases: ModelDefinition = { // IEnumerable = Enumerable fieldWithDefaultEmptyValue: Enumerable, - fieldCalculatedAsEmptyValue: ({ fieldWithDefaultEmptyValue }) => fieldWithDefaultEmptyValue && Enumerable, + fieldCalculatedAsEmptyValue: ({ fieldWithDefaultEmptyValue }) => + fieldWithDefaultEmptyValue && Enumerable, optionalFieldWithDefaultEmptyValue: Enumerable, - optionalFieldCalculatedAsEmptyValue: ({ optionalFieldWithDefaultEmptyValue }) => optionalFieldWithDefaultEmptyValue && Enumerable, + optionalFieldCalculatedAsEmptyValue: ({ + optionalFieldWithDefaultEmptyValue, + }) => optionalFieldWithDefaultEmptyValue && Enumerable, // IEnumerable[] = [Enumerable] listedFieldWithDefaultEmptyValues: [Enumerable], - listedFieldCalculatedAsEmptyValues: ({ listedFieldWithDefaultEmptyValues }) => listedFieldWithDefaultEmptyValues && [Enumerable], + listedFieldCalculatedAsEmptyValues: ({ listedFieldWithDefaultEmptyValues }) => + listedFieldWithDefaultEmptyValues && [Enumerable], listedOptionalFieldWithDefaultEmptyValues: [Enumerable], - listedOptionalFieldCalculatedAsEmptyValues: ({ listedOptionalFieldWithDefaultEmptyValues }) => listedOptionalFieldWithDefaultEmptyValues && [Enumerable], - + listedOptionalFieldCalculatedAsEmptyValues: ({ + listedOptionalFieldWithDefaultEmptyValues, + }) => listedOptionalFieldWithDefaultEmptyValues && [Enumerable], + // IEnumerable[] = [Enumerable, { loose }] loosedListedFieldWithDefaultEmptyValue: [Enumerable, { loose: true }], - loosedListedFieldCalculatedAsEmptyValue: ({ loosedListedFieldWithDefaultEmptyValue }) => loosedListedFieldWithDefaultEmptyValue && [Enumerable, { loose: true }], + loosedListedFieldCalculatedAsEmptyValue: ({ + loosedListedFieldWithDefaultEmptyValue, + }) => loosedListedFieldWithDefaultEmptyValue && [Enumerable, { loose: true }], loosedListedOptionalFieldWithDefaultEmptyValue: [Enumerable, { loose: true }], - loosedListedOptionalFieldCalculatedAsEmptyValue: ({ loosedListedOptionalFieldWithDefaultEmptyValue }) => loosedListedOptionalFieldWithDefaultEmptyValue && [Enumerable, { loose: true }], -} - -const EnumerableNegativeCases: Model = { + loosedListedOptionalFieldCalculatedAsEmptyValue: ({ + loosedListedOptionalFieldWithDefaultEmptyValue, + }) => + loosedListedOptionalFieldWithDefaultEmptyValue && [ + Enumerable, + { loose: true }, + ], +}; + +const EnumerableNegativeCases: ModelDefinition = { // IEnumerable = enumerable /// @ts-expect-error fieldWithDefaultValue: enumerable, @@ -312,35 +434,46 @@ const EnumerableNegativeCases: Model = { /// @ts-expect-error optionalFieldWithDefaultValue: enumerable, /// @ts-expect-error - optionalFieldCalculatedAsValue: ({ optionalFieldWithDefaultValue }) => optionalFieldWithDefaultValue, + optionalFieldCalculatedAsValue: ({ optionalFieldWithDefaultValue }) => + optionalFieldWithDefaultValue, // IEnumerable[] = enumerable[] /// @ts-expect-error listedFieldWithDefaultValues: [enumerable, enumerable], /// @ts-expect-error - listedFieldCalculatedAsValues: ({ listedFieldWithDefaultValues }) => listedFieldWithDefaultValues, + listedFieldCalculatedAsValues: ({ listedFieldWithDefaultValues }) => + listedFieldWithDefaultValues, /// @ts-expect-error listedOptionalFieldWithDefaultValues: [enumerable, enumerable], /// @ts-expect-error - listedOptionalFieldCalculatedAsValues: ({ listedOptionalFieldWithDefaultValues }) => listedOptionalFieldWithDefaultValues, - + listedOptionalFieldCalculatedAsValues: ({ + listedOptionalFieldWithDefaultValues, + }) => listedOptionalFieldWithDefaultValues, + // IEnumerable = undefined /// @ts-expect-error fieldWithDefaultUndefinedValue: undefined, /// @ts-expect-error - fieldCalculatedAsUndefinedValue: ({ fieldWithDefaultUndefinedValue }) => fieldWithDefaultUndefinedValue && undefined, + fieldCalculatedAsUndefinedValue: ({ fieldWithDefaultUndefinedValue }) => + fieldWithDefaultUndefinedValue && undefined, /// @ts-expect-error optionalFieldWithDefaultUndefinedValue: undefined, /// @ts-expect-error - optionalFieldCalculatedAsUndefinedValue: ({ optionalFieldWithDefaultUndefinedValue }) => optionalFieldWithDefaultUndefinedValue && undefined, + optionalFieldCalculatedAsUndefinedValue: ({ + optionalFieldWithDefaultUndefinedValue, + }) => optionalFieldWithDefaultUndefinedValue && undefined, // IEnumerable[] = undefined[] /// @ts-expect-error listedFieldWithDefaultUndefinedValues: [undefined], /// @ts-expect-error - listedFieldCalculatedAsUndefinedValues: ({ listedFieldWithDefaultUndefinedValues }) => listedFieldWithDefaultUndefinedValues && [undefined], + listedFieldCalculatedAsUndefinedValues: ({ + listedFieldWithDefaultUndefinedValues, + }) => listedFieldWithDefaultUndefinedValues && [undefined], /// @ts-expect-error listedOptionalFieldWithDefaultUndefinedValues: [undefined], /// @ts-expect-error - listedOptionalFieldCalculatedAsUndefinedValues: ({ listedOptionalFieldWithDefaultUndefinedValues }) => listedOptionalFieldWithDefaultUndefinedValues && [undefined], -} + listedOptionalFieldCalculatedAsUndefinedValues: ({ + listedOptionalFieldWithDefaultUndefinedValues, + }) => listedOptionalFieldWithDefaultUndefinedValues && [undefined], +}; diff --git a/test/types/store/record.ts b/test/types/store/record.ts index e2382b4c..fb59b2bc 100644 --- a/test/types/store/record.ts +++ b/test/types/store/record.ts @@ -1,18 +1,25 @@ -import { Model, define, store } from "/types/index"; +import { PickIndexes, FieldDefinition, GuardedModel, ModelDefinition, define, store, StoreRecord } from "/types/index"; + +type A = { a: string } interface IEnumerableModel { id: string; - values: Record; + property: string + values: Record; } -const IEnumerableModel: Model = { +type B = FieldDefinition + +const IEnumerableModel: ModelDefinition = { id: true, + property: "", values: store.record({ a: "test" }), }; -const IOtherModel: Model = { +const IOtherModel: ModelDefinition = { id: true, - values: store.record(store.ref(() => ({ a: "test" }))), + property: "", + values: store.ref(() => store.record(({ a: "test" }))), }; interface IAComponent extends HTMLElement { diff --git a/test/types/store/ref.ts b/test/types/store/ref.ts index a81912c5..5fb7131a 100644 --- a/test/types/store/ref.ts +++ b/test/types/store/ref.ts @@ -1,4 +1,4 @@ -import { Model, store } from "/types/index"; +import { ModelDefinition, store } from "/types/index"; interface IOtherModel { a: string; @@ -9,11 +9,11 @@ interface IEnumerableModel { other: IOtherModel; } -const IOtherModel: Model = { +const IOtherModel: ModelDefinition = { a: "", }; -const IEnumerableModel: Model = { +const IEnumerableModel: ModelDefinition = { id: true, other: store.ref(() => IOtherModel), }; diff --git a/test/types/store/storage-external.ts b/test/types/store/storage-external.ts index 6dabeac4..b9dcd2ad 100644 --- a/test/types/store/storage-external.ts +++ b/test/types/store/storage-external.ts @@ -6,8 +6,19 @@ const EnumerableModelsSource = new Map< ModelIdentifier, StorageValues >([ - ["0", { id: "0", stringProperty: "qweqwe", numberProperty: 5, nestedEnumerable: "2" }], - ["1", { id: "1", numberProperty: 1711014651455, nestedEnumerables: ["1", "2"] }], + [ + "0", + { + id: "0", + stringProperty: "qweqwe", + numberProperty: 5, + nestedEnumerable: "2", + }, + ], + [ + "1", + { id: "1", numberProperty: 1711014651455, nestedEnumerables: ["1", "2"] }, + ], ["2", { id: "2", stringProperty: "swswswsws" }], ]); diff --git a/types/index.d.ts b/types/index.d.ts index a0bf9f19..936f2223 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -4,7 +4,10 @@ export type Property = | Descriptor; export interface Descriptor { - value: V | ((host: E & HTMLElement, value?: any) => V); + value: + | V + | ((host: E & HTMLElement) => V) + | ((host: E & HTMLElement, value: any) => V); connect?( host: E & HTMLElement & { __property_key__: V }, @@ -39,14 +42,14 @@ export type Component = ComponentBase & { keyof Omit, string >]: property extends "render" - ? RenderFunction | RenderDescriptor - : Property; + ? RenderFunction | RenderDescriptor + : Property; } & { render?: RenderFunction | RenderDescriptor; }; export interface HybridElement { - new (): E & HTMLElement; + new(): E & HTMLElement; prototype: E & HTMLElement; } @@ -82,92 +85,453 @@ export function children( /* Store */ -export type ModelInstance = { id?: ModelIdentifier } & object & - NonArrayObject & - NonModelDefinition; -export type EnumerableInstance = { id: ModelIdentifier } & ModelInstance; -export type SingletonInstance = { id?: never } & ModelInstance; - +/** + * Extracts the element type from an array type. + * @deprecated Use built-in array type utilities instead. This type will be removed in future versions. + * @template T - Target type + * @example + * type Item = Unarray; // string + * type Value = Unarray; // number + */ export type Unarray = T extends Array ? U : T; -export type NonConstructor = { readonly prototype?: never }; -export type NonArrayObject = { [Symbol.iterator]?: never } & object; -export type NonModelDefinition = { __store__connect__?: never } & object; - -export type Model = NonArrayObject & { - [property in keyof Omit]-?: NonNullable< - M[property] - > extends Array - ? - | NestedArrayModel> - | (NonConstructor & - (( - model: M, - ) => undefined extends M[property] - ? undefined | NestedArrayModel - : NestedArrayModel)) - : NonNullable extends string | String - ? string | (NonConstructor & ((model: M) => M[property])) - : NonNullable extends number | Number - ? number | (NonConstructor & ((model: M) => M[property])) - : NonNullable extends boolean | Boolean - ? boolean | (NonConstructor & ((model: M) => M[property])) - : NonNullable extends ModelInstance - ? - | Model> - | (NonConstructor & - (( - model: M, - ) => undefined extends M[property] - ? undefined | Model> - : Model>)) - : NonNullable extends NonArrayObject - ? - | NonNullable - | (NonConstructor & ((model: M) => M[property])) - : never; -} & (M extends EnumerableInstance - ? { - id: true; - } - : {}) & { - __store__connect__?: Storage | Storage["get"]; - }; -export type NestedArrayModel = - NonNullable> extends string | String - ? T | string[] | [String | StringConstructor] - : NonNullable> extends number | Number - ? T | number[] | [Number | NumberConstructor] - : NonNullable> extends boolean | Boolean - ? T | boolean[] | [Boolean | BooleanConstructor] - : NonNullable> extends EnumerableInstance - ? - | [Model>>] - | [Model>>, { loose?: boolean }] - : NonNullable> extends NonArrayObject - ? T - : never; +/** + * Represents non-array object types. + * @deprecated Use `StrictObject` instead. This type will be removed in future versions. + */ +export type NonArrayObject = NonArray & object; + +/** + * Excludes constructor types (classes) by requiring absence of `new` and `prototype` properties. + * @example + * declare function create(obj: NonConstructor & T): void; + * create({ foo: 1 }); // OK + * create(class {}); // Error - has constructor properties + */ +export type NonConstructor = { new?: never, prototype?: never }; + +/** + * Excludes iterable types (like arrays) by requiring absence of `[Symbol.iterator]`. + * @example + * declare function acceptNonArray(obj: NonArray & T): void; + * acceptNonArray({}); // OK + * acceptNonArray([]); // Error - array is iterable + */ +export type NonArray = { [Symbol.iterator]?: never }; + +/** + * Excludes function types by making the function signature return `never`. + * @example + * declare function acceptNonFunction(obj: NonFunction & T): void; + * acceptNonFunction(42); // OK + * acceptNonFunction(() => {}); // Error - function detected + */ +export type NonFunction = { (...args: any[]): never }; + +/** + * Represents a strict non-array, non-constructor object type. + * Acts as a type guard against unintended matches in complex type operations. + * + * @template T - Base object type to extend + * @example + * // Prevents array/class/function from matching object type: + * type Test1 = [1,2,3] extends StrictObject<{}> ? true : false; // false + * type Test2 = class {} extends StrictObject<{}> ? true : false; // false + */ +export type StrictObject = T & object & NonArray & NonConstructor + +/** + * Represents a function that cannot be used as a constructor. + * @template T - Function type to enforce + * @example + * declare function wrapFunction(fn: StrictFunction): void; + * wrapFunction(() => console.log("ok")); // OK + * wrapFunction(class {}); // Error - constructor prohibited + */ +export type StrictFunction any> = T & NonConstructor; + +/** + * Represents a class constructor that cannot be called as a plain function. + * @template T - Instance type of the class + * @example + * declare function registerClass(cls: StrictClass): void; + * registerClass(class Foo {}); // OK + * registerFunction(function() {}); // Error - not a class + */ +export type StrictClass = { new(...args: any[]): T; prototype: T; } & NonFunction; + +/** + * Marker type to exclude model definition objects. + * Contains hidden system property that prevents accidental type matching. + * + * @internal + * @example + * // Without NonModelDefinition, this would incorrectly return true: + * type Test = ModelDefinition extends Model ? true : false; // false + */ +export type NonModelDefinition = { __store__connect__?: never }; + + +/** + * Base model type requiring plain objects with optional `id` property. + * Combines multiple protective markers to prevent type misclassification: + * 1. StrictObject - blocks arrays/classes + * 2. NonModelDefinition - blocks model definitions + * + * @example + * // Critical for type discrimination in functions like: + * function resolve(input: M | ModelDefinition | [ModelDefinition]) { + * // Without protective markers: + * // ModelDefinition would match Model + * // ModelDefinition[] would match Model + * } + */ +export type Model = StrictObject<{ id?: ModelIdentifier }> & NonModelDefinition; + +/** + * Model type requiring explicit identifier (`id` property required). + * Inherits same protective markers as base Model. + * + * @example + * // Without StrictObject/NonModelDefinition: + * type Problem1 = ModelDefinition extends EnumerableModel ? true : false; + * // Would be true (incorrect) + */ +export type EnumerableModel = StrictObject<{ id: ModelIdentifier }> & NonModelDefinition; + +/** + * Model type prohibiting identifier (`id` property forbidden). + * Protective markers ensure only true singletons match. + * + * @example + * // Prevents array of definitions from matching: + * type Test = [ModelDefinition] extends SingletonModel ? true : false; // false + */ +export type SingletonModel = StrictObject<{ id?: never }> & NonModelDefinition; + +/** + * Removes index signatures (string, number, and symbol) from object types. + * + * Used to eliminate phantom keys that TypeScript automatically includes + * when index signatures like `[key: string]: T` or `[key: number]: T` are present. + * + * #### The Problem + * When an interface contains an index signature, TypeScript automatically + * includes all possible keys in `keyof` (including `string` and `number`). + * This interferes with key-specific mappings and causes unwanted iteration behavior. + * + * #### The Solution + * `StripIndex` filters out generic `string`, `number`, and `symbol` keys + * from `keyof T`, preserving only explicitly defined properties. + * + * #### How It Works + * Uses key remapping with conditional exclusion: + * 1. For string keys: `key extends string ? (string extends key ? never : key)` + * 2. For number keys: `key extends number ? (number extends key ? never : key)` + * 3. For symbol keys: `key extends symbol ? (symbol extends key ? never : key)` + * + * #### Example: + * ```ts + * type Raw = { + * id: string; + * name: string; + * [key: string]: unknown; // Index signature + * } + * + * type Clean = StripIndex; + * // Result: { + * // id: string; + * // name: string + * // } // No indexes! + * ``` + * + * @template T Object type to remove index signatures from + */ +export type OmitIndexes = { + [key in keyof T as + key extends string ? (string extends key ? never : key) : + key extends number ? (number extends key ? never : key) : + key extends symbol ? (symbol extends key ? never : key) : + key + ]: T[key]; +} + +export type PickIndexes = { + [key in keyof T as + key extends string ? (string extends key ? key : never) : + key extends number ? (number extends key ? key : never) : + key extends symbol ? (symbol extends key ? key : never) : + key + ]: T[key] +} extends infer IndexPart ? [keyof IndexPart] extends [never] ? void : IndexPart : never; + +type A = PickIndexes<{}> + +/** + * Defines the structure and behavior of a model in the system. + * Maps each model property to either: + * - Identity marker (for 'id' properties) + * - Field definition + * - Value resolver function + * + * @template TModel - Model type being defined (must extend `Model`) + * + * ### Structure + * 1. **Property Mappings**: + * - Identity properties: Marked with `true` + * - Other properties: Field definitions or resolver functions + * 2. **Storage Connector** (optional): + * - Connection to storage system (`store.connect`) + * + * ### Key Features + * - Removes index signatures via `StripIndex` + * - Makes all properties required (`-?` modifier) + * - Distinguishes identity properties via `IsIdentityProperty` + * - Allows computed properties via `ValueResolver` + * + * @example + * ```tsx + * const User: ModelDefinition = { + * id: true, // Identity property + * name: "", // Default value (string field) + * email: { // Field definition + * type: String, + * validate: emailValidator + * }, + * fullName: (user) => `${user.first} ${user.last}`, // Computed property + * [store.connect]: (id) => api.fetchUser(id) // Storage connector + * }; + * ``` + */ +export type ModelDefinition = { + /** + * Maps each model property to its definition: + * - Identity properties → `true` + * - Other properties → Field definition or resolver function + * + * Uses `StripIndex` to remove index signatures and ensure only + * explicit properties are considered + */ + [key in keyof Omit, "id">]-?: + | (TModel[key] extends object ? + PickIndexes extends { [key: string]: infer ItemType } ? Referable> : + PickIndexes extends { [key: number]: infer ItemType } ? Referable> : + PickIndexes extends { [key: symbol]: infer ItemType } ? Referable> : + Referable> : + Referable>) + | ValueResolver +} & EnumerableIndicator & StorageConnector + + +type EnumerableIndicator = TModel extends EnumerableModel ? { id: true } : {} + +/** + * Optional storage system connector + * - Used with `store.connect` symbol in implementations + * - Can be either: + * a) Full storage interface + * b) Storage's `get` method for fetching data + */ +type StorageConnector = { + __store__connect__?: Storage | Storage["get"]; +} + +type StoreRecord = { + __store__record__: TValue +} +/** + * Determines if a property is the model's identity property. + * + * - Must be named 'id' + * - Must have a valid ModelIdentifier type + * + * @template TKey - Property name + * @template TValue - Property value type + * + * @example + * ```ts + * type Test1 = IsIdentityProperty<'id', string>; // true + * type Test2 = IsIdentityProperty<'name', string>; // false + * type Test3 = IsIdentityProperty<'id', boolean>; // false + * ``` + */ +export type IsIdentityProperty = TKey extends "id" ? TValue extends ModelIdentifier ? true : false : false + +/** + * Represents possible types for model identifiers. + * + * - Single string value + * - Composite key (record of primitive values) + * - Undefined (for singleton models) + * + * @example + * ```ts + * type UserID = string; // Simple identifier + * type OrderID = { orderNo: string, region: string }; // Composite key + * ``` + */ export type ModelIdentifier = | string | Record | undefined; -export type ModelValues = { +/** + * Special flag marking identity properties in model definitions. + * Always set to `true` for 'id' fields. + * + * @example + * ```ts + * const ProductModel = { + * id: true, // IdentityFlag + * // ... + * } + * ``` + */ +export type IdentityFlag = true + +/** + * Strict function type for computed property resolvers. + * + * - Receives the model instance as input + * - Returns computed value + * - Prevents constructor usage + * + * @template TModel - Model type + * @template Value - Computed value type + * + * @example + * ```ts + * const resolver: ValueResolver = + * (user) => `${user.firstName} ${user.lastName}`; + * ``` + */ +export type ValueResolver = StrictFunction<(model: TModel) => Value> + +/** + * Defines type mappings for model fields based on their data type. + * Uses distributive conditional types to handle union types correctly. + * + * #### Distributivity Importance + * Without distributivity: + * - Union types would fail (`string | number` wouldn't match either branch) + * - Complex types wouldn't resolve correctly + * + * @template FieldType - Type of the model field being defined + * + * @example Array Handling + * ```ts + * // Array of strings: + * type StringArrayDef = FieldDefinition; // GuardedStringArray + * + * // Array of models: + * type ModelArrayDef = FieldDefinition; + * // GuardedModelArray | Ref> + * ``` + * + * @example Primitive Handling + * ```ts + * type StringDef = FieldDefinition; // GuardedString + * type NumberDef = FieldDefinition; // GuardedNumber + * type BooleanDef = FieldDefinition; // GuardedBoolean + * ``` + */ +export type FieldDefinition = + // ARRAY (distributive check) + FieldType extends Array ? + ItemType extends string | String ? GuardedStringArray : + ItemType extends number | Number ? GuardedNumberArray : + ItemType extends boolean | Boolean ? GuardedBooleanArray : + ItemType extends Model ? GuardedModelArray : + ItemType extends EnumerableModel ? GuardedEnumerableModelArray : + never : + // REGULAR (distributive check) + FieldType extends string | String ? GuardedString : + FieldType extends number | Number ? GuardedNumber : + FieldType extends boolean | Boolean ? GuardedBoolean : + FieldType extends Model ? GuardedModel : + never; + +/** + * Reference wrapper type for lazy evaluation. + * Allows defining values as functions: `() => T` + */ +export type Reference = () => T + +export type Referable = T | Reference + +/** Primitive string type for field definitions */ +export type GuardedString = string + +/** Primitive number type for field definitions */ +export type GuardedNumber = number + +/** Primitive boolean type for field definitions */ +export type GuardedBoolean = boolean + +/** + * Model definition type for single model references. + * Represents a complete model definition. + */ +export type GuardedModel = ModelDefinition + +/** + * Definition for string arrays. + * Allows either: + * - Actual string array: `string[]` + * - TypeScript constructor hint: `[String]` or `[StringConstructor]` + */ +export type GuardedStringArray = string[] | [String | StringConstructor] + +/** + * Definition for number arrays. + * Allows either: + * - Actual number array: `number[]` + * - TypeScript constructor hint: `[Number]` or `[NumberConstructor]` + */ +export type GuardedNumberArray = number[] | [Number | NumberConstructor] + +/** + * Definition for boolean arrays. + * Allows either: + * - Actual boolean array: `boolean[]` + * - TypeScript constructor hint: `[Boolean]` or `[BooleanConstructor]` + */ +export type GuardedBooleanArray = boolean[] | [Boolean | BooleanConstructor] + +/** + * Definition for model arrays. + * Uses tuple form to capture model definition: `[ModelDefinition]` + */ +export type GuardedModelArray = [ModelDefinition] + +/** + * Special definition for enumerable model arrays. + * Adds loose mode option for non-strict relationships. + * + * ### Options + * - `[ModelDefinition]`: Strict relationship + * - `[ModelDefinition, { loose?: boolean }]`: Optional loose mode + */ +export type GuardedEnumerableModelArray = + | [ModelDefinition] + | [ModelDefinition, { loose?: boolean }] + +export type ModelValues = { [property in keyof M]?: - NonNullable extends Array - ? Array>> | string | undefined> - : NonNullable extends ModelInstance - ? ModelValues> | string | undefined - : M[property]; + NonNullable extends Array + ? Array>> | string | undefined> + : NonNullable extends Model + ? ModelValues> | string | undefined + : M[property]; }; -export type StorageResult = +export type StorageResult = | ModelValues | null | undefined; -export type Storage = { +export type Storage = { get?: (id: ModelIdentifier) => StorageResult | Promise>; set?: ( @@ -188,20 +552,20 @@ export type Storage = { }; // Enumerable - This overload must be the first one, then its signature and documentation will be displayed in intelephence by default. -export function store( - model: Model, +export function store( + model: ModelDefinition, options?: { draft?: false; id?: keyof E | ((host: E) => ModelIdentifier) }, ): Descriptor; // Enumerable Draft -export function store( - model: Model, +export function store( + model: ModelDefinition, options: { draft: true; id?: keyof E | ((host: E) => ModelIdentifier) }, ): Descriptor; // Enumerable Listing -export function store( - model: [Model], +export function store( + model: [ModelDefinition], options?: { draft?: false; id?: keyof E | ((host: E) => ModelIdentifier); @@ -210,108 +574,107 @@ export function store( ): Descriptor; // Singleton -export function store( - model: M extends Array ? never : Model, +export function store( + model: M extends Array ? never : ModelDefinition, options?: { draft?: false; id?: keyof E | ((host: E) => ModelIdentifier) }, ): Descriptor; // Singleton Draft -export function store( - model: M extends Array ? never : Model, +export function store( + model: M extends Array ? never : ModelDefinition, options: { draft: true; id?: keyof E | ((host: E) => ModelIdentifier) }, ): Descriptor; export namespace store { const connect = "__store__connect__"; - function get( - Model: Model, + function get( + Model: ModelDefinition, id?: ModelIdentifier, ): M; - function get( - Model: [Model], + function get( + Model: [ModelDefinition], id?: ModelIdentifier, ): M[]; - function set( - model: Model, + function set( + model: ModelDefinition, values: NoInfer>, ): Promise; - function set( - model: Model, + function set( + model: ModelDefinition, values: null, ): Promise; - function set( + function set( model: M, values: NoInfer | null>, ): Promise; - function sync( - model: Model, + function sync( + model: ModelDefinition, values: NoInfer>, ): M; - function sync( - model: Model, + function sync( + model: ModelDefinition, values: null, ): M; - function sync( + function sync( model: M, values: NoInfer | null>, ): M; - function clear( - model: Model | [Model] | M, + function clear( + model: ModelDefinition | [ModelDefinition] | M, clearValue?: boolean, ): void; - function pending(model: M): false | Promise; - function pending( + function pending(model: M): false | Promise; + function pending( ...models: Array ): false | Promise; - function error( + function error( model: M, propertyName?: keyof M | null, ): false | Error | any; - function ready(model: M): boolean; - function ready(...models: Array): boolean; + function ready(model: M): boolean; + function ready(...models: Array): boolean; - function submit( + function submit( draft: M, values?: ModelValues, ): Promise; - function resolve(model: M): Promise; - function resolve( - model: Model, + function resolve(model: M): Promise; + function resolve( + model: ModelDefinition, id?: ModelIdentifier, ): Promise; - function resolve( - model: [Model], + function resolve( + model: [ModelDefinition], id?: ModelIdentifier, ): Promise; - function ref(fn: () => T): () => T; + function ref(fn: Reference): Reference; - function record(value: V): Record; - function record {}>(value: V): Record>; + function record(value: FieldDefinition>): StoreRecord; - interface ValidateFunction { + interface ValidateFunction { (value: T, key: string, model: M): string | boolean | void; } - function value( + function value( defaultValue: string, validate?: ValidateFunction | RegExp, errorMessage?: string, ): string; - function value( + function value( defaultValue: number, validate?: ValidateFunction | RegExp, errorMessage?: string, ): number; - function value( + function value( defaultValue: boolean, validate?: ValidateFunction | RegExp, errorMessage?: string, @@ -384,15 +747,15 @@ export namespace router { export type Messages = { [key: string]: { message: - | string - | { - zero?: string; - one?: string; - two?: string; - few?: string; - many?: string; - other?: string; - }; + | string + | { + zero?: string; + one?: string; + two?: string; + few?: string; + many?: string; + other?: string; + }; description?: string; }; };