@opensaas/keystone-nextjs-auth 20.5.0 → 21.1.1

Sign up to get free protection for your applications and to get access to all the features.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # @opensaas-keystone/nextjs-auth
2
2
 
3
+ ## 21.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - e48cb6c: Fix signin redirect error
8
+
9
+ ## 21.1.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 9d35d01: Patch dependancies
14
+ - 4a593d7: dependancy updates
15
+
16
+ ## 21.0.0
17
+
18
+ ### Major Changes
19
+
20
+ - 4119c1c: Add ability to configure custom pages use `pages` configuration
21
+ - 4119c1c: Move `userMap` `accountMap` and `userMap` into a resolver function - `resolver` function takes in `{user,account,profile}` and returns a object that is passed in to create the identity
22
+
3
23
  ## 20.5.0
4
24
 
5
25
  ### Minor Changes
package/README.md CHANGED
@@ -44,9 +44,11 @@ const auth = createAuth({
44
44
  identityField: 'subjectId',
45
45
  sessionData: `id name email`,
46
46
  autoCreate: true,
47
- userMap: { subjectId: 'id', name: 'name' },
48
- accountMap: {},
49
- profileMap: { email: 'email' },
47
+ resolver: async ({user, profile, account}) => {
48
+ const username = user.name as string;
49
+ const email = user.email as string;
50
+ return { email, username };
51
+ },
50
52
  keystonePath: '/admin',
51
53
  sessionSecret,
52
54
  providers: [
@@ -1,9 +1,7 @@
1
1
  import type { BaseItem } from '@keystone-6/core/types';
2
2
  import { graphql } from '@keystone-6/core';
3
- import { AuthGqlNames } from '../types';
4
- export declare function getBaseAuthSchema({ listKey, gqlNames, base, }: {
3
+ export declare function getBaseAuthSchema({ listKey, base, }: {
5
4
  listKey: string;
6
- gqlNames: AuthGqlNames;
7
5
  base: graphql.BaseSchemaMeta;
8
6
  }): {
9
7
  extension: {
@@ -1,11 +1,11 @@
1
- import { BaseListTypeInfo, KeystoneConfig } from '@keystone-6/core/types';
2
- import { AuthConfig, KeystoneAuthConfig } from './types';
1
+ import { BaseListTypeInfo, KeystoneConfig } from "@keystone-6/core/types";
2
+ import { AuthConfig, KeystoneOAuthConfig } from "./types";
3
3
  /**
4
4
  * createAuth function
5
5
  *
6
6
  * Generates config for Keystone to implement standard auth features.
7
7
  */
8
- export type { NextAuthProviders, KeystoneAuthConfig } from './types';
9
- export declare function createAuth<GeneratedListTypes extends BaseListTypeInfo>({ listKey, identityField, sessionData, autoCreate, userMap, accountMap, profileMap, keystonePath, providers, sessionSecret, }: AuthConfig<GeneratedListTypes>): {
10
- withAuth: (keystoneConfig: KeystoneConfig) => KeystoneAuthConfig;
8
+ export type { NextAuthProviders, KeystoneOAuthConfig } from "./types";
9
+ export declare function createAuth<GeneratedListTypes extends BaseListTypeInfo>({ autoCreate, cookies, identityField, listKey, keystonePath, pages, resolver, providers, sessionData, sessionSecret, }: AuthConfig<GeneratedListTypes>): {
10
+ withAuth: (keystoneConfig: KeystoneConfig) => KeystoneOAuthConfig;
11
11
  };
@@ -1,18 +1,25 @@
1
+ import { CookiesOptions, EventCallbacks, PagesOptions } from 'next-auth';
1
2
  import type { KeystoneListsAPI } from '@keystone-6/core/types';
2
3
  import { Provider } from 'next-auth/providers';
3
- declare type NextAuthPageProps = {
4
+ import { JWTOptions } from 'next-auth/jwt';
5
+ declare type CoreNextAuthPageProps = {
6
+ autoCreate: boolean;
7
+ cookies?: Partial<CookiesOptions>;
8
+ events?: Partial<EventCallbacks>;
4
9
  identityField: string;
5
- mutationName: string;
6
- providers: Provider[];
7
- query: KeystoneListsAPI<any>;
8
- sessionData: string;
10
+ jwt?: Partial<JWTOptions>;
9
11
  listKey: string;
10
- autoCreate: boolean;
11
- userMap: any;
12
- accountMap: any;
13
- profileMap: any;
12
+ pages?: Partial<PagesOptions>;
13
+ providers?: Provider[];
14
+ resolver?: Function | undefined;
15
+ sessionData: string | undefined;
14
16
  sessionSecret: string;
15
17
  };
18
+ declare type NextAuthGglProps = {
19
+ mutationName?: string;
20
+ query?: KeystoneListsAPI<any>;
21
+ };
22
+ export declare type NextAuthPageProps = CoreNextAuthPageProps & NextAuthGglProps;
16
23
  export default function NextAuthPage(props: NextAuthPageProps): any;
17
24
  export declare const getNextAuthPage: (props: NextAuthPageProps) => () => any;
18
25
  export {};
@@ -1,7 +1,5 @@
1
1
  import { ExtendGraphqlSchema } from '@keystone-6/core/types';
2
- import { AuthGqlNames } from './types';
3
- export declare const getSchemaExtension: ({ identityField, listKey, gqlNames, }: {
2
+ export declare const getSchemaExtension: ({ listKey, }: {
4
3
  identityField: string;
5
4
  listKey: string;
6
- gqlNames: AuthGqlNames;
7
5
  }) => ExtendGraphqlSchema;
@@ -1,12 +1,4 @@
1
- import { AuthGqlNames } from '../types';
2
- export declare const authTemplate: ({ gqlNames, identityField, sessionData, listKey, autoCreate, userMap, accountMap, profileMap, sessionSecret, }: {
3
- gqlNames: AuthGqlNames;
4
- identityField: string;
5
- sessionData: any;
6
- listKey: string;
7
- autoCreate: boolean;
8
- userMap: any;
9
- accountMap: any;
10
- profileMap: any;
11
- sessionSecret: string;
12
- }) => string;
1
+ import { NextAuthPageProps } from '../pages/NextAuthPage';
2
+ declare type AuthTemplateOptions = NextAuthPageProps;
3
+ export declare const authTemplate: ({ autoCreate, identityField, listKey, sessionData, sessionSecret, }: AuthTemplateOptions) => string;
4
+ export {};
@@ -1,42 +1,39 @@
1
1
  import { BaseListTypeInfo, KeystoneConfig } from '@keystone-6/core/types';
2
+ import { CookiesOptions, PagesOptions } from 'next-auth';
2
3
  import { Provider } from 'next-auth/providers';
3
- export declare type AuthGqlNames = {
4
- CreateInitialInput: string;
5
- createInitialItem: string;
6
- authenticateItemWithPassword: string;
7
- ItemAuthenticationWithPasswordResult: string;
8
- ItemAuthenticationWithPasswordSuccess: string;
9
- ItemAuthenticationWithPasswordFailure: string;
10
- };
11
4
  export declare type NextAuthSession = {
12
5
  listKey: string;
13
6
  itemId: string;
14
7
  data: any;
15
8
  };
16
9
  export declare type NextAuthProviders = Provider[];
17
- declare type KeytoneAuthProviders = {
10
+ declare type KeytoneOAuthOptions = {
18
11
  providers: NextAuthProviders;
12
+ pages?: Partial<PagesOptions>;
13
+ };
14
+ declare type NextAuthOptions = {
15
+ cookies?: Partial<CookiesOptions>;
16
+ resolver: any;
19
17
  };
20
- export declare type KeystoneAuthConfig = KeystoneConfig & KeytoneAuthProviders;
18
+ export declare type KeystoneOAuthConfig = KeystoneConfig & KeytoneOAuthOptions & NextAuthOptions;
21
19
  export declare type AuthConfig<GeneratedListTypes extends BaseListTypeInfo> = {
20
+ /** Auth Create users in Keystone DB from Auth Provider */
21
+ autoCreate: boolean;
22
+ /** Adds ability to customize cookie options, for example, to facilitate cross-subdomain functionality */
23
+ cookies?: Partial<CookiesOptions>;
22
24
  /** The key of the list to authenticate users with */
23
25
  listKey: GeneratedListTypes['key'];
24
26
  /** The path of the field the identity is stored in; must be text-ish */
25
27
  identityField: GeneratedListTypes['fields'];
26
- /** Session data population */
27
- sessionData?: string;
28
- /** Auth Create users in Keystone DB from Auth Provider */
29
- autoCreate: boolean;
30
- /** Map User in next-auth to item */
31
- userMap: any;
32
- /** Map Account in next-auth to item */
33
- accountMap: any;
34
- /** Map Profile in next-auth to item */
35
- profileMap: any;
36
28
  /** Path for Keystone interface */
37
29
  keystonePath?: string;
30
+ pages?: any;
38
31
  /** Providers for Next Auth */
39
32
  providers: NextAuthProviders;
33
+ /** Resolver for user to define their profile */
34
+ resolver?: Function | undefined;
35
+ /** Session data population */
36
+ sessionData?: string | undefined;
40
37
  /** Next-Auth Session Secret */
41
38
  sessionSecret: string;
42
39
  };
@@ -14,7 +14,6 @@ var jwt = require('next-auth/jwt');
14
14
  var cookie = require('cookie');
15
15
  var ejs = require('ejs');
16
16
  var _filterInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/filter');
17
- var graphql = require('graphql');
18
17
  var core = require('@keystone-6/core');
19
18
 
20
19
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
@@ -55,6 +54,9 @@ module.exports = withPreconstruct({
55
54
  typescript: {
56
55
  ignoreBuildErrors: true,
57
56
  },
57
+ env: {
58
+ NEXTAUTH_URL: process.env.NEXTAUTH_URL || 'http://localhost:<%= process.env.PORT || 3000 %><%= keystonePath || '' %>/api/auth',
59
+ },
58
60
  eslint: {
59
61
  ignoreDuringBuilds: true,
60
62
  },
@@ -110,7 +112,6 @@ const nextConfigTemplate = ({
110
112
 
111
113
  function getBaseAuthSchema({
112
114
  listKey,
113
- gqlNames,
114
115
  base
115
116
  }) {
116
117
  const extension = {
@@ -150,22 +151,12 @@ function getBaseAuthSchema({
150
151
  }
151
152
 
152
153
  const getSchemaExtension = ({
153
- identityField,
154
- listKey,
155
- gqlNames
154
+ listKey
156
155
  }) => core.graphql.extend(base => {
157
156
  var _context;
158
157
 
159
- const uniqueWhereInputType = graphql.assertInputObjectType(base.schema.getType(`${listKey}WhereUniqueInput`));
160
- const identityFieldOnUniqueWhere = uniqueWhereInputType.getFields()[identityField];
161
-
162
- if ((identityFieldOnUniqueWhere === null || identityFieldOnUniqueWhere === void 0 ? void 0 : identityFieldOnUniqueWhere.type) !== graphql.GraphQLString && (identityFieldOnUniqueWhere === null || identityFieldOnUniqueWhere === void 0 ? void 0 : identityFieldOnUniqueWhere.type) !== graphql.GraphQLID) {
163
- throw new Error(`createAuth was called with an identityField of ${identityField} on the list ${listKey} ` + `but that field doesn't allow being searched uniquely with a String or ID. ` + `You should likely add \`isIndexed: 'unique'\` ` + `to the field at ${listKey}.${identityField}`);
164
- }
165
-
166
158
  const baseSchema = getBaseAuthSchema({
167
159
  listKey,
168
- gqlNames,
169
160
  base
170
161
  });
171
162
  return _filterInstanceProperty__default["default"](_context = [baseSchema.extension]).call(_context, x => x !== undefined);
@@ -177,38 +168,29 @@ import { query } from '.keystone/api';
177
168
  import keystoneConfig from '../../../../../keystone';
178
169
 
179
170
  export default getNextAuthPage({
171
+ autoCreate: <%= autoCreate %>,
180
172
  identityField: '<%= identityField %>',
181
- sessionData: '<%= sessionData %>',
182
173
  listKey: '<%= listKey %>',
183
- userMap: <%- JSON.stringify(userMap) %>,
184
- accountMap: <%- JSON.stringify(accountMap) %>,
185
- profileMap: <%- JSON.stringify(profileMap) %>,
186
- autoCreate: <%= autoCreate %>,
187
- sessionSecret: '<%= sessionSecret %>',
174
+ pages: keystoneConfig.pages,
188
175
  providers: keystoneConfig.providers,
189
176
  query,
177
+ resolver: keystoneConfig.resolver,
178
+ sessionData: '<%= sessionData %>',
179
+ sessionSecret: '<%= sessionSecret %>',
190
180
  });
191
181
  `;
192
182
  const authTemplate = ({
193
- gqlNames,
183
+ autoCreate,
194
184
  identityField,
195
- sessionData,
196
185
  listKey,
197
- autoCreate,
198
- userMap,
199
- accountMap,
200
- profileMap,
186
+ sessionData,
201
187
  sessionSecret
202
188
  }) => {
203
189
  const authOut = ejs__default["default"].render(template, {
204
- gqlNames,
205
190
  identityField,
206
191
  sessionData,
207
192
  listKey,
208
193
  autoCreate,
209
- userMap,
210
- accountMap,
211
- profileMap,
212
194
  sessionSecret
213
195
  });
214
196
  return authOut;
@@ -222,32 +204,22 @@ const _excluded = ["get", "start"];
222
204
  */
223
205
 
224
206
  function createAuth({
225
- listKey,
226
- identityField,
227
- sessionData,
228
207
  autoCreate,
229
- userMap,
230
- accountMap,
231
- profileMap,
208
+ cookies,
209
+ identityField,
210
+ listKey,
232
211
  keystonePath,
212
+ pages,
213
+ resolver,
233
214
  providers,
215
+ sessionData,
234
216
  sessionSecret
235
217
  }) {
236
218
  // The protectIdentities flag is currently under review to see whether it should be
237
219
  // part of the createAuth API (in which case its use cases need to be documented and tested)
238
220
  // or whether always being true is what we want, in which case we can refactor our code
239
221
  // to match this. -TL
240
- const gqlNames = {
241
- // Core
242
- authenticateItemWithPassword: `authenticate${listKey}WithPassword`,
243
- ItemAuthenticationWithPasswordResult: `${listKey}AuthenticationWithPasswordResult`,
244
- ItemAuthenticationWithPasswordSuccess: `${listKey}AuthenticationWithPasswordSuccess`,
245
- ItemAuthenticationWithPasswordFailure: `${listKey}AuthenticationWithPasswordFailure`,
246
- // Initial data
247
- CreateInitialInput: `CreateInitial${listKey}Input`,
248
- createInitialItem: `createInitial${listKey}`
249
- };
250
- const customPath = !keystonePath || keystonePath === '/' ? '' : keystonePath;
222
+ const customPath = !keystonePath || keystonePath === "/" ? "" : keystonePath;
251
223
  /**
252
224
  * pageMiddleware
253
225
  *
@@ -269,21 +241,17 @@ function createAuth({
269
241
  } = context;
270
242
  const pathname = url__default["default"].parse(req === null || req === void 0 ? void 0 : req.url).pathname;
271
243
 
272
- if (pathname === `${customPath}/api/__keystone_api_build`) {
273
- return;
274
- }
275
-
276
244
  if (isValidSession) {
277
245
  if (pathname === `${customPath}/api/auth/signin`) {
278
246
  return {
279
- kind: 'redirect',
247
+ kind: "redirect",
280
248
  to: `${customPath}`
281
249
  };
282
250
  }
283
251
 
284
- if (customPath !== '' && pathname === '/') {
252
+ if (customPath !== "" && pathname === "/") {
285
253
  return {
286
- kind: 'redirect',
254
+ kind: "redirect",
287
255
  to: `${customPath}`
288
256
  };
289
257
  }
@@ -291,10 +259,14 @@ function createAuth({
291
259
  return;
292
260
  }
293
261
 
262
+ if (_includesInstanceProperty__default["default"](pathname).call(pathname, "/_next/") || _includesInstanceProperty__default["default"](pathname).call(pathname, "/api/auth/") || _includesInstanceProperty__default["default"](pathname).call(pathname, pages === null || pages === void 0 ? void 0 : pages.signIn) || _includesInstanceProperty__default["default"](pathname).call(pathname, pages === null || pages === void 0 ? void 0 : pages.error) || _includesInstanceProperty__default["default"](pathname).call(pathname, pages === null || pages === void 0 ? void 0 : pages.signOut)) {
263
+ return;
264
+ }
265
+
294
266
  if (!session && !_includesInstanceProperty__default["default"](pathname).call(pathname, `${customPath}/api/auth/`)) {
295
267
  return {
296
- kind: 'redirect',
297
- to: `${customPath}/api/auth/signin`
268
+ kind: "redirect",
269
+ to: (pages === null || pages === void 0 ? void 0 : pages.signIn) || `${customPath}/api/auth/signin`
298
270
  };
299
271
  }
300
272
  };
@@ -310,22 +282,18 @@ function createAuth({
310
282
 
311
283
  const getAdditionalFiles = () => {
312
284
  const filesToWrite = [{
313
- mode: 'write',
314
- outputPath: 'pages/api/auth/[...nextauth].js',
285
+ mode: "write",
286
+ outputPath: "pages/api/auth/[...nextauth].js",
315
287
  src: authTemplate({
316
- gqlNames,
288
+ autoCreate,
317
289
  identityField,
318
- sessionData,
319
290
  listKey,
320
- autoCreate,
321
- userMap,
322
- accountMap,
323
- profileMap,
291
+ sessionData,
324
292
  sessionSecret
325
293
  })
326
294
  }, {
327
- mode: 'write',
328
- outputPath: 'next.config.js',
295
+ mode: "write",
296
+ outputPath: "next.config.js",
329
297
  src: nextConfigTemplate({
330
298
  keystonePath: customPath
331
299
  })
@@ -339,7 +307,8 @@ function createAuth({
339
307
  */
340
308
 
341
309
 
342
- const publicPages = [`${customPath}/api/auth/csrf`, `${customPath}/api/auth/signin`, `${customPath}/api/auth/callback`, `${customPath}/api/auth/session`, `${customPath}/api/auth/providers`, `${customPath}/api/auth/signout`];
310
+ const publicPages = [`${customPath}/api/__keystone_api_build`, `${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
311
+ // @ts-ignore
343
312
 
344
313
  function addPages(provider) {
345
314
  const name = provider.id;
@@ -357,8 +326,7 @@ function createAuth({
357
326
 
358
327
  const extendGraphqlSchema = getSchemaExtension({
359
328
  identityField,
360
- listKey,
361
- gqlNames
329
+ listKey
362
330
  });
363
331
  /**
364
332
  * validateConfig
@@ -372,7 +340,9 @@ function createAuth({
372
340
  if (listConfig === undefined) {
373
341
  const msg = `A createAuth() invocation specifies the list "${listKey}" but no list with that key has been defined.`;
374
342
  throw new Error(msg);
375
- } // TODO: Check for String-like typing for identityField? How?
343
+ } // TODO: Check if providers
344
+ // TODO: Check other required commands/data
345
+ // TODO: Check for String-like typing for identityField? How?
376
346
  // TODO: Validate that the identifyField is unique.
377
347
  // TODO: If this field isn't required, what happens if I try to log in as `null`?
378
348
 
@@ -380,9 +350,9 @@ function createAuth({
380
350
  const identityFieldConfig = listConfig.fields[identityField];
381
351
 
382
352
  if (identityFieldConfig === undefined) {
383
- const i = _JSON$stringify__default["default"](identityField);
353
+ const identityFieldName = _JSON$stringify__default["default"](identityField);
384
354
 
385
- const msg = `A createAuth() invocation for the "${listKey}" list specifies ${i} as its identityField but no field with that key exists on the list.`;
355
+ const msg = `A createAuth() invocation for the "${listKey}" list specifies ${identityFieldName} as its identityField but no field with that key exists on the list.`;
386
356
  throw new Error(msg);
387
357
  }
388
358
  };
@@ -405,7 +375,15 @@ function createAuth({
405
375
  sessionStrategy = _objectWithoutProperties(_sessionStrategy, _excluded);
406
376
 
407
377
  return _objectSpread(_objectSpread({}, sessionStrategy), {}, {
408
- start,
378
+ start: async ({
379
+ res
380
+ }) => {
381
+ console.log("start");
382
+ const session = await start({
383
+ res
384
+ });
385
+ return session;
386
+ },
409
387
  get: async ({
410
388
  req
411
389
  }) => {
@@ -413,16 +391,15 @@ function createAuth({
413
391
 
414
392
  const pathname = url__default["default"].parse(req === null || req === void 0 ? void 0 : req.url).pathname;
415
393
 
416
- if (_includesInstanceProperty__default["default"](pathname).call(pathname, '/api/auth')) {
394
+ if (_includesInstanceProperty__default["default"](pathname).call(pathname, "/api/auth")) {
417
395
  return;
418
396
  }
419
397
 
420
- if (((_req$headers$authoriz = req.headers.authorization) === null || _req$headers$authoriz === void 0 ? void 0 : _req$headers$authoriz.split(' ')[0]) === 'Bearer') {
398
+ if (((_req$headers$authoriz = req.headers.authorization) === null || _req$headers$authoriz === void 0 ? void 0 : _req$headers$authoriz.split(" ")[0]) === "Bearer") {
421
399
  var _token$data;
422
400
 
423
- const request = req;
424
401
  const token = await jwt.getToken({
425
- req: request,
402
+ req,
426
403
  secret: sessionSecret
427
404
  });
428
405
 
@@ -443,14 +420,15 @@ function createAuth({
443
420
  res,
444
421
  req
445
422
  }) => {
446
- const TOKEN_NAME = process.env.NODE_ENV === 'production' ? '__Secure-next-auth.session-token' : 'next-auth.session-token';
447
- res.setHeader('Set-Cookie', cookie__namespace.serialize(TOKEN_NAME, '', {
423
+ const TOKEN_NAME = process.env.NODE_ENV === "production" ? "__Secure-next-auth.session-token" : "next-auth.session-token";
424
+ res.setHeader("Set-Cookie", cookie__namespace.serialize(TOKEN_NAME, "", {
448
425
  maxAge: 0,
449
426
  expires: new Date(),
450
427
  httpOnly: true,
451
- secure: process.env.NODE_ENV === 'production',
452
- path: '/',
453
- sameSite: 'lax',
428
+ secure: process.env.NODE_ENV === "production",
429
+ path: "/",
430
+ sameSite: "lax",
431
+ // TODO: Update parse to URL
454
432
  domain: url__default["default"].parse(req.url).hostname
455
433
  }));
456
434
  }
@@ -487,30 +465,37 @@ function createAuth({
487
465
  },
488
466
  enableSessionItem: true,
489
467
  isAccessAllowed: async context => {
490
- var _context$req, _context$req2, _keystoneConfig$ui3;
468
+ var _context$req, _keystoneConfig$ui3;
469
+
470
+ const {
471
+ req
472
+ } = context;
473
+ const pathname = url__default["default"].parse(req === null || req === void 0 ? void 0 : req.url).pathname; // Allow nextjs scripts and static files to be accessed without auth
491
474
 
492
- if (process.env.NODE_ENV !== 'production' && ((_context$req = context.req) === null || _context$req === void 0 ? void 0 : _context$req.url) !== undefined && new _URL__default["default"](context.req.url, 'http://example.com').pathname === `${customPath}/api/__keystone_api_build`) {
475
+ if (_includesInstanceProperty__default["default"](pathname).call(pathname, "/_next/")) {
493
476
  return true;
494
- } // Allow access to the adminMeta data from the /init path to correctly render that page
495
- // even if the user isn't logged in (which should always be the case if they're seeing /init)
477
+ } // Allow keystone to access /api/__keystone_api_build for hot reloading
496
478
 
497
479
 
498
- const headers = (_context$req2 = context.req) === null || _context$req2 === void 0 ? void 0 : _context$req2.headers;
499
- const host = headers ? headers['x-forwarded-host'] || headers.host : null;
500
- const thisUrl = headers !== null && headers !== void 0 && headers.referer ? new _URL__default["default"](headers.referer) : undefined;
501
- const accessingInitPage = (thisUrl === null || thisUrl === void 0 ? void 0 : thisUrl.pathname) === '/init' && (thisUrl === null || thisUrl === void 0 ? void 0 : thisUrl.host) === host && (await context.sudo().query[listKey].count({})) === 0;
502
- return accessingInitPage || ((_keystoneConfig$ui3 = keystoneConfig.ui) !== null && _keystoneConfig$ui3 !== void 0 && _keystoneConfig$ui3.isAccessAllowed ? keystoneConfig.ui.isAccessAllowed(context) : context.session !== undefined);
480
+ if (process.env.NODE_ENV !== "production" && ((_context$req = context.req) === null || _context$req === void 0 ? void 0 : _context$req.url) !== undefined && new _URL__default["default"](context.req.url, "http://example.com").pathname === `${customPath}/api/__keystone_api_build`) {
481
+ return true;
482
+ }
483
+
484
+ return (_keystoneConfig$ui3 = keystoneConfig.ui) !== null && _keystoneConfig$ui3 !== void 0 && _keystoneConfig$ui3.isAccessAllowed ? keystoneConfig.ui.isAccessAllowed(context) : context.session !== undefined;
503
485
  }
504
486
  });
505
487
  }
506
488
 
507
- if (!keystoneConfig.session) throw new TypeError('Missing .session configuration');
489
+ if (!keystoneConfig.session) throw new TypeError("Missing .session configuration");
508
490
  const session = withItemData(keystoneConfig.session);
509
491
  const existingExtendGraphQLSchema = keystoneConfig.extendGraphqlSchema;
510
492
  return _objectSpread(_objectSpread({}, keystoneConfig), {}, {
511
493
  ui,
512
- session,
494
+ cookies,
513
495
  providers,
496
+ pages,
497
+ resolver,
498
+ session,
514
499
  lists: _objectSpread({}, keystoneConfig.lists),
515
500
  experimental: _objectSpread(_objectSpread({}, keystoneConfig.experimental), {}, {
516
501
  generateNodeAPI: true