@opensaas/keystone-nextjs-auth 20.5.0 → 21.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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