Skip to content

Commit

Permalink
fix: fix optional field filter in apply (#909)
Browse files Browse the repository at this point in the history
<!--
Pull requests are squashed and merged using:
- their title as the commit message
- their description as the commit body

Having a good title and description is important for the users to get
readable changelog.
-->

<!-- 1. Explain WHAT the change is about -->

- Fix the optional field filter on apply: resolve types before matching.

<!-- 2. Explain WHY the change cannot be made simpler -->



<!-- 3. Explain HOW users should update their code -->

#### Migration notes
_No migrations needed._

---

- [x] The change comes with new or modified tests
- [ ] Hard-to-understand functions have explanatory comments
- [ ] End-user documentation is updated to reflect the change
  • Loading branch information
Natoandro authored Nov 9, 2024
1 parent 2d177ec commit d69f9ce
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 15 deletions.
5 changes: 0 additions & 5 deletions deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 13 additions & 9 deletions src/typegraph/core/src/params/apply.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

use crate::errors::{ErrorContext, Result, TgError};
use crate::t::{self, TypeBuilder};
use crate::types::{Type, TypeDef, TypeId};
use crate::types::{AsTypeDefEx as _, TypeDef, TypeId};
use crate::wit::core::{ParameterTransform, TransformData};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
Expand Down Expand Up @@ -307,26 +307,30 @@ impl TransformDataBuildContext {
.filter_map(|(&k, &type_id)| {
TypeId(type_id)
.as_type()
.map(|ty| {
if !matches!(ty, Type::Def(TypeDef::Optional(_))) {
Some(k)
} else {
None
}
})
.with_context(|| {
format!(
"Error while resolving type #{type_id} at the field {k:?} at {path:?}",
path = stringify_path(&self.path).unwrap()
)
})
.and_then(|ty| {
ty.as_xdef()
.with_context(|| format!("resolving type: {}", ty.id().repr().unwrap()))
})
.map(|ty| {
if !matches!(ty.type_def, TypeDef::Optional(_)) {
Some(k)
} else {
None
}
})
.transpose()
})
.collect::<Result<Vec<_>>>()?;

if !non_optional_fields.is_empty() {
Err(format!(
"Missing non-optional fields {non_optional_fields:?} at {path:?}",
"missing non-optional fields {non_optional_fields:?} at {path:?}",
path = stringify_path(&self.path).unwrap()
)
.into())
Expand Down
68 changes: 67 additions & 1 deletion tests/params/apply_test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
// Copyright Metatype OÜ, licensed under the Mozilla Public License Version 2.0.
// SPDX-License-Identifier: MPL-2.0

import { gql, Meta } from "../utils/mod.ts";
import { randomPGConnStr } from "test-utils/database.ts";
import { gql, Meta } from "test-utils/mod.ts";
import { dropSchemas, recreateMigrations } from "test-utils/migrations.ts";
import { assertEquals } from "@std/assert/equals";

Meta.test("(python (sdk): apply)", async (t) => {
const e = await t.engine("params/apply.py", {
Expand Down Expand Up @@ -253,3 +256,66 @@ Meta.test("nested context access", async (t) => {
.on(e);
});
});

Meta.test("apply with prisma generated types", async (t) => {
const { connStr, schema: _ } = randomPGConnStr();
const e = await t.engine("params/prisma_apply.py", {
secrets: {
"POSTGRES": connStr,
},
});
await dropSchemas(e);
await recreateMigrations(e);

let id: string = null!;

await t.should("create user", async () => {
await gql`
mutation {
createUser(
name: "Alice"
email: "[email protected]"
age: 30
) {
id
name
email
age
}
}
`
.expectBody((body) => {
id = body.data.createUser.id;
assertEquals(body.data.createUser, {
id: id,
name: "Alice",
email: "[email protected]",
age: 30,
});
})
.on(e);
});

await t.should("find user by id", async () => {
await gql`
query Q($id: ID!) {
findUser(id: $id) {
id
name
email
age
}
}
`
.withVars({ id })
.expectData({
findUser: {
id,
name: "Alice",
email: "[email protected]",
age: 30,
},
})
.on(e);
});
});
38 changes: 38 additions & 0 deletions tests/params/prisma_apply.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from typegraph import Graph, Policy, t, typegraph
from typegraph.providers import PrismaRuntime


@typegraph()
def prisma_apply(g: Graph):
prisma = PrismaRuntime("db", "POSTGRES")
public = Policy.public()

user = t.struct(
{
"id": t.uuid(config=["auto"]).id(),
"name": t.string(),
"email": t.email(config=["unique"]),
"age": t.integer(),
},
name="user",
)

g.expose(
public,
createUser=prisma.create(user).apply(
{
"data": {
"name": g.as_arg(),
"email": g.as_arg(),
"age": g.as_arg(),
}
}
),
findUser=prisma.find_unique(user).apply(
{
"where": {
"id": g.as_arg(),
}
}
),
)

0 comments on commit d69f9ce

Please sign in to comment.