Skip to content

Commit

Permalink
Merge pull request #8367 from ballerina-platform/bff-demo
Browse files Browse the repository at this point in the history
Add Bff to master
  • Loading branch information
sm1990 authored Nov 28, 2023
2 parents fa1bd77 + 311e98e commit 0f515c7
Show file tree
Hide file tree
Showing 26 changed files with 1,396 additions and 0 deletions.
694 changes: 694 additions & 0 deletions components/bff/code/Code.js

Large diffs are not rendered by default.

52 changes: 52 additions & 0 deletions components/bff/code/Code.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/* .box div {
border: 1px solid #D9D9D9;
padding: 20px;
} */

.box h3 {
font-size: 20px;
color: #585a5e;
}

a.cDownload {
display: flex;
transition: none !important;
font-weight: 400;
color: #20b6b0 !important;
text-decoration: none;
margin-bottom: 20px;
}

a.cDownload span {
margin-right: 10px !important;
}

.codeSnippet div pre {
margin-top: 0;
padding-left: 30px;
padding-right: 30px;
padding-top: 30px;
padding-bottom: 30px;
font-size: 11.375px;
line-height: 18px;
}

/* .codeSnippet div pre.shiki {
padding-top: 0 !important;
background-color: #ffffff !important;
} */

.box img:not(.doNotFill) {
border-radius: 4px;
width: -moz-available !important;
width: -webkit-fill-available !important;
width: fill-available !important;
}

.box.ipaas {
text-align: center;
}

.description {
margin-bottom: 20px;
}
25 changes: 25 additions & 0 deletions components/bff/code/bff-bbe/client-auth.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
title: 'Securely interact with internal/external services'
description: Ballerina back-ends can securely call services with the necessary security features such as client-side OAuth2, mutual TLS, and JWT-encapsulated user data.
url: 'https://github.com/ballerina-guides/bff-samples/tree/main/securely_consume_services_from_backends'
---
```
service /logistics on new http:Listener(9090) {
resource function post cargos(Cargo cargo)
returns http:Ok|http:InternalServerError {
cargoTable.add(cargo);
http:Client serviceClient = getServiceClient(cargo.cargoType);
http:Response|error res = serviceClient->post("/shipments", cargo);
if res is http:Response && res.statusCode == 202 {
return <http:Ok>{body: "Successfully submitted the shipment"};
}
return <http:InternalServerError>{
body: {message: "Error occurred while submitting the shipment"}
};
};
resource function get cargos() returns Cargo[] {
return cargoTable.toArray();
};
}
```
39 changes: 39 additions & 0 deletions components/bff/code/bff-bbe/constraint-validation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
title: 'Validate payload constraints in web back-ends'
description: Ballerina's inherent JSON capabilities enable the direct mapping of JSON data into Ballerina records, incorporating functionalities such as constraint validations.
url: 'https://github.com/ballerina-guides/bff-samples/tree/main/validate_payloads_constraints_in_web_backends'
---
```
type Order record {|
readonly string id;
@constraint:String {
pattern: {
value: re `C-[0-9]{3}`,
message: "Customer id should be in the format C-XXX"
}
}
string customerId;
string? shipId;
string date;
OrderStatus status;
@constraint:Int {
minValue: {value: 1, message: "Quantity should be greater than one"},
maxValue: {value: 10, message: "Quantity should not exceed 10"}
}
int quantity;
string item;
|};
service /sales on new http:Listener(9090) {
resource function post orders(Order orderRequest)
returns Order|http:BadRequest {
if orders.hasKey(orderRequest.id) {
return <http:BadRequest>{
body: string `Order id already exists.`
};
}
orders.add(orderRequest);
return orderRequest;
}
}
```
6 changes: 6 additions & 0 deletions components/bff/code/bff-bbe/deployment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
title: 'Develop flexible & scalable back-ends'
description: Ballerina-based back-ends offer the flexibility to manage varying loads. Components can be deployed and scaled independently, providing flexibility and scalability, particularly on platforms like Kubernetes.<br><br>In addition, Ballerina back-ends can be instantly taken to production by deploying in Choreo, a comprehensive app development platform with pre-built CI/CD pipelines, multi-environment support, and robust monitoring for Ballerina apps.
image: 'images/choreo-ipaas-image-v2.png'
url: 'https://wso2.com/choreo/internal-developer-platform'
---
35 changes: 35 additions & 0 deletions components/bff/code/bff-bbe/graphql.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
title: 'Efficiently expose complex data with GraphQL'
description: With Ballerina's built-in GraphQL functionality, developers can simply expose Ballerina records via GraphQL services, facilitating querying and selectively fetching complex data structures.
url: 'https://github.com/ballerina-guides/bff-samples/tree/main/expose_complex_data_with_graphql'
---
```
type Order record {|
readonly string id;
string customerId;
string? shipId;
Address? shippingAddress;
string date;
OrderStatus status;
int quantity;
string item;
|};
type Address record {|
string number;
string street;
string city;
string state;
|};
service /sales on new graphql:Listener(9090) {
resource function get orders(string? customerId) returns Order[] {
if customerId is () {
return orders.toArray();
}
return from Order entry in orders
where entry.customerId == customerId
select entry;
}
}
```
33 changes: 33 additions & 0 deletions components/bff/code/bff-bbe/json-support.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
title: 'Streamline back-end data handling'
description: Ballerina has built-in support for multi-part payloads, constraint validations, transformations, and, enrichments for working with complex payloads.
url: 'https://github.com/ballerina-guides/bff-samples/tree/main/handle-mulipart-form-data'
---
```
service /crm on new http:Listener(9090) {
resource function get customers/[string customerId]/agreement()
returns byte[]|http:InternalServerError {
byte[]|error agreementForm = getAgreementForm(customerId);
if agreementForm is error {
return http:INTERNAL_SERVER_ERROR;
}
return agreementForm;
}
resource function post customers(http:Request request)
returns http:Created|http:InternalServerError {
do {
mime:Entity[] bodyParts = check request.getBodyParts();
string formData = check bodyParts[0].getText();
CustomerData data = check formData.fromJsonStringWithType();
byte[] image = check bodyParts[1].getByteArray();
byte[] agreemntForm = check bodyParts[2].getByteArray();
check registerCustomer(data, agreemntForm, image);
return http:CREATED;
} on fail {
return http:INTERNAL_SERVER_ERROR;
}
}
}
```
30 changes: 30 additions & 0 deletions components/bff/code/bff-bbe/persist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
title: 'Automate data access with Ballerina'
description: Ballerina's persistence features offer a straightforward way to create a data access layer for any complex application by providing a simplified interface for CRUD operations.
url: 'https://github.com/ballerina-guides/bff-samples/tree/main/persistently-store-data-using-Ballerina'
---
```
Client dbClient = check new ();
service /sales on new http:Listener(9090) {
resource function get orders() returns Order[]|error {
return from Order entry in orderDatabase->/orders(Order)
select entry;
};
resource function post orders(Order orderEntry)
returns http:Ok|http:InternalServerError|http:BadRequest {
orderEntry.cargoId = getCargoId();
string[]|persist:Error result = orderDatabase->/orders.post([orderEntry]);
if result is string[] {
return http:OK;
}
if result is persist:ConstraintViolationError {
return <http:BadRequest>{
body: {message: string `Invalid cargo id: ${orderEntry.cargoId}`}
};
}
return http:INTERNAL_SERVER_ERROR;
};
}
```
30 changes: 30 additions & 0 deletions components/bff/code/bff-bbe/rest-support.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
title: 'Simplify back-end development with native REST features'
description: Ballerina provides REST features like path/query parameters, HTTP headers, status codes, and complex JSON structures as first-class citizens within the language itself.
url: 'https://github.com/ballerina-guides/bff-samples/tree/main/restful-order-service'
---
```
service /sales on new http:Listener(9090) {
resource function get orders() returns Order[] {
return orders.toArray();
};
resource function get orders/[string id]() returns Order|http:NotFound {
return orders[id] ?: <http:NotFound>{
body: string `Order not found. Order ID: ${id}`
};
};
resource function post orders(Order orderRequest)
returns Order|http:BadRequest {
if orders.hasKey(orderRequest.id) {
return <http:BadRequest>{
body: string `Order id already exists.`
};
}
orders.add(orderRequest);
return orderRequest;
}
}
```
34 changes: 34 additions & 0 deletions components/bff/code/bff-bbe/security.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
title: "Comprehensive security for web back-ends"
description: Ballerina-based back-ends can simplify securing sensitive data during transit, validating server identity, managing CORS, and enforcing message type restrictions via annotations.
url: 'https://github.com/ballerina-guides/bff-samples/tree/main/comprehensive-security-for-web-backends'
---
```
@http:ServiceConfig {
cors: {
allowOrigins: ["http://localhost:3000", "http://www.hmart.com"],
allowHeaders: ["REQUEST_ID"],
exposeHeaders: ["RESPONSE_ID"],
maxAge: 84900
}
}
service /sales on new http:Listener(9090,
secureSocket = {
key: {
certFile: "../path/to/cert",
keyFile: "../path/to/private-key"
}
}
) {
@http:ResourceConfig {
cors: {
allowOrigins: ["http://localhost:3000", "http://www.hmart.com"],
allowCredentials: true
}
}
resource function post orders(Order orderEntry) returns http:Ok {
orderTable.add(orderEntry);
return <http:Ok>{body: {message: "Order submitted successfully"}};
};
}
```
34 changes: 34 additions & 0 deletions components/bff/code/bff-bbe/server-auth.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
title: 'Simplify user authentications and authorizations'
description: Ballerina apps can be seamlessly integrated with any OAuth2-compatible identity provider using a simple set of annotations.
url: 'https://github.com/ballerina-guides/bff-samples/tree/main/connect_with_asgardeo_for_building_secure_services'
---
```
@http:ServiceConfig {
auth: [
{
jwtValidatorConfig: {
issuer: issuer,
audience: audience,
signatureConfig: {
jwksConfig: {
url: jwksUrl
}
}
},
scopes: ["order_insert", "order_read", "cargo_insert", "cargo_read"]
}
]
}
service /sales on new http:Listener(9090) {
@http:ResourceConfig {
auth: {
scopes: ["order_insert"]
}
}
resource function post orders(Order orders) returns http:Ok {
orderTable.add(orders);
return <http:Ok>{body: {message: "Order submitted successfully"}};
};
}
```
37 changes: 37 additions & 0 deletions components/bff/code/bff-bbe/websockets.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
title: 'Expose real-time data to front-ends via webSockets'
description: Ballerina allows real-time data to be streamed just by implementing a service. This comes with enterprise-ready security features like TLS, mutual TLS, and OAuth2.
url: 'https://github.com/ballerina-guides/bff-samples/tree/main/exposing-realtime-data-using-websockets'
---
```
service /logistics on new websocket:Listener(9091) {
resource function get vehicles/[string vehicleId]()
returns websocket:Service {
return new LocationService(vehicleId);
}
}
distinct service class LocationService {
*websocket:Service;
remote function onOpen(websocket:Caller caller) returns error? {
// Create a new strand and allocate it to send the locations
_ = start self.routeLocationFromServerToClient(caller, self.vehicleId);
return;
}
function routeLocationFromServerToClient(
websocket:Caller caller, string vehicleId) returns error? {
while true {
Location currentLocation = {
latitude: check random:createIntInRange(668700, 1246700) * 1.0
/ 10000.0,
longitude: check random:createIntInRange(258400, 493800) * 1.0
/ 10000.0
};
check caller->writeMessage(currentLocation);
runtime:sleep(3);
}
}
}
```
Loading

0 comments on commit 0f515c7

Please sign in to comment.