Skip to content

Commit

Permalink
Update documentation for withRequest (#8104)
Browse files Browse the repository at this point in the history
Co-authored-by: Josh Calder <josh.calder@thinkmill.com.au>
  • Loading branch information
dcousens and Josh Calder committed Nov 23, 2022
1 parent bbc2969 commit f22bbc7
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 29 deletions.
2 changes: 1 addition & 1 deletion .changeset/goodbye-busted-session.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
'@keystone-6/core': major
---

Removes `createContext`, `createRequestContext` - replace any relevant usage with `.sudo`, `.withSession` or `withRequest`
Removes `createContext`, `createRequestContext` - replace any relevant usage with `context.sudo()`, `context.withSession()` or `context.withRequest()`
27 changes: 10 additions & 17 deletions docs/pages/docs/config/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,8 @@ export default config({
maxFileSize: 200 * 1024 * 1024,
healthCheck: true,
{% if $nextRelease %}
extendExpressApp: (app, context) => { /* ... */ },
extendHttpServer: (httpServer, context, graphQLSchema) => { /* ... */ },
extendExpressApp: (app, commonContext) => { /* ... */ },
extendHttpServer: (httpServer, commonContext, graphQLSchema) => { /* ... */ },
{% else /%}
extendExpressApp: (app, createContext) => { /* ... */ },
extendHttpServer: (httpServer, createContext, graphQLSchema) => { /* ... */ },
Expand Down Expand Up @@ -276,7 +276,7 @@ The function is passed two arguments:
{% if $nextRelease %}
- `context`: A Keystone Context
{% else /%}
- `async createContext(req, res)`: A function you can call to create a Keystone Context for the request
- `async createRequestContext(req, res)`: A function you can call to create a Keystone Context for the request
{% /if %}

For example, you could add your own request logging middleware:
Expand Down Expand Up @@ -314,17 +314,17 @@ You could also use it to add custom REST endpoints to your server, by creating a
export default config({
server: {
{% if $nextRelease %}
extendExpressApp: (app, _context) => {
extendExpressApp: (app, commonContext) => {
app.get('/api/users', async (req, res) => {
const context = _context.withRequest(req, res);
const context = commonContext.withRequest(req, res);
const users = await context.query.User.findMany();
res.json(users);
});
},
{% else /%}
extendExpressApp: (app, createContext) => {
extendExpressApp: (app, createRequestContext) => {
app.get('/api/users', async (req, res) => {
const context = await createContext(req, res);
const context = await createRequestContext(req, res);
const users = await context.query.User.findMany();
res.json(users);
});
Expand All @@ -338,7 +338,7 @@ The created context will be bound to the request, including the current visitor'

_ProTip!_: `extendExpressApp` can be `async`

## extendHttpServer
### extendHttpServer

This lets you interact with the node [http.Server](https://nodejs.org/api/http.html#class-httpserver) that Keystone uses.

Expand All @@ -361,7 +361,7 @@ import { useServer as wsUseServer } from 'graphql-ws/lib/use/ws';
export default config({
server: {
{% if $nextRelease %}
extendHttpServer: (httpServer, context, graphqlSchema) => {
extendHttpServer: (httpServer, commonContext, graphqlSchema) => {
const wss = new WebSocketServer({
server: httpServer,
path: '/api/graphql',
Expand Down Expand Up @@ -394,18 +394,11 @@ import type { SessionStrategy } from '@keystone-6/core/types';
The `session` config option allows you to configure session management of your Keystone system.
It has a TypeScript type of `SessionStrategy<any>`.

{% if $nextRelease %}
In general you will use `SessionStrategy` objects from the `@keystone-6/auth/session` package, rather than writing this yourself.
{% else /%}
In general you will use `SessionStrategy` objects from the `@keystone-6/core/session` package, rather than writing this yourself.
{% /if %}


```typescript
{% if $nextRelease %}
import { statelessSessions } from '@keystone-6/auth/session';
{% else /%}
import { statelessSessions } from '@keystone-6/core/session';
{% /if %}

export default config({
session: statelessSessions({ /* ... */ }),
Expand Down
13 changes: 12 additions & 1 deletion docs/pages/docs/config/session.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,25 @@ Interface:

## Session context

If you configure your Keystone session with session management then the [`KeystoneContext`](../context/overview) type will include three session related properties.
If you configure your Keystone session with session management then the [`KeystoneContext`](../context/overview) type will include the following session related properties.

{% if $nextRelease %}
- `session`: An object representing the session data. The value will depend on the value passed into `context.sessionStrategy.start()`.
- `sessionStrategy`: an object that, when using `statelessSessions` or `storedSessions` from `@keystone-6/core/session` includes the following functions:
- `get({context})`: a function that returns a `session` object based on `context` - this needs to be a `context` with a valid `req` (using `context.withRequest`). This function is called by Keystone to get the value of `context.session`
- `start({context, data})`: a function that, given a valid `context.res` starts a new session containing what is passed into `data`.
- `end({context})`: a function that, given a valid `context.res` ends a session.

The `start` and `end` functions will be used by [authentication mutations](./auth) to start and end authenticated sessions.
These mutations will set the value of `session` to include the values `{ listKey, itemId }`.
{% else /%}
- `session`: An object representing the session data. The value will depend on the value passed into `context.startSession()`.
- `startSession`: A function `data => {...}` which will start a new session using the provided `data` value.
- `endSession`: A function `() => {...}` which will end the current session.

The `startSession` and `endSession` functions will be used by [authentication mutations](./auth) to start and end authenticated sessions.
These mutations will set the value of `session` to include the values `{ listKey, itemId }`.
{% /if %}

## Related resources

Expand Down
26 changes: 20 additions & 6 deletions docs/pages/docs/context/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,37 @@ import type { Context } from '.keystone/types';
context = {
// HTTP request object
req,
{% if $nextRelease %}
res,
{% /if %}

// Query API
query,

// Internal DB object API
db
db,

// GraphQL helpers
graphql: {
schema,
run,
raw,
};
},

// Session API
session,
{% if $nextRelease %}
sessionStrategy
{% else /%}
startSession,
endSession,
{% /if %}

// New context creators
sudo,
exitSudo,
withSession,
withRequest,

// Database access
prisma,
Expand All @@ -57,8 +65,10 @@ context = {

### HTTP request object

`req`: The [IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage) object from the HTTP request which called the GraphQL API.

`req`: The [IncomingMessage](https://nodejs.org/api/http.html#class-httpincomingmessage) object from the HTTP request.
{% if $nextRelease %}
`res`: The [ServerResonse](https://nodejs.org/api/http.html#class-httpserverresponse) object for HTTP request.
{% /if %}
### Query API

`query`: The [Query API](./query), which can be used to perform CRUD operations against your GraphQL API and return a queried value.
Expand Down Expand Up @@ -93,18 +103,22 @@ See the [session API](../config/session#session-context) for more details.

`session`: The current session data object.

{% if $nextRelease %}
`sessionStrategy`: an object containing functions(`get`, `start` and `end`) that manipulate a session. See the [session API](../config/session#session-context) for more details.
{% else /%}
`startSession`: An internal helper function used by authentication mutations to start a session on a successful login. This should not be called directly.

`endSession`: An internal helper function used by authentication mutations to end a session on logout. This should not be called directly.
{% /if %}

### New context creators

When using the `context.query`, `context.graphql.run`, and `context.graphql.raw` APIs, access control and session information is passed through to these calls from the `context` object.
The following functions will create a new `Context` object with this behaviour modified.

`sudo()`: A function which returns a new `Context` object with all access control disabled and all filters enabled for subsequent API calls.
`sudo()`: A function which returns a new elevated `Context` object with all access control disabled and all filters enabled for subsequent API calls.

`exitSudo()`: A function which returns a new `Context` object with all access control re-enabled for subsequent API calls.
`withRequest(req, res)`: A function which returns a new user `Context` object with a session and access control based on the `req` given.

`withSession(newSession)`: A function which returns a new `Context` object with the `.session` object replaced with `newSession`.

Expand Down
4 changes: 2 additions & 2 deletions examples/extend-graphql-subscriptions/websocket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ globalThis.graphqlSubscriptionPubSub = pubSub;

export const extendHttpServer = (
httpServer: http.Server,
_context: Context,
commonContext: Context,
graphqlSchema: KeystoneGraphQLAPI['schema']
): void => {
// Setup WebSocket server using 'ws'
Expand All @@ -34,7 +34,7 @@ export const extendHttpServer = (
schema: graphqlSchema,
// run these onSubscribe functions as needed or remove them if you don't need them
onSubscribe: async (ctx: any, msg) => {
const context = await _context.withRequest(ctx.extra.request);
const context = await commonContext.withRequest(ctx.extra.request);
// Return the execution args for this subscription passing through the Keystone Context
return {
schema: graphqlSchema,
Expand Down
4 changes: 2 additions & 2 deletions examples/rest-api/keystone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ export default config({
- Adds a GET handler for tasks, which will query for tasks in the
Keystone schema and return the results as JSON
*/
extendExpressApp: (app, context) => {
extendExpressApp: (app, commonContext) => {
app.use('/rest', async (req, res, next) => {
(req as any).context = await context.withRequest(req, res);
(req as any).context = await commonContext.withRequest(req, res);
next();
});

Expand Down

1 comment on commit f22bbc7

@vercel
Copy link

@vercel vercel bot commented on f22bbc7 Nov 23, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.