From 73f203aa9696a495518fec3cff46bac8f0637b3f Mon Sep 17 00:00:00 2001 From: Daniel Cousens <413395+dcousens@users.noreply.github.com> Date: Thu, 15 Feb 2024 11:40:27 +1100 Subject: [PATCH 1/6] move most Keystone defaults to system.initConfig --- .../core/src/lib/core/initialise-lists.ts | 22 ++--- .../src/lib/server/createAdminUIMiddleware.ts | 1 + .../src/lib/server/createExpressServer.ts | 7 +- packages/core/src/system.ts | 96 ++++++++++++++++--- 4 files changed, 103 insertions(+), 23 deletions(-) diff --git a/packages/core/src/lib/core/initialise-lists.ts b/packages/core/src/lib/core/initialise-lists.ts index 95a79a26b9f..2515ab25f83 100644 --- a/packages/core/src/lib/core/initialise-lists.ts +++ b/packages/core/src/lib/core/initialise-lists.ts @@ -1,17 +1,17 @@ import type { CacheHint } from '@apollo/cache-control-types' import { GraphQLString, isInputObjectType } from 'graphql' import { type getGqlNames, QueryMode } from '../../types' -import type { - BaseItem, - BaseListTypeInfo, - CacheHintArgs, - FindManyArgs, - GraphQLTypesForList, - KeystoneConfig, - ListGraphQLTypes, - ListHooks, - MaybePromise, - NextFieldType, +import { + type BaseItem, + type BaseListTypeInfo, + type CacheHintArgs, + type FindManyArgs, + type GraphQLTypesForList, + type ListGraphQLTypes, + type ListHooks, + type KeystoneConfig, + type MaybePromise, + type NextFieldType, } from '../../types' import { graphql } from '../..' import type { FieldHooks, ResolvedListHooks, ResolvedFieldHooks } from '../../types/config/hooks' diff --git a/packages/core/src/lib/server/createAdminUIMiddleware.ts b/packages/core/src/lib/server/createAdminUIMiddleware.ts index b3c744859b9..e2f4ea9df98 100644 --- a/packages/core/src/lib/server/createAdminUIMiddleware.ts +++ b/packages/core/src/lib/server/createAdminUIMiddleware.ts @@ -21,6 +21,7 @@ export function createAdminUIMiddlewareWithNextApp ( const { ui: { + // TODO: remove default in breaking change, prefer resolveDefaults isAccessAllowed = defaultIsAccessAllowed, pageMiddleware, publicPages = [], diff --git a/packages/core/src/lib/server/createExpressServer.ts b/packages/core/src/lib/server/createExpressServer.ts index c05293b3eb1..e69da30ea43 100644 --- a/packages/core/src/lib/server/createExpressServer.ts +++ b/packages/core/src/lib/server/createExpressServer.ts @@ -57,10 +57,12 @@ export async function createExpressServer ( const httpServer = createServer(expressServer) if (config.server?.cors) { + // TODO: remove default in breaking change, prefer resolveDefaults const corsConfig = - typeof config.server.cors === 'boolean' + config.server.cors === true ? { origin: true, credentials: true } : config.server.cors + expressServer.use(cors(corsConfig)) } @@ -102,6 +104,8 @@ export async function createExpressServer ( } const apolloConfig = config.graphql?.apolloConfig + + // TODO: remove default in breaking change, prefer resolveDefaults const playgroundOption = config.graphql?.playground ?? process.env.NODE_ENV !== 'production' const serverConfig = { formatError: formatError(config.graphql), @@ -128,6 +132,7 @@ export async function createExpressServer ( expressServer.use(graphqlUploadExpress({ maxFileSize })) await apolloServer.start() expressServer.use( + // TODO: remove default in breaking change, prefer resolveDefaults config.graphql?.path ?? '/api/graphql', json(config.graphql?.bodyParser), expressMiddleware(apolloServer, { diff --git a/packages/core/src/system.ts b/packages/core/src/system.ts index 65081be4b56..3e9ee2633c6 100644 --- a/packages/core/src/system.ts +++ b/packages/core/src/system.ts @@ -1,29 +1,84 @@ import type express from 'express' import next from 'next' import { + type IdFieldConfig, type KeystoneConfig, type KeystoneContext } from './types' import { createAdminUIMiddlewareWithNextApp } from './lib/server/createAdminUIMiddleware' -import { applyIdFieldDefaults } from './lib/config' +import { + idFieldType +} from './lib/id-field' -/** @deprecated */ +/** @deprecated, TODO: remove in breaking change */ export { createSystem } from './lib/createSystem' -/** @deprecated */ +/** @deprecated, TODO: remove in breaking change */ export { createExpressServer } from './lib/server/createExpressServer' +function injectIdFields (config: KeystoneConfig, defaultIdField: IdFieldConfig) { + // some error checking + for (const [listKey, list] of Object.entries(config.lists)) { + if (list.fields.id) { + throw new Error(`"fields.id" is reserved by Keystone, use "db.idField" for the "${listKey}" list`) + } + + if (list.isSingleton && list.db?.idField) { + throw new Error(`"db.idField" on the "${listKey}" list conflicts with singleton defaults`) + } + } + + const listsWithIds: KeystoneConfig['lists'] = {} + + for (const [listKey, list] of Object.entries(config.lists)) { + if (list.isSingleton) { + listsWithIds[listKey] = { + ...list, + fields: { + id: idFieldType({ kind: 'autoincrement', type: 'Int' }), + ...list.fields, + }, + } + + continue + } + + listsWithIds[listKey] = { + ...list, + fields: { + id: idFieldType(list.db?.idField ?? defaultIdField), + ...list.fields, + }, + } + } + + return listsWithIds +} + +function defaultIsAccessAllowed ({ session, sessionStrategy }: KeystoneContext) { + if (!sessionStrategy) return true + return session !== undefined +} + /** @deprecated, TODO: remove in breaking change */ -export function initConfig (config: KeystoneConfig) { +export function initConfig (config: KeystoneConfig): KeystoneConfig { + return resolveDefaults(config) +} + +function resolveDefaults (config: KeystoneConfig) { if (!['postgresql', 'sqlite', 'mysql'].includes(config.db.provider)) { - throw new TypeError( - 'Invalid db configuration. Please specify db.provider as either "sqlite", "postgresql" or "mysql"' - ) + throw new TypeError(`"db.provider" only supports "sqlite", "postgresql" or "mysql"`) } // WARNING: Typescript should prevent this, but any string is useful for Prisma errors config.db.url ??= 'postgres://' + const defaultIdField = config.db.idField ?? { kind: 'cuid' } + const cors = + config.server?.cors === true + ? { origin: true, credentials: true } + : config.server?.cors ?? false + return { ...config, types: { @@ -31,25 +86,44 @@ export function initConfig (config: KeystoneConfig) { ...config.types, }, db: { + shadowDatabaseUrl: '', // TODO: is this ok + extendPrismaSchema: (schema: string) => schema, + prismaClientPath: '@prisma/client', prismaSchemaPath: 'schema.prisma', ...config.db, + idField: defaultIdField, }, graphql: { + path: '/api/graphql', + playground: process.env.NODE_ENV !== 'production', schemaPath: 'schema.graphql', ...config.graphql, }, - lists: applyIdFieldDefaults(config), + lists: injectIdFields(config, defaultIdField), server: { - cors: false, maxFileSize: 200 * 1024 * 1024, // 200 MiB extendExpressApp: async () => {}, extendHttpServer: async () => {}, ...config.server, + cors, }, - } + // TODO: remove in breaking change, move to .graphql.extendSchema + extendGraphqlSchema: config.extendGraphqlSchema ?? ((s) => s), + storage: { + ...config?.storage + }, + telemetry: config?.telemetry ?? true, + ui: { + isAccessAllowed: defaultIsAccessAllowed, + pageMiddleware: async () => {}, + publicPages: [], + basePath: '', + ...config?.ui, + }, + } satisfies KeystoneConfig } -/** @deprecated */ +/** @deprecated, TODO: remove in breaking change */ export async function createAdminUIMiddleware ( config: KeystoneConfig, context: KeystoneContext, From c3f38adfa4bc7d0c9e5ac8556b4516bce7dece76 Mon Sep 17 00:00:00 2001 From: Daniel Cousens <413395+dcousens@users.noreply.github.com> Date: Thu, 15 Feb 2024 12:11:42 +1100 Subject: [PATCH 2/6] Use `idField` type of `{ kind: number, kind: Int | BigInt }` internally for singletons --- .changeset/add-number-id.md | 5 ++ examples/custom-id/schema.graphql | 67 +++++++++++++++++++++++++ examples/custom-id/schema.prisma | 7 +++ examples/custom-id/schema.ts | 17 +++++++ packages/core/src/lib/config.ts | 55 -------------------- packages/core/src/lib/id-field.ts | 18 ++----- packages/core/src/system.ts | 2 +- packages/core/src/types/config/lists.ts | 1 + 8 files changed, 103 insertions(+), 69 deletions(-) create mode 100644 .changeset/add-number-id.md delete mode 100644 packages/core/src/lib/config.ts diff --git a/.changeset/add-number-id.md b/.changeset/add-number-id.md new file mode 100644 index 00000000000..bcb9552ec13 --- /dev/null +++ b/.changeset/add-number-id.md @@ -0,0 +1,5 @@ +---- +'@keystone-6/core': patch +---- + +Use `idField` type of `{ kind: 'number', kind: 'Int' | 'BigInt' }` internally for singletons diff --git a/examples/custom-id/schema.graphql b/examples/custom-id/schema.graphql index 44b58196fda..44f240dbc4c 100644 --- a/examples/custom-id/schema.graphql +++ b/examples/custom-id/schema.graphql @@ -176,6 +176,8 @@ type Order { id: ID! description: String assignedTo: Person + options(where: OptionWhereInput! = {}, orderBy: [OptionOrderByInput!]! = [], take: Int, skip: Int! = 0, cursor: OptionWhereUniqueInput): [Option!] + optionsCount(where: OptionWhereInput! = {}): Int orderedAt: DateTime } @@ -190,9 +192,16 @@ input OrderWhereInput { id: IDFilter description: StringFilter assignedTo: PersonWhereInput + options: OptionManyRelationFilter orderedAt: DateTimeNullableFilter } +input OptionManyRelationFilter { + every: OptionWhereInput + some: OptionWhereInput + none: OptionWhereInput +} + input OrderOrderByInput { id: OrderDirection description: OrderDirection @@ -202,9 +211,17 @@ input OrderOrderByInput { input OrderUpdateInput { description: String assignedTo: PersonRelateToOneForUpdateInput + options: OptionRelateToManyForUpdateInput orderedAt: DateTime } +input OptionRelateToManyForUpdateInput { + disconnect: [OptionWhereUniqueInput!] + set: [OptionWhereUniqueInput!] + create: [OptionCreateInput!] + connect: [OptionWhereUniqueInput!] +} + input OrderUpdateArgs { where: OrderWhereUniqueInput! data: OrderUpdateInput! @@ -213,9 +230,50 @@ input OrderUpdateArgs { input OrderCreateInput { description: String assignedTo: PersonRelateToOneForCreateInput + options: OptionRelateToManyForCreateInput orderedAt: DateTime } +input OptionRelateToManyForCreateInput { + create: [OptionCreateInput!] + connect: [OptionWhereUniqueInput!] +} + +type Option { + id: ID! + description: String +} + +input OptionWhereUniqueInput { + id: ID +} + +input OptionWhereInput { + AND: [OptionWhereInput!] + OR: [OptionWhereInput!] + NOT: [OptionWhereInput!] + id: IDFilter + description: StringFilter +} + +input OptionOrderByInput { + id: OrderDirection + description: OrderDirection +} + +input OptionUpdateInput { + description: String +} + +input OptionUpdateArgs { + where: OptionWhereUniqueInput! + data: OptionUpdateInput! +} + +input OptionCreateInput { + description: String +} + """ The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). """ @@ -240,6 +298,12 @@ type Mutation { updateOrders(data: [OrderUpdateArgs!]!): [Order] deleteOrder(where: OrderWhereUniqueInput!): Order deleteOrders(where: [OrderWhereUniqueInput!]!): [Order] + createOption(data: OptionCreateInput!): Option + createOptions(data: [OptionCreateInput!]!): [Option] + updateOption(where: OptionWhereUniqueInput!, data: OptionUpdateInput!): Option + updateOptions(data: [OptionUpdateArgs!]!): [Option] + deleteOption(where: OptionWhereUniqueInput!): Option + deleteOptions(where: [OptionWhereUniqueInput!]!): [Option] } type Query { @@ -252,6 +316,9 @@ type Query { orders(where: OrderWhereInput! = {}, orderBy: [OrderOrderByInput!]! = [], take: Int, skip: Int! = 0, cursor: OrderWhereUniqueInput): [Order!] order(where: OrderWhereUniqueInput!): Order ordersCount(where: OrderWhereInput! = {}): Int + options(where: OptionWhereInput! = {}, orderBy: [OptionOrderByInput!]! = [], take: Int, skip: Int! = 0, cursor: OptionWhereUniqueInput): [Option!] + option(where: OptionWhereUniqueInput!): Option + optionsCount(where: OptionWhereInput! = {}): Int keystone: KeystoneMeta! } diff --git a/examples/custom-id/schema.prisma b/examples/custom-id/schema.prisma index 5ea27feecfb..ef7791950cf 100644 --- a/examples/custom-id/schema.prisma +++ b/examples/custom-id/schema.prisma @@ -34,7 +34,14 @@ model Order { description String @default("") assignedTo Person? @relation("Order_assignedTo", fields: [assignedToId], references: [id]) assignedToId String? @map("assignedTo") + options Option[] @relation("Order_options") orderedAt DateTime? @@index([assignedToId]) } + +model Option { + id Int @id + description String @default("") + from_Order_options Order[] @relation("Order_options") +} diff --git a/examples/custom-id/schema.ts b/examples/custom-id/schema.ts index 822aee677dc..8531f8e56b7 100644 --- a/examples/custom-id/schema.ts +++ b/examples/custom-id/schema.ts @@ -38,6 +38,7 @@ export const lists = { fields: { description: text({ validation: { isRequired: true } }), assignedTo: relationship({ ref: 'Person', many: false }), + options: relationship({ ref: 'Option', many: true }), orderedAt: timestamp(), }, hooks: { @@ -48,4 +49,20 @@ export const lists = { }, }, }), + Option: list({ + access: allowAll, + db: { + idField: { kind: 'number', type: 'Int' }, + }, + fields: { + description: text({ validation: { isRequired: true } }), + }, + hooks: { + resolveInput: { + create: async ({ listKey, operation, resolvedData }) => { + return { ...resolvedData, id: 3 } + }, + }, + }, + }), } satisfies Lists diff --git a/packages/core/src/lib/config.ts b/packages/core/src/lib/config.ts deleted file mode 100644 index af23b437251..00000000000 --- a/packages/core/src/lib/config.ts +++ /dev/null @@ -1,55 +0,0 @@ -import type { KeystoneConfig } from '../types' -import { idFieldType } from './id-field' - -export function applyIdFieldDefaults (config: KeystoneConfig): KeystoneConfig['lists'] { - // some error checking - for (const [listKey, list] of Object.entries(config.lists)) { - if (list.fields.id) { - throw new Error( - `A field with the \`id\` path is defined in the fields object on the ${JSON.stringify( - listKey - )} list. This is not allowed, use the idField option instead.` - ) - } - - if (list.isSingleton && list.db?.idField) { - throw new Error( - `A singleton list cannot specify an idField, but it is configured at db.idField on the ${listKey} list` - ) - } - } - - // inject ID fields - const listsWithIds: KeystoneConfig['lists'] = {} - - for (const [listKey, list] of Object.entries(config.lists)) { - if (list.isSingleton) { - // Singletons can only use an Int, idFieldType function ignores the `kind` if isSingleton is true - listsWithIds[listKey] = { - ...list, - fields: { - id: idFieldType( - { - kind: 'autoincrement', - type: 'Int', - }, - true - ), - ...list.fields, - }, - } - - continue - } - - listsWithIds[listKey] = { - ...list, - fields: { - id: idFieldType(list.db?.idField ?? config.db.idField ?? { kind: 'cuid' }, false), - ...list.fields, - }, - } - } - - return listsWithIds -} diff --git a/packages/core/src/lib/id-field.ts b/packages/core/src/lib/id-field.ts index ca9a969dc15..78ceffb0c2f 100644 --- a/packages/core/src/lib/id-field.ts +++ b/packages/core/src/lib/id-field.ts @@ -126,24 +126,16 @@ function unpack (i: IdFieldConfig) { }, } as const } - const { kind } = i + const { kind, type } = i if (kind === 'cuid') return { kind: 'cuid', type: 'String', default_: { kind } } as const if (kind === 'uuid') return { kind: 'uuid', type: 'String', default_: { kind } } as const if (kind === 'string') return { kind: 'string', type: 'String', default_: undefined } as const - if (kind === 'autoincrement') { - if (i.type === 'BigInt') { - return { kind: 'autoincrement', type: 'BigInt', default_: { kind } } as const - } - return { kind: 'autoincrement', type: 'Int', default_: { kind } } as const - } - + if (kind === 'number') return { kind: 'number', type: type ?? 'Int', default_: undefined } as const + if (kind === 'autoincrement') return { kind: 'autoincrement', type: type ?? 'Int', default_: { kind } } as const throw new Error(`Unknown id type ${kind}`) } -export function idFieldType ( - config: IdFieldConfig, - isSingleton: boolean -): FieldTypeFunc { +export function idFieldType (config: IdFieldConfig): FieldTypeFunc { const { kind, type: type_, default_ } = unpack(config) const parseTypeFn = { Int: isInt, @@ -170,7 +162,7 @@ export function idFieldType ( mode: 'required', scalar: type_, nativeType: NATIVE_TYPES[meta.provider]?.[kind], - default: isSingleton ? undefined : default_, + default: default_, })({ ...config, diff --git a/packages/core/src/system.ts b/packages/core/src/system.ts index 3e9ee2633c6..78e6b687c41 100644 --- a/packages/core/src/system.ts +++ b/packages/core/src/system.ts @@ -35,7 +35,7 @@ function injectIdFields (config: KeystoneConfig, defaultIdField: IdFieldConfig) listsWithIds[listKey] = { ...list, fields: { - id: idFieldType({ kind: 'autoincrement', type: 'Int' }), + id: idFieldType({ kind: 'number', type: 'Int' }), ...list.fields, }, } diff --git a/packages/core/src/types/config/lists.ts b/packages/core/src/types/config/lists.ts index e58faf72f0c..850efe57c28 100644 --- a/packages/core/src/types/config/lists.ts +++ b/packages/core/src/types/config/lists.ts @@ -241,6 +241,7 @@ export type IdFieldConfig = } | { kind: 'cuid' | 'uuid' | 'string', type?: 'String' } | { kind: 'autoincrement', type?: 'Int' | 'BigInt' } + | { kind: 'number', type: 'Int' | 'BigInt' } export type ListDBConfig = { /** From 3a30e9b6f0be73a8b84ce0a316ef93aead89ae50 Mon Sep 17 00:00:00 2001 From: Daniel Cousens <413395+dcousens@users.noreply.github.com> Date: Thu, 15 Feb 2024 12:28:02 +1100 Subject: [PATCH 3/6] flatten lib/ --- .../core/src/lib/{server => }/createAdminUIMiddleware.ts | 7 +++++-- .../core/src/lib/{server => }/createExpressServer.ts | 9 ++++++--- packages/core/src/lib/defaults.ts | 1 - packages/core/src/scripts/dev.ts | 6 +++--- packages/core/src/scripts/start.ts | 4 ++-- packages/core/src/system.ts | 4 ++-- 6 files changed, 18 insertions(+), 13 deletions(-) rename packages/core/src/lib/{server => }/createAdminUIMiddleware.ts (95%) rename packages/core/src/lib/{server => }/createExpressServer.ts (95%) delete mode 100644 packages/core/src/lib/defaults.ts diff --git a/packages/core/src/lib/server/createAdminUIMiddleware.ts b/packages/core/src/lib/createAdminUIMiddleware.ts similarity index 95% rename from packages/core/src/lib/server/createAdminUIMiddleware.ts rename to packages/core/src/lib/createAdminUIMiddleware.ts index e2f4ea9df98..251a714b04f 100644 --- a/packages/core/src/lib/server/createAdminUIMiddleware.ts +++ b/packages/core/src/lib/createAdminUIMiddleware.ts @@ -2,8 +2,11 @@ import url from 'url' import path from 'path' import type express from 'express' import type next from 'next' -import type { KeystoneConfig, KeystoneContext } from '../../types' -import { pkgDir } from '../../pkg-dir' +import { + type KeystoneConfig, + type KeystoneContext +} from '../types' +import { pkgDir } from '../pkg-dir' const adminErrorHTMLFilepath = path.join(pkgDir, 'static', 'admin-error.html') diff --git a/packages/core/src/lib/server/createExpressServer.ts b/packages/core/src/lib/createExpressServer.ts similarity index 95% rename from packages/core/src/lib/server/createExpressServer.ts rename to packages/core/src/lib/createExpressServer.ts index e69da30ea43..8f9e3833dc5 100644 --- a/packages/core/src/lib/server/createExpressServer.ts +++ b/packages/core/src/lib/createExpressServer.ts @@ -12,8 +12,11 @@ import { ApolloServerPluginLandingPageDisabled } from '@apollo/server/plugin/dis import { ApolloServerPluginLandingPageLocalDefault } from '@apollo/server/plugin/landingPage/default' // @ts-expect-error import graphqlUploadExpress from 'graphql-upload/graphqlUploadExpress.js' -import type { KeystoneConfig, KeystoneContext, GraphQLConfig } from '../../types' -import { healthCheckPath as defaultHealthCheckPath } from '../defaults' +import { + type GraphQLConfig, + type KeystoneConfig, + type KeystoneContext, +} from '../types' /* NOTE: This creates the main Keystone express server, including the @@ -70,7 +73,7 @@ export async function createExpressServer ( if (config.server?.healthCheck) { const healthCheck = config.server.healthCheck === true ? {} : config.server.healthCheck - expressServer.use(healthCheck.path ?? defaultHealthCheckPath, (req, res) => { + expressServer.use(healthCheck.path ?? '/_healthcheck', (req, res) => { if (typeof healthCheck.data === 'function') return res.json(healthCheck.data()) if (healthCheck.data) return res.json(healthCheck.data) diff --git a/packages/core/src/lib/defaults.ts b/packages/core/src/lib/defaults.ts deleted file mode 100644 index 81b5ae4a493..00000000000 --- a/packages/core/src/lib/defaults.ts +++ /dev/null @@ -1 +0,0 @@ -export const healthCheckPath = '/_healthcheck' diff --git a/packages/core/src/scripts/dev.ts b/packages/core/src/scripts/dev.ts index a5d3b784935..510046b8b6d 100644 --- a/packages/core/src/scripts/dev.ts +++ b/packages/core/src/scripts/dev.ts @@ -6,13 +6,13 @@ import { createServer } from 'node:http' import next from 'next' import express from 'express' import { GraphQLSchema, printSchema } from 'graphql' -import esbuild, { BuildResult } from 'esbuild' +import esbuild, { type BuildResult } from 'esbuild' import { generateAdminUI } from '../admin-ui/system' import { devMigrations, pushPrismaSchemaToDatabase } from '../lib/migrations' import { createSystem } from '../lib/createSystem' import { getEsbuildConfig } from '../lib/esbuild' -import { createExpressServer } from '../lib/server/createExpressServer' -import { createAdminUIMiddlewareWithNextApp } from '../lib/server/createAdminUIMiddleware' +import { createExpressServer } from '../lib/createExpressServer' +import { createAdminUIMiddlewareWithNextApp } from '../lib/createAdminUIMiddleware' import { runTelemetry } from '../lib/telemetry' import { generatePrismaAndGraphQLSchemas, diff --git a/packages/core/src/scripts/start.ts b/packages/core/src/scripts/start.ts index c06c6bcaf8d..acbe6a20357 100644 --- a/packages/core/src/scripts/start.ts +++ b/packages/core/src/scripts/start.ts @@ -2,8 +2,8 @@ import fs from 'node:fs/promises' import type { ListenOptions } from 'node:net' import next from 'next' import { createSystem } from '../lib/createSystem' -import { createExpressServer } from '../lib/server/createExpressServer' -import { createAdminUIMiddlewareWithNextApp } from '../lib/server/createAdminUIMiddleware' +import { createExpressServer } from '../lib/createExpressServer' +import { createAdminUIMiddlewareWithNextApp } from '../lib/createAdminUIMiddleware' import { getBuiltKeystoneConfigurationPath, getBuiltKeystoneConfiguration, diff --git a/packages/core/src/system.ts b/packages/core/src/system.ts index 78e6b687c41..79999865a90 100644 --- a/packages/core/src/system.ts +++ b/packages/core/src/system.ts @@ -5,7 +5,7 @@ import { type KeystoneConfig, type KeystoneContext } from './types' -import { createAdminUIMiddlewareWithNextApp } from './lib/server/createAdminUIMiddleware' +import { createAdminUIMiddlewareWithNextApp } from './lib/createAdminUIMiddleware' import { idFieldType } from './lib/id-field' @@ -14,7 +14,7 @@ import { export { createSystem } from './lib/createSystem' /** @deprecated, TODO: remove in breaking change */ -export { createExpressServer } from './lib/server/createExpressServer' +export { createExpressServer } from './lib/createExpressServer' function injectIdFields (config: KeystoneConfig, defaultIdField: IdFieldConfig) { // some error checking From f9420a64d9658f63922989519dc45fda45112e96 Mon Sep 17 00:00:00 2001 From: Daniel Cousens <413395+dcousens@users.noreply.github.com> Date: Thu, 15 Feb 2024 12:48:07 +1100 Subject: [PATCH 4/6] prefer charAt(0) for string mutations, less duplicates --- design-system/packages/toast/src/Toast.tsx | 2 +- .../website/pages/components/button.tsx | 8 ++++---- .../website/pages/components/loading.tsx | 8 ++++---- .../website/pages/components/notice.tsx | 4 ++-- .../website/pages/components/toast.tsx | 7 ++----- design-system/website/utils.ts | 8 ++++++-- packages/core/src/lib/utils.ts | 11 ++--------- packages/core/src/types/utils.ts | 4 ++-- packages/core/tests/utils.test.ts | 18 ++++++------------ 9 files changed, 29 insertions(+), 41 deletions(-) diff --git a/design-system/packages/toast/src/Toast.tsx b/design-system/packages/toast/src/Toast.tsx index eb400a8d7a1..e7a889941f0 100644 --- a/design-system/packages/toast/src/Toast.tsx +++ b/design-system/packages/toast/src/Toast.tsx @@ -15,7 +15,7 @@ import { type ToastProps, type ToastPropsExact } from './types' // Provider // ------------------------------ -export const ToastProvider = ({ children }: { children: ReactNode }) => { +export function ToastProvider ({ children }: { children: ReactNode }) { const [toastStack, setToastStack] = useState([]) const context = useMemo( diff --git a/design-system/website/pages/components/button.tsx b/design-system/website/pages/components/button.tsx index 2da124980f4..5c3a788eadc 100644 --- a/design-system/website/pages/components/button.tsx +++ b/design-system/website/pages/components/button.tsx @@ -5,16 +5,16 @@ import { jsx, Stack } from '@keystone-ui/core' import { Button, buttonToneValues, type ToneKey, buttonWeightValues } from '@keystone-ui/button' import { Page } from '../../components/Page' -import { toLabel } from '../../utils' +import { capitalise } from '../../utils' -const Variants = ({ tone }: { tone: ToneKey }) => { - const toneLabel = toLabel(tone) +function Variants ({ tone }: { tone: ToneKey }) { + const toneLabel = capitalise(tone) return (

{toneLabel} Tone

{buttonWeightValues.map(weight => { - const weightLabel = toLabel(weight) + const weightLabel = capitalise(weight) return (