| | | 1 | | // SPDX-FileCopyrightText: 2026 Alper Çelik <[email protected]> |
| | | 2 | | // |
| | | 3 | | // SPDX-License-Identifier: AGPL-3.0-or-later |
| | | 4 | | using System.Linq.Expressions; |
| | | 5 | | using System.Text.Json; |
| | | 6 | | using GreenDonut.Data; |
| | | 7 | | using LinqKit; |
| | | 8 | | using Microsoft.EntityFrameworkCore; |
| | | 9 | | |
| | | 10 | | namespace Api.Utils; |
| | | 11 | | |
| | | 12 | | public static class GeneralUtils |
| | | 13 | | { |
| | | 14 | | // Mostly Ai Generated - Start |
| | | 15 | | public static IQueryable<T> WithQueryContext<T>( |
| | | 16 | | this IQueryable<T> query, |
| | | 17 | | QueryContext<T> qc |
| | | 18 | | ) |
| | | 19 | | where T : IEntityMetadata => |
| | 1 | 20 | | query.With( |
| | 1 | 21 | | qc with |
| | 1 | 22 | | { |
| | 1 | 23 | | Selector = null, |
| | 1 | 24 | | }, |
| | 1 | 25 | | sort => sort.Operations.Length == 0 ? sort.AddAscending(t => t.Id) : sort |
| | 1 | 26 | | ); |
| | | 27 | | |
| | | 28 | | // Mostly Ai Generated - End |
| | | 29 | | public static async Task<Page<T>> ToPageWithDataLoaderAsync<T>( |
| | | 30 | | this IQueryable<T> table, |
| | | 31 | | PagingArguments pg, |
| | | 32 | | IDataLoader<Guid, T> dataLoader, |
| | | 33 | | CancellationToken ct |
| | | 34 | | ) |
| | | 35 | | where T : IEntityMetadata |
| | 1 | 36 | | { |
| | 1 | 37 | | var page = await table.ToPageAsync(pg, includeTotalCount: true, ct); |
| | | 38 | | |
| | 1 | 39 | | foreach (var item in page) |
| | 1 | 40 | | { |
| | 1 | 41 | | dataLoader.SetCacheEntry(item.Id, item); |
| | 1 | 42 | | } |
| | 1 | 43 | | return page; |
| | 1 | 44 | | } |
| | | 45 | | |
| | | 46 | | public static async Task<IDictionary<Guid, Guid[]>> GetManyToManyIds<T>( |
| | | 47 | | this IQueryable<T> table, |
| | | 48 | | IReadOnlyList<Guid> tableIds, |
| | | 49 | | Guid userId, |
| | | 50 | | Expression<Func<T, IEnumerable<Guid>>> manyIdSelector, |
| | | 51 | | CancellationToken ct |
| | | 52 | | ) |
| | | 53 | | where T : IDbEntityMetadata |
| | 1 | 54 | | { |
| | 1 | 55 | | return await table |
| | 1 | 56 | | .Where(t => t.OwnerId == userId) |
| | 1 | 57 | | .Where(t => tableIds.Contains(t.Id)) |
| | 1 | 58 | | .Select(t => new { t.Id, ManyIds = manyIdSelector.Invoke(t) }) |
| | 1 | 59 | | .ToDictionaryAsync(ids => ids.Id, ids => ids.ManyIds.ToArray(), ct); |
| | 1 | 60 | | } |
| | | 61 | | |
| | | 62 | | public static string NormalizeEmail(this string email) => |
| | 1 | 63 | | email.Trim().Normalize().ToLowerInvariant(); |
| | | 64 | | |
| | | 65 | | public static NodaTime.Instant Now() => |
| | 1 | 66 | | NodaTime.SystemClock.Instance.GetCurrentInstant(); |
| | | 67 | | |
| | | 68 | | public static Guid? TryParseGuid(this ReadOnlySpan<char> s) => |
| | 1 | 69 | | Guid.TryParse(s, out Guid g) ? g : null; |
| | | 70 | | |
| | | 71 | | public static T? TryDeserialize<T>( |
| | | 72 | | this JsonDocument doc, |
| | | 73 | | JsonSerializerOptions? opt = null |
| | | 74 | | ) |
| | | 75 | | where T : class |
| | 1 | 76 | | { |
| | | 77 | | try |
| | 1 | 78 | | { |
| | 1 | 79 | | return doc.Deserialize<T>(opt); |
| | | 80 | | } |
| | 0 | 81 | | catch (JsonException) |
| | 0 | 82 | | { |
| | 0 | 83 | | return null; |
| | | 84 | | } |
| | 1 | 85 | | } |
| | | 86 | | } |