Skip to content

Commit b4496bf

Browse files
authored
Merge branch 'main' into jwt-claim-pagination
2 parents 1465ad3 + 35ed095 commit b4496bf

File tree

32 files changed

+645
-88
lines changed

32 files changed

+645
-88
lines changed

README.md

Lines changed: 27 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -27,93 +27,51 @@
2727
- [Explore the docs](https://stepzen.com/docs)
2828
- [View Demo](https://stepzen.com/developers/videos/graph-of-graphs)
2929
- [Report Bug](https://github.com/stepzen-dev/snippets/issues)
30-
- [Request Snippet](https://github.com/stepzen-dev/issues)
30+
- [Request Snippet](https://github.com/stepzen-dev/snippets/issues)
3131
- [Join our Discord Server](https://discord.com/invite/9k2VdPn2FR)
3232
</p>
3333
</div>
3434

35-
<!-- TABLE OF CONTENTS -->
36-
<details>
37-
<summary>Table of Contents</summary>
38-
<ol>
39-
<li>
40-
<a href="#about-the-project">About The Project</a>
41-
</li>
42-
<li><a href="#transforms">`@transforms`</a></li>
43-
<li><a href="#sequence">`@sequence`</a></li>
44-
<li><a href="#protection">protection</a></li>
45-
<li><a href="#rest-calls-and-responses">`@rest` calls and responses</a></li>
46-
47-
</ol>
48-
</details>
49-
5035
## About the project
5136

52-
This repo contains `.graphql` (and in some case, `config.yaml` files) for various "self-contained" example code for doing operations in StepZen.
37+
Code snippets that demonstrate use of custom directives and other techniques in
38+
IBM API Connect Essentials (StepZen).
5339

5440
## Getting Started
5541

56-
[Install](https://stepzen.com/docs/quick-start/install-and-setup) the StepZen command line interface.
57-
58-
To run these examples,
59-
60-
- `git clone` this repo
61-
- Change to the right working directory.
62-
- run `stepzen start`
63-
64-
## transforms
65-
66-
For more on what `transforms` is and how it operates within the custom `@rest` directive, [see our documentation](https://stepzen.com/docs/custom-graphql-directives/directives#transforms).
67-
68-
These are available in `/transforms`:
69-
70-
- `/filter` shows how the response of a REST API can be filtered
71-
- `/combineintostring` shows how a new field in the return type can be created by concatenating some other fields (like address parts into one address)
72-
- `/jsonobjectToJsonarray` shows how an array of data (say coords) can be converted into an object, `{"lat":, "lon",..}` so that it can be fed into some other system that requires data to be expressed that way
73-
- `/jsonobjectToJsonarray` shows how an object (typically where each key is an id of a record) can be converted into an array (e.g., `{"1":{"name": "john"}, "2": "jane"}` can be converted to `[{"id":"1", "name": "john"}, {"id":"2", name: "jane"}]`), so that it can then behave well for GraphQL processing.
74-
75-
## @sequence
76-
77-
View the StepZen [documentation](https://stepzen.com/docs/custom-graphql-directives/directives#-sequence) on the custom directive `@sequence`.
78-
79-
These are available in `/sequence`:
80-
81-
- `/arguments` shows how query arguments get passed down a sequence
82-
- `/forLoops` shows how sequence acts as a nested for loop
83-
- `/transformsInMaterializer` shows how connecting two subgraphs can invoke transformations in between. For example, the `city` of a customer can be fed into a `weather` that takes `lat,lon` by calling some geocoding in the sequence
84-
- `/useOfJSON` shows how, in long sequences, a new type does not have to created for every step--treat everything as JSON up to the last step, and your type system stays clean.
85-
86-
## @dbquery
87-
88-
View the documentation for the [`@dbquery` custom directive](https://www.ibm.com/docs/en/api-connect/ace/saas?topic=directives-directive-dbquery) in the documentation.
89-
90-
Uses a database filled with mock data.
91-
92-
- `/pagination` shows how to implement connection model pagination for a database.
93-
94-
## protection
42+
Sign up for a free API Connect Essentials SaaS plan: https://www.ibm.com/account/reg/us-en/signup?formid=urx-52542
9543

96-
For more information on protecting your API, [see our documentation](https://stepzen.com/docs/access-control).
44+
Read: [understanding API Connect Essentials (StepZen)](https://www.ibm.com/docs/en/api-connect/ace/saas?topic=understanding-api-connect-essentials)
9745

98-
In `/protection`, you will find several subdirectories. Each contains a `.graphql` file, and `index.graphql` file and a `config.yaml` settings (which enables you to get extremely granular (or coarse) with protecting who can call what query/mutation).
46+
[Install](https://www.ibm.com/docs/en/api-connect/ace/saas?topic=setting-up-your-environment#set-up-env__title__3) the StepZen command line interface.
9947

100-
- `/makeAllPublic` shows how you can easily make all queries public.
101-
- `/makeSomePublic` shows how you can make some public, and some private (which can still be accessed using your `admin` or `service` keys)
48+
Documentation: https://www.ibm.com/docs/en/api-connect/ace/saas
10249

103-
## @rest calls and responses
50+
## Snippets
10451

105-
Where possible, we use [httpbingo.org](https://httpbingo.org) as our REST endpoint, since it allows us to mimic lots of REST capabilities.
52+
The snippets are generally broken up into functional areas, with each folder covering a specific topic:
10653

107-
- `/restWithParameters` shows how GraphQL query arguments are automatically added to the REST call--there is nothing for you to do!
108-
- `/restWithConfigYaml` shows how REST query parameters can also be fetched from `config.yaml`--this allows you to keep your SDL code separate from your secrets.
109-
- `/postbody` shows how a POST body can be automatically filled with query arguments when the `Content-Type:application/x-www-form-urlencoded`. This is the easiest way to send postbodies down the REST API
110-
- `/morecomplexpost` shows how a POST body can be filled with query arguments using `{{.Get \"name-of-query-argument\"}}` when the `Content-Type:application/x-www-form-urlencoded`.
54+
### Custom Directives
11155

112-
## union types
56+
- [@dbquery](dbquery/README.md) - Use `@dbquery` for connecting to databases, including pagination and filtering.
57+
- [@materializer](materializer) - Use of `@materializer` to extend types by linking disparate backends into a single unified view.
58+
- @rest - Connects to REST APIs
59+
- [rest](rest/README.md) - Use of `@rest` for connecting to REST endpoints, including pagination.
60+
- [transforms](transforms/README.md) - How to transform REST API responses to match GraphQL types with `@rest`.
61+
- [@sequence](sequence/README.md) - Use of `@sequence` to resolve a field from multiple field resolutions, such as multiple backend calls.
62+
- @sdl
63+
- [executable](executable) - How GraphQL _executable documents_ can be registered and used with a schema or endpoint.
64+
- @supplies
65+
- [routing](routing)
66+
- @value
67+
- [value](value)
11368

114-
Union types are valuable when you have a field that can return one of several types.
69+
### General topics
11570

116-
- `/errorsAsData` shows how to implement the "errors as data" pattern. This is useful when you want to return a field that can return either a value or an error.
71+
- [pocs](pocs) - Techniques that can be used during development of proof of concepts with StepZen.
72+
- [protection](protection/README.md) - How to protect or expose GraphQL endpoints including field based access rules.
73+
- [reshape](reshape/README.md) - How to reshape GraphQL schema elements.
74+
- [unions](unions/README.md) - Uses of the GraphQL `union` type.
11775

11876
<!-- MARKDOWN LINKS & IMAGES -->
11977
<!-- https://www.markdownguide.org/basic-syntax/#reference-style-links -->

dbquery/README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# @dbquery
2+
3+
The custom directive `@dbquery` allows easy declarative inclusion of a database backend in a GraphQL schema.
4+
5+
GraphQL pagination and filtering are easily supported.
6+
7+
View the documentation for the [`@dbquery` custom directive](https://www.ibm.com/docs/en/api-connect/ace/saas?topic=directives-directive-dbquery) in the documentation.
8+
9+
Uses a database filled with mock data.
10+
11+
- [pagination](pagination) shows how to implement connection model pagination for a database.
12+
- [pings](pings) has snippets that can be deployed to see if connectivity to a database is setup correctly.

dbquery/custom-query/README.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
2+
# SQL Queries with `@dbquery`
3+
4+
This snippet demonstrates how to configure the `@dbquery` directive for custom SQL queries.
5+
6+
## Getting Started
7+
8+
[Install](https://www.ibm.com/docs/en/api-connect/ace/saas?topic=setting-up-your-environment) the StepZen command line interface.
9+
10+
To run these examples,
11+
12+
- `git clone` this repo
13+
- Change to the right working directory.
14+
- run `stepzen deploy`
15+
16+
This example uses a demo database filled with mock data, you can inspect the `config.yaml` file to find the credentials for this database. Also you can configure the connection in the `config.yaml` file by providing your database credentials.
17+
18+
Here’s a more generalized and specific description of the `@dbquery` directive functionality without referring to any particular data:
19+
20+
---
21+
22+
## The `@dbquery` Directive with SQL Query
23+
24+
The `@dbquery` directive in StepZen is used to connect your GraphQL API to databases and allows you to execute custom SQL queries within your schema. It supports various database types, such as MySQL, PostgreSQL, MSSQL, and Snowflake.
25+
26+
In this snippet, the `query` argument is used to define custom SQL queries for more control over the data being fetched. The functionality of the `query` argument allows for:
27+
28+
- Running complex SQL queries directly from GraphQL fields.
29+
- Retrieving data from specific columns or joining multiple tables based on your query requirements.
30+
- Filtering and querying data using SQL syntax when database field names or structures differ from the GraphQL schema.
31+
32+
The `query` argument provides the flexibility to write any SQL statement, while the **configuration** argument references the connection settings defined in the `config.yaml` file.
33+
34+
For example, a query may look like this:
35+
36+
```graphql
37+
@dbquery(
38+
query: "SELECT column1, column2 FROM your_table WHERE condition = $1",
39+
type: "postgresql",
40+
configuration: "your_config"
41+
)
42+
```
43+
44+
This allows you to fetch exactly the data you need, based on the custom SQL query provided. You can adjust the queries to match your database schema and use case.
45+
46+
## Try it Out!
47+
48+
Deploy the schema from `dbquery/custom-query` relative to the repository's root directory:
49+
50+
```
51+
stepzen deploy
52+
```
53+
54+
Run the [sample operations](operations.graphql):
55+
56+
- **Fetch all customers**:
57+
```
58+
stepzen request -f operations.graphql --operation-name=Customers
59+
```
60+
61+
- **Fetch a customer by ID**:
62+
```
63+
stepzen request -f operations.graphql --operation-name=Customer --var id=1
64+
```
65+

dbquery/custom-query/api.graphql

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# This example shows how @dbquery is configured for custom SQL queries with Customer data.
2+
3+
"""
4+
Represents a customer in the system, stored in the 'customer' table of a PostgreSQL database.
5+
Each customer has an ID, name, and email. The 'Customer' type maps directly to the
6+
corresponding table fields.
7+
"""
8+
type Customer {
9+
id: ID!
10+
name: String
11+
email: String
12+
}
13+
14+
"""
15+
Defines the root-level queries for fetching customer data.
16+
These queries use the `@dbquery` directive to execute custom SQL queries.
17+
The SQL queries include parameter markers, which correspond to the GraphQL field arguments.
18+
19+
The 'customer' table in PostgreSQL has the following structure:
20+
21+
CREATE TABLE customer (
22+
id SERIAL PRIMARY KEY, -- Unique identifier with sequence
23+
name CHARACTER(50) NOT NULL, -- Customer's name, max 50 characters
24+
email CHARACTER(50) NOT NULL, -- Customer's email, max 50 characters, must be unique
25+
CONSTRAINT customer_email_key UNIQUE (email) -- Unique constraint on email
26+
);
27+
These queries demonstrate basic SQL interactions with this table.
28+
"""
29+
type Query {
30+
"""
31+
Fetches a list of all customers from the database.
32+
33+
The custom SQL query retrieves the `id`, `name`, and `email` fields from the 'customer' table.
34+
35+
**@dbquery Directive Usage**:
36+
- `query`: This is the SQL query that will be executed. Here, it fetches all records from the 'customer' table.
37+
- `type`: Specifies the type of database being queried. In this case, it’s a PostgreSQL database.
38+
- `configuration`: References the database configuration (connection details) in StepZen.
39+
40+
This field does not take any arguments, and hence there are no parameter markers in the SQL query.
41+
The SQL query is static, always returning all customers from the database.
42+
"""
43+
customers: [Customer]
44+
@dbquery(
45+
query: "SELECT id, name, email FROM customer"
46+
type: "postgresql"
47+
configuration: "postgresql_config"
48+
)
49+
50+
"""
51+
Fetches a single customer by their ID from the database.
52+
53+
**Field Argument to Parameter Marker Mapping**:
54+
- Maps the `id` argument to the `$1` marker in the SQL query, allowing dynamic ID-based retrieval.
55+
- `$1` serves as a placeholder, which will be replaced by the provided `id` value during execution.
56+
57+
**@dbquery Directive Usage**:
58+
- `query`: This is the SQL query that will be executed. Here, the customer data is fetched based on the provided `id` value.
59+
- The `$1` marker is a placeholder for the value of the `id` argument, which is passed as a variable when executing the query.
60+
- `type`: Specifies the type of database being queried (PostgreSQL).
61+
- `configuration`: References the database configuration (connection details) in StepZen.
62+
63+
This field requires an `id` argument as input, which is passed as a variable from the GraphQL request. The variable's value is used to fetch the corresponding customer from the database.
64+
"""
65+
customer(id: Int!): Customer
66+
@dbquery(
67+
query: "SELECT id, name, email FROM customer WHERE id = $1"
68+
type: "postgresql"
69+
configuration: "postgresql_config"
70+
)
71+
}

dbquery/custom-query/config.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
configurationset:
2+
- configuration:
3+
name: postgresql_config
4+
uri: postgresql://postgresql.introspection.stepzen.net/introspection?user=testUserIntrospection&password=HurricaneStartingSample1934

dbquery/custom-query/index.graphql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
schema @sdl(files: ["api.graphql"]) {
2+
query: Query
3+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Retrieve a specific customer by ID using a variable
2+
query Customer($id: Int!) {
3+
customer(id: $id) {
4+
id
5+
name
6+
email
7+
}
8+
}
9+
10+
# Retrieve all customers in the system
11+
query Customers {
12+
customers {
13+
id
14+
name
15+
email
16+
}
17+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"endpoint": "api/miscellaneous"
3+
}
4+

dbquery/custom-query/tests/Test.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
const fs = require("fs");
2+
const path = require("node:path");
3+
const {
4+
deployAndRun,
5+
stepzen,
6+
getTestDescription,
7+
} = require("../../../tests/gqltest.js");
8+
9+
testDescription = getTestDescription("snippets", __dirname);
10+
11+
// Read the GraphQL operations from the operations file
12+
const requestsFile = path.join(path.dirname(__dirname), "operations.graphql");
13+
const requests = fs.readFileSync(requestsFile, "utf8").toString();
14+
15+
describe(testDescription, function () {
16+
17+
const tests = [
18+
{
19+
label: "fetch all customers",
20+
query: requests,
21+
operationName: "Customers",
22+
variables: {},
23+
expected: {
24+
customers: [
25+
{ id: "1", name: "Lucas Bill ", email: "[email protected] " },
26+
{ id: "2", name: "Mandy Jones ", email: "[email protected] " },
27+
{ id: "3", name: "Salim Ali ", email: "[email protected] " },
28+
{ id: "4", name: "Jane Xiu ", email: "[email protected] " },
29+
{ id: "5", name: "John Doe ", email: "[email protected] " },
30+
{ id: "6", name: "Jane Smith ", email: "[email protected] " },
31+
{ id: "7", name: "Sandeep Bhushan ", email: "[email protected] " },
32+
{ id: "8", name: "George Han ", email: "[email protected] " },
33+
{ id: "9", name: "Asha Kumari ", email: "[email protected] " },
34+
{ id: "10", name: "Salma Khan ", email: "[email protected] " }
35+
]
36+
},
37+
},
38+
{
39+
label: "fetch customer by ID",
40+
query: requests,
41+
operationName: "Customer",
42+
variables: {
43+
id: 1
44+
},
45+
expected: {
46+
customer: {
47+
id: "1",
48+
name: "Lucas Bill ",
49+
50+
}
51+
},
52+
},
53+
];
54+
55+
// Run the tests against the deployed schema
56+
return deployAndRun(__dirname, tests, stepzen.admin);
57+
});

pocs/README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Developing PoCs.
2+
3+
## Sharing
4+
5+
When developing a GraphQL PoC using IBM API Connect Essentials (StepZen) you will typically
6+
want to share the endpoint to allow others to evaluate it by making GraphQL requests against it.
7+
8+
### Admin key
9+
10+
> [!CAUTION]
11+
> Never share an endpoint by handing out the account's adminkey (`stepzen whoami --adminkey`).
12+
13+
### API key
14+
15+
The most simple (but somewhat risky) approach is to share the account's apikey (`stepzen whoami --apikey`).
16+
17+
> [!WARNING]
18+
> The admin key grants access to all endpoints within an account. Thus if you are working on different PoCs, by providing access to one you provide access to all
19+
> which could leak information between different departments or clients.
20+
21+
### Obfuscated endpoints
22+
23+
Obfuscated endpoints allow sharing without handing out any keys or tokens.
24+
25+
The concept can include single-use or short-lived endpoints for a demos, or time-limited evaluations.
26+
27+
> [!WARNING]
28+
> Obfuscated endpoints are public, but have a hard to guess endpoint URL so anyone with the URL has access to the API.
29+
30+
See [obfuscated-endpoint-url](obfuscated-endpoint-url/README.md)
31+
32+
### JWT
33+
34+
_Coming Soon_!

0 commit comments

Comments
 (0)