diff --git a/.github/workflows/discord-pr-notifications.yaml b/.github/workflows/discord-pr-notifications.yaml
new file mode 100644
index 00000000..5fe96ef2
--- /dev/null
+++ b/.github/workflows/discord-pr-notifications.yaml
@@ -0,0 +1,17 @@
+name: Pull Request Notification to Discord
+
+on:
+ pull_request:
+ types: [opened, closed]
+
+jobs:
+ notify:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Send notification to Discord
+ env:
+ WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
+ run: |
+ curl -X POST -H "Content-Type: application/json" \
+ -d "{\"content\": \"🔔 New Pull Request: **${{ github.event.pull_request.title }}** by ${{ github.actor }} - ${{ github.event.pull_request.html_url }}\"}" \
+ $WEBHOOK_URL
\ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
index 0861f8f2..11e21f86 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -16,8 +16,15 @@ keywords = ["async", "graphql", "mysql", "postgres", "sqlite"]
categories = ["database"]
[dependencies]
-async-graphql = { version = "7.0", features = ["decimal", "chrono", "dataloader", "dynamic-schema"] }
-sea-orm = { version = "~1.1.0", default-features = false, features = ["seaography"] }
+async-graphql = { version = "7.0", features = [
+ "decimal",
+ "chrono",
+ "dataloader",
+ "dynamic-schema",
+] }
+sea-orm = { version = "1.0.*", default-features = false, features = [
+ "seaography",
+] }
itertools = { version = "0.12.0" }
heck = { version = "0.4.1" }
thiserror = { version = "1.0.44" }
@@ -32,6 +39,7 @@ with-uuid = ["sea-orm/with-uuid"]
with-decimal = ["sea-orm/with-rust_decimal", "async-graphql/decimal"]
with-bigdecimal = ["sea-orm/with-bigdecimal", "async-graphql/bigdecimal"]
with-postgres-array = ["sea-orm/postgres-array"]
+offset-pagination = []
# with-ipnetwork = ["sea-orm/with-ipnetwork"]
# with-mac_address = ["sea-orm/with-mac_address"]
field-snake-case = []
diff --git a/README.md b/README.md
index 674838d1..0ba4c997 100644
--- a/README.md
+++ b/README.md
@@ -6,9 +6,9 @@
🧠A GraphQL framework and code generator for SeaORM
- [](https://crates.io/crates/seaography)
- [](https://docs.rs/seaography)
- [](https://github.com/SeaQL/seaography/actions/workflows/tests.yaml)
+[](https://crates.io/crates/seaography)
+[](https://docs.rs/seaography)
+[](https://github.com/SeaQL/seaography/actions/workflows/tests.yaml)
@@ -18,27 +18,27 @@
## Benefits
-* Quick and easy to get started
-* Generates readable code
-* Extensible project structure
-* Based on popular async libraries: [async-graphql](https://github.com/async-graphql/async-graphql) and [SeaORM](https://github.com/SeaQL/sea-orm)
+- Quick and easy to get started
+- Generates readable code
+- Extensible project structure
+- Based on popular async libraries: [async-graphql](https://github.com/async-graphql/async-graphql) and [SeaORM](https://github.com/SeaQL/sea-orm)
## Features
-* Relational query (1-to-1, 1-to-N)
-* Pagination for queries and relations (1-N)
-* Filtering with operators (e.g. gt, lt, eq)
-* Order by any column
-* Guard fields, queries or relations
-* Rename fields
-* Mutations (create, update, delete)
+- Relational query (1-to-1, 1-to-N)
+- Pagination for queries and relations (1-N)
+- Filtering with operators (e.g. gt, lt, eq)
+- Order by any column
+- Guard fields, queries or relations
+- Rename fields
+- Mutations (create, update, delete)
(Right now there is no mutation, but it's on our plan!)
## SeaORM Version Compatibility
-| Seaography | SeaORM |
-|----------------------------------------------------------|-------------------------------------------------------|
+| Seaography | SeaORM |
+| -------------------------------------------------------- | ----------------------------------------------------- |
| [1.1-rc](https://crates.io/crates/seaography/1.1.0-rc.1) | [1.1-rc](https://crates.io/crates/sea-orm/1.1.0-rc.1) |
| [1.0](https://crates.io/crates/seaography/1.0.0) | [1.0](https://crates.io/crates/sea-orm/1.0.0) |
| [0.12](https://crates.io/crates/seaography/0.12.0) | [0.12](https://crates.io/crates/sea-orm/0.12.14) |
@@ -70,19 +70,22 @@ Go to http://localhost:8000/ and try out the following queries:
```graphql
{
- film(pagination: { page: { limit: 10, page: 0 } }, orderBy: { title: ASC }) {
- nodes {
- title
- description
- releaseYear
- actor {
+ film(
+ pagination: { page: { limit: 10, page: 0 } }
+ orderBy: { title: ASC }
+ ) {
nodes {
- firstName
- lastName
+ title
+ description
+ releaseYear
+ actor {
+ nodes {
+ firstName
+ lastName
+ }
+ }
}
- }
}
- }
}
```
@@ -90,19 +93,19 @@ Go to http://localhost:8000/ and try out the following queries:
```graphql
{
- store(filters: { storeId: { eq: 1 } }) {
- nodes {
- storeId
- address {
- address
- address2
- }
- staff {
- firstName
- lastName
- }
+ store(filters: { storeId: { eq: 1 } }) {
+ nodes {
+ storeId
+ address {
+ address
+ address2
+ }
+ staff {
+ firstName
+ lastName
+ }
+ }
}
- }
}
```
@@ -110,20 +113,20 @@ Go to http://localhost:8000/ and try out the following queries:
```graphql
{
- customer(
- filters: { active: { eq: 0 } }
- pagination: { page: { page: 2, limit: 3 } }
- ) {
- nodes {
- customerId
- lastName
- email
- }
- paginationInfo {
- pages
- current
+ customer(
+ filters: { active: { eq: 0 } }
+ pagination: { page: { page: 2, limit: 3 } }
+ ) {
+ nodes {
+ customerId
+ lastName
+ email
+ }
+ paginationInfo {
+ pages
+ current
+ }
}
- }
}
```
@@ -131,21 +134,21 @@ Go to http://localhost:8000/ and try out the following queries:
```graphql
{
- customer(
- filters: { active: { eq: 0 } }
- pagination: { cursor: { limit: 3, cursor: "Int[3]:271" } }
- ) {
- nodes {
- customerId
- lastName
- email
- }
- pageInfo {
- hasPreviousPage
- hasNextPage
- endCursor
+ customer(
+ filters: { active: { eq: 0 } }
+ pagination: { cursor: { limit: 3, cursor: "Int[3]:271" } }
+ ) {
+ nodes {
+ customerId
+ lastName
+ email
+ }
+ pageInfo {
+ hasPreviousPage
+ hasNextPage
+ endCursor
+ }
}
- }
}
```
@@ -155,57 +158,58 @@ Find all inactive customers, include their address, and their payments with amou
```graphql
{
- customer(
- filters: { active: { eq: 0 } }
- pagination: { cursor: { limit: 3, cursor: "Int[3]:271" } }
- ) {
- nodes {
- customerId
- lastName
- email
- address {
- address
- }
- payment(
- filters: { amount: { gt: "7" } }
- orderBy: { amount: ASC }
- pagination: { page: { limit: 1, page: 1 } }
- ) {
+ customer(
+ filters: { active: { eq: 0 } }
+ pagination: { cursor: { limit: 3, cursor: "Int[3]:271" } }
+ ) {
nodes {
- paymentId
- amount
- }
- paginationInfo {
- pages
- current
+ customerId
+ lastName
+ email
+ address {
+ address
+ }
+ payment(
+ filters: { amount: { gt: "7" } }
+ orderBy: { amount: ASC }
+ pagination: { page: { limit: 1, page: 1 } }
+ ) {
+ nodes {
+ paymentId
+ amount
+ }
+ paginationInfo {
+ pages
+ current
+ }
+ pageInfo {
+ hasPreviousPage
+ hasNextPage
+ }
+ }
}
pageInfo {
- hasPreviousPage
- hasNextPage
+ hasPreviousPage
+ hasNextPage
+ endCursor
}
- }
}
- pageInfo {
- hasPreviousPage
- hasNextPage
- endCursor
- }
- }
}
```
### Filter using enumeration
+
```graphql
{
- film(
- filters: { rating: { eq: NC17 } }
- pagination: { page: { page: 1, limit: 5 } }
- ) {
- nodes {
- filmId
- rating
+ film(
+ filters: { rating: { eq: NC17 } }
+ pagination: { page: { page: 1, limit: 5 } }
+ ) {
+ nodes {
+ filmId
+ rating
+ }
}
- }
}
```
@@ -233,4 +237,4 @@ cargo run
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
-Seaography is a community driven project. We welcome you to participate, contribute and together build for Rust's future.
+Seaography is a community driven project. We welcome you to participate, contribute and together build for Rust's future.
\ No newline at end of file
diff --git a/examples/mysql/Cargo.toml b/examples/mysql/Cargo.toml
index 1b423ec8..7ff88ef2 100644
--- a/examples/mysql/Cargo.toml
+++ b/examples/mysql/Cargo.toml
@@ -22,5 +22,8 @@ features = ["with-decimal", "with-chrono"]
[dev-dependencies]
serde_json = { version = "1.0.103" }
+[features]
+offset-pagination = ["seaography/offset-pagination"]
+
[workspace]
-members = []
+members = []
\ No newline at end of file
diff --git a/examples/mysql/tests/mutation_tests.rs b/examples/mysql/tests/mutation_tests.rs
index 44a1948d..f638ddba 100644
--- a/examples/mysql/tests/mutation_tests.rs
+++ b/examples/mysql/tests/mutation_tests.rs
@@ -1,6 +1,7 @@
use async_graphql::{dynamic::*, Response};
use sea_orm::Database;
+#[cfg(not(feature = "offset-pagination"))]
async fn main() {
test_simple_insert_one().await;
test_complex_insert_one().await;
@@ -620,4 +621,4 @@ async fn test_delete_mutation() {
}
"#,
);
-}
+}
\ No newline at end of file
diff --git a/examples/mysql/tests/offset_pagination_query_tests.rs b/examples/mysql/tests/offset_pagination_query_tests.rs
new file mode 100644
index 00000000..d966d07e
--- /dev/null
+++ b/examples/mysql/tests/offset_pagination_query_tests.rs
@@ -0,0 +1,137 @@
+use async_graphql::{dynamic::*, Response};
+use sea_orm::Database;
+
+pub async fn get_schema() -> Schema {
+ let database = Database::connect("mysql://sea:sea@127.0.0.1/sakila")
+ .await
+ .unwrap();
+ let schema = seaography_mysql_example::query_root::schema(database, None, None).unwrap();
+
+ schema
+}
+
+pub fn assert_eq(a: Response, b: &str) {
+ assert_eq!(
+ a.data.into_json().unwrap(),
+ serde_json::from_str::(b).unwrap()
+ )
+}
+
+#[cfg(feature = "offset-pagination")]
+#[tokio::test]
+async fn test_simple_query() {
+ let schema = get_schema().await;
+
+ assert_eq(
+ schema
+ .execute(
+ r#"
+ {
+ store {
+ storeId
+ staff {
+ firstName
+ lastName
+ }
+ }
+ }
+ "#,
+ )
+ .await,
+ r#"
+ {
+ "store": [
+ {
+ "storeId": 1,
+ "staff": {
+ "firstName": "Mike",
+ "lastName": "Hillyer"
+ }
+ },
+ {
+ "storeId": 2,
+ "staff": {
+ "firstName": "Jon",
+ "lastName": "Stephens"
+ }
+ }
+ ]
+ }
+ "#,
+ )
+}
+
+#[cfg(feature = "offset-pagination")]
+#[tokio::test]
+async fn test_simple_query_with_filter() {
+ let schema = get_schema().await;
+
+ assert_eq(
+ schema
+ .execute(
+ r#"
+ {
+ store(filters: {storeId:{eq: 1}}) {
+ storeId
+ staff {
+ firstName
+ lastName
+ }
+ }
+ }
+ "#,
+ )
+ .await,
+ r#"
+ {
+ "store": [
+ {
+ "storeId": 1,
+ "staff": {
+ "firstName": "Mike",
+ "lastName": "Hillyer"
+ }
+ }
+ ]
+ }
+ "#,
+ )
+}
+
+#[cfg(feature = "offset-pagination")]
+#[tokio::test]
+async fn test_filter_with_pagination() {
+ let schema = get_schema().await;
+
+ assert_eq(
+ schema
+ .execute(
+ r#"
+ {
+ customer(
+ filters: { active: { eq: 0 } }
+ pagination: { page: { page: 2, limit: 3 } }
+ ) {
+ customerId
+ }
+ }
+ "#,
+ )
+ .await,
+ r#"
+ {
+ "customer": [
+ {
+ "customerId": 315
+ },
+ {
+ "customerId": 368
+ },
+ {
+ "customerId": 406
+ }
+ ]
+ }
+ "#,
+ )
+}
\ No newline at end of file
diff --git a/examples/mysql/tests/query_tests.rs b/examples/mysql/tests/query_tests.rs
index 97ca5a8c..d6b5ffbd 100644
--- a/examples/mysql/tests/query_tests.rs
+++ b/examples/mysql/tests/query_tests.rs
@@ -17,6 +17,7 @@ pub fn assert_eq(a: Response, b: &str) {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn test_simple_query() {
let schema = get_schema().await;
@@ -64,6 +65,7 @@ async fn test_simple_query() {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn test_simple_query_with_filter() {
let schema = get_schema().await;
@@ -104,6 +106,7 @@ async fn test_simple_query_with_filter() {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn test_filter_with_pagination() {
let schema = get_schema().await;
@@ -153,6 +156,7 @@ async fn test_filter_with_pagination() {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn test_complex_filter_with_pagination() {
let schema = get_schema().await;
@@ -202,6 +206,7 @@ async fn test_complex_filter_with_pagination() {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn test_cursor_pagination() {
let schema = get_schema().await;
@@ -297,6 +302,7 @@ async fn test_cursor_pagination() {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn test_cursor_pagination_prev() {
let schema = get_schema().await;
@@ -374,6 +380,7 @@ async fn test_cursor_pagination_prev() {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn test_cursor_pagination_no_next() {
let schema = get_schema().await;
@@ -442,6 +449,7 @@ async fn test_cursor_pagination_no_next() {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn test_self_ref() {
let schema = get_schema().await;
@@ -506,6 +514,7 @@ async fn test_self_ref() {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn related_queries_filters() {
let schema = get_schema().await;
@@ -696,6 +705,7 @@ async fn related_queries_filters() {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn related_queries_pagination() {
let schema = get_schema().await;
@@ -833,6 +843,7 @@ async fn related_queries_pagination() {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn enumeration_filter() {
let schema = get_schema().await;
@@ -884,4 +895,4 @@ async fn enumeration_filter() {
}
"#,
)
-}
+}
\ No newline at end of file
diff --git a/examples/postgres/Cargo.toml b/examples/postgres/Cargo.toml
index c6539f5e..653dc1ea 100644
--- a/examples/postgres/Cargo.toml
+++ b/examples/postgres/Cargo.toml
@@ -22,5 +22,8 @@ features = ["with-decimal", "with-chrono", "with-postgres-array"]
[dev-dependencies]
serde_json = { version = "1.0.103" }
+[features]
+offset-pagination = ["seaography/offset-pagination"]
+
[workspace]
-members = []
+members = []
\ No newline at end of file
diff --git a/examples/postgres/tests/mutation_tests.rs b/examples/postgres/tests/mutation_tests.rs
index 1fa66e91..2cff0963 100644
--- a/examples/postgres/tests/mutation_tests.rs
+++ b/examples/postgres/tests/mutation_tests.rs
@@ -1,6 +1,7 @@
use async_graphql::{dynamic::*, Response};
use sea_orm::Database;
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn main() {
test_simple_insert_one().await;
@@ -630,4 +631,4 @@ async fn test_delete_mutation() {
}
"#,
);
-}
+}
\ No newline at end of file
diff --git a/examples/postgres/tests/offset_pagination_query_tests.rs b/examples/postgres/tests/offset_pagination_query_tests.rs
new file mode 100644
index 00000000..5285ec02
--- /dev/null
+++ b/examples/postgres/tests/offset_pagination_query_tests.rs
@@ -0,0 +1,137 @@
+use async_graphql::{dynamic::*, Response};
+use sea_orm::Database;
+
+pub async fn get_schema() -> Schema {
+ let database = Database::connect("postgres://sea:sea@127.0.0.1/sakila")
+ .await
+ .unwrap();
+ let schema = seaography_postgres_example::query_root::schema(database, None, None).unwrap();
+
+ schema
+}
+
+pub fn assert_eq(a: Response, b: &str) {
+ assert_eq!(
+ a.data.into_json().unwrap(),
+ serde_json::from_str::(b).unwrap()
+ )
+}
+
+#[cfg(feature = "offset-pagination")]
+#[tokio::test]
+async fn test_simple_query() {
+ let schema = get_schema().await;
+
+ assert_eq(
+ schema
+ .execute(
+ r#"
+ {
+ store {
+ storeId
+ staff {
+ firstName
+ lastName
+ }
+ }
+ }
+ "#,
+ )
+ .await,
+ r#"
+ {
+ "store": [
+ {
+ "storeId": 1,
+ "staff": {
+ "firstName": "Mike",
+ "lastName": "Hillyer"
+ }
+ },
+ {
+ "storeId": 2,
+ "staff": {
+ "firstName": "Jon",
+ "lastName": "Stephens"
+ }
+ }
+ ]
+ }
+ "#,
+ )
+}
+
+#[cfg(feature = "offset-pagination")]
+#[tokio::test]
+async fn test_simple_query_with_filter() {
+ let schema = get_schema().await;
+
+ assert_eq(
+ schema
+ .execute(
+ r#"
+ {
+ store(filters: {storeId:{eq: 1}}) {
+ storeId
+ staff {
+ firstName
+ lastName
+ }
+ }
+ }
+ "#,
+ )
+ .await,
+ r#"
+ {
+ "store": [
+ {
+ "storeId": 1,
+ "staff": {
+ "firstName": "Mike",
+ "lastName": "Hillyer"
+ }
+ }
+ ]
+ }
+ "#,
+ )
+}
+
+#[cfg(feature = "offset-pagination")]
+#[tokio::test]
+async fn test_filter_with_pagination() {
+ let schema = get_schema().await;
+
+ assert_eq(
+ schema
+ .execute(
+ r#"
+ {
+ customer(
+ filters: { active: { eq: 0 } }
+ pagination: { page: { page: 2, limit: 3 } }
+ ) {
+ customerId
+ }
+ }
+ "#,
+ )
+ .await,
+ r#"
+ {
+ "customer": [
+ {
+ "customerId": 315
+ },
+ {
+ "customerId": 368
+ },
+ {
+ "customerId": 406
+ }
+ ]
+ }
+ "#,
+ )
+}
\ No newline at end of file
diff --git a/examples/postgres/tests/query_tests.rs b/examples/postgres/tests/query_tests.rs
index 7c3d340d..c69ecb93 100644
--- a/examples/postgres/tests/query_tests.rs
+++ b/examples/postgres/tests/query_tests.rs
@@ -17,6 +17,7 @@ pub fn assert_eq(a: Response, b: &str) {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn test_simple_query() {
let schema = get_schema().await;
@@ -64,6 +65,7 @@ async fn test_simple_query() {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn test_simple_query_with_filter() {
let schema = get_schema().await;
@@ -104,6 +106,7 @@ async fn test_simple_query_with_filter() {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn test_filter_with_pagination() {
let schema = get_schema().await;
@@ -153,6 +156,7 @@ async fn test_filter_with_pagination() {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn test_complex_filter_with_pagination() {
let schema = get_schema().await;
@@ -202,6 +206,7 @@ async fn test_complex_filter_with_pagination() {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn test_cursor_pagination() {
let schema = get_schema().await;
@@ -297,6 +302,7 @@ async fn test_cursor_pagination() {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn test_cursor_pagination_prev() {
let schema = get_schema().await;
@@ -374,6 +380,7 @@ async fn test_cursor_pagination_prev() {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn test_cursor_pagination_no_next() {
let schema = get_schema().await;
@@ -507,6 +514,7 @@ async fn test_cursor_pagination_no_next() {
// )
// }
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn related_queries_filters() {
let schema = get_schema().await;
@@ -694,6 +702,7 @@ async fn related_queries_filters() {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn related_queries_pagination() {
let schema = get_schema().await;
@@ -831,6 +840,7 @@ async fn related_queries_pagination() {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn enumeration_filter() {
let schema = get_schema().await;
@@ -884,6 +894,7 @@ async fn enumeration_filter() {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn test_boolean_field() {
let schema = get_schema().await;
@@ -916,4 +927,4 @@ async fn test_boolean_field() {
}
"#,
)
-}
+}
\ No newline at end of file
diff --git a/examples/sqlite/Cargo.toml b/examples/sqlite/Cargo.toml
index 39338e1c..11e70c60 100644
--- a/examples/sqlite/Cargo.toml
+++ b/examples/sqlite/Cargo.toml
@@ -22,5 +22,8 @@ features = ["with-decimal", "with-chrono"]
[dev-dependencies]
serde_json = { version = "1.0.103" }
+[features]
+offset-pagination = ["seaography/offset-pagination"]
+
[workspace]
-members = []
+members = []
\ No newline at end of file
diff --git a/examples/sqlite/tests/guard_mutation_tests.rs b/examples/sqlite/tests/guard_mutation_tests.rs
index ced4915a..c1eee029 100644
--- a/examples/sqlite/tests/guard_mutation_tests.rs
+++ b/examples/sqlite/tests/guard_mutation_tests.rs
@@ -80,7 +80,7 @@ pub fn assert_eq(a: Response, b: &str) {
serde_json::from_str::(b).unwrap()
)
}
-
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn entity_guard_mutation() {
let schema = get_schema().await;
@@ -130,6 +130,7 @@ async fn entity_guard_mutation() {
assert_eq!(response.errors[0].message, "Entity guard triggered.");
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn field_guard_mutation() {
let schema = get_schema().await;
@@ -141,7 +142,7 @@ async fn field_guard_mutation() {
languageUpdate(data: { name: "Cantonese" }, filter: { languageId: { eq: 6 } }) {
languageId
}
- }
+ }
"#,
)
.await;
@@ -149,4 +150,4 @@ async fn field_guard_mutation() {
assert_eq!(response.errors.len(), 1);
assert_eq!(response.errors[0].message, "Field guard triggered.");
-}
+}
\ No newline at end of file
diff --git a/examples/sqlite/tests/guard_tests.rs b/examples/sqlite/tests/guard_tests.rs
index 9e9340a6..0d75ff02 100644
--- a/examples/sqlite/tests/guard_tests.rs
+++ b/examples/sqlite/tests/guard_tests.rs
@@ -285,6 +285,7 @@ pub fn assert_eq(a: Response, b: &str) {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn entity_guard() {
let schema = get_schema().await;
@@ -357,6 +358,7 @@ async fn entity_guard() {
assert_eq!(response.errors[0].message, "Entity guard triggered.");
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn field_guard() {
let schema = get_schema().await;
@@ -380,4 +382,4 @@ async fn field_guard() {
assert_eq!(response.errors.len(), 1);
assert_eq!(response.errors[0].message, "Field guard triggered.");
-}
+}
\ No newline at end of file
diff --git a/examples/sqlite/tests/mutation_tests.rs b/examples/sqlite/tests/mutation_tests.rs
index c3f9dec5..53be711d 100644
--- a/examples/sqlite/tests/mutation_tests.rs
+++ b/examples/sqlite/tests/mutation_tests.rs
@@ -1,6 +1,7 @@
use async_graphql::{dynamic::*, Response};
use sea_orm::Database;
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn main() {
test_simple_insert_one().await;
@@ -24,6 +25,7 @@ pub fn assert_eq(a: Response, b: &str) {
)
}
+#[cfg(not(feature = "offset-pagination"))]
async fn test_simple_insert_one() {
let schema = get_schema().await;
@@ -106,6 +108,7 @@ async fn test_simple_insert_one() {
);
}
+#[cfg(not(feature = "offset-pagination"))]
async fn test_complex_insert_one() {
let schema = get_schema().await;
@@ -218,6 +221,7 @@ async fn test_complex_insert_one() {
);
}
+#[cfg(not(feature = "offset-pagination"))]
async fn test_create_batch_mutation() {
let schema = get_schema().await;
@@ -320,6 +324,7 @@ async fn test_create_batch_mutation() {
);
}
+#[cfg(not(feature = "offset-pagination"))]
async fn test_update_mutation() {
let schema = get_schema().await;
@@ -498,6 +503,7 @@ async fn test_update_mutation() {
);
}
+#[cfg(not(feature = "offset-pagination"))]
async fn test_delete_mutation() {
let schema = get_schema().await;
@@ -601,4 +607,4 @@ async fn test_delete_mutation() {
}
"#,
);
-}
+}
\ No newline at end of file
diff --git a/examples/sqlite/tests/offset_pagination_query_tests.rs b/examples/sqlite/tests/offset_pagination_query_tests.rs
new file mode 100644
index 00000000..bf4ac006
--- /dev/null
+++ b/examples/sqlite/tests/offset_pagination_query_tests.rs
@@ -0,0 +1,135 @@
+use async_graphql::{dynamic::*, Response};
+use sea_orm::Database;
+
+pub async fn get_schema() -> Schema {
+ let database = Database::connect("sqlite://sakila.db").await.unwrap();
+ let schema = seaography_sqlite_example::query_root::schema(database, None, None).unwrap();
+
+ schema
+}
+
+pub fn assert_eq(a: Response, b: &str) {
+ assert_eq!(
+ a.data.into_json().unwrap(),
+ serde_json::from_str::(b).unwrap()
+ )
+}
+
+#[cfg(feature = "offset-pagination")]
+#[tokio::test]
+async fn test_simple_query() {
+ let schema = get_schema().await;
+
+ assert_eq(
+ schema
+ .execute(
+ r#"
+ {
+ store {
+ storeId
+ staff {
+ firstName
+ lastName
+ }
+ }
+ }
+ "#,
+ )
+ .await,
+ r#"
+ {
+ "store": [
+ {
+ "storeId": 1,
+ "staff": {
+ "firstName": "Mike",
+ "lastName": "Hillyer"
+ }
+ },
+ {
+ "storeId": 2,
+ "staff": {
+ "firstName": "Jon",
+ "lastName": "Stephens"
+ }
+ }
+ ]
+ }
+ "#,
+ )
+}
+
+#[cfg(feature = "offset-pagination")]
+#[tokio::test]
+async fn test_simple_query_with_filter() {
+ let schema = get_schema().await;
+
+ assert_eq(
+ schema
+ .execute(
+ r#"
+ {
+ store(filters: {storeId:{eq: 1}}) {
+ storeId
+ staff {
+ firstName
+ lastName
+ }
+ }
+ }
+ "#,
+ )
+ .await,
+ r#"
+ {
+ "store": [
+ {
+ "storeId": 1,
+ "staff": {
+ "firstName": "Mike",
+ "lastName": "Hillyer"
+ }
+ }
+ ]
+ }
+ "#,
+ )
+}
+
+#[cfg(feature = "offset-pagination")]
+#[tokio::test]
+async fn test_filter_with_pagination() {
+ let schema = get_schema().await;
+
+ assert_eq(
+ schema
+ .execute(
+ r#"
+ {
+ customer(
+ filters: { active: { eq: 0 } }
+ pagination: { page: { page: 2, limit: 3 } }
+ ) {
+ customerId
+ }
+ }
+ "#,
+ )
+ .await,
+ r#"
+ {
+ "customer": [
+ {
+ "customerId": 315
+ },
+ {
+ "customerId": 368
+ },
+ {
+ "customerId": 406
+ }
+ ]
+ }
+ "#,
+ )
+}
\ No newline at end of file
diff --git a/examples/sqlite/tests/query_tests.rs b/examples/sqlite/tests/query_tests.rs
index 0f04935e..4104de1e 100644
--- a/examples/sqlite/tests/query_tests.rs
+++ b/examples/sqlite/tests/query_tests.rs
@@ -15,6 +15,7 @@ pub fn assert_eq(a: Response, b: &str) {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn test_simple_query() {
let schema = get_schema().await;
@@ -62,6 +63,7 @@ async fn test_simple_query() {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn test_simple_query_with_filter() {
let schema = get_schema().await;
@@ -102,6 +104,7 @@ async fn test_simple_query_with_filter() {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn test_filter_with_pagination() {
let schema = get_schema().await;
@@ -151,6 +154,7 @@ async fn test_filter_with_pagination() {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn test_complex_filter_with_pagination() {
let schema = get_schema().await;
@@ -200,6 +204,7 @@ async fn test_complex_filter_with_pagination() {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn test_cursor_pagination() {
let schema = get_schema().await;
@@ -295,6 +300,7 @@ async fn test_cursor_pagination() {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn test_cursor_pagination_prev() {
let schema = get_schema().await;
@@ -372,6 +378,7 @@ async fn test_cursor_pagination_prev() {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn test_cursor_pagination_no_next() {
let schema = get_schema().await;
@@ -440,6 +447,7 @@ async fn test_cursor_pagination_no_next() {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn test_self_ref() {
let schema = get_schema().await;
@@ -504,6 +512,7 @@ async fn test_self_ref() {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn related_queries_filters() {
let schema = get_schema().await;
@@ -706,6 +715,7 @@ async fn related_queries_filters() {
)
}
+#[cfg(not(feature = "offset-pagination"))]
#[tokio::test]
async fn related_queries_pagination() {
let schema = get_schema().await;
@@ -841,4 +851,4 @@ async fn related_queries_pagination() {
}
"#,
)
-}
+}
\ No newline at end of file
diff --git a/generator/src/templates/actix_cargo.toml b/generator/src/templates/actix_cargo.toml
index c0fc0236..7e892926 100644
--- a/generator/src/templates/actix_cargo.toml
+++ b/generator/src/templates/actix_cargo.toml
@@ -21,5 +21,8 @@ features = ["with-decimal", "with-chrono"]
[dev-dependencies]
serde_json = { version = "1.0.103" }
+[features]
+offset-pagination = ["seaography/offset-pagination"]
+
[workspace]
-members = []
+members = []
\ No newline at end of file
diff --git a/generator/src/templates/axum_cargo.toml b/generator/src/templates/axum_cargo.toml
index 37f2d00e..728b4064 100644
--- a/generator/src/templates/axum_cargo.toml
+++ b/generator/src/templates/axum_cargo.toml
@@ -21,5 +21,8 @@ features = ["with-decimal", "with-chrono"]
[dev-dependencies]
serde_json = { version = "1.0.103" }
+[features]
+offset-pagination = ["seaography/offset-pagination"]
+
[workspace]
-members = []
+members = []
\ No newline at end of file
diff --git a/generator/src/templates/poem_cargo.toml b/generator/src/templates/poem_cargo.toml
index 3313908c..32a0250d 100644
--- a/generator/src/templates/poem_cargo.toml
+++ b/generator/src/templates/poem_cargo.toml
@@ -21,5 +21,8 @@ features = ["with-decimal", "with-chrono"]
[dev-dependencies]
serde_json = { version = "1.0.103" }
+[features]
+offset-pagination = ["seaography/offset-pagination"]
+
[workspace]
-members = []
+members = []
\ No newline at end of file
diff --git a/src/builder.rs b/src/builder.rs
index 592f5041..f24dcd7a 100644
--- a/src/builder.rs
+++ b/src/builder.rs
@@ -1,15 +1,19 @@
use async_graphql::{
dataloader::DataLoader,
- dynamic::{Enum, Field, FieldFuture, InputObject, Object, Schema, SchemaBuilder, TypeRef},
+ dynamic::{
+ Enum, Field, FieldFuture, InputObject, Interface, Object, Schema, SchemaBuilder, TypeRef,
+ ValueAccessor,
+ },
};
-use sea_orm::{ActiveEnum, ActiveModelTrait, EntityTrait, IntoActiveModel};
+use sea_orm::{ActiveEnum, ActiveModelTrait, EntityTrait, IntoActiveModel, RelationDef};
use crate::{
- ActiveEnumBuilder, ActiveEnumFilterInputBuilder, BuilderContext, ConnectionObjectBuilder,
- CursorInputBuilder, EdgeObjectBuilder, EntityCreateBatchMutationBuilder,
- EntityCreateOneMutationBuilder, EntityDeleteMutationBuilder, EntityInputBuilder,
- EntityObjectBuilder, EntityQueryFieldBuilder, EntityUpdateMutationBuilder, FilterInputBuilder,
- FilterTypesMapHelper, OffsetInputBuilder, OneToManyLoader, OneToOneLoader, OrderByEnumBuilder,
+ ActiveEnumBuilder, ActiveEnumFilterInputBuilder, BuilderContext, CascadeInputBuilder,
+ ConnectionObjectBuilder, CursorInputBuilder, EdgeObjectBuilder,
+ EntityCreateBatchMutationBuilder, EntityCreateOneMutationBuilder, EntityDeleteMutationBuilder,
+ EntityGetFieldBuilder, EntityInputBuilder, EntityObjectBuilder, EntityQueryFieldBuilder,
+ EntityUpdateMutationBuilder, FilterInputBuilder, FilterTypesMapHelper, NewOrderInputBuilder,
+ OffsetInputBuilder, OneToManyLoader, OneToOneLoader, OrderByEnumBuilder, OrderEnumBuilder,
OrderInputBuilder, PageInfoObjectBuilder, PageInputBuilder, PaginationInfoObjectBuilder,
PaginationInputBuilder,
};
@@ -25,6 +29,9 @@ pub struct Builder {
/// holds all output object types
pub outputs: Vec