@opensaas/keystone-nextjs-auth 26.0.0 → 27.0.0

Sign up to get free protection for your applications and to get access to all the features.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @opensaas-keystone/nextjs-auth
2
2
 
3
+ ## 27.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - ec29144: Update dependency @keystone-6/core to v5
8
+
9
+ ### Patch Changes
10
+
11
+ - 0a8ea8e: Update patch dependencies (patch)
12
+
3
13
  ## 26.0.0
4
14
 
5
15
  ### Major Changes
@@ -75,17 +75,14 @@ function getBaseAuthSchema(_ref) {
75
75
  types: [base.object(listKey)],
76
76
  resolveType: (root, context) => {
77
77
  var _context$session;
78
-
79
78
  return (_context$session = context.session) === null || _context$session === void 0 ? void 0 : _context$session.listKey;
80
79
  }
81
80
  }),
82
-
83
81
  resolve(root, args, _ref2) {
84
82
  let {
85
83
  session,
86
84
  db
87
85
  } = _ref2;
88
-
89
86
  if (typeof (session === null || session === void 0 ? void 0 : session.itemId) === 'string' && typeof session.listKey === 'string') {
90
87
  return db[session.listKey].findOne({
91
88
  where: {
@@ -93,10 +90,8 @@ function getBaseAuthSchema(_ref) {
93
90
  }
94
91
  });
95
92
  }
96
-
97
93
  return null;
98
94
  }
99
-
100
95
  })
101
96
  }
102
97
  };
@@ -111,7 +106,6 @@ const getSchemaExtension = _ref => {
111
106
  } = _ref;
112
107
  return core.graphql.extend(base => {
113
108
  var _context;
114
-
115
109
  const baseSchema = getBaseAuthSchema({
116
110
  listKey,
117
111
  base
@@ -161,6 +155,7 @@ const authTemplate = _ref => {
161
155
  };
162
156
 
163
157
  const _excluded = ["get", "end"];
158
+
164
159
  /**
165
160
  * createAuth function
166
161
  *
@@ -184,6 +179,7 @@ function createAuth(_ref) {
184
179
  // part of the createAuth API (in which case its use cases need to be documented and tested)
185
180
  // or whether always being true is what we want, in which case we can refactor our code
186
181
  // to match this. -TL
182
+
187
183
  const customPath = !keystonePath || keystonePath === '/' ? '' : keystonePath;
188
184
  /**
189
185
  * pageMiddleware
@@ -195,29 +191,25 @@ function createAuth(_ref) {
195
191
  * - to the init page when initFirstItem is configured, and there are no user in the database
196
192
  * - to the signin page when no valid session is present
197
193
  */
198
-
199
194
  const authMiddleware = async _ref2 => {
200
195
  let {
201
196
  context,
202
- isValidSession
197
+ wasAccessAllowed
203
198
  } = _ref2;
204
199
  const {
205
200
  req,
206
201
  session
207
202
  } = context;
208
203
  const pathname = url__default["default"].parse(req === null || req === void 0 ? void 0 : req.url).pathname;
209
-
210
- if (isValidSession) {
204
+ if (wasAccessAllowed) {
211
205
  if (customPath !== '' && pathname === '/') {
212
206
  return {
213
207
  kind: 'redirect',
214
208
  to: `${customPath}`
215
209
  };
216
210
  }
217
-
218
211
  return;
219
212
  }
220
-
221
213
  if (!session && !_includesInstanceProperty__default["default"](pathname).call(pathname, `${customPath}/api/auth/`)) {
222
214
  return {
223
215
  kind: 'redirect',
@@ -225,6 +217,7 @@ function createAuth(_ref) {
225
217
  };
226
218
  }
227
219
  };
220
+
228
221
  /**
229
222
  * authGetAdditionalFiles
230
223
  *
@@ -233,8 +226,6 @@ function createAuth(_ref) {
233
226
  *
234
227
  * The signin page is always included, and the init page is included when initFirstItem is set
235
228
  */
236
-
237
-
238
229
  const authGetAdditionalFiles = () => {
239
230
  const filesToWrite = [{
240
231
  mode: 'write',
@@ -255,84 +246,75 @@ function createAuth(_ref) {
255
246
  }];
256
247
  return filesToWrite;
257
248
  };
249
+
258
250
  /**
259
251
  * publicAuthPages
260
252
  *
261
253
  * Must be added to the ui.publicPages config
262
254
  */
263
-
264
-
265
- const authPublicPages = [`${customPath}/api/auth/csrf`, `${customPath}/api/auth/signin`, `${customPath}/api/auth/callback`, `${customPath}/api/auth/session`, `${customPath}/api/auth/providers`, `${customPath}/api/auth/signout`, `${customPath}/api/auth/error`]; // TODO: Add Provider Types
255
+ const authPublicPages = [`${customPath}/api/auth/csrf`, `${customPath}/api/auth/signin`, `${customPath}/api/auth/callback`, `${customPath}/api/auth/session`, `${customPath}/api/auth/providers`, `${customPath}/api/auth/signout`, `${customPath}/api/auth/error`];
256
+ // TODO: Add Provider Types
266
257
  // @ts-ignore
267
-
268
258
  function addPages(provider) {
269
259
  const name = provider.id;
270
260
  authPublicPages.push(`${customPath}/api/auth/signin/${name}`);
271
261
  authPublicPages.push(`${customPath}/api/auth/callback/${name}`);
272
262
  }
273
-
274
263
  _mapInstanceProperty__default["default"](providers).call(providers, addPages);
264
+
275
265
  /**
276
266
  * extendGraphqlSchema
277
267
  *
278
268
  * Must be added to the extendGraphqlSchema config. Can be composed.
279
269
  */
280
-
281
-
282
270
  const extendGraphqlSchema = getSchemaExtension({
283
271
  identityField,
284
272
  listKey
285
273
  });
274
+
286
275
  /**
287
276
  * validateConfig
288
277
  *
289
278
  * Validates the provided auth config; optional step when integrating auth
290
279
  */
291
-
292
280
  const validateConfig = keystoneConfig => {
293
281
  const listConfig = keystoneConfig.lists[listKey];
294
-
295
282
  if (listConfig === undefined) {
296
283
  const msg = `A createAuth() invocation specifies the list "${listKey}" but no list with that key has been defined.`;
297
284
  throw new Error(msg);
298
- } // TODO: Check if providers
285
+ }
286
+
287
+ // TODO: Check if providers
299
288
  // TODO: Check other required commands/data
289
+
300
290
  // TODO: Check for String-like typing for identityField? How?
301
291
  // TODO: Validate that the identifyField is unique.
302
292
  // TODO: If this field isn't required, what happens if I try to log in as `null`?
303
-
304
-
305
293
  const identityFieldConfig = listConfig.fields[identityField];
306
-
307
294
  if (identityFieldConfig === undefined) {
308
295
  const identityFieldName = _JSON$stringify__default["default"](identityField);
309
-
310
296
  const msg = `A createAuth() invocation for the "${listKey}" list specifies ${identityFieldName} as its identityField but no field with that key exists on the list.`;
311
297
  throw new Error(msg);
312
298
  }
313
299
  };
300
+
314
301
  /**
315
302
  * withItemData
316
303
  *
317
304
  * Automatically injects a session.data value with the authenticated item
318
305
  */
319
-
320
306
  /* TODO:
321
307
  - [ ] We could support additional where input to validate item sessions (e.g an isEnabled boolean)
322
308
  */
323
-
324
-
325
309
  const withItemData = _sessionStrategy => {
326
310
  const {
327
- get,
328
- end
329
- } = _sessionStrategy,
330
- sessionStrategy = _objectWithoutProperties(_sessionStrategy, _excluded);
331
-
311
+ get,
312
+ end
313
+ } = _sessionStrategy,
314
+ sessionStrategy = _objectWithoutProperties(_sessionStrategy, _excluded);
332
315
  return _objectSpread(_objectSpread({}, sessionStrategy), {}, {
333
316
  get: async _ref3 => {
334
317
  var _req$headers, _req$headers$authoriz;
335
-
336
318
  let {
337
319
  context
338
320
  } = _ref3;
@@ -342,13 +324,10 @@ function createAuth(_ref) {
342
324
  const pathname = url__default["default"].parse(req === null || req === void 0 ? void 0 : req.url).pathname;
343
325
  let nextSession;
344
326
  if (!req) return;
345
-
346
327
  if (_includesInstanceProperty__default["default"](pathname).call(pathname, '/api/auth')) {
347
328
  return;
348
329
  }
349
-
350
330
  const sudoContext = context.sudo();
351
-
352
331
  if (((_req$headers = req.headers) === null || _req$headers === void 0 ? void 0 : (_req$headers$authoriz = _req$headers.authorization) === null || _req$headers$authoriz === void 0 ? void 0 : _req$headers$authoriz.split(' ')[0]) === 'Bearer') {
353
332
  nextSession = await jwt.getToken({
354
333
  req: req,
@@ -359,11 +338,9 @@ function createAuth(_ref) {
359
338
  req
360
339
  });
361
340
  }
362
-
363
341
  if (!nextSession || !nextSession.listKey || nextSession.listKey !== listKey || !nextSession.itemId || !sudoContext.query[listKey] || !nextSession.itemId) {
364
342
  return;
365
343
  }
366
-
367
344
  const reqWithUser = req;
368
345
  reqWithUser.user = {
369
346
  istKey: nextSession.listKey,
@@ -405,7 +382,6 @@ function createAuth(_ref) {
405
382
  }
406
383
  });
407
384
  };
408
-
409
385
  function defaultIsAccessAllowed(_ref5) {
410
386
  let {
411
387
  session
@@ -422,16 +398,12 @@ function createAuth(_ref) {
422
398
  * It validates the auth config against the provided keystone config, and preserves existing
423
399
  * config by composing existing extendGraphqlSchema functions and ui config.
424
400
  */
425
-
426
-
427
401
  const withAuth = keystoneConfig => {
428
402
  var _ui;
429
-
430
403
  validateConfig(keystoneConfig);
431
404
  let {
432
405
  ui
433
406
  } = keystoneConfig;
434
-
435
407
  if (!((_ui = ui) !== null && _ui !== void 0 && _ui.isDisabled)) {
436
408
  const {
437
409
  getAdditionalFiles = [],
@@ -443,13 +415,10 @@ function createAuth(_ref) {
443
415
  publicPages: [...publicPages, ...authPublicPages],
444
416
  isAccessAllowed: async context => {
445
417
  var _context$req;
446
-
447
418
  const pathname = url__default["default"].parse((_context$req = context.req) === null || _context$req === void 0 ? void 0 : _context$req.url).pathname;
448
-
449
419
  if (_startsWithInstanceProperty__default["default"](pathname).call(pathname, `${customPath}/_next`) || _startsWithInstanceProperty__default["default"](pathname).call(pathname, `${customPath}/__next`) || _startsWithInstanceProperty__default["default"](pathname).call(pathname, `${customPath}/api/auth/`) || pages !== null && pages !== void 0 && pages.signIn && _includesInstanceProperty__default["default"](pathname).call(pathname, pages === null || pages === void 0 ? void 0 : pages.signIn) || pages !== null && pages !== void 0 && pages.error && _includesInstanceProperty__default["default"](pathname).call(pathname, pages === null || pages === void 0 ? void 0 : pages.error) || pages !== null && pages !== void 0 && pages.signOut && _includesInstanceProperty__default["default"](pathname).call(pathname, pages === null || pages === void 0 ? void 0 : pages.signOut)) {
450
420
  return true;
451
421
  }
452
-
453
422
  return await isAccessAllowed(context);
454
423
  },
455
424
  getAdditionalFiles: [...getAdditionalFiles, authGetAdditionalFiles],
@@ -460,7 +429,6 @@ function createAuth(_ref) {
460
429
  }
461
430
  });
462
431
  }
463
-
464
432
  if (!keystoneConfig.session) throw new TypeError('Missing .session configuration');
465
433
  const session = withItemData(keystoneConfig.session);
466
434
  const existingExtendGraphQLSchema = keystoneConfig.extendGraphqlSchema;
@@ -475,16 +443,15 @@ function createAuth(_ref) {
475
443
  extendGraphqlSchema: existingExtendGraphQLSchema ? schema => existingExtendGraphQLSchema(extendGraphqlSchema(schema)) : extendGraphqlSchema
476
444
  });
477
445
  };
478
-
479
446
  return {
480
- withAuth // In the future we may want to return the following so that developers can
447
+ withAuth
448
+ // In the future we may want to return the following so that developers can
481
449
  // roll their own. This is pending a review of the use cases this might be
482
450
  // appropriate for, along with documentation and testing.
483
451
  // ui: { enableSessionItem: true, pageMiddleware, getAdditionalFiles, publicPages },
484
452
  // fields,
485
453
  // extendGraphqlSchema,
486
454
  // validateConfig,
487
-
488
455
  };
489
456
  }
490
457
 
@@ -75,17 +75,14 @@ function getBaseAuthSchema(_ref) {
75
75
  types: [base.object(listKey)],
76
76
  resolveType: (root, context) => {
77
77
  var _context$session;
78
-
79
78
  return (_context$session = context.session) === null || _context$session === void 0 ? void 0 : _context$session.listKey;
80
79
  }
81
80
  }),
82
-
83
81
  resolve(root, args, _ref2) {
84
82
  let {
85
83
  session,
86
84
  db
87
85
  } = _ref2;
88
-
89
86
  if (typeof (session === null || session === void 0 ? void 0 : session.itemId) === 'string' && typeof session.listKey === 'string') {
90
87
  return db[session.listKey].findOne({
91
88
  where: {
@@ -93,10 +90,8 @@ function getBaseAuthSchema(_ref) {
93
90
  }
94
91
  });
95
92
  }
96
-
97
93
  return null;
98
94
  }
99
-
100
95
  })
101
96
  }
102
97
  };
@@ -111,7 +106,6 @@ const getSchemaExtension = _ref => {
111
106
  } = _ref;
112
107
  return core.graphql.extend(base => {
113
108
  var _context;
114
-
115
109
  const baseSchema = getBaseAuthSchema({
116
110
  listKey,
117
111
  base
@@ -161,6 +155,7 @@ const authTemplate = _ref => {
161
155
  };
162
156
 
163
157
  const _excluded = ["get", "end"];
158
+
164
159
  /**
165
160
  * createAuth function
166
161
  *
@@ -184,6 +179,7 @@ function createAuth(_ref) {
184
179
  // part of the createAuth API (in which case its use cases need to be documented and tested)
185
180
  // or whether always being true is what we want, in which case we can refactor our code
186
181
  // to match this. -TL
182
+
187
183
  const customPath = !keystonePath || keystonePath === '/' ? '' : keystonePath;
188
184
  /**
189
185
  * pageMiddleware
@@ -195,29 +191,25 @@ function createAuth(_ref) {
195
191
  * - to the init page when initFirstItem is configured, and there are no user in the database
196
192
  * - to the signin page when no valid session is present
197
193
  */
198
-
199
194
  const authMiddleware = async _ref2 => {
200
195
  let {
201
196
  context,
202
- isValidSession
197
+ wasAccessAllowed
203
198
  } = _ref2;
204
199
  const {
205
200
  req,
206
201
  session
207
202
  } = context;
208
203
  const pathname = url__default["default"].parse(req === null || req === void 0 ? void 0 : req.url).pathname;
209
-
210
- if (isValidSession) {
204
+ if (wasAccessAllowed) {
211
205
  if (customPath !== '' && pathname === '/') {
212
206
  return {
213
207
  kind: 'redirect',
214
208
  to: `${customPath}`
215
209
  };
216
210
  }
217
-
218
211
  return;
219
212
  }
220
-
221
213
  if (!session && !_includesInstanceProperty__default["default"](pathname).call(pathname, `${customPath}/api/auth/`)) {
222
214
  return {
223
215
  kind: 'redirect',
@@ -225,6 +217,7 @@ function createAuth(_ref) {
225
217
  };
226
218
  }
227
219
  };
220
+
228
221
  /**
229
222
  * authGetAdditionalFiles
230
223
  *
@@ -233,8 +226,6 @@ function createAuth(_ref) {
233
226
  *
234
227
  * The signin page is always included, and the init page is included when initFirstItem is set
235
228
  */
236
-
237
-
238
229
  const authGetAdditionalFiles = () => {
239
230
  const filesToWrite = [{
240
231
  mode: 'write',
@@ -255,84 +246,75 @@ function createAuth(_ref) {
255
246
  }];
256
247
  return filesToWrite;
257
248
  };
249
+
258
250
  /**
259
251
  * publicAuthPages
260
252
  *
261
253
  * Must be added to the ui.publicPages config
262
254
  */
263
-
264
-
265
- const authPublicPages = [`${customPath}/api/auth/csrf`, `${customPath}/api/auth/signin`, `${customPath}/api/auth/callback`, `${customPath}/api/auth/session`, `${customPath}/api/auth/providers`, `${customPath}/api/auth/signout`, `${customPath}/api/auth/error`]; // TODO: Add Provider Types
255
+ const authPublicPages = [`${customPath}/api/auth/csrf`, `${customPath}/api/auth/signin`, `${customPath}/api/auth/callback`, `${customPath}/api/auth/session`, `${customPath}/api/auth/providers`, `${customPath}/api/auth/signout`, `${customPath}/api/auth/error`];
256
+ // TODO: Add Provider Types
266
257
  // @ts-ignore
267
-
268
258
  function addPages(provider) {
269
259
  const name = provider.id;
270
260
  authPublicPages.push(`${customPath}/api/auth/signin/${name}`);
271
261
  authPublicPages.push(`${customPath}/api/auth/callback/${name}`);
272
262
  }
273
-
274
263
  _mapInstanceProperty__default["default"](providers).call(providers, addPages);
264
+
275
265
  /**
276
266
  * extendGraphqlSchema
277
267
  *
278
268
  * Must be added to the extendGraphqlSchema config. Can be composed.
279
269
  */
280
-
281
-
282
270
  const extendGraphqlSchema = getSchemaExtension({
283
271
  identityField,
284
272
  listKey
285
273
  });
274
+
286
275
  /**
287
276
  * validateConfig
288
277
  *
289
278
  * Validates the provided auth config; optional step when integrating auth
290
279
  */
291
-
292
280
  const validateConfig = keystoneConfig => {
293
281
  const listConfig = keystoneConfig.lists[listKey];
294
-
295
282
  if (listConfig === undefined) {
296
283
  const msg = `A createAuth() invocation specifies the list "${listKey}" but no list with that key has been defined.`;
297
284
  throw new Error(msg);
298
- } // TODO: Check if providers
285
+ }
286
+
287
+ // TODO: Check if providers
299
288
  // TODO: Check other required commands/data
289
+
300
290
  // TODO: Check for String-like typing for identityField? How?
301
291
  // TODO: Validate that the identifyField is unique.
302
292
  // TODO: If this field isn't required, what happens if I try to log in as `null`?
303
-
304
-
305
293
  const identityFieldConfig = listConfig.fields[identityField];
306
-
307
294
  if (identityFieldConfig === undefined) {
308
295
  const identityFieldName = _JSON$stringify__default["default"](identityField);
309
-
310
296
  const msg = `A createAuth() invocation for the "${listKey}" list specifies ${identityFieldName} as its identityField but no field with that key exists on the list.`;
311
297
  throw new Error(msg);
312
298
  }
313
299
  };
300
+
314
301
  /**
315
302
  * withItemData
316
303
  *
317
304
  * Automatically injects a session.data value with the authenticated item
318
305
  */
319
-
320
306
  /* TODO:
321
307
  - [ ] We could support additional where input to validate item sessions (e.g an isEnabled boolean)
322
308
  */
323
-
324
-
325
309
  const withItemData = _sessionStrategy => {
326
310
  const {
327
- get,
328
- end
329
- } = _sessionStrategy,
330
- sessionStrategy = _objectWithoutProperties(_sessionStrategy, _excluded);
331
-
311
+ get,
312
+ end
313
+ } = _sessionStrategy,
314
+ sessionStrategy = _objectWithoutProperties(_sessionStrategy, _excluded);
332
315
  return _objectSpread(_objectSpread({}, sessionStrategy), {}, {
333
316
  get: async _ref3 => {
334
317
  var _req$headers, _req$headers$authoriz;
335
-
336
318
  let {
337
319
  context
338
320
  } = _ref3;
@@ -342,13 +324,10 @@ function createAuth(_ref) {
342
324
  const pathname = url__default["default"].parse(req === null || req === void 0 ? void 0 : req.url).pathname;
343
325
  let nextSession;
344
326
  if (!req) return;
345
-
346
327
  if (_includesInstanceProperty__default["default"](pathname).call(pathname, '/api/auth')) {
347
328
  return;
348
329
  }
349
-
350
330
  const sudoContext = context.sudo();
351
-
352
331
  if (((_req$headers = req.headers) === null || _req$headers === void 0 ? void 0 : (_req$headers$authoriz = _req$headers.authorization) === null || _req$headers$authoriz === void 0 ? void 0 : _req$headers$authoriz.split(' ')[0]) === 'Bearer') {
353
332
  nextSession = await jwt.getToken({
354
333
  req: req,
@@ -359,11 +338,9 @@ function createAuth(_ref) {
359
338
  req
360
339
  });
361
340
  }
362
-
363
341
  if (!nextSession || !nextSession.listKey || nextSession.listKey !== listKey || !nextSession.itemId || !sudoContext.query[listKey] || !nextSession.itemId) {
364
342
  return;
365
343
  }
366
-
367
344
  const reqWithUser = req;
368
345
  reqWithUser.user = {
369
346
  istKey: nextSession.listKey,
@@ -405,7 +382,6 @@ function createAuth(_ref) {
405
382
  }
406
383
  });
407
384
  };
408
-
409
385
  function defaultIsAccessAllowed(_ref5) {
410
386
  let {
411
387
  session
@@ -422,16 +398,12 @@ function createAuth(_ref) {
422
398
  * It validates the auth config against the provided keystone config, and preserves existing
423
399
  * config by composing existing extendGraphqlSchema functions and ui config.
424
400
  */
425
-
426
-
427
401
  const withAuth = keystoneConfig => {
428
402
  var _ui;
429
-
430
403
  validateConfig(keystoneConfig);
431
404
  let {
432
405
  ui
433
406
  } = keystoneConfig;
434
-
435
407
  if (!((_ui = ui) !== null && _ui !== void 0 && _ui.isDisabled)) {
436
408
  const {
437
409
  getAdditionalFiles = [],
@@ -443,13 +415,10 @@ function createAuth(_ref) {
443
415
  publicPages: [...publicPages, ...authPublicPages],
444
416
  isAccessAllowed: async context => {
445
417
  var _context$req;
446
-
447
418
  const pathname = url__default["default"].parse((_context$req = context.req) === null || _context$req === void 0 ? void 0 : _context$req.url).pathname;
448
-
449
419
  if (_startsWithInstanceProperty__default["default"](pathname).call(pathname, `${customPath}/_next`) || _startsWithInstanceProperty__default["default"](pathname).call(pathname, `${customPath}/__next`) || _startsWithInstanceProperty__default["default"](pathname).call(pathname, `${customPath}/api/auth/`) || pages !== null && pages !== void 0 && pages.signIn && _includesInstanceProperty__default["default"](pathname).call(pathname, pages === null || pages === void 0 ? void 0 : pages.signIn) || pages !== null && pages !== void 0 && pages.error && _includesInstanceProperty__default["default"](pathname).call(pathname, pages === null || pages === void 0 ? void 0 : pages.error) || pages !== null && pages !== void 0 && pages.signOut && _includesInstanceProperty__default["default"](pathname).call(pathname, pages === null || pages === void 0 ? void 0 : pages.signOut)) {
450
420
  return true;
451
421
  }
452
-
453
422
  return await isAccessAllowed(context);
454
423
  },
455
424
  getAdditionalFiles: [...getAdditionalFiles, authGetAdditionalFiles],
@@ -460,7 +429,6 @@ function createAuth(_ref) {
460
429
  }
461
430
  });
462
431
  }
463
-
464
432
  if (!keystoneConfig.session) throw new TypeError('Missing .session configuration');
465
433
  const session = withItemData(keystoneConfig.session);
466
434
  const existingExtendGraphQLSchema = keystoneConfig.extendGraphqlSchema;
@@ -475,16 +443,15 @@ function createAuth(_ref) {
475
443
  extendGraphqlSchema: existingExtendGraphQLSchema ? schema => existingExtendGraphQLSchema(extendGraphqlSchema(schema)) : extendGraphqlSchema
476
444
  });
477
445
  };
478
-
479
446
  return {
480
- withAuth // In the future we may want to return the following so that developers can
447
+ withAuth
448
+ // In the future we may want to return the following so that developers can
481
449
  // roll their own. This is pending a review of the use cases this might be
482
450
  // appropriate for, along with documentation and testing.
483
451
  // ui: { enableSessionItem: true, pageMiddleware, getAdditionalFiles, publicPages },
484
452
  // fields,
485
453
  // extendGraphqlSchema,
486
454
  // validateConfig,
487
-
488
455
  };
489
456
  }
490
457