Skip to content

Commit 01995bd

Browse files
committed
[DOCS-3787] Remove FQL typer workarounds
1 parent f11b9c4 commit 01995bd

File tree

8 files changed

+60
-65
lines changed

8 files changed

+60
-65
lines changed

DotNetSampleApp/Controllers/Customers.cs

+20-22
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
namespace DotNetSampleApp.Controllers;
77

88
/// <summary>
9-
/// Customers controller
9+
/// Customers controller
1010
/// </summary>
1111
/// <param name="client">Fauna Client</param>
1212
[ApiController,
@@ -30,10 +30,10 @@ public async Task<IActionResult> GetCustomer([FromRoute] string customerId)
3030
//
3131
// Use projection to only return the fields you need.
3232
var query = Query.FQL($"""
33-
let customer: Any = Customer.byId({customerId})!
33+
let customer = Customer.byId({customerId})!
3434
{QuerySnippets.CustomerResponse()}
3535
""");
36-
36+
3737
// Connect to fauna using the client. The query method accepts an FQL query
3838
// as a parameter and a generic type parameter representing the return type.
3939
var res = await client.QueryAsync<Customer>(query);
@@ -52,16 +52,16 @@ public async Task<IActionResult> CreateCustomer(CustomerRequest customer)
5252
{
5353
// Create a new Customer document with the provided fields.
5454
var query = Query.FQL($"""
55-
let customer: Any = Customer.create({customer})
55+
let customer = Customer.create({customer})
5656
{QuerySnippets.CustomerResponse()}
5757
""");
58-
58+
5959
// Connect to fauna using the client. The query method accepts an FQL query
6060
// as a parameter and a generic type parameter representing the return type.
6161
var res = await client.QueryAsync<Customer>(query);
6262
return CreatedAtAction(nameof(GetCustomer), new { customerId = res.Data.Id }, res.Data);
6363
}
64-
64+
6565
/// <summary>
6666
/// Update Customer Details
6767
/// </summary>
@@ -85,10 +85,10 @@ public async Task<IActionResult> UpdateCustomer(
8585
//
8686
// Use projection to only return the fields you need.
8787
var query = Query.FQL($"""
88-
let customer: Any = Customer.byId({customerId})!.update({customer})
88+
let customer = Customer.byId({customerId})!.update({customer})
8989
{QuerySnippets.CustomerResponse()}
9090
""");
91-
91+
9292
// Connect to fauna using the client. The query method accepts an FQL query
9393
// as a parameter and a generic type parameter representing the return type.
9494
var res = await client.QueryAsync<Customer>(query);
@@ -116,25 +116,23 @@ public async Task<IActionResult> GetOrdersByCustomer(
116116
// Make sure to URL encode the `afterToken` value to preserve these
117117
// characters in URLs.
118118
var query = !string.IsNullOrEmpty(afterToken)
119-
119+
120120
// Paginate with the after token if it's present.
121121
? Query.FQL($"Set.paginate({afterToken})")
122-
122+
123123
// Define an FQL query to retrieve a page of orders for a given customer.
124124
// Get the Customer document by id, using the ! operator to assert that the document exists.
125125
// If the document does not exist, Fauna will throw a document_not_found error. We then
126126
// use the Order.byCustomer index to retrieve all orders for that customer and map over
127127
// the results to return only the fields we care about.
128128
: Query.FQL($$"""
129-
let customer: Any = Customer.byId({{customerId}})!
129+
let customer = Customer.byId({{customerId}})!
130130
Order.byCustomer(customer).pageSize({{pageSize}}).map((order) => {
131-
let order: Any = order
132-
133131
// Return the order.
134132
{{QuerySnippets.OrderResponse()}}
135133
})
136134
""");
137-
135+
138136
// Connect to fauna using the client. The query method accepts an FQL query
139137
// as a parameter and a generic type parameter representing the return type.
140138
var result = await client.QueryAsync<Page<Order>>(query);
@@ -156,12 +154,12 @@ public async Task<IActionResult> CreateCart([FromRoute] string customerId)
156154
// Call our getOrCreateCart UDF to get the customer's cart. The function
157155
// definition can be found 'server/schema/functions.fsl'.
158156
var query = Query.FQL($"""
159-
let order: Any = getOrCreateCart({customerId})
160-
157+
let order = getOrCreateCart({customerId})
158+
161159
// Return the cart.
162160
{QuerySnippets.OrderResponse()}
163161
""");
164-
162+
165163
// Connect to fauna using the client. The query method accepts an FQL query
166164
// as a parameter and a generic type parameter representing the return type.
167165
var res = await client.QueryAsync<Order>(query);
@@ -184,12 +182,12 @@ public async Task<IActionResult> AddItemToCart([FromRoute] string customerId, Ad
184182
// definition can be found 'server/schema/functions.fsl'.
185183
var query = Query.FQL($"""
186184
let req = {item}
187-
let order: Any = createOrUpdateCartItem({customerId}, req.productName, req.quantity)
185+
let order = createOrUpdateCartItem({customerId}, req.productName, req.quantity)
188186
189187
// Return the cart as an OrderResponse object.
190188
{QuerySnippets.OrderResponse()}
191189
""");
192-
190+
193191
// Connect to fauna using the client. The query method accepts an FQL query
194192
// as a parameter and a generic type parameter representing the return type.
195193
var res = await client.QueryAsync<Order>(query);
@@ -210,12 +208,12 @@ public async Task<IActionResult> GetCart([FromRoute] string customerId)
210208
// Get the customer's cart by id, using the ! operator to assert that the document exists.
211209
// If the document does not exist, Fauna will throw a document_not_found error.
212210
var query = Query.FQL($"""
213-
let order: Any = Customer.byId({customerId})!.cart
214-
211+
let order = Customer.byId({customerId})!.cart
212+
215213
// Return the cart as an OrderResponse object.
216214
{QuerySnippets.OrderResponse()}
217215
""");
218-
216+
219217
// Connect to fauna using the client. The query method accepts an FQL query
220218
// as a parameter and a generic type parameter representing the return type.
221219
var res = await client.QueryAsync<Order>(query);

DotNetSampleApp/Controllers/Orders.cs

+6-6
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ public class Orders(Client client) : ControllerBase
2626
public async Task<IActionResult> GetOrder([FromRoute] string id)
2727
{
2828
var query = Query.FQL($"""
29-
let order: Any = Order.byId({id})!
29+
let order = Order.byId({id})!
3030
{QuerySnippets.OrderResponse()}
3131
""");
32-
32+
3333
// Connect to fauna using the client. The query method accepts an FQL query
3434
// as a parameter and a generic type parameter representing the return type.
3535
var res = await client.QueryAsync<Order>(query);
@@ -58,19 +58,19 @@ OrderRequest order
5858
// for validating that the order in a valid state to be processed and decrements the stock
5959
// of each product in the order. This ensures that the product stock is updated in the same transaction
6060
// as the order status.
61-
var query = order.Status == "processing"
61+
var query = order.Status == "processing"
6262
? Query.FQL($"""
6363
let req = {order}
64-
let order: Any = checkout({id}, req.status, req.payment)
64+
let order = checkout({id}, req.status, req.payment)
6565
{QuerySnippets.OrderResponse()}
6666
""")
67-
67+
6868
// Define an FQL query to update the order. The query first retrieves the order by id
6969
// using the Order.byId function. If the order does not exist, Fauna will throw a document_not_found
7070
// error. We then use the validateOrderStatusTransition UDF to ensure that the order status transition
7171
// is valid. If the transition is not valid, the UDF will throw an abort error.
7272
: Query.FQL($$"""
73-
let order: Any = Order.byId({{id}})!
73+
let order = Order.byId({{id}})!
7474
let req = {{order}}
7575
7676
// Validate the order status transition if a status is provided.

DotNetSampleApp/Controllers/Products.cs

+17-17
Original file line numberDiff line numberDiff line change
@@ -36,24 +36,24 @@ public async Task<IActionResult> PaginateProducts(
3636
// fragment will either return all products sorted by category or all products in a specific
3737
// category depending on whether the category query parameter is provided. This will later
3838
// be embedded in a larger query.
39-
var queryPrefix = string.IsNullOrEmpty(category)
40-
? Query.FQL($"Product.sortedByCategory().pageSize({pageSize})")
39+
var queryPrefix = string.IsNullOrEmpty(category)
40+
? Query.FQL($"Product.sortedByCategory().pageSize({pageSize})")
4141
: Query.FQL($"""
4242
let category = Category.byName({category}).first()
4343
if (category == null) abort("Category does not exist.")
44-
44+
4545
Product.byCategory(category).pageSize({pageSize})
4646
""");
47-
47+
4848
// The `afterToken` parameter contains a Fauna `after` cursor.
4949
// `after` cursors may contain special characters, such as `.` or `+`).
5050
// Make sure to URL encode the `afterToken` value to preserve these
5151
// characters in URLs.
52-
var query = !string.IsNullOrEmpty(afterToken)
53-
52+
var query = !string.IsNullOrEmpty(afterToken)
53+
5454
// Paginate with the after token if it's present.
5555
? Query.FQL($"Set.paginate({afterToken})")
56-
56+
5757
// Define the main query. This query will return a page of products using the query fragment
5858
// defined above.
5959
: Query.FQL($$"""
@@ -90,17 +90,17 @@ public async Task<IActionResult> CreateProduct(ProductRequest product)
9090
if (category == null) abort("Category does not exist.")
9191
9292
// Create the product with the given values.
93-
let args = {
93+
let args = {
9494
name: {{product.Name}},
9595
price: {{product.Price}},
9696
stock: {{product.Stock}},
9797
description: {{product.Description}},
98-
category: category
98+
category: category
9999
}
100-
let product: Any = Product.create(args)
100+
let product = Product.create(args)
101101
{{QuerySnippets.ProductResponse()}}
102102
""");
103-
103+
104104
// Connect to fauna using the client. The query method accepts an FQL query
105105
// as a parameter and a generic type parameter representing the return type.
106106
var result = await client.QueryAsync<Product>(query);
@@ -125,7 +125,7 @@ public async Task<IActionResult> UpdateProductById(
125125
var query = Query.FQL($$"""
126126
// Get the product by id, using the ! operator to assert that the product exists.
127127
// If it does not exist Fauna will throw a document_not_found error.
128-
let product: Any = Product.byId({{id}})!
128+
let product = Product.byId({{id}})!
129129
if (product == null) abort("Product does not exist.")
130130
131131
// Get the category by name. We can use .first() here because we know that the category
@@ -134,7 +134,7 @@ public async Task<IActionResult> UpdateProductById(
134134
if (category == null) abort("Category does not exist.")
135135
136136
// Update category if a new one was provided
137-
let newCategory: Any = Category.byName({{product.Category}})?.first()
137+
let newCategory = Category.byName({{product.Category}})?.first()
138138
139139
let fields = {
140140
name: {{product.Name}},
@@ -154,7 +154,7 @@ public async Task<IActionResult> UpdateProductById(
154154
155155
{{QuerySnippets.ProductResponse()}}
156156
""");
157-
157+
158158
// Connect to fauna using the client. The query method accepts an FQL query
159159
// as a parameter and a generic type parameter representing the return type.
160160
var result = await client.QueryAsync<Product>(query);
@@ -185,10 +185,10 @@ public async Task<IActionResult> SearchProducts(
185185
// Make sure to URL encode the `afterToken` value to preserve these
186186
// characters in URLs.
187187
var query = !string.IsNullOrEmpty(afterToken)
188-
188+
189189
// Paginate with the after token if it's present.
190190
? Query.FQL($"Set.paginate({afterToken})")
191-
191+
192192
// This is an example of a covered query. A covered query is a query where all fields
193193
// returned are indexed fields. In this case, we are querying the Product collection
194194
// for products with a price between minPrice and maxPrice. We are also limiting the
@@ -204,7 +204,7 @@ public async Task<IActionResult> SearchProducts(
204204
{{QuerySnippets.ProductResponse()}}
205205
})
206206
""");
207-
207+
208208
// Connect to fauna using the client. The query method accepts an FQL query
209209
// as a parameter and a generic type parameter representing the return type.
210210
var result = await client.QueryAsync<Page<Product>>(query);

DotNetSampleApp/Controllers/QuerySnippets.cs

+8-9
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace DotNetSampleApp.Controllers;
88
public static class QuerySnippets
99
{
1010
/// <summary>
11-
/// A Query snippet for customer response projection.
11+
/// A Query snippet for customer response projection.
1212
/// </summary>
1313
/// <returns></returns>
1414
public static Query CustomerResponse()
@@ -25,11 +25,11 @@ public static Query CustomerResponse()
2525
}
2626

2727
/// <summary>
28-
/// A Query snippet for order response projection.
28+
/// A Query snippet for order response projection.
2929
/// </summary>
3030
/// <returns></returns>
3131
public static Query OrderResponse()
32-
{
32+
{
3333
return Query.FQL($$"""
3434
{
3535
id: order.id,
@@ -63,27 +63,26 @@ public static Query OrderResponse()
6363
}
6464

6565
/// <summary>
66-
/// A Query snippet for product response projection.
66+
/// A Query snippet for product response projection.
6767
/// </summary>
6868
/// <returns></returns>
6969
public static Query ProductResponse()
7070
{
7171
return Query.FQL($$"""
7272
// Use projection to return only the necessary fields.
7373
let product: Any = product
74-
let category: Any = product.category
7574
product {
7675
id: product.id,
7776
name: product.name,
7877
price: product.price,
7978
description: product.description,
8079
stock: product.stock,
8180
category: {
82-
id: category.id,
83-
name: category.name,
84-
description: category.description
81+
id: product.category.id,
82+
name: product.category.name,
83+
description: product.category.description
8584
},
8685
}
8786
""");
8887
}
89-
}
88+
}

DotNetSampleApp/Services/SeedService.cs

+5-5
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public static void Init(Client client)
4545
{name: 'The Godfather II', price: 1299, description: 'A movie by Francis Ford Coppola', stock: 10, category: 'movies'},
4646
{name: 'The Godfather III', price: 1299, description: 'A movie by Francis Ford Coppola', stock: 10, category: 'movies'}
4747
].map(p => {
48-
let existing: Any = Product.byName(p.name).first()
48+
let existing = Product.byName(p.name).first()
4949
if (existing != null) {
5050
existing!.update({ stock: p.stock })
5151
} else {
@@ -85,16 +85,16 @@ public static void Init(Client client)
8585
client.QueryAsync(Query.FQL($$"""
8686
let customer = Customer.byEmail('[email protected]').first()!
8787
let orders = ['cart', 'processing', 'shipped', 'delivered'].map(status => {
88-
let order: Any = Order.byCustomer(customer).firstWhere(o => o.status == status)
88+
let order = Order.byCustomer(customer).firstWhere(o => o.status == status)
8989
if (order == null) {
90-
let newOrder: Any = Order.create({
90+
let newOrder = Order.create({
9191
customer: customer,
9292
status: status,
9393
createdAt: Time.now(),
9494
payment: {}
9595
})
96-
let product: Any = Product.byName('Drone').first()!
97-
let orderItem: Any = OrderItem.create({ order: newOrder, product: product, quantity: 1 })
96+
let product = Product.byName('Drone').first()!
97+
let orderItem = OrderItem.create({ order: newOrder, product: product, quantity: 1 })
9898
orderItem
9999
newOrder
100100
} else {

README.md

-1
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,6 @@ Customer documents and related API responses:
265265
+ // Use a computed field to calculate the customer's cumulative purchase total.
266266
+ // The field sums purchase `total` values from the customer's linked Order documents.
267267
+ compute totalPurchaseAmt: Number = (customer => customer.orders.fold(0, (sum, order) => {
268-
+ let order: Any = order
269268
+ sum + order.total
270269
+ }))
271270
...

schema/collections.fsl

+1-2
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,8 @@ collection Order {
7272

7373
compute items: Set<OrderItem> = (order => OrderItem.byOrder(order))
7474
compute total: Number = (order => order.items.fold(0, (sum, orderItem) => {
75-
let orderItem: Any = orderItem
7675
if (orderItem.product != null) {
77-
sum + orderItem.product.price * orderItem.quantity
76+
sum + orderItem.product!.price * orderItem.quantity
7877
} else {
7978
sum
8079
}

0 commit comments

Comments
 (0)