dangl - LightQuery 1.6.2-beta0001
ASP.NET Core ActionFilter for sorting and pagination
PM> Install-Package LightQuery -Version 1.6.2-beta0001 -Source https://www.myget.org/F/dangl/api/v3/index.json
> nuget.exe install LightQuery -Version 1.6.2-beta0001 -Source https://www.myget.org/F/dangl/api/v3/index.json
> dotnet add package LightQuery --version 1.6.2-beta0001 --source https://www.myget.org/F/dangl/api/v3/index.json
source https://www.myget.org/F/dangl/api/v3/index.json
nuget LightQuery ~> 1.6.2-beta0001
Copy to clipboard
> choco install LightQuery --version 1.6.2-beta0001 --source https://www.myget.org/F/dangl/api/v2
Import-Module PowerShellGet
Register-PSRepository -Name "dangl" -SourceLocation "https://www.myget.org/F/dangl/api/v2"
Install-Module -Name "LightQuery" -RequiredVersion "1.6.2-beta0001" -Repository "dangl" -AllowPreRelease
Copy to clipboard
LightQuery
This project aims to provide a lightweight ActionFilterAttribute
that takes care of sorting and paginating Asp.Net Core API results.
This project is for you if you're still waiting for OData support in Asp.Net Core, even though you
only need the most basic of operations. It's also for everyone tired of writing like the 17th
string sort = "Username"
parameter and lines over lines of switch statements in their controller actions.
It supports EntityFrameworkCores async query materialization with the optional LightQuery.EntityFrameworkCore
package.
In addition to the C# client, there's also a client for Angular 5+ on npm: ng-lightquery
Version 1.2.0 and above are compatible with Angular 6+ and rxjs >= 6.0.0.
Installation
The package is available on nuget. Daily builds are on myget.
MyGet feed: https://www.myget.org/F/dangl/api/v3/index.json
PM> Install-Package LightQuery
Includes the core functionality to sort and paginate Asp.Net Core controller results
PM> Install-Package LightQuery.EntityFrameworkCore
Includes support for EntityFramework.Core async query materialization
PM> Install-Package LightQuery.Client
Includes LightQuery models and the QueryBuilder utility
NETStandard 2.0 and .Net 4.6.1 are supported.
Testing
Tests are run via powershell ./build.ps1 Coverage
(or build.sh Coverage
) in the root directory.
Documentation - Server
See below how to apply sorting & filtering to your API controllers. At a glance:
- Return an
ObjectResult
from your controller with anIQueryable
value - Use
sort
to sort,page
&pageSize
for pagination in your requests
You can find a demo in the integration test projects for an example of using this in an Asp.Net Core MVC application for sorting and filtering.
Sorting
using LightQuery;
public class ApiController : Controller
{
[LightQuery]
[ProducesResponseType(typeof(IEnumerable<User>), 200)]
public IActionResult GetValues()
{
var values = _repository.GetAllValuesAsQueryable();
return Ok(values);
}
}
Annotate your controller actions with the LightQueryAttribute
and it takes care of
applying url queries to the result. All ObjectResult
s
(docs)
that have an IQueryable
value
will be transformed. You're free to return any other results, too, from the annotated action
and it will simply be ignored.
Example:
http://your.api.com/values?sort=email desc
This will sort the result by its Email
property (it is title-cased if no email
property is found) in descending
order.
Default Sort Order
You can specifiy a default sort order via the defaultSort
parameter of the [LightQuery]
attribute. It expects a string that
is in the same format as the query string, e.g. defaultSort: "email desc"
.
If relational sorting is active, null checks are introduced.
Relational Sorting
It is possible to sort by nested properties. This means that properties may be specified in a dotted way to access nested elements,
e.g. sorting can be done by using bankAccount.balance
. Take this example:
[
{
"name": "George",
"bankAccount": { "balance": 500 }
},
{
"name": "Alice",
"bankAccount": { "balance": 800 }
},
{
"name": "Bob",
"bankAccount": null
}
]
If you apply the sorting expression bankAccount.balance
, the user Bob
will not be present in the
result set because the bankAccount
property is null. The query will only be applied to George
and Alice
.
Handling Null Values in Relational Sorting
With v2.0.0, LightQuery introduced a new property wrapNestedSortInNullChecks
to the ASP.NET Core controller attributes.
This defaults to false
for regular [LightQuery]
and to true
for [AsyncLightQuery]
. It controls whether nested sorting / relational sorting will introduce null checks, e.g. sorting by x.SubProperty.SubId
is either translated as .Where(x => x.SubProperty != null).OrderBy(x => x.SubProperty.SubId)
or directly as .OrderBy(x => x.SubProperty.SubId)
. For Entity Framework (using the [AsyncLightQuery]
attribute), the database provider usually handles null checking via appropriate join conditions and versions before .NET 5 might produce errors otherwise.
ThenSort
LightQuery supports an additional sort level via the thenSort
parameter. For example, take the following url:
`http://your.api.com/values?sort=country&thenSort=email desc`
This would return your values first sorted by the country
property and then by the email
(descending) property. There is currently no support
for multiple thenSort
parameters and relational sorting is ignored in thenSort
.
Pagination & Sorting
Paging is active when the request includes pagination query parameters or via explicitly setting the forcePagination
parameter to true in the attributes' constructor. Sorting works in combination with paging.
using LightQuery;
public class ApiController : Controller
{
[LightQuery(forcePagination: true, defaultPageSize: 3, defaultSort: "columnName desc")]
[ProducesResponseType(typeof(PaginationResult<User>), 200)]
public IActionResult GetValues()
{
var values = _repository.GetAllValuesAsQueryable();
return Ok(values);
}
}
Example:
http://your.api.com/values?sort=email&page=2&pageSize=3
Response
{
"page": 2,
"pageSize": 3,
"totalCount": 20,
"data": [
{ "userName": "Dave", "email": "dave@example.com" },
{ "userName": "Emilia", "email": "emilia@example.com" },
{ "userName": "Fred", "email": "fred@example.com" }
]
}
Async Materialization
The LightQuery.EntityFrameworkCore
package provides an AsyncLightQueryAttribute
. This can be used for data sources that support async materialization of queries, e.g. ToListAsync()
. To use it, you also need to return just an IQueryable
because LightQuery will itself call the async methods when materializing the result.
So, to return a paginatable list of users that is asynchronously materialized, just return something like OK(context.Users)
.
Documentation - C# Client
The LightQuery.Client
package contains the PaginationResult<T>
base class as well as a QueryBuilder
utlity class to construct queries.
Example
using LightQuery.Client;
var url = QueryBuilder.Build(page: 3, pageSize: 25, sortParam: "email");
var response = await _client.GetAsync(url);
var responseContent = await response.Content.ReadAsStringAsync();
var deserializedResponse = JsonConvert.DeserializeObject<PaginationResult<User>>(responseContent);
PaginationBaseService
The LightQuery.Client
package contains an abstract class PaginationBaseService<T>
that can be used in reactive clients. It is similar in functionality
to the TypeScript client.
Documentation - TypeScript & Angular
The npm package ng-lightquery
contains client libraries for LightQuery that can be used in Angular 5+ projects. It has a generic PaginationBaseService<T>
that your own services can inherit from. As of now, you have to provide a concrete implementation for each generic type argument that you want to use, since the dependency injection in Angular does not currently resolve generics. So if you want two LightQuery services - one to retrieve users
and one to retrieve values
- you need to create two services yourself.
Example with Angular Material 2 DataTable
You'll have three files in this example:
users.component.html
The Angular template which contains an Anguler Material table view.
<md-table [dataSource]="dataSource"
mdSort
[mdSortActive]="usersService.sort?.propertyName"
[mdSortDirection]="usersService.sort?.isDescending ? 'desc' : 'asc'"
(mdSortChange)="onSort($event)">
<ng-container cdkColumnDef="email">
<md-header-cell md-sort-header *cdkHeaderCellDef> Email </md-header-cell>
<md-cell *cdkCellDef="let row">
{{row.email}}
</md-cell>
</ng-container>
<md-header-row *cdkHeaderRowDef="['email']"></md-header-row>
<md-row *cdkRowDef="let row; columns: ['email'];"></md-row>
</md-table>
<md-paginator [length]="usersPaginated.totalCount"
[pageSize]="usersPaginated.pageSize"
[pageIndex]="usersPaginated.page - 1"
(page)="onPage($event)">
</md-paginator>
users.component.ts
The component which is backing the view.
export class UsersComponent implements OnInit, OnDestroy {
constructor(public userService: UserService) { }
private usersPaginatedSubscription: Subscription;
usersPaginated: PaginationResult<User>;
dataSource: DataSource<User>;
onPage(pageEvent: PageEvent) {
this.userService.page = pageEvent.pageIndex + 1;
this.userService.pageSize = pageEvent.pageSize;
}
onSort(event: { active: string, direction: string }) {
if (!event.direction) {
this.userService.sort = null;
} else {
this.userService.sort = { propertyName: event.active, isDescending: event.direction === 'desc' };
}
}
ngOnInit() {
this.dataSource = this.userService;
this.usersPaginatedSubscription = this.userService.paginationResult.subscribe(r => this.usersPaginated = r);
}
ngOnDestroy() {
this.usersPaginatedSubscription.unsubscribe();
}
}
users.service.ts
To use the pagination service, simple let your own service inherit from the one provided by the ng-lightquery
package via extends PaginationBaseService<T>
. You can omit the implementation of the DataSource<User>
interface and the connect()
and disconnect()
methods if you're not working with Angular Material.
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { PaginationBaseService } from 'ng-lightquery';
import { User } from '../models/user';
import { DataSource } from '@angular/cdk/collections';
@Injectable()
export class UsersDetailsService extends PaginationBaseService<User> implements DataSource<User> {
constructor(protected http: HttpClient) {
super(http);
this.baseUrl = '/api/users';
// You can optionally initialize with some default values,
// e.g. for sorting, page size or custom url query attributes
this.sort = {
isDescending: false,
propertyName: 'email'
};
}
connect(): Observable<User[]> {
return this.paginationResult
.map((r: PaginationResult<User>) => r.data);
}
disconnect() { }
}
Swagger & OpenAPI Support
The packages LightQuery.NSwag and LightQuery.Swashbuckle support the automatic generation of correct Swagger & OpenAPI parameter descriptions for the sort and pagination parameters.
Example with NSwag
Just add the LightQuery.NSwag.LightQueryOperationsProcessor
to your document generation:
services.AddSwaggerDocument(nSwagConfig =>
{
nSwagConfig.DocumentName = "swagger20";
nSwagConfig.OperationProcessors.Add(new LightQueryOperationsProcessor());
});
services.AddOpenApiDocument(nSwagConfig =>
{
nSwagConfig.DocumentName = "openapi30";
nSwagConfig.OperationProcessors.Add(new LightQueryOperationsProcessor());
});
Example with Swashbuckle
Just add the LightQuery.Swashbuckle.LightQueryOperationFilter
to your document generation:
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("swagger20", new OpenApiInfo()
{
Description = "swagger20"
});
options.OperationFilter<LightQueryOperationFilter>();
});
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("openapi30", new OpenApiInfo()
{
Description = "openapi30"
});
options.OperationFilter<LightQueryOperationFilter>();
});
Assembly Strong Naming & Usage in Signed Applications
This module produces strong named assemblies when compiled. When consumers of this package require strongly named assemblies, for example when they
themselves are signed, the outputs should work as-is.
The key file to create the strong name is adjacent to the csproj
file in the root of the source project. Please note that this does not increase
security or provide tamper-proof binaries, as the key is available in the source code per
Microsoft guidelines
v1.6.1:
- Fix issue where
BadRequest
results inAsyncLightQuery
decorated controllers withforcePagination:true
were returning an emptyOkResult
with status code200
instead of the original404 - Bad Request
v1.6.0:
- The generated assemblies now have a strong name. This is a breaking change of the binary API and will require recompilation on all systems that consume this package. The strong name of the generated assembly allows compatibility with other, signed tools. Please note that this does not increase security or provide tamper-proof binaries, as the key is available in the source code per Microsoft guidelines
v1.5.2:
- Bugfix: Empty results now report the
page
as1
instead of0
. Thanks to GitHub user @erdembas for the pull request!
v1.5.1:
- When a
page
is requested that is higher than the last available one, the last available one will be returned instead. Thanks to GitHub user @erdembas for the pull request!
v1.5.0:
- It's now possible to do relational sorting, meaning that nested properties can be used for sorting. For example, it is now possible to sort by
user.bankAccount.balance
. Thanks to GitHub user @erdembas for the pull request!
v1.4.0:
- The
defaultSort
parameter was introduced for the server side controller attributes. Thanks to GitHub user @erdembas for the pull request!
v1.3.0:
- Raise minimum supported .NET Standard version to
netstandard2.0
- Bump version to align .NET and npm package versions
v1.1.0:
- Publish ng-lightquery npm package for angular and include PaginationBaseService in the client libraries
v1.0.2:
- Update version to align with new releases of LightQuery.EntityFrameworkCore and LightQuery.Client. Added support for EntityFrameworkCore async materialization of queries and a client side package for easier consuming of APIs
v1.0.1:
- Forced pagination was not applied when no query string at all was present in the Http request
v1.0.0:
- Initial release
-
.NETFramework 4.6.1
- LightQuery.Client (>= 1.6.2-beta0001)
- LightQuery.Shared (>= 1.6.2-beta0001)
-
.NETStandard 2.0
- LightQuery.Client (>= 1.6.2-beta0001)
- LightQuery.Shared (>= 1.6.2-beta0001)
- .NETFramework 4.6.1: 4.6.1.0
- .NETStandard 2.0: 2.0.0.0
OwnersGeorg Dangl |
AuthorsGeorg Dangl |
Project URLhttps://github.com/GeorgDangl/LightQuery |
LicenseMIT |
TagsAsp-Net-Core Querying Sorting Filtering |
Info1444 total downloads |
12 downloads for version 1.6.2-beta0001 |
Download (9.64 KB) |
Found on the current feed only |
Package history
Version | Size | Last updated | Downloads | Mirrored? | |||
---|---|---|---|---|---|---|---|
2.4.1 | 28.54 KB | Thu, 04 Jul 2024 22:18:38 GMT | 4 | ||||
2.4.0 | 28.5 KB | Wed, 21 Feb 2024 23:19:17 GMT | 10 | ||||
2.3.0 | 36.73 KB | Fri, 25 Nov 2022 16:04:15 GMT | 11 | ||||
2.3.0-beta0014 | 36.76 KB | Fri, 25 Nov 2022 16:00:14 GMT | 11 | ||||
2.2.3-beta0002 | 32.39 KB | Wed, 21 Sep 2022 09:12:47 GMT | 11 | ||||
2.2.3-beta0001 | 32.38 KB | Mon, 22 Aug 2022 11:47:32 GMT | 12 | ||||
2.2.2 | 32.35 KB | Mon, 22 Aug 2022 11:44:01 GMT | 11 | ||||
2.2.2-beta0004 | 32.38 KB | Mon, 22 Aug 2022 11:38:44 GMT | 10 | ||||
2.2.1 | 32.32 KB | Wed, 03 Aug 2022 14:34:52 GMT | 13 | ||||
2.2.1-beta0007 | 32.33 KB | Wed, 03 Aug 2022 14:30:54 GMT | 11 | ||||
2.2.1-beta0006 | 32.3 KB | Wed, 03 Aug 2022 13:47:20 GMT | 11 | ||||
2.2.1-beta0004 | 32.28 KB | Wed, 03 Aug 2022 13:43:17 GMT | 11 | ||||
2.2.1-beta0001 | 32.3 KB | Fri, 01 Jul 2022 15:48:29 GMT | 11 | ||||
2.2.0 | 32.25 KB | Fri, 01 Jul 2022 15:42:15 GMT | 13 | ||||
2.2.0-beta0043 | 32.29 KB | Fri, 01 Jul 2022 15:38:01 GMT | 10 | ||||
2.2.0-beta0039 | 32.3 KB | Wed, 22 Jun 2022 20:31:36 GMT | 9 | ||||
2.2.0-beta0037 | 32.27 KB | Fri, 29 Apr 2022 14:30:00 GMT | 11 | ||||
2.2.0-beta0036 | 32.29 KB | Wed, 20 Apr 2022 20:45:04 GMT | 11 | ||||
2.2.0-beta0034 | 32.3 KB | Wed, 20 Apr 2022 20:39:28 GMT | 10 | ||||
2.1.1-beta0022 | 32.26 KB | Tue, 29 Mar 2022 12:27:13 GMT | 11 | ||||
2.1.1-beta0020 | 32.27 KB | Mon, 21 Feb 2022 22:05:13 GMT | 11 | ||||
2.1.1-beta0013 | 32.26 KB | Sat, 12 Feb 2022 09:42:26 GMT | 11 | ||||
2.1.1-beta0012 | 32.25 KB | Sat, 12 Feb 2022 09:30:41 GMT | 11 | ||||
2.1.1-beta0009 | 32.27 KB | Sat, 12 Feb 2022 09:01:39 GMT | 11 | ||||
2.1.1-beta0005 | 32.25 KB | Fri, 11 Feb 2022 18:42:06 GMT | 10 | ||||
2.1.1-beta0003 | 32.24 KB | Fri, 11 Feb 2022 14:47:00 GMT | 11 | ||||
2.1.1-beta0001 | 32.24 KB | Thu, 02 Dec 2021 21:00:02 GMT | 11 | ||||
2.1.0 | 32.24 KB | Wed, 25 Aug 2021 19:34:30 GMT | 11 | ||||
2.1.0-beta0012 | 32.28 KB | Wed, 25 Aug 2021 19:16:04 GMT | 12 | ||||
2.0.1-beta0004 | 32.26 KB | Wed, 25 Aug 2021 18:35:41 GMT | 13 | ||||
2.0.0 | 32.21 KB | Thu, 15 Jul 2021 20:49:46 GMT | 10 | ||||
2.0.0-beta0028 | 32.25 KB | Sat, 26 Jun 2021 11:41:53 GMT | 9 | ||||
2.0.0-beta0027 | 32.25 KB | Sat, 26 Jun 2021 11:36:18 GMT | 10 | ||||
2.0.0-beta0025 | 32.24 KB | Sat, 19 Jun 2021 20:30:49 GMT | 9 | ||||
2.0.0-beta0024 | 32.25 KB | Sat, 19 Jun 2021 20:20:29 GMT | 10 | ||||
2.0.0-beta0023 | 32.13 KB | Mon, 14 Jun 2021 20:13:29 GMT | 10 | ||||
2.0.0-beta0022 | 31.76 KB | Wed, 26 May 2021 12:46:44 GMT | 10 | ||||
2.0.0-beta0020 | 31.76 KB | Tue, 18 May 2021 20:49:59 GMT | 8 | ||||
1.9.2-pullrequest0010-0001 | 27.53 KB | Sat, 05 Sep 2020 00:27:58 GMT | 10 | ||||
1.9.2-beta0018 | 27.63 KB | Sun, 09 May 2021 10:33:33 GMT | 10 | ||||
1.9.2-beta0016 | 27.61 KB | Thu, 06 May 2021 22:29:35 GMT | 11 | ||||
1.9.2-beta0014 | 27.63 KB | Thu, 22 Apr 2021 19:19:09 GMT | 10 | ||||
1.9.2-beta0012 | 27.62 KB | Mon, 08 Mar 2021 19:33:25 GMT | 9 | ||||
1.9.2-beta0010 | 27.62 KB | Wed, 13 Jan 2021 17:01:38 GMT | 11 | ||||
1.9.2-beta0009 | 27.61 KB | Tue, 12 Jan 2021 22:29:59 GMT | 13 | ||||
1.9.2-beta0006 | 27.42 KB | Mon, 19 Oct 2020 14:03:55 GMT | 11 | ||||
1.9.2-beta0002 | 27.47 KB | Mon, 19 Oct 2020 13:55:55 GMT | 14 | ||||
1.9.1 | 27.56 KB | Mon, 01 Mar 2021 14:30:45 GMT | 12 | ||||
1.9.1-beta0005 | 27.44 KB | Thu, 16 Jul 2020 08:59:17 GMT | 12 | ||||
1.9.0 | 27.36 KB | Mon, 01 Jun 2020 06:10:38 GMT | 10 | ||||
1.9.0-beta0012 | 27.42 KB | Sun, 31 May 2020 20:19:41 GMT | 11 | ||||
1.9.0-beta0003 | 27.41 KB | Wed, 27 May 2020 22:26:59 GMT | 14 | ||||
1.9.0-beta0002 | 27.41 KB | Wed, 27 May 2020 21:58:27 GMT | 11 | ||||
1.8.2-beta0001 | 27.35 KB | Tue, 19 May 2020 20:23:09 GMT | 11 | ||||
1.8.1 | 27.29 KB | Thu, 14 May 2020 17:58:12 GMT | 12 | ||||
1.8.1-beta0004 | 27.35 KB | Thu, 14 May 2020 17:31:41 GMT | 12 | ||||
1.8.1-beta0003 | 27.32 KB | Thu, 14 May 2020 16:58:55 GMT | 11 | ||||
1.8.1-beta0001 | 27.29 KB | Thu, 30 Jan 2020 21:50:48 GMT | 13 | ||||
1.8.0 | 27.25 KB | Mon, 06 Jan 2020 13:54:26 GMT | 12 | ||||
1.7.3-beta0006 | 27.29 KB | Mon, 06 Jan 2020 12:44:28 GMT | 13 | ||||
1.7.3-beta0005 | 27.3 KB | Mon, 06 Jan 2020 12:37:59 GMT | 11 | ||||
1.7.3-beta0004 | 27.25 KB | Sun, 05 Jan 2020 22:41:36 GMT | 12 | ||||
1.7.2 | 27.02 KB | Wed, 16 Oct 2019 19:34:06 GMT | 13 | ||||
1.7.2-beta0002 | 27.09 KB | Wed, 16 Oct 2019 19:11:15 GMT | 11 | ||||
1.7.1 | 26.95 KB | Wed, 16 Oct 2019 14:53:38 GMT | 13 | ||||
1.7.1-beta0005 | 26.98 KB | Wed, 16 Oct 2019 12:30:55 GMT | 12 | ||||
1.7.1-beta0004 | 26.99 KB | Wed, 16 Oct 2019 09:24:28 GMT | 13 | ||||
1.7.1-beta0001 | 26.85 KB | Mon, 14 Oct 2019 17:32:49 GMT | 12 | ||||
1.7.0 | 26.8 KB | Mon, 14 Oct 2019 10:05:59 GMT | 13 | ||||
1.7.0-beta0002 | 26.87 KB | Sat, 12 Oct 2019 21:27:25 GMT | 11 | ||||
1.6.3-beta0001 | 21.27 KB | Sun, 29 Sep 2019 18:16:36 GMT | 12 | ||||
1.6.2 | 9.64 KB | Sun, 29 Sep 2019 16:20:27 GMT | 13 | ||||
1.6.2-beta0004 | 9.68 KB | Sun, 29 Sep 2019 16:04:47 GMT | 12 | ||||
1.6.2-beta0001 | 9.64 KB | Fri, 06 Sep 2019 10:32:04 GMT | 12 | ||||
1.6.1 | 9.59 KB | Fri, 09 Aug 2019 17:07:34 GMT | 13 | ||||
1.6.1-beta0003 | 9.63 KB | Fri, 09 Aug 2019 14:25:51 GMT | 11 | ||||
1.6.0 | 9.34 KB | Tue, 06 Aug 2019 15:49:06 GMT | 13 | ||||
1.6.0-beta0010 | 9.37 KB | Tue, 06 Aug 2019 15:35:40 GMT | 12 | ||||
1.5.3-beta0002 | 8.4 KB | Mon, 20 May 2019 10:40:28 GMT | 12 | ||||
1.5.3-beta0001 | 8.41 KB | Sat, 02 Mar 2019 13:31:43 GMT | 12 | ||||
1.5.2 | 8.39 KB | Thu, 31 Jan 2019 12:04:42 GMT | 13 | ||||
1.5.2-dependabot-npm--0001 | 27.77 KB | Mon, 19 Oct 2020 13:55:55 GMT | 9 | ||||
1.5.2-beta0004 | 8.43 KB | Thu, 31 Jan 2019 11:51:51 GMT | 12 | ||||
1.5.2-beta0002 | 8.38 KB | Thu, 31 Jan 2019 11:41:11 GMT | 12 | ||||
1.5.1 | 8.31 KB | Thu, 31 Jan 2019 07:39:52 GMT | 13 | ||||
1.5.1-beta0009 | 8.35 KB | Thu, 31 Jan 2019 07:12:56 GMT | 14 | ||||
1.5.1-beta0007 | 8.35 KB | Thu, 31 Jan 2019 07:07:58 GMT | 12 | ||||
1.5.1-beta0001 | 8.06 KB | Thu, 03 Jan 2019 14:55:09 GMT | 12 | ||||
1.5.0 | 8.04 KB | Thu, 29 Nov 2018 21:05:03 GMT | 12 | ||||
1.4.1-beta0013 | 8.07 KB | Thu, 29 Nov 2018 20:50:59 GMT | 12 | ||||
1.4.1-beta0007 | 7.97 KB | Thu, 29 Nov 2018 16:59:34 GMT | 12 | ||||
1.4.0 | 7.94 KB | Tue, 27 Nov 2018 21:16:06 GMT | 13 | ||||
1.3.1-beta0008 | 7.97 KB | Tue, 27 Nov 2018 21:05:29 GMT | 12 | ||||
1.3.1-beta0002 | 7.49 KB | Tue, 27 Nov 2018 20:10:29 GMT | 14 | ||||
1.3.0 | 7.4 KB | Sat, 15 Sep 2018 21:45:20 GMT | 15 | ||||
1.1.1-build-28 | 7.15 KB | Sat, 05 May 2018 21:56:06 GMT | 12 | ||||
1.1.1-build-27 | 7.15 KB | Sat, 05 May 2018 21:53:46 GMT | 13 | ||||
1.1.1-build-26 | 7.15 KB | Mon, 16 Apr 2018 12:52:00 GMT | 12 | ||||
1.1.1-build-25 | 7.07 KB | Thu, 01 Feb 2018 18:11:56 GMT | 13 | ||||
1.1.1-build-24 | 7.06 KB | Thu, 04 Jan 2018 20:09:45 GMT | 13 | ||||
1.1.1-build-23 | 7.07 KB | Thu, 21 Dec 2017 18:44:51 GMT | 12 | ||||
1.1.1-build-22 | 7.07 KB | Thu, 21 Dec 2017 18:41:19 GMT | 13 | ||||
1.1.1-build-21 | 7.06 KB | Fri, 01 Dec 2017 16:47:04 GMT | 13 | ||||
1.1.1-build-19 | 7.07 KB | Thu, 23 Nov 2017 18:01:40 GMT | 13 | ||||
1.1.1-build-18 | 7.07 KB | Sat, 18 Nov 2017 17:27:20 GMT | 13 | ||||
1.1.1-build-17 | 7.07 KB | Fri, 17 Nov 2017 12:03:12 GMT | 12 | ||||
1.1.1-build-16 | 7.07 KB | Thu, 16 Nov 2017 22:12:09 GMT | 14 | ||||
1.1.1-beta0056 | 7.42 KB | Sat, 15 Sep 2018 21:29:29 GMT | 11 | ||||
1.1.1-beta0054 | 7.43 KB | Sat, 15 Sep 2018 21:19:14 GMT | 13 | ||||
1.1.1-beta0051 | 7.42 KB | Sat, 15 Sep 2018 19:50:15 GMT | 12 | ||||
1.1.0 | 7.01 KB | Thu, 16 Nov 2017 21:22:38 GMT | 13 | ||||
1.0.3-build-9 | 7.03 KB | Sun, 12 Nov 2017 21:09:07 GMT | 12 | ||||
1.0.3-build-8 | 7.03 KB | Sun, 12 Nov 2017 20:03:35 GMT | 13 | ||||
1.0.3-build-7 | 7.03 KB | Sun, 12 Nov 2017 18:15:40 GMT | 12 | ||||
1.0.3-build-6 | 7.03 KB | Sun, 12 Nov 2017 15:47:09 GMT | 13 | ||||
1.0.3-build-5 | 7.03 KB | Sun, 12 Nov 2017 15:33:47 GMT | 12 | ||||
1.0.3-build-4 | 7.03 KB | Sun, 12 Nov 2017 15:21:49 GMT | 11 | ||||
1.0.3-build-3 | 7.03 KB | Sun, 12 Nov 2017 12:23:25 GMT | 13 | ||||
1.0.3-build-2 | 7.03 KB | Fri, 01 Sep 2017 21:00:19 GMT | 12 | ||||
1.0.3-build-14 | 7.04 KB | Thu, 16 Nov 2017 18:54:47 GMT | 12 | ||||
1.0.3-build-12 | 7.04 KB | Wed, 15 Nov 2017 23:00:34 GMT | 11 | ||||
1.0.3-build-11 | 7.04 KB | Wed, 15 Nov 2017 21:17:42 GMT | 10 | ||||
1.0.3-build-10 | 7.03 KB | Mon, 13 Nov 2017 21:51:57 GMT | 13 | ||||
1.0.3-build-1 | 7.03 KB | Fri, 01 Sep 2017 20:57:00 GMT | 15 |