From 7adb00b51f5634578fa6130e082764d56e9823cb Mon Sep 17 00:00:00 2001 From: Ard van der Marel <109339598+Ard2025@users.noreply.github.com> Date: Sun, 24 Aug 2025 09:15:53 +0200 Subject: [PATCH 01/15] Replace JsonConstructor by MagicConstructor --- .../Exceptions/MagicConstructorException.cs | 3 +++ Magic.IndexedDb/Helpers/PropertyMappingCache.cs | 12 +++++++++--- .../SchemaAnnotations/MagicConstructorAttribute.cs | 6 ++++++ TestBase/Models/Person.cs | 2 +- 4 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 Magic.IndexedDb/Exceptions/MagicConstructorException.cs create mode 100644 Magic.IndexedDb/SchemaAnnotations/MagicConstructorAttribute.cs diff --git a/Magic.IndexedDb/Exceptions/MagicConstructorException.cs b/Magic.IndexedDb/Exceptions/MagicConstructorException.cs new file mode 100644 index 0000000..b6da8b0 --- /dev/null +++ b/Magic.IndexedDb/Exceptions/MagicConstructorException.cs @@ -0,0 +1,3 @@ +namespace Magic.IndexedDb.Exceptions; + +public class MagicConstructorException(string message) : Exception(message); \ No newline at end of file diff --git a/Magic.IndexedDb/Helpers/PropertyMappingCache.cs b/Magic.IndexedDb/Helpers/PropertyMappingCache.cs index cc9750d..fe61d0c 100644 --- a/Magic.IndexedDb/Helpers/PropertyMappingCache.cs +++ b/Magic.IndexedDb/Helpers/PropertyMappingCache.cs @@ -5,6 +5,7 @@ using System.Collections.Concurrent; using System.Reflection; using System.Text.Json.Serialization; +using Magic.IndexedDb.Exceptions; namespace Magic.IndexedDb.Helpers; @@ -37,9 +38,14 @@ public SearchPropEntry(Type type, Dictionary _proper EnforcePascalCase = false; } - // 🔥 Pick the best constructor: Prefer JsonConstructor, then fall back to a parameterized one, else fallback to parameterless - var jsonConstructor = constructors.FirstOrDefault(c => c.GetCustomAttribute() != null); - if (jsonConstructor == null) + // 🔥 Pick the best constructor: Prefer MagicConstructor, then fall back to a parameterized one, else fallback to parameterless + if (constructors.Count(c => c.GetCustomAttribute() != null) > 1) + { + throw new MagicConstructorException("Only one magic constructor is allowed"); + } + + var magicConstructor = constructors.FirstOrDefault(c => c.GetCustomAttribute() != null); + if (magicConstructor == null) { Constructor = constructors.OrderByDescending(c => c.GetParameters().Length).FirstOrDefault(); } diff --git a/Magic.IndexedDb/SchemaAnnotations/MagicConstructorAttribute.cs b/Magic.IndexedDb/SchemaAnnotations/MagicConstructorAttribute.cs new file mode 100644 index 0000000..9dd5430 --- /dev/null +++ b/Magic.IndexedDb/SchemaAnnotations/MagicConstructorAttribute.cs @@ -0,0 +1,6 @@ +namespace Magic.IndexedDb.SchemaAnnotations; + +/// +/// Sets the preferred constructor for serialization for MagicDB +/// +public class MagicConstructorAttribute : Attribute; \ No newline at end of file diff --git a/TestBase/Models/Person.cs b/TestBase/Models/Person.cs index 8e5afd3..9fc4738 100644 --- a/TestBase/Models/Person.cs +++ b/TestBase/Models/Person.cs @@ -14,7 +14,7 @@ public class Nested public class Person : MagicTableTool, IMagicTable { - [JsonConstructor] + [MagicConstructor] public Person() { DoNotMapTest2 = "Test"; From a46fc71d551506ecc9c198094a80716d6211c980 Mon Sep 17 00:00:00 2001 From: Ard van der Marel <109339598+Ard2025@users.noreply.github.com> Date: Sun, 24 Aug 2025 11:33:30 +0200 Subject: [PATCH 02/15] SingleOrDefault rewrite MagicConstructor --- Magic.IndexedDb/Helpers/PropertyMappingCache.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Magic.IndexedDb/Helpers/PropertyMappingCache.cs b/Magic.IndexedDb/Helpers/PropertyMappingCache.cs index fe61d0c..615b655 100644 --- a/Magic.IndexedDb/Helpers/PropertyMappingCache.cs +++ b/Magic.IndexedDb/Helpers/PropertyMappingCache.cs @@ -39,16 +39,19 @@ public SearchPropEntry(Type type, Dictionary _proper } // 🔥 Pick the best constructor: Prefer MagicConstructor, then fall back to a parameterized one, else fallback to parameterless - if (constructors.Count(c => c.GetCustomAttribute() != null) > 1) + try { + var magicConstructor = constructors.SingleOrDefault(c => c.GetCustomAttribute() != null); + if (magicConstructor == null) + { + Constructor = constructors.OrderByDescending(c => c.GetParameters().Length).FirstOrDefault(); + } + } + + catch (InvalidOperationException){ throw new MagicConstructorException("Only one magic constructor is allowed"); } - var magicConstructor = constructors.FirstOrDefault(c => c.GetCustomAttribute() != null); - if (magicConstructor == null) - { - Constructor = constructors.OrderByDescending(c => c.GetParameters().Length).FirstOrDefault(); - } HasConstructorParameters = Constructor != null && Constructor.GetParameters().Length > 0; // 🔥 Cache constructor parameter mappings From dfe321adbb488823f3c7217ca9a65217e23cf107 Mon Sep 17 00:00:00 2001 From: Ard van der Marel <109339598+Ard2025@users.noreply.github.com> Date: Sun, 24 Aug 2025 13:29:19 +0200 Subject: [PATCH 03/15] improvement from yueyinqiu --- Magic.IndexedDb/Helpers/PropertyMappingCache.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Magic.IndexedDb/Helpers/PropertyMappingCache.cs b/Magic.IndexedDb/Helpers/PropertyMappingCache.cs index 615b655..efec81d 100644 --- a/Magic.IndexedDb/Helpers/PropertyMappingCache.cs +++ b/Magic.IndexedDb/Helpers/PropertyMappingCache.cs @@ -41,16 +41,13 @@ public SearchPropEntry(Type type, Dictionary _proper // 🔥 Pick the best constructor: Prefer MagicConstructor, then fall back to a parameterized one, else fallback to parameterless try { - var magicConstructor = constructors.SingleOrDefault(c => c.GetCustomAttribute() != null); - if (magicConstructor == null) - { - Constructor = constructors.OrderByDescending(c => c.GetParameters().Length).FirstOrDefault(); - } + Constructor = constructors.SingleOrDefault(c => c.GetCustomAttribute() is not null); } - - catch (InvalidOperationException){ + catch (InvalidOperationException) + { throw new MagicConstructorException("Only one magic constructor is allowed"); } + Constructor ??= constructors.OrderByDescending(c => c.GetParameters().Length).FirstOrDefault(); HasConstructorParameters = Constructor != null && Constructor.GetParameters().Length > 0; From 29c1b8fb34d5b62a7ef9c9fe2884454c5d8f9e60 Mon Sep 17 00:00:00 2001 From: Ard van der Marel <109339598+Ard2025@users.noreply.github.com> Date: Mon, 25 Aug 2025 22:07:00 +0200 Subject: [PATCH 04/15] Proper constructor work when deserializing T. properties that are not passed to the constructor will get initialized --- .../Models/MagicContractResolver.cs | 26 ++++++++++++++----- TestBase/Models/Person.cs | 3 ++- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/Magic.IndexedDb/Models/MagicContractResolver.cs b/Magic.IndexedDb/Models/MagicContractResolver.cs index 38de04b..6359fcd 100644 --- a/Magic.IndexedDb/Models/MagicContractResolver.cs +++ b/Magic.IndexedDb/Models/MagicContractResolver.cs @@ -1,5 +1,6 @@ using System.Collections; using System.Collections.Concurrent; +using System.Runtime.CompilerServices; using System.Text.Json; using System.Text.Json.Serialization; using Magic.IndexedDb.Helpers; @@ -62,25 +63,38 @@ internal class MagicContractResolver : JsonConverter private object CreateObjectFromDictionary(Type type, Dictionary propertyValues, SearchPropEntry search) { - // 🚀 If there's a constructor with parameters, use it - if (search.ConstructorParameterMappings.Count > 0) + object? obj = null; + List unInitializedProperties = new List(); + // If the constructor set in the SearchPropEntry contains parameters, fill them + if (search.HasConstructorParameters) { var constructorArgs = new object?[search.ConstructorParameterMappings.Count]; foreach (var (paramName, index) in search.ConstructorParameterMappings) { if (propertyValues.TryGetValue(paramName, out var value)) + { constructorArgs[index] = value; + propertyValues.Remove(paramName); + } else constructorArgs[index] = GetDefaultValue(type.GetProperty(paramName)?.PropertyType ?? typeof(object)); } - return search.InstanceCreator(constructorArgs) ?? throw new InvalidOperationException($"Failed to create instance of type {type.Name}."); + obj = search.InstanceCreator(constructorArgs); + } + else + { + // 🚀 Use parameterless constructor + obj = search.InstanceCreator([]); + } + + if (obj is null) + { + throw new InvalidOperationException($"Failed to create instance of type {type.Name}."); } - // 🚀 Use parameterless constructor - var obj = search.InstanceCreator(Array.Empty()) ?? throw new InvalidOperationException($"Failed to create instance of type {type.Name}."); - // 🚀 Assign property values + // 🚀 Assign property values (to properties not passed to constructor) foreach (var (propName, value) in propertyValues) { if (search.propertyEntries.TryGetValue(propName, out var propEntry)) diff --git a/TestBase/Models/Person.cs b/TestBase/Models/Person.cs index 9fc4738..1c7c5f9 100644 --- a/TestBase/Models/Person.cs +++ b/TestBase/Models/Person.cs @@ -14,6 +14,7 @@ public class Nested public class Person : MagicTableTool, IMagicTable { + [MagicConstructor] public Person() { @@ -22,7 +23,7 @@ public Person() public Person(int _Id) { - DoNotMapTest2 = _Id.ToString(); + this._Id = _Id; } public List GetCompoundIndexes() => From c3483b094bb38019a3501bcca9e621cc19fc343e Mon Sep 17 00:00:00 2001 From: Ard van der Marel <109339598+Ard2025@users.noreply.github.com> Date: Mon, 25 Aug 2025 22:15:14 +0200 Subject: [PATCH 05/15] Small styling improvement --- Magic.IndexedDb/Models/MagicContractResolver.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Magic.IndexedDb/Models/MagicContractResolver.cs b/Magic.IndexedDb/Models/MagicContractResolver.cs index 6359fcd..6c16707 100644 --- a/Magic.IndexedDb/Models/MagicContractResolver.cs +++ b/Magic.IndexedDb/Models/MagicContractResolver.cs @@ -77,7 +77,10 @@ private object CreateObjectFromDictionary(Type type, Dictionary propertyValues.Remove(paramName); } else - constructorArgs[index] = GetDefaultValue(type.GetProperty(paramName)?.PropertyType ?? typeof(object)); + { + constructorArgs[index] = + GetDefaultValue(type.GetProperty(paramName)?.PropertyType ?? typeof(object)); + } } obj = search.InstanceCreator(constructorArgs); From e6f14b46e682e402e12dffbf28d5b2b05ad14444 Mon Sep 17 00:00:00 2001 From: Ard van der Marel <109339598+Ard2025@users.noreply.github.com> Date: Thu, 28 Aug 2025 10:01:32 +0200 Subject: [PATCH 06/15] Use debuglog method more consistantly --- Magic.IndexedDb/wwwroot/magicDB.js | 13 +++++++------ Magic.IndexedDb/wwwroot/magicMigration.js | 4 +++- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Magic.IndexedDb/wwwroot/magicDB.js b/Magic.IndexedDb/wwwroot/magicDB.js index 7a79fa8..11c9d42 100644 --- a/Magic.IndexedDb/wwwroot/magicDB.js +++ b/Magic.IndexedDb/wwwroot/magicDB.js @@ -3,6 +3,7 @@ /// import Dexie from "./dexie/dexie.js"; import { magicQueryAsync, magicQueryYield } from "./magicLinqToIndexedDb.js"; +import {debugLog} from "./utilities/utilityHelpers.js"; /** * @typedef {Object} DatabasesItem * @property {string} name @@ -77,7 +78,7 @@ export function listOpenDatabases() { export function createDb(dbStore) { - console.log("Debug: Received dbStore in createDb", dbStore); + debugLog("Received dbStore in createDb", dbStore); if (!dbStore || !dbStore.name) { console.error("Blazor.IndexedDB.Framework - Invalid dbStore provided"); @@ -144,7 +145,7 @@ export function createDb(dbStore) { stores[schema.tableName] = def; } - console.log("Dexie Store Definition:", stores); + debugLog("Dexie Store Definition:", stores); db.version(dbStore.version).stores(stores); @@ -178,7 +179,7 @@ export function closeAll() { databases.forEach((entry, dbName) => { entry.db.close(); entry.isOpen = false; - console.log(`Database ${dbName} closed.`); + debugLog(`Database ${dbName} closed.`); }); } @@ -205,7 +206,7 @@ export async function deleteDb(dbName) { } await Dexie.delete(dbName); - console.log(`Database '${dbName}' deleted.`); + debugLog(`Database '${dbName}' deleted.`); } catch (deleteErr) { console.error(`deleteDb: Failed to delete DB '${dbName}'`, deleteErr); } @@ -297,7 +298,7 @@ export async function deleteAllDatabases() { for (const dbName of databases.keys()) { await deleteDb(dbName); } - console.log("All databases deleted."); + debugLog("All databases deleted."); } @@ -457,7 +458,7 @@ export async function bulkDelete(dbName, storeName, items) { items.map(item => getKeyArrayForDelete(dbName, storeName, item)) ); - console.log('Keys to delete:', formattedKeys); + debugLog('Keys to delete:', formattedKeys); await table.bulkDelete(formattedKeys); return items.length; } catch (e) { diff --git a/Magic.IndexedDb/wwwroot/magicMigration.js b/Magic.IndexedDb/wwwroot/magicMigration.js index 72842c6..8b5f7cf 100644 --- a/Magic.IndexedDb/wwwroot/magicMigration.js +++ b/Magic.IndexedDb/wwwroot/magicMigration.js @@ -1,10 +1,12 @@ +import {debugLog} from "./utilities/utilityHelpers.js"; + export class MagicMigration { constructor(db) { this.db = db; } Initialize() { - console.log("Using Dexie from MagicDB:", this.db); + debugLog("Using Dexie from MagicDB:", this.db); // You can now do any Dexie operations here } } From 7a548e9f3af76f77b28e0064a123e97d7bee55de Mon Sep 17 00:00:00 2001 From: Ard van der Marel <109339598+Ard2025@users.noreply.github.com> Date: Sun, 5 Oct 2025 21:09:46 +0200 Subject: [PATCH 07/15] Reduce memory useage on serializing --- Magic.IndexedDb/Models/MagicContractResolver.cs | 3 ++- TestWasm/Pages/Home.razor | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Magic.IndexedDb/Models/MagicContractResolver.cs b/Magic.IndexedDb/Models/MagicContractResolver.cs index 38de04b..4e71656 100644 --- a/Magic.IndexedDb/Models/MagicContractResolver.cs +++ b/Magic.IndexedDb/Models/MagicContractResolver.cs @@ -374,7 +374,8 @@ private void WriteSimpleType(Utf8JsonWriter writer, object value) switch (value) { case string str: - writer.WriteStringValue(str); + str = str.Replace("\"", "\\\""); + writer.WriteRawValue("\"" + str + "\"", true); break; case bool b: writer.WriteBooleanValue(b); diff --git a/TestWasm/Pages/Home.razor b/TestWasm/Pages/Home.razor index 396097c..339b8b8 100644 --- a/TestWasm/Pages/Home.razor +++ b/TestWasm/Pages/Home.razor @@ -234,7 +234,7 @@ IndexOrderingProperties = new List> { Person[] persons = new Person[] { - new Person { Name = "Zack", DateOfBirth = null, TestInt = 9, _Age = 45, GUIY = Guid.NewGuid(), DoNotMapTest = "I buried treasure behind my house", Access=Person.Permissions.CanRead}, + new Person { Name = "Zack", DateOfBirth = null, TestInt = 9, _Age = 45, GUIY = Guid.NewGuid(), DoNotMapTest = "I buried treasure behind my house", Access=Person.Permissions.CanRead, Secret = new String('a', 45000000)}, new Person { Name = "Luna", TestInt = 9, DateOfBirth = GetDateWithSameMonthDay(GetRandomYear()), _Age = 35, GUIY = Guid.NewGuid(), DoNotMapTest = "Jerry is my husband and I had an affair with Bob.", Access = Person.Permissions.CanRead|Person.Permissions.CanWrite}, new Person { Name = "Jerry", TestInt = 9, DateOfBirth = GetDateWithSameMonthDay(GetRandomYear()), _Age = 35, GUIY = Guid.NewGuid(), DoNotMapTest = "My wife is amazing", Access = Person.Permissions.CanRead|Person.Permissions.CanWrite|Person.Permissions.CanCreate}, new Person { Name = "Jamie", TestInt = 9, DateOfBirth = GetDateWithSameMonthDay(GetRandomYear()), _Age = 35, GUIY = Guid.NewGuid(), DoNotMapTest = "My wife is amazing", Access = Person.Permissions.CanRead|Person.Permissions.CanWrite|Person.Permissions.CanCreate}, From 399c1d3a0586811a547fcfdfe11148fb36312288 Mon Sep 17 00:00:00 2001 From: Ard van der Marel <109339598+Ard2025@users.noreply.github.com> Date: Sun, 5 Oct 2025 21:11:59 +0200 Subject: [PATCH 08/15] update server test to test memory 45MB --- TestBase/Data/PersonData.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestBase/Data/PersonData.cs b/TestBase/Data/PersonData.cs index 256a244..a963b50 100644 --- a/TestBase/Data/PersonData.cs +++ b/TestBase/Data/PersonData.cs @@ -6,7 +6,7 @@ public static class PersonData { public static Person[] persons = [ - new Person { _Id = 1, Name = "Zack", DateOfBirth = null, TestInt = 9, _Age = 45, GUIY = Guid.NewGuid(), DoNotMapTest = "I buried treasure behind my house", Access=Person.Permissions.CanRead}, + new Person { _Id = 1, Name = "Zack", DateOfBirth = null, TestInt = 9, _Age = 45, GUIY = Guid.NewGuid(), DoNotMapTest = "I buried treasure behind my house", Access=Person.Permissions.CanRead, Secret = new String('a', 45000000)}, new Person { _Id = 2, Name = "Luna", TestInt = 9, DateOfBirth = new DateTime(1980, 1, 1), _Age = 35, GUIY = Guid.NewGuid(), DoNotMapTest = "Jerry is my husband and I had an affair with Bob.", Access = Person.Permissions.CanRead|Person.Permissions.CanWrite}, new Person { _Id = 3, Name = "Jerry", TestInt = 9, DateOfBirth = new DateTime(1981, 1, 1), _Age = 35, GUIY = Guid.NewGuid(), DoNotMapTest = "My wife is amazing", Access = Person.Permissions.CanRead|Person.Permissions.CanWrite|Person.Permissions.CanCreate}, new Person { _Id = 4, Name = "Jamie", TestInt = 9, DateOfBirth = new DateTime(1982, 1, 1), _Age = 35, GUIY = Guid.NewGuid(), DoNotMapTest = "My wife is amazing", Access = Person.Permissions.CanRead|Person.Permissions.CanWrite|Person.Permissions.CanCreate}, From a6c0ddb9073698de754fab243a18de8ef92d74ba Mon Sep 17 00:00:00 2001 From: Ard van der Marel <109339598+Ard2025@users.noreply.github.com> Date: Sun, 5 Oct 2025 21:41:55 +0200 Subject: [PATCH 09/15] Andisposing the responseStream correctly --- Magic.IndexedDb/Extensions/MagicJsInvoke.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Magic.IndexedDb/Extensions/MagicJsInvoke.cs b/Magic.IndexedDb/Extensions/MagicJsInvoke.cs index cf6eaf3..abe9e4f 100644 --- a/Magic.IndexedDb/Extensions/MagicJsInvoke.cs +++ b/Magic.IndexedDb/Extensions/MagicJsInvoke.cs @@ -122,7 +122,7 @@ internal async Task CallInvokeVoidDefaultJsAsync(string modulePath, string funct stream.Position = 0; - var streamRef = new DotNetStreamReference(stream); + using var streamRef = new DotNetStreamReference(stream); // Send to JS var responseStreamRef = await _jsModule.InvokeAsync("streamedJsHandler", @@ -133,6 +133,7 @@ internal async Task CallInvokeVoidDefaultJsAsync(string modulePath, string funct using var reader = new StreamReader(responseStream); string jsonResponse = await reader.ReadToEndAsync(); + await responseStreamRef.DisposeAsync(); return MagicSerializationHelper.DeserializeObject(jsonResponse, settings); } From 2d9550ad34f6683b0e366b382968434f16638eec Mon Sep 17 00:00:00 2001 From: Ard van der Marel <109339598+Ard2025@users.noreply.github.com> Date: Fri, 14 Nov 2025 14:32:10 +0100 Subject: [PATCH 10/15] Improve internal serializeing of List> and enum --- Magic.IndexedDb/Interfaces/ITypedArgument.cs | 1 - Magic.IndexedDb/Models/MagicContractResolver.cs | 9 +++++++++ Magic.IndexedDb/Models/TypedArgument.cs | 5 ----- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Magic.IndexedDb/Interfaces/ITypedArgument.cs b/Magic.IndexedDb/Interfaces/ITypedArgument.cs index 098f65d..ec5c9c5 100644 --- a/Magic.IndexedDb/Interfaces/ITypedArgument.cs +++ b/Magic.IndexedDb/Interfaces/ITypedArgument.cs @@ -5,7 +5,6 @@ namespace Magic.IndexedDb.Interfaces; public interface ITypedArgument { - string Serialize(); // Still needed for some cases JsonElement SerializeToJsonElement(MagicJsonSerializationSettings? settings = null); // Ensures proper object passing string SerializeToJsonString(MagicJsonSerializationSettings? settings = null); } \ No newline at end of file diff --git a/Magic.IndexedDb/Models/MagicContractResolver.cs b/Magic.IndexedDb/Models/MagicContractResolver.cs index 4e71656..e3aca0b 100644 --- a/Magic.IndexedDb/Models/MagicContractResolver.cs +++ b/Magic.IndexedDb/Models/MagicContractResolver.cs @@ -342,6 +342,12 @@ private bool SerializeIEnumerable(Utf8JsonWriter writer, object? value, JsonSeri continue; } + if (item is IEnumerable nestedEnumerable && item.GetType() != typeof(string)) + { + SerializeIEnumerable(writer, nestedEnumerable, options); + continue; + } + if (item != null) { Type itemType = item.GetType(); @@ -398,6 +404,9 @@ private void WriteSimpleType(Utf8JsonWriter writer, object value) case Guid guid: writer.WriteStringValue(guid.ToString()); break; + case Enum e: + writer.WriteNumberValue(((IConvertible)e).ToInt32(null)); + break; default: JsonSerializer.Serialize(writer, value); break; diff --git a/Magic.IndexedDb/Models/TypedArgument.cs b/Magic.IndexedDb/Models/TypedArgument.cs index 6074336..adfd757 100644 --- a/Magic.IndexedDb/Models/TypedArgument.cs +++ b/Magic.IndexedDb/Models/TypedArgument.cs @@ -13,11 +13,6 @@ public TypedArgument(T? value) Value = value; } - public string Serialize() - { - return MagicSerializationHelper.SerializeObject(Value); - } - public JsonElement SerializeToJsonElement(MagicJsonSerializationSettings? settings = null) { return MagicSerializationHelper.SerializeObjectToJsonElement(Value, settings); From a786beae1518fb68f6fbdb43f0cd6f9a27f6eac0 Mon Sep 17 00:00:00 2001 From: Ard van der Marel <109339598+Ard2025@users.noreply.github.com> Date: Sun, 28 Dec 2025 09:54:02 +0100 Subject: [PATCH 11/15] Clean testwasm --- TestBase/Data/PersonData.cs | 2 +- TestWasm/Layout/NavMenu.razor | 10 -- TestWasm/Models/DbNames.cs | 6 - TestWasm/Models/Person.cs | 97 ---------------- TestWasm/Pages/Counter.razor | 18 --- TestWasm/Pages/Home.razor | 160 +------------------------- TestWasm/Pages/Weather.razor | 57 --------- TestWasm/Repository/IndexDbContext.cs | 11 -- TestWasm/Share/PanelCustomTests.razor | 29 ----- 9 files changed, 5 insertions(+), 385 deletions(-) delete mode 100644 TestWasm/Models/DbNames.cs delete mode 100644 TestWasm/Models/Person.cs delete mode 100644 TestWasm/Pages/Counter.razor delete mode 100644 TestWasm/Pages/Weather.razor delete mode 100644 TestWasm/Repository/IndexDbContext.cs diff --git a/TestBase/Data/PersonData.cs b/TestBase/Data/PersonData.cs index a963b50..6fb76c9 100644 --- a/TestBase/Data/PersonData.cs +++ b/TestBase/Data/PersonData.cs @@ -6,7 +6,7 @@ public static class PersonData { public static Person[] persons = [ - new Person { _Id = 1, Name = "Zack", DateOfBirth = null, TestInt = 9, _Age = 45, GUIY = Guid.NewGuid(), DoNotMapTest = "I buried treasure behind my house", Access=Person.Permissions.CanRead, Secret = new String('a', 45000000)}, + new Person { _Id = 1, Name = "Zack", DateOfBirth = null, TestInt = 9, _Age = 45, GUIY = Guid.NewGuid(), DoNotMapTest = "I buried treasure behind my house", Access=Person.Permissions.CanRead, Secret = new String('a', 45)}, new Person { _Id = 2, Name = "Luna", TestInt = 9, DateOfBirth = new DateTime(1980, 1, 1), _Age = 35, GUIY = Guid.NewGuid(), DoNotMapTest = "Jerry is my husband and I had an affair with Bob.", Access = Person.Permissions.CanRead|Person.Permissions.CanWrite}, new Person { _Id = 3, Name = "Jerry", TestInt = 9, DateOfBirth = new DateTime(1981, 1, 1), _Age = 35, GUIY = Guid.NewGuid(), DoNotMapTest = "My wife is amazing", Access = Person.Permissions.CanRead|Person.Permissions.CanWrite|Person.Permissions.CanCreate}, new Person { _Id = 4, Name = "Jamie", TestInt = 9, DateOfBirth = new DateTime(1982, 1, 1), _Age = 35, GUIY = Guid.NewGuid(), DoNotMapTest = "My wife is amazing", Access = Person.Permissions.CanRead|Person.Permissions.CanWrite|Person.Permissions.CanCreate}, diff --git a/TestWasm/Layout/NavMenu.razor b/TestWasm/Layout/NavMenu.razor index aeddca1..9e8c6c2 100644 --- a/TestWasm/Layout/NavMenu.razor +++ b/TestWasm/Layout/NavMenu.razor @@ -14,16 +14,6 @@ Home - - diff --git a/TestWasm/Models/DbNames.cs b/TestWasm/Models/DbNames.cs deleted file mode 100644 index 31f1d41..0000000 --- a/TestWasm/Models/DbNames.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace TestWasm.Models; - -public static class DbNames -{ - public const string Client = "client"; -} \ No newline at end of file diff --git a/TestWasm/Models/Person.cs b/TestWasm/Models/Person.cs deleted file mode 100644 index 20cd2a5..0000000 --- a/TestWasm/Models/Person.cs +++ /dev/null @@ -1,97 +0,0 @@ -using Magic.IndexedDb; - -using Magic.IndexedDb.SchemaAnnotations; -using TestWasm.Repository; -using static TestWasm.Models.Person; - -namespace TestWasm.Models; - -public class Nested -{ - public string Value { get; set; } = "abc"; -} - - -public class Person : MagicTableTool, IMagicTable -{ - public List GetCompoundIndexes() => - new List() { - CreateCompoundIndex(x => x.TestIntStable2, x => x.Name) - }; - - //public IMagicCompoundKey GetKeys() => - // CreateCompoundKey(x => x.TestIntStable2, x => x.TestIntStable); - - public IMagicCompoundKey GetKeys() => - CreatePrimaryKey(x => x._Id, true); - - public string GetTableName() => "Person"; - public IndexedDbSet GetDefaultDatabase() => IndexDbContext.Client; - public DbSets Databases { get; } = new(); - public sealed class DbSets - { - public readonly IndexedDbSet Client = IndexDbContext.Client; - public readonly IndexedDbSet Employee = IndexDbContext.Employee; - } - - - public int TestIntStable { get; set; } - public int TestIntStable2 { get; set; } = 10; - - public Nested Nested { get; set; } = new Nested(); - - [MagicName("_id")] - public int _Id { get; set; } - - [MagicName("guid1")] - public Guid Guid1 { get; set; } = new Guid(); - - [MagicName("guid2")] - public Guid Guid2 { get; set; } = new Guid(); - - [MagicIndex] - public string Name { get; set; } - - [MagicName("Age")] - public int _Age { get; set; } - - [MagicIndex("TestInt")] - public int TestInt { get; set; } - - public DateTime? DateOfBirth { get; set; } - - [MagicUniqueIndex("guid")] - public Guid GUIY { get; set; } = Guid.NewGuid(); - public string Secret { get; set; } - - [MagicNotMapped] - public string DoNotMapTest { get; set; } - - [MagicNotMapped] - public static string DoNotMapTest2 { get; set; } - - [MagicNotMapped] - public string SecretDecrypted { get; set; } - - - public object Payload { get; set; } = new { Property = "test" }; - - private bool testPrivate { get; set; } = false; - - public bool GetTest() - { - return true; - } - - [Flags] - public enum Permissions - { - None = 0, - CanRead = 1, - CanWrite = 1 << 1, - CanDelete = 1 << 2, - CanCreate = 1 << 3 - } - - public Permissions Access { get; set; } -} \ No newline at end of file diff --git a/TestWasm/Pages/Counter.razor b/TestWasm/Pages/Counter.razor deleted file mode 100644 index ef23cb3..0000000 --- a/TestWasm/Pages/Counter.razor +++ /dev/null @@ -1,18 +0,0 @@ -@page "/counter" - -Counter - -

Counter

- -

Current count: @currentCount

- - - -@code { - private int currentCount = 0; - - private void IncrementCount() - { - currentCount++; - } -} diff --git a/TestWasm/Pages/Home.razor b/TestWasm/Pages/Home.razor index 339b8b8..613ca2a 100644 --- a/TestWasm/Pages/Home.razor +++ b/TestWasm/Pages/Home.razor @@ -1,12 +1,10 @@ @page "/" @using Magic.IndexedDb -@using TestWasm.Models -@using TestWasm.Repository +@using TestBase.Models +@using TestBase.Repository @using System.Linq; @using TestBase.Helpers -@using TestBase.Models @using TestWasm.Share -@using Person = TestWasm.Models.Person @inject IMagicIndexedDb _MagicDb @@ -220,68 +218,7 @@ IndexOrderingProperties = new List> { personQuery = await _MagicDb.Query(); await personQuery.ClearTable(); - // Choose an assigned database to Person with strictly typed enforced connected Db's. - IMagicQuery employeeDbQuery = await _MagicDb.Query(x => x.Databases.Client); - - // Not implemented yet - // // // Highly not suggested, but you're allowed to target databases not assigned to the Person table - // IMagicQuery animalDbQuery = await _MagicDb.Query(IndexDbContext.Animal); - - // // // DO NOT DO THIS! I only am allowing this for maximum flexibility but this is very dangerous. - // IMagicQuery unassignedDbQuery = await _MagicDb.QueryOverride("DbName", "SchemaName"); - - - - - Person[] persons = new Person[] { - new Person { Name = "Zack", DateOfBirth = null, TestInt = 9, _Age = 45, GUIY = Guid.NewGuid(), DoNotMapTest = "I buried treasure behind my house", Access=Person.Permissions.CanRead, Secret = new String('a', 45000000)}, - new Person { Name = "Luna", TestInt = 9, DateOfBirth = GetDateWithSameMonthDay(GetRandomYear()), _Age = 35, GUIY = Guid.NewGuid(), DoNotMapTest = "Jerry is my husband and I had an affair with Bob.", Access = Person.Permissions.CanRead|Person.Permissions.CanWrite}, - new Person { Name = "Jerry", TestInt = 9, DateOfBirth = GetDateWithSameMonthDay(GetRandomYear()), _Age = 35, GUIY = Guid.NewGuid(), DoNotMapTest = "My wife is amazing", Access = Person.Permissions.CanRead|Person.Permissions.CanWrite|Person.Permissions.CanCreate}, - new Person { Name = "Jamie", TestInt = 9, DateOfBirth = GetDateWithSameMonthDay(GetRandomYear()), _Age = 35, GUIY = Guid.NewGuid(), DoNotMapTest = "My wife is amazing", Access = Person.Permissions.CanRead|Person.Permissions.CanWrite|Person.Permissions.CanCreate}, - new Person { Name = "James", TestInt = 9, DateOfBirth = GetDateWithSameMonthDay(GetRandomYear()), _Age = 35, GUIY = Guid.NewGuid(), DoNotMapTest = "My wife is amazing", Access = Person.Permissions.CanRead|Person.Permissions.CanWrite|Person.Permissions.CanCreate}, - new Person { Name = "Jack", TestInt = 9, DateOfBirth = GetDateWithSameMonthDay(GetRandomYear()), _Age = 35, GUIY = Guid.NewGuid(), DoNotMapTest = "My wife is amazing", Access = Person.Permissions.CanRead|Person.Permissions.CanWrite|Person.Permissions.CanCreate}, - new Person { Name = "Jon", TestInt = 9, DateOfBirth = GetDateWithSameMonthDay(GetRandomYear()), _Age = 37, GUIY = Guid.NewGuid(), DoNotMapTest = "I black mail Luna for money because I know her secret", Access = Person.Permissions.CanRead}, - new Person { Name = "Jack", TestInt = 9, DateOfBirth = GetDateWithSameMonthDay(GetRandomYear()), _Age = 37, GUIY = Guid.NewGuid(), DoNotMapTest = "I have a drug problem", Access = Person.Permissions.CanRead|Person.Permissions.CanWrite}, - new Person { Name = "Cathy", TestInt = 9, DateOfBirth = GetDateWithSameMonthDay(GetRandomYear()), _Age = 22, GUIY = Guid.NewGuid(), DoNotMapTest = "I got away with reading Bobs diary.", Access = Person.Permissions.CanRead | Person.Permissions.CanWrite}, - new Person { Name = "Bob", TestInt = 3 , DateOfBirth = GetDateWithSameMonthDay(GetRandomYear()), _Age = 69, GUIY = Guid.NewGuid(), DoNotMapTest = "I caught Cathy reading my diary, but I'm too shy to confront her.", Access = Person.Permissions.CanRead }, - new Person { Name = "Alex", TestInt = 3 , DateOfBirth = null, _Age = 80, GUIY = Guid.NewGuid(), DoNotMapTest = "I'm naked! But nobody can know!" }, - new Person { Name = "Zapoo", DateOfBirth = null, TestInt = 9, _Age = 45, GUIY = Guid.NewGuid(), DoNotMapTest = "I buried treasure behind my house", Access=Person.Permissions.CanRead}, - - new Person { Name = "Sarah", TestInt = -1, _Age = 30, GUIY = Guid.NewGuid(), DoNotMapTest = "I hate my job", Access=Person.Permissions.CanRead}, - new Person { Name = "Michael", TestInt = 15, _Age = 50, GUIY = Guid.NewGuid(), DoNotMapTest = "I'm hiding a big secret", Access=Person.Permissions.CanRead | Person.Permissions.CanWrite}, - new Person { Name = "Tommy", TestInt = 7, _Age = 12, GUIY = Guid.NewGuid(), DoNotMapTest = "I am just a kid" }, - new Person { Name = "Grace", TestInt = 3, _Age = 90, GUIY = Guid.NewGuid(), DoNotMapTest = "I have seen the world" }, - new Person { Name = "Xylophone", TestInt = 9, _Age = 27, GUIY = Guid.NewGuid(), DoNotMapTest = "I have the weirdest name" }, - new Person { Name = "Yasmine", TestInt = 9, _Age = 40, GUIY = Guid.NewGuid(), DoNotMapTest = null }, - // Additional test case persons to stress-test LINQ validation - new Person { Name = "Alicia", TestInt = 42, _Age = 16, GUIY = Guid.NewGuid(), DoNotMapTest = "I just got my driver's license" }, - new Person { Name = "Ben", TestInt = 0, _Age = 25, GUIY = Guid.NewGuid(), DoNotMapTest = "I have no TestInt value" }, - new Person { Name = "Clara", TestInt = 100, _Age = 65, GUIY = Guid.NewGuid(), DoNotMapTest = "I retired last week", Access = Person.Permissions.CanRead | Person.Permissions.CanWrite }, - new Person { Name = "Danny", TestInt = 9, _Age = 40, GUIY = Guid.NewGuid(), DoNotMapTest = null }, // Null handling - new Person { Name = "Elliot", TestInt = -20, _Age = 55, GUIY = Guid.NewGuid(), DoNotMapTest = "My test int is negative" }, - new Person { Name = "Fiona", TestInt = 11, _Age = 33, GUIY = Guid.NewGuid(), DoNotMapTest = "I like puzzles" }, - new Person { Name = "George", TestInt = 8, _Age = 72, GUIY = Guid.NewGuid(), DoNotMapTest = "I fought in a war", Access = Person.Permissions.CanRead | Person.Permissions.CanWrite | Person.Permissions.CanCreate }, - new Person { Name = "Henry", TestInt = 99, _Age = 29, GUIY = Guid.NewGuid(), DoNotMapTest = "I almost made it to 100 TestInt" }, - new Person { Name = "Isla", TestInt = 2, _Age = 18, GUIY = Guid.NewGuid(), DoNotMapTest = "I just turned into an adult" }, - new Person { Name = "Jackie", TestInt = 75, _Age = 60, GUIY = Guid.NewGuid(), DoNotMapTest = "I love cooking" }, - new Person { Name = "Kevin", TestInt = 5, _Age = 48, GUIY = Guid.NewGuid(), DoNotMapTest = "I own a small business" }, - new Person { Name = "Liam", TestInt = 9, _Age = 55, GUIY = Guid.NewGuid(), DoNotMapTest = "I just became a grandfather" }, - new Person { Name = "Mona", TestInt = 88, _Age = 35, GUIY = Guid.NewGuid(), DoNotMapTest = "I am a detective", Access = Person.Permissions.CanRead | Person.Permissions.CanWrite }, - new Person { Name = "Nathan", TestInt = 7, _Age = 27, GUIY = Guid.NewGuid(), DoNotMapTest = "I play guitar" }, - new Person { Name = "Olivia", TestInt = 13, _Age = 45, GUIY = Guid.NewGuid(), DoNotMapTest = "I run marathons" }, - new Person { Name = "Patrick", TestInt = 3, _Age = 52, GUIY = Guid.NewGuid(), DoNotMapTest = "I work in IT" }, - new Person { Name = "Quinn", TestInt = 22, _Age = 42, GUIY = Guid.NewGuid(), DoNotMapTest = "I design board games" }, - new Person { Name = "Rachel", TestInt = 77, _Age = 36, GUIY = Guid.NewGuid(), DoNotMapTest = "I am a pilot" }, - new Person { Name = "Steve", TestInt = 9, _Age = 38, GUIY = Guid.NewGuid(), DoNotMapTest = "I am an engineer" }, - new Person { Name = "Tina", TestInt = 3, _Age = 68, GUIY = Guid.NewGuid(), DoNotMapTest = "I just got my pension" }, - new Person { Name = "Uma", TestInt = 14, _Age = 39, GUIY = Guid.NewGuid(), DoNotMapTest = "I teach yoga" }, - new Person { Name = "Victor", TestInt = 6, _Age = 31, GUIY = Guid.NewGuid(), DoNotMapTest = "I am an artist" }, - new Person { Name = "Wendy", TestInt = 50, _Age = 50, GUIY = Guid.NewGuid(), DoNotMapTest = "My age matches my test int" }, - new Person { Name = "Xander", TestInt = 19, _Age = 21, GUIY = Guid.NewGuid(), DoNotMapTest = "I am a college student" }, - new Person { Name = "Yara", TestInt = 90, _Age = 32, GUIY = Guid.NewGuid(), DoNotMapTest = "I work in finance" }, - new Person { Name = "Zane", TestInt = 101, _Age = 47, DateOfBirth = new DateTime(2020, 2, 10), GUIY = Guid.NewGuid(), DoNotMapTest = "I love motorcycles" }, - - }; + var persons = TestBase.Data.PersonData.persons; var guiys = new HashSet(); var count = 0; @@ -299,23 +236,7 @@ IndexOrderingProperties = new List> { Console.WriteLine($"Duplicate GUID found! {p.Name} - {p.GUIY}"); } } - - //var storageInfo = await _MagicDb.GetStorageEstimateAsync(); - //storageQuota = storageInfo.QuotaInMegabytes; - //storageUsage = storageInfo.UsageInMegabytes; - - - - - // WhereExample = await (manager.Where(x => x.Name.StartsWith("c", StringComparison.OrdinalIgnoreCase) - // || x.Name.StartsWith("l", StringComparison.OrdinalIgnoreCase) - // || x.Name.StartsWith("j", StringComparison.OrdinalIgnoreCase) && x._Age > 35 - // || x.Name.Contains("bo", StringComparison.OrdinalIgnoreCase) - // ).OrderBy(x => x._Id).Skip(1).AsAsyncEnumerable()).ToListAsync(); - - //IMagicQuery personQuery = manager.Query(); - - //await personQuery.AddRangeAsync(persons); + foreach (var p in persons.OrderBy(x => x._Id)) { await personQuery.AddAsync(p); @@ -324,79 +245,6 @@ IndexOrderingProperties = new List> { allPeople = await personQuery.ToListAsync(); - StateHasChanged(); - - @* //await manager.ClearTableAsync(); - var db = await _MagicDb.Database(IndexDbContext.Client); - //await db.DeleteAsync(); - await db.CloseAsync(); - bool doesExist = await db.DoesExistAsync(); - bool isOpen = await db.IsOpenAsync(); - await db.OpenAsync(); - bool isOpenNow = await db.IsOpenAsync(); *@ - - var d = new DateTime(); - var asdf = d.DayOfWeek; - var asdf2 = d.DayOfYear; - - - // I know the validation of "allPeople" targets differently but I know this is the right result. - // This is a weird .NET memory grab weirdess. - - - - // var blueprint = new QueryTestBlueprint - // { - // WherePredicates = [x => x.TestInt == 9], - // OrderBys = [x => x._Age], - // OrderByDescendings = [x => x._Age], - // TakeValues = [2], - // TakeLastValues = [1], - // SkipValues = [1], - // }; - - // var tests = MagicQueryPathWalker.GenerateAllPaths(personQuery, allPeople, blueprint); - - // foreach (var test in tests) - // { - // try - // { - // var executedTestDb = await test.ExecuteDb(); - // var mem = test.ExecuteInMemory(); - // RunTest(test.Name, executedTestDb, mem); - // } - // catch (Exception ex) - // { - // //RunTest(test.Name, [], [], $"Exception: {ex.Message}"); - // } - // } - - - // RunTest("Test Test", - // await personQuery.Cursor(x => x.TestInt == 9).OrderBy(x => x._Age).Skip(1).ToListAsync(), - // allPeople.Where(x => x.TestInt == 9).OrderBy(x => x._Age).ThenBy(x => x._Id).Skip(1)); - - // var asdfdffddf = await personQuery.Cursor(x => x.TestInt == 9).OrderBy(x => x._Age).Skip(1).ToListAsync(); - // RunTest("Test Test", - // await personQuery.Cursor(x => x.TestInt == 9).OrderBy(x => x._Age).Skip(1).ToListAsync(), - // allPeople.Where(x => x.TestInt == 9).OrderBy(x => x._Age).ThenBy(x => x._Id).Skip(1)); - - var result1 = await personQuery.Take(2).ToListAsync(); - - - var result2 = allPeople.OrderBy(x => x._Id).Take(2).ToList(); - - - - - // ends with not yet supported - // // 🔀 Complex AND/OR Mix (Nested Multiple Layers) - // RunTest("Deeply Nested AND within OR", - // await personQuery.Where(x => (x._Age > 30 && (x.TestInt == 9 || x.Name.StartsWith("J"))) || (x.TestInt == 3 && x.Name.EndsWith("b", StringComparison.OrdinalIgnoreCase))) - // .ToListAsync(), - // allPeople.Where(x => (x._Age > 30 && (x.TestInt == 9 || x.Name.StartsWith("J"))) || (x.TestInt == 3 && x.Name.EndsWith("b", StringComparison.OrdinalIgnoreCase)))); - - StateHasChanged(); } catch (Exception ex) diff --git a/TestWasm/Pages/Weather.razor b/TestWasm/Pages/Weather.razor deleted file mode 100644 index 8a083fc..0000000 --- a/TestWasm/Pages/Weather.razor +++ /dev/null @@ -1,57 +0,0 @@ -@page "/weather" -@inject HttpClient Http - -Weather - -

Weather

- -

This component demonstrates fetching data from the server.

- -@if (forecasts == null) -{ -

Loading...

-} -else -{ - - - - - - - - - - - @foreach (var forecast in forecasts) - { - - - - - - - } - -
DateTemp. (C)Temp. (F)Summary
@forecast.Date.ToShortDateString()@forecast.TemperatureC@forecast.TemperatureF@forecast.Summary
-} - -@code { - private WeatherForecast[]? forecasts; - - protected override async Task OnInitializedAsync() - { - forecasts = await Http.GetFromJsonAsync("sample-data/weather.json"); - } - - public class WeatherForecast - { - public DateOnly Date { get; set; } - - public int TemperatureC { get; set; } - - public string? Summary { get; set; } - - public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); - } -} diff --git a/TestWasm/Repository/IndexDbContext.cs b/TestWasm/Repository/IndexDbContext.cs deleted file mode 100644 index 59a007d..0000000 --- a/TestWasm/Repository/IndexDbContext.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Magic.IndexedDb; -using Magic.IndexedDb.Interfaces; - -namespace TestWasm.Repository; - -public class IndexDbContext : IMagicRepository -{ - public static readonly IndexedDbSet Client = new ("Client"); - public static readonly IndexedDbSet Employee = new ("Employee"); - public static readonly IndexedDbSet Animal = new ("Animal"); -} \ No newline at end of file diff --git a/TestWasm/Share/PanelCustomTests.razor b/TestWasm/Share/PanelCustomTests.razor index 852d74e..28b8ec4 100644 --- a/TestWasm/Share/PanelCustomTests.razor +++ b/TestWasm/Share/PanelCustomTests.razor @@ -1,8 +1,6 @@ @using Magic.IndexedDb @using TestBase.Helpers @using TestBase.Models -@using TestWasm.Models -@using Person = TestWasm.Models.Person @inject IMagicIndexedDb _MagicDb @@ -16,33 +14,6 @@ - - Custom Person table tests: - - @foreach (var (testName, response, countResults) in TestResults) - { -
- @if (response.Success) - { - ✅ @testName @($" - {countResults}") - } - else - { - ❌ @testName @($"- {countResults}") - - @if (!string.IsNullOrWhiteSpace(response.Message)) - { - var messages = response.Message.Split('\n', StringSplitOptions.RemoveEmptyEntries); - foreach (var message in messages) - { -
🔍 @message
- } - } - } -
- } -
- @foreach (var (testName, response, countResults) in TestResults) {
From dce3835f44a74a152f4f268f63e101f51a0054bf Mon Sep 17 00:00:00 2001 From: Ard van der Marel <109339598+Ard2025@users.noreply.github.com> Date: Sun, 28 Dec 2025 11:39:51 +0100 Subject: [PATCH 12/15] upgrade to dotnet 10 --- E2eTest/E2eTest.csproj | 12 ++++----- E2eTestWebApp/E2eTestWebApp.csproj | 3 ++- Magic.IndexedDb/Helpers/SchemaHelper.cs | 27 ++++++++++++++----- .../Extensions/UniversalExpressionBuilder.cs | 21 ++++++++++----- Magic.IndexedDb/Magic.IndexedDb.csproj | 7 ++--- TestBase/TestBase.csproj | 3 ++- .../TestServer.Client.csproj | 7 ++--- TestServer/TestServer/TestServer.csproj | 7 ++--- TestWasm/TestWasm.csproj | 9 ++++--- 9 files changed, 62 insertions(+), 34 deletions(-) diff --git a/E2eTest/E2eTest.csproj b/E2eTest/E2eTest.csproj index 4f73598..d05e6a8 100644 --- a/E2eTest/E2eTest.csproj +++ b/E2eTest/E2eTest.csproj @@ -1,17 +1,17 @@  - net9.0 - latest + net10.0 + 13 enable enable - - - - + + + + diff --git a/E2eTestWebApp/E2eTestWebApp.csproj b/E2eTestWebApp/E2eTestWebApp.csproj index 9846fed..ab1b37e 100644 --- a/E2eTestWebApp/E2eTestWebApp.csproj +++ b/E2eTestWebApp/E2eTestWebApp.csproj @@ -1,9 +1,10 @@ - net9.0 + net10.0 enable enable + 13 diff --git a/Magic.IndexedDb/Helpers/SchemaHelper.cs b/Magic.IndexedDb/Helpers/SchemaHelper.cs index 9d504d5..7d8de6a 100644 --- a/Magic.IndexedDb/Helpers/SchemaHelper.cs +++ b/Magic.IndexedDb/Helpers/SchemaHelper.cs @@ -20,6 +20,25 @@ internal static void EnsureSchemaIsCached(Type type) }); } + private static List getAllLoadableTypes() + { + return AppDomain.CurrentDomain.GetAssemblies() + // ADD THIS LINE: Skip the WebAssembly library that crashes on Server + .SelectMany(a => + { + try + { + return a.GetTypes(); + } + catch (ReflectionTypeLoadException ex) + { + return ex.Types.Where(t => t != null)!; + } + }) + .ToList(); + } + + public static bool ImplementsIMagicTable(Type type) { return type.GetInterfaces().Any(i => i.IsGenericType @@ -28,18 +47,14 @@ public static bool ImplementsIMagicTable(Type type) public static List? GetAllMagicTables() { - var assemblies = AppDomain.CurrentDomain.GetAssemblies(); - return assemblies - .SelectMany(a => a.GetTypes()) + return getAllLoadableTypes() .Where(t => t.IsClass && !t.IsAbstract && SchemaHelper.ImplementsIMagicTable(t)) .ToList(); } public static List? GetAllMagicRepositories() { - var assemblies = AppDomain.CurrentDomain.GetAssemblies(); - return assemblies - .SelectMany(a => a.GetTypes()) + return getAllLoadableTypes() .Where(t => t.IsClass && !t.IsAbstract && ImplementsIMagicRepository(t)) .ToList(); } diff --git a/Magic.IndexedDb/LinqTranslation/Extensions/UniversalExpressionBuilder.cs b/Magic.IndexedDb/LinqTranslation/Extensions/UniversalExpressionBuilder.cs index 3b1dc53..1c65381 100644 --- a/Magic.IndexedDb/LinqTranslation/Extensions/UniversalExpressionBuilder.cs +++ b/Magic.IndexedDb/LinqTranslation/Extensions/UniversalExpressionBuilder.cs @@ -744,16 +744,23 @@ private static ConstantExpression ToConst(Expression expr) { expr = StripConvert(expr); // <-- handle Convert wrappers - return expr switch + try { - ConstantExpression c => c, + return expr switch + { + ConstantExpression c => c, - // e.g., new DateTime(...) or anything not marked constant but compile-safe - NewExpression or MemberExpression or MethodCallExpression => - Expression.Constant(Expression.Lambda(expr).Compile().DynamicInvoke()), + // e.g., new DateTime(...) or anything not marked constant but compile-safe + NewExpression or MemberExpression or MethodCallExpression => + Expression.Constant(Expression.Lambda(expr).Compile().DynamicInvoke()), - _ => throw new InvalidOperationException($"Unsupported or non-constant expression: {expr}") - }; + _ => throw new InvalidOperationException($"Unsupported or non-constant expression: {expr}") + }; + } + catch (Exception ex) + { + throw ex; + } } private static Expression StripConvert(Expression expr) diff --git a/Magic.IndexedDb/Magic.IndexedDb.csproj b/Magic.IndexedDb/Magic.IndexedDb.csproj index 946cdc0..a9cd826 100644 --- a/Magic.IndexedDb/Magic.IndexedDb.csproj +++ b/Magic.IndexedDb/Magic.IndexedDb.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 enable enable Magic.IndexedDb @@ -18,6 +18,7 @@ LICENSE.txt 1.01 2.0.2 + 13 @@ -42,7 +43,7 @@ - - + + diff --git a/TestBase/TestBase.csproj b/TestBase/TestBase.csproj index 4924a89..659a82f 100644 --- a/TestBase/TestBase.csproj +++ b/TestBase/TestBase.csproj @@ -1,9 +1,10 @@  - net8.0 + net10.0 enable enable + 13 diff --git a/TestServer/TestServer.Client/TestServer.Client.csproj b/TestServer/TestServer.Client/TestServer.Client.csproj index 1786b3a..da0c01c 100644 --- a/TestServer/TestServer.Client/TestServer.Client.csproj +++ b/TestServer/TestServer.Client/TestServer.Client.csproj @@ -1,16 +1,17 @@ - net9.0 + net10.0 enable enable true Default + 13 - - + + diff --git a/TestServer/TestServer/TestServer.csproj b/TestServer/TestServer/TestServer.csproj index 47915bb..8e7d8f3 100644 --- a/TestServer/TestServer/TestServer.csproj +++ b/TestServer/TestServer/TestServer.csproj @@ -1,17 +1,18 @@ - net9.0 + net10.0 enable enable + 13 - - + + diff --git a/TestWasm/TestWasm.csproj b/TestWasm/TestWasm.csproj index 32cb0e1..bc66f4c 100644 --- a/TestWasm/TestWasm.csproj +++ b/TestWasm/TestWasm.csproj @@ -1,15 +1,16 @@ - net8.0 + net10.0 enable enable + 13 - - - + + + From 4c02f2eb0b93642b67fe32d63ed14062cc8f98f1 Mon Sep 17 00:00:00 2001 From: Ard van der Marel <109339598+Ard2025@users.noreply.github.com> Date: Sun, 28 Dec 2025 11:44:35 +0100 Subject: [PATCH 13/15] update playright unit tests --- E2eTest/E2eTest.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/E2eTest/E2eTest.csproj b/E2eTest/E2eTest.csproj index d05e6a8..765709b 100644 --- a/E2eTest/E2eTest.csproj +++ b/E2eTest/E2eTest.csproj @@ -10,8 +10,8 @@ - - + + From f01a5f95cf87932aa5ca61a243cc31d3bc5b1b42 Mon Sep 17 00:00:00 2001 From: Ard van der Marel <109339598+Ard2025@users.noreply.github.com> Date: Sun, 28 Dec 2025 11:48:03 +0100 Subject: [PATCH 14/15] . --- Magic.IndexedDb/Helpers/SchemaHelper.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Magic.IndexedDb/Helpers/SchemaHelper.cs b/Magic.IndexedDb/Helpers/SchemaHelper.cs index 7d8de6a..b31f524 100644 --- a/Magic.IndexedDb/Helpers/SchemaHelper.cs +++ b/Magic.IndexedDb/Helpers/SchemaHelper.cs @@ -23,7 +23,6 @@ internal static void EnsureSchemaIsCached(Type type) private static List getAllLoadableTypes() { return AppDomain.CurrentDomain.GetAssemblies() - // ADD THIS LINE: Skip the WebAssembly library that crashes on Server .SelectMany(a => { try From 78de43b76787bf51f43427290e0d98196c377a34 Mon Sep 17 00:00:00 2001 From: Paul Elliott Date: Wed, 1 Apr 2026 09:51:11 +1300 Subject: [PATCH 15/15] Upgrade to .Net 9 and provide a longer js timeout to allow for large data --- E2eTest/E2eTest.csproj | 4 ++-- E2eTestWebApp/E2eTestWebApp.csproj | 2 +- Magic.IndexedDb/Extensions/MagicJsInvoke.cs | 2 +- Magic.IndexedDb/Magic.IndexedDb.csproj | 6 +++--- TestBase/TestBase.csproj | 2 +- TestServer/TestServer.Client/TestServer.Client.csproj | 8 ++++---- TestServer/TestServer/TestServer.csproj | 8 ++++---- TestWasm/TestWasm.csproj | 10 +++++----- 8 files changed, 21 insertions(+), 21 deletions(-) diff --git a/E2eTest/E2eTest.csproj b/E2eTest/E2eTest.csproj index 765709b..e9e49db 100644 --- a/E2eTest/E2eTest.csproj +++ b/E2eTest/E2eTest.csproj @@ -1,14 +1,14 @@  - net10.0 + net9.0 13 enable enable - + diff --git a/E2eTestWebApp/E2eTestWebApp.csproj b/E2eTestWebApp/E2eTestWebApp.csproj index ab1b37e..a87d15b 100644 --- a/E2eTestWebApp/E2eTestWebApp.csproj +++ b/E2eTestWebApp/E2eTestWebApp.csproj @@ -1,7 +1,7 @@ - net10.0 + net9.0 enable enable 13 diff --git a/Magic.IndexedDb/Extensions/MagicJsInvoke.cs b/Magic.IndexedDb/Extensions/MagicJsInvoke.cs index abe9e4f..a96105c 100644 --- a/Magic.IndexedDb/Extensions/MagicJsInvoke.cs +++ b/Magic.IndexedDb/Extensions/MagicJsInvoke.cs @@ -125,7 +125,7 @@ internal async Task CallInvokeVoidDefaultJsAsync(string modulePath, string funct using var streamRef = new DotNetStreamReference(stream); // Send to JS - var responseStreamRef = await _jsModule.InvokeAsync("streamedJsHandler", + var responseStreamRef = await _jsModule.InvokeAsync("streamedJsHandler", TimeSpan.FromSeconds(120), streamRef, instanceId, DotNetObjectReference.Create(this), _jsMessageSizeBytes); // 🚀 Convert the stream reference back to JSON in C# diff --git a/Magic.IndexedDb/Magic.IndexedDb.csproj b/Magic.IndexedDb/Magic.IndexedDb.csproj index a9cd826..fcff6ce 100644 --- a/Magic.IndexedDb/Magic.IndexedDb.csproj +++ b/Magic.IndexedDb/Magic.IndexedDb.csproj @@ -1,7 +1,7 @@  - net10.0 + net9.0 enable enable Magic.IndexedDb @@ -17,7 +17,7 @@ README.md LICENSE.txt 1.01 - 2.0.2 + 2.9.2 13 @@ -43,7 +43,7 @@ - + diff --git a/TestBase/TestBase.csproj b/TestBase/TestBase.csproj index 659a82f..46ef327 100644 --- a/TestBase/TestBase.csproj +++ b/TestBase/TestBase.csproj @@ -1,7 +1,7 @@  - net10.0 + net9.0 enable enable 13 diff --git a/TestServer/TestServer.Client/TestServer.Client.csproj b/TestServer/TestServer.Client/TestServer.Client.csproj index da0c01c..7fe7f14 100644 --- a/TestServer/TestServer.Client/TestServer.Client.csproj +++ b/TestServer/TestServer.Client/TestServer.Client.csproj @@ -1,7 +1,7 @@ - + - net10.0 + net9.0 enable enable true @@ -10,8 +10,8 @@ - - + + diff --git a/TestServer/TestServer/TestServer.csproj b/TestServer/TestServer/TestServer.csproj index 8e7d8f3..a2ee381 100644 --- a/TestServer/TestServer/TestServer.csproj +++ b/TestServer/TestServer/TestServer.csproj @@ -1,7 +1,7 @@ - + - net10.0 + net9.0 enable enable 13 @@ -11,8 +11,8 @@ - - + + diff --git a/TestWasm/TestWasm.csproj b/TestWasm/TestWasm.csproj index bc66f4c..f1eb202 100644 --- a/TestWasm/TestWasm.csproj +++ b/TestWasm/TestWasm.csproj @@ -1,16 +1,16 @@ - + - net10.0 + net9.0 enable enable 13 - - - + + +