mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-05-24 00:52:23 -04:00
Polish 6 (#3371)
This commit is contained in:
parent
6a75291a67
commit
c849eff33e
@ -119,6 +119,11 @@ public class PersonController : BaseApiController
|
||||
return Ok(_mapper.Map<PersonDto>(person));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to download the cover from CoversDB (Note: Not yet release in Kavita)
|
||||
/// </summary>
|
||||
/// <param name="personId"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("fetch-cover")]
|
||||
public async Task<ActionResult<string>> DownloadCoverImage([FromQuery] int personId)
|
||||
{
|
||||
@ -129,13 +134,13 @@ public class PersonController : BaseApiController
|
||||
var personImage = await _coverDbService.DownloadPersonImageAsync(person, settings.EncodeMediaAs);
|
||||
|
||||
if (string.IsNullOrEmpty(personImage)) return BadRequest(await _localizationService.Translate(User.GetUserId(), "person-image-doesnt-exist"));
|
||||
|
||||
person.CoverImage = personImage;
|
||||
_imageService.UpdateColorScape(person);
|
||||
_unitOfWork.PersonRepository.Update(person);
|
||||
await _unitOfWork.CommitAsync();
|
||||
await _eventHub.SendMessageAsync(MessageFactory.CoverUpdate, MessageFactory.CoverUpdateEvent(person.Id, "person"), false);
|
||||
|
||||
|
||||
return Ok(personImage);
|
||||
}
|
||||
|
||||
@ -150,6 +155,12 @@ public class PersonController : BaseApiController
|
||||
return Ok(await _unitOfWork.PersonRepository.GetSeriesKnownFor(personId));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all individual chapters by role. Limited to 20 results.
|
||||
/// </summary>
|
||||
/// <param name="personId"></param>
|
||||
/// <param name="role"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("chapters-by-role")]
|
||||
public async Task<ActionResult<IEnumerable<StandaloneChapterDto>>> GetChaptersByRole(int personId, PersonRole role)
|
||||
{
|
||||
|
@ -56,7 +56,7 @@ public class VolumeDto : IHasReadTimeEstimate, IHasCoverImage
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does this volume hold only specials?
|
||||
/// Does this volume hold only specials
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool IsSpecial()
|
||||
|
@ -1192,7 +1192,7 @@ public class SeriesRepository : ISeriesRepository
|
||||
|
||||
private static IQueryable<Series> BuildFilterQuery(int userId, FilterV2Dto filterDto, IQueryable<Series> query)
|
||||
{
|
||||
if (filterDto.Statements == null || !filterDto.Statements.Any()) return query;
|
||||
if (filterDto.Statements == null || filterDto.Statements.Count == 0) return query;
|
||||
|
||||
|
||||
var queries = filterDto.Statements
|
||||
|
@ -167,6 +167,7 @@ public static class SeriesFilter
|
||||
throw new ArgumentOutOfRangeException(nameof(comparison), comparison, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static IQueryable<Series> HasAverageReadTime(this IQueryable<Series> queryable, bool condition,
|
||||
FilterComparison comparison, int avgReadTime)
|
||||
{
|
||||
@ -175,17 +176,17 @@ public static class SeriesFilter
|
||||
switch (comparison)
|
||||
{
|
||||
case FilterComparison.NotEqual:
|
||||
return queryable.Where(s => s.AvgHoursToRead != avgReadTime);
|
||||
return queryable.WhereNotEqual(s => s.AvgHoursToRead, avgReadTime);
|
||||
case FilterComparison.Equal:
|
||||
return queryable.Where(s => s.AvgHoursToRead == avgReadTime);
|
||||
return queryable.WhereEqual(s => s.AvgHoursToRead, avgReadTime);
|
||||
case FilterComparison.GreaterThan:
|
||||
return queryable.Where(s => s.AvgHoursToRead > avgReadTime);
|
||||
return queryable.WhereGreaterThan(s => s.AvgHoursToRead, avgReadTime);
|
||||
case FilterComparison.GreaterThanEqual:
|
||||
return queryable.Where(s => s.AvgHoursToRead >= avgReadTime);
|
||||
return queryable.WhereGreaterThanOrEqual(s => s.AvgHoursToRead, avgReadTime);
|
||||
case FilterComparison.LessThan:
|
||||
return queryable.Where(s => s.AvgHoursToRead < avgReadTime);
|
||||
return queryable.WhereLessThan(s => s.AvgHoursToRead, avgReadTime);
|
||||
case FilterComparison.LessThanEqual:
|
||||
return queryable.Where(s => s.AvgHoursToRead <= avgReadTime);
|
||||
return queryable.WhereLessThanOrEqual(s => s.AvgHoursToRead, avgReadTime);
|
||||
case FilterComparison.Contains:
|
||||
case FilterComparison.Matches:
|
||||
case FilterComparison.NotContains:
|
||||
@ -257,29 +258,29 @@ public static class SeriesFilter
|
||||
Series = s,
|
||||
Percentage = s.Progress
|
||||
.Where(p => p != null && p.AppUserId == userId)
|
||||
.Sum(p => p != null ? (p.PagesRead * 1.0f / s.Pages) : 0) * 100
|
||||
.Sum(p => p != null ? (p.PagesRead * 1.0f / s.Pages) : 0f) * 100f
|
||||
})
|
||||
.AsSplitQuery();
|
||||
|
||||
switch (comparison)
|
||||
{
|
||||
case FilterComparison.Equal:
|
||||
subQuery = subQuery.Where(s => Math.Abs(s.Percentage - readProgress) < FloatingPointTolerance);
|
||||
subQuery = subQuery.WhereEqual(s => s.Percentage, readProgress);
|
||||
break;
|
||||
case FilterComparison.GreaterThan:
|
||||
subQuery = subQuery.Where(s => s.Percentage > readProgress);
|
||||
subQuery = subQuery.WhereGreaterThan(s => s.Percentage, readProgress);
|
||||
break;
|
||||
case FilterComparison.GreaterThanEqual:
|
||||
subQuery = subQuery.Where(s => s.Percentage >= readProgress);
|
||||
subQuery = subQuery.WhereGreaterThanOrEqual(s => s.Percentage, readProgress);
|
||||
break;
|
||||
case FilterComparison.LessThan:
|
||||
subQuery = subQuery.Where(s => s.Percentage < readProgress);
|
||||
subQuery = subQuery.WhereLessThan(s => s.Percentage, readProgress);
|
||||
break;
|
||||
case FilterComparison.LessThanEqual:
|
||||
subQuery = subQuery.Where(s => s.Percentage <= readProgress);
|
||||
subQuery = subQuery.WhereLessThanOrEqual(s => s.Percentage, readProgress);
|
||||
break;
|
||||
case FilterComparison.NotEqual:
|
||||
subQuery = subQuery.Where(s => Math.Abs(s.Percentage - readProgress) > FloatingPointTolerance);
|
||||
subQuery = subQuery.WhereNotEqual(s => s.Percentage, readProgress);
|
||||
break;
|
||||
case FilterComparison.IsEmpty:
|
||||
case FilterComparison.Matches:
|
||||
@ -306,7 +307,6 @@ public static class SeriesFilter
|
||||
{
|
||||
if (!condition) return queryable;
|
||||
|
||||
|
||||
var subQuery = queryable
|
||||
.Where(s => s.ExternalSeriesMetadata != null)
|
||||
.Include(s => s.ExternalSeriesMetadata)
|
||||
@ -316,27 +316,27 @@ public static class SeriesFilter
|
||||
AverageRating = s.ExternalSeriesMetadata.AverageExternalRating
|
||||
})
|
||||
.AsSplitQuery()
|
||||
.AsEnumerable();
|
||||
.AsQueryable();
|
||||
|
||||
switch (comparison)
|
||||
{
|
||||
case FilterComparison.Equal:
|
||||
subQuery = subQuery.Where(s => Math.Abs(s.AverageRating - rating) < FloatingPointTolerance);
|
||||
subQuery = subQuery.WhereEqual(s => s.AverageRating, rating);
|
||||
break;
|
||||
case FilterComparison.GreaterThan:
|
||||
subQuery = subQuery.Where(s => s.AverageRating > rating);
|
||||
subQuery = subQuery.WhereGreaterThan(s => s.AverageRating, rating);
|
||||
break;
|
||||
case FilterComparison.GreaterThanEqual:
|
||||
subQuery = subQuery.Where(s => s.AverageRating >= rating);
|
||||
subQuery = subQuery.WhereGreaterThanOrEqual(s => s.AverageRating, rating);
|
||||
break;
|
||||
case FilterComparison.LessThan:
|
||||
subQuery = subQuery.Where(s => s.AverageRating < rating);
|
||||
subQuery = subQuery.WhereLessThan(s => s.AverageRating, rating);
|
||||
break;
|
||||
case FilterComparison.LessThanEqual:
|
||||
subQuery = subQuery.Where(s => s.AverageRating <= rating);
|
||||
subQuery = subQuery.WhereLessThanOrEqual(s => s.AverageRating, rating);
|
||||
break;
|
||||
case FilterComparison.NotEqual:
|
||||
subQuery = subQuery.Where(s => Math.Abs(s.AverageRating - rating) > FloatingPointTolerance);
|
||||
subQuery = subQuery.WhereNotEqual(s => s.AverageRating, rating);
|
||||
break;
|
||||
case FilterComparison.Matches:
|
||||
case FilterComparison.Contains:
|
||||
@ -534,21 +534,21 @@ public static class SeriesFilter
|
||||
{
|
||||
case FilterComparison.Equal:
|
||||
case FilterComparison.Contains:
|
||||
return queryable.Where(s => s.Metadata.People.Any(p => people.Contains(p.PersonId)));
|
||||
return queryable.Where(s => s.Metadata.People.Any(p => people.Contains(p.PersonId) && p.Role == role));
|
||||
case FilterComparison.NotEqual:
|
||||
case FilterComparison.NotContains:
|
||||
return queryable.Where(s => s.Metadata.People.All(t => !people.Contains(t.PersonId)));
|
||||
return queryable.Where(s => s.Metadata.People.All(p => !people.Contains(p.PersonId) || p.Role != role));
|
||||
case FilterComparison.MustContains:
|
||||
// Deconstruct and do a Union of a bunch of where statements since this doesn't translate
|
||||
var queries = new List<IQueryable<Series>>()
|
||||
{
|
||||
queryable
|
||||
};
|
||||
queries.AddRange(people.Select(gId => queryable.Where(s => s.Metadata.People.Any(p => p.PersonId == gId))));
|
||||
queries.AddRange(people.Select(personId =>
|
||||
queryable.Where(s => s.Metadata.People.Any(p => p.PersonId == personId && p.Role == role))));
|
||||
|
||||
return queries.Aggregate((q1, q2) => q1.Intersect(q2));
|
||||
case FilterComparison.IsEmpty:
|
||||
// Check if there are no people with specific roles (e.g., Writer, Penciller, etc.)
|
||||
// Ensure no person with the given role exists
|
||||
return queryable.Where(s => s.Metadata.People.All(p => p.Role != role));
|
||||
case FilterComparison.GreaterThan:
|
||||
case FilterComparison.GreaterThanEqual:
|
||||
|
@ -16,6 +16,8 @@ namespace API.Extensions.QueryExtensions;
|
||||
|
||||
public static class QueryableExtensions
|
||||
{
|
||||
private const float DefaultTolerance = 0.001f;
|
||||
|
||||
public static Task<AgeRestriction> GetUserAgeRestriction(this DbSet<AppUser> queryable, int userId)
|
||||
{
|
||||
if (userId < 1)
|
||||
@ -125,6 +127,140 @@ public static class QueryableExtensions
|
||||
return queryable.Where(lambda);
|
||||
}
|
||||
|
||||
public static IQueryable<T> WhereGreaterThan<T>(this IQueryable<T> source,
|
||||
Expression<Func<T, float>> selector,
|
||||
float value,
|
||||
float tolerance = DefaultTolerance)
|
||||
{
|
||||
var parameter = selector.Parameters[0];
|
||||
var propertyAccess = selector.Body;
|
||||
|
||||
// Absolute difference comparison: (propertyAccess - value) > tolerance
|
||||
var difference = Expression.Subtract(propertyAccess, Expression.Constant(value));
|
||||
var absoluteDifference = Expression.Condition(
|
||||
Expression.LessThan(difference, Expression.Constant(0f)),
|
||||
Expression.Negate(difference),
|
||||
difference);
|
||||
|
||||
var greaterThanExpression = Expression.GreaterThan(propertyAccess, Expression.Constant(value));
|
||||
var toleranceExpression = Expression.GreaterThan(absoluteDifference, Expression.Constant(tolerance));
|
||||
var combinedExpression = Expression.AndAlso(greaterThanExpression, toleranceExpression);
|
||||
|
||||
var lambda = Expression.Lambda<Func<T, bool>>(combinedExpression, parameter);
|
||||
|
||||
return source.Where(lambda);
|
||||
}
|
||||
|
||||
public static IQueryable<T> WhereGreaterThanOrEqual<T>(this IQueryable<T> source,
|
||||
Expression<Func<T, float>> selector,
|
||||
float value,
|
||||
float tolerance = DefaultTolerance)
|
||||
{
|
||||
var parameter = selector.Parameters[0];
|
||||
var propertyAccess = selector.Body;
|
||||
|
||||
var difference = Expression.Subtract(propertyAccess, Expression.Constant(value));
|
||||
var absoluteDifference = Expression.Condition(
|
||||
Expression.LessThan(difference, Expression.Constant(0f)),
|
||||
Expression.Negate(difference),
|
||||
difference);
|
||||
|
||||
var greaterThanOrEqualExpression = Expression.GreaterThanOrEqual(propertyAccess, Expression.Constant(value));
|
||||
var toleranceExpression = Expression.GreaterThanOrEqual(absoluteDifference, Expression.Constant(tolerance));
|
||||
var combinedExpression = Expression.AndAlso(greaterThanOrEqualExpression, toleranceExpression);
|
||||
|
||||
var lambda = Expression.Lambda<Func<T, bool>>(combinedExpression, parameter);
|
||||
|
||||
return source.Where(lambda);
|
||||
}
|
||||
|
||||
public static IQueryable<T> WhereLessThan<T>(this IQueryable<T> source,
|
||||
Expression<Func<T, float>> selector,
|
||||
float value,
|
||||
float tolerance = DefaultTolerance)
|
||||
{
|
||||
var parameter = selector.Parameters[0];
|
||||
var propertyAccess = selector.Body;
|
||||
|
||||
var difference = Expression.Subtract(propertyAccess, Expression.Constant(value));
|
||||
var absoluteDifference = Expression.Condition(
|
||||
Expression.LessThan(difference, Expression.Constant(0f)),
|
||||
Expression.Negate(difference),
|
||||
difference);
|
||||
|
||||
var lessThanExpression = Expression.LessThan(propertyAccess, Expression.Constant(value));
|
||||
var toleranceExpression = Expression.LessThan(absoluteDifference, Expression.Constant(tolerance));
|
||||
var combinedExpression = Expression.AndAlso(lessThanExpression, toleranceExpression);
|
||||
|
||||
var lambda = Expression.Lambda<Func<T, bool>>(combinedExpression, parameter);
|
||||
|
||||
return source.Where(lambda);
|
||||
}
|
||||
|
||||
public static IQueryable<T> WhereLessThanOrEqual<T>(this IQueryable<T> source,
|
||||
Expression<Func<T, float>> selector,
|
||||
float value,
|
||||
float tolerance = DefaultTolerance)
|
||||
{
|
||||
var parameter = selector.Parameters[0];
|
||||
var propertyAccess = selector.Body;
|
||||
|
||||
var difference = Expression.Subtract(propertyAccess, Expression.Constant(value));
|
||||
var absoluteDifference = Expression.Condition(
|
||||
Expression.LessThan(difference, Expression.Constant(0f)),
|
||||
Expression.Negate(difference),
|
||||
difference);
|
||||
|
||||
var lessThanOrEqualExpression = Expression.LessThanOrEqual(propertyAccess, Expression.Constant(value));
|
||||
var toleranceExpression = Expression.LessThanOrEqual(absoluteDifference, Expression.Constant(tolerance));
|
||||
var combinedExpression = Expression.AndAlso(lessThanOrEqualExpression, toleranceExpression);
|
||||
|
||||
var lambda = Expression.Lambda<Func<T, bool>>(combinedExpression, parameter);
|
||||
|
||||
return source.Where(lambda);
|
||||
}
|
||||
|
||||
public static IQueryable<T> WhereEqual<T>(this IQueryable<T> source,
|
||||
Expression<Func<T, float>> selector,
|
||||
float value,
|
||||
float tolerance = DefaultTolerance)
|
||||
{
|
||||
var parameter = selector.Parameters[0];
|
||||
var propertyAccess = selector.Body;
|
||||
|
||||
// Absolute difference comparison: Math.Abs(propertyAccess - value) < tolerance
|
||||
var difference = Expression.Subtract(propertyAccess, Expression.Constant(value));
|
||||
var absoluteDifference = Expression.Condition(
|
||||
Expression.LessThan(difference, Expression.Constant(0f)),
|
||||
Expression.Negate(difference),
|
||||
difference);
|
||||
|
||||
var toleranceExpression = Expression.LessThan(absoluteDifference, Expression.Constant(tolerance));
|
||||
var lambda = Expression.Lambda<Func<T, bool>>(toleranceExpression, parameter);
|
||||
|
||||
return source.Where(lambda);
|
||||
}
|
||||
|
||||
public static IQueryable<T> WhereNotEqual<T>(this IQueryable<T> source,
|
||||
Expression<Func<T, float>> selector,
|
||||
float value,
|
||||
float tolerance = DefaultTolerance)
|
||||
{
|
||||
var parameter = selector.Parameters[0];
|
||||
var propertyAccess = selector.Body;
|
||||
|
||||
var difference = Expression.Subtract(propertyAccess, Expression.Constant(value));
|
||||
var absoluteDifference = Expression.Condition(
|
||||
Expression.LessThan(difference, Expression.Constant(0f)),
|
||||
Expression.Negate(difference),
|
||||
difference);
|
||||
|
||||
var toleranceExpression = Expression.GreaterThan(absoluteDifference, Expression.Constant(tolerance));
|
||||
var lambda = Expression.Lambda<Func<T, bool>>(toleranceExpression, parameter);
|
||||
|
||||
return source.Where(lambda);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a WhereLike that ORs multiple fields
|
||||
/// </summary>
|
||||
|
@ -213,9 +213,8 @@ public class ProcessSeries : IProcessSeries
|
||||
return;
|
||||
}
|
||||
|
||||
BackgroundJob.Enqueue(() =>
|
||||
_metadataService.GenerateCoversForSeries(series.LibraryId, series.Id, false, false));
|
||||
BackgroundJob.Enqueue(() => _wordCountAnalyzerService.ScanSeries(series.LibraryId, series.Id, forceUpdate));
|
||||
await _metadataService.GenerateCoversForSeries(series.LibraryId, series.Id, false, false);
|
||||
await _wordCountAnalyzerService.ScanSeries(series.LibraryId, series.Id, forceUpdate);
|
||||
}
|
||||
|
||||
private async Task ReportDuplicateSeriesLookup(Library library, ParserInfo firstInfo, Exception ex)
|
||||
|
15
UI/Web/package-lock.json
generated
15
UI/Web/package-lock.json
generated
@ -464,6 +464,7 @@
|
||||
"version": "18.2.9",
|
||||
"resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-18.2.9.tgz",
|
||||
"integrity": "sha512-4iMoRvyMmq/fdI/4Gob9HKjL/jvTlCjbS4kouAYHuGO9w9dmUhi1pY1z+mALtCEl9/Q8CzU2W8e5cU2xtV4nVg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/core": "7.25.2",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14",
|
||||
@ -491,6 +492,7 @@
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz",
|
||||
"integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"readdirp": "^4.0.1"
|
||||
},
|
||||
@ -505,6 +507,7 @@
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz",
|
||||
"integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 14.16.0"
|
||||
},
|
||||
@ -4007,7 +4010,8 @@
|
||||
"node_modules/convert-source-map": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
|
||||
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="
|
||||
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/cosmiconfig": {
|
||||
"version": "8.3.6",
|
||||
@ -4514,6 +4518,7 @@
|
||||
"version": "0.1.13",
|
||||
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
|
||||
"integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"iconv-lite": "^0.6.2"
|
||||
@ -4523,6 +4528,7 @@
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||
@ -7464,7 +7470,8 @@
|
||||
"node_modules/reflect-metadata": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz",
|
||||
"integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q=="
|
||||
"integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/replace-in-file": {
|
||||
"version": "7.1.0",
|
||||
@ -7735,7 +7742,7 @@
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||
"devOptional": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/sass": {
|
||||
"version": "1.77.6",
|
||||
@ -7769,6 +7776,7 @@
|
||||
"version": "7.6.3",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
|
||||
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
@ -8323,6 +8331,7 @@
|
||||
"version": "5.5.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz",
|
||||
"integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
|
Loading…
x
Reference in New Issue
Block a user