From 75ac9befaa3f582a20bb6cd96def15a9662165bb Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Mon, 24 Nov 2025 11:19:56 +1100 Subject: [PATCH 1/4] add missing ts-expect-error --- packages/core/src/lib/migrations.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/core/src/lib/migrations.ts b/packages/core/src/lib/migrations.ts index f87f4d7d05f..a13d60cbb9b 100644 --- a/packages/core/src/lib/migrations.ts +++ b/packages/core/src/lib/migrations.ts @@ -65,9 +65,11 @@ export async function withMigrate( }, }) } finally { - await (migrate.engine as any).initPromise + // @ts-expect-error + await migrate.engine.initPromise const closePromise = new Promise(resolve => { - ;(migrate.engine as any).child.once('exit', resolve) + // @ts-expect-error + migrate.engine.child.once('exit', resolve) }) migrate.stop() await closePromise From 762dfcd2bc77d72e8d084f71cca02f37a4ff1959 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Tue, 25 Nov 2025 09:32:16 +1100 Subject: [PATCH 2/4] fix whitespace in migration messages --- packages/core/src/scripts/dev.ts | 33 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/packages/core/src/scripts/dev.ts b/packages/core/src/scripts/dev.ts index fab8c27717e..14a727fbe9a 100644 --- a/packages/core/src/scripts/dev.ts +++ b/packages/core/src/scripts/dev.ts @@ -46,6 +46,17 @@ function stripExtendHttpServer(config: KeystoneConfig): KeystoneConfig { } } +function maybePrint (context: string, list: string[]) { + if (!list.length) return + console.error() + console.error(context) + console.error() + for (const item of list) { + console.error(` • ${item}`) + } + console.error() +} + function resolvablePromise() { let _resolve!: (value: T) => void const promise: any = new Promise(resolve => { @@ -173,19 +184,8 @@ export async function dev( // if there are unexecutable steps, we need to reset the database [or the user can use migrations] if (migration_.unexecutable.length) { - console.error( - `${chalk.bold.red('\n⚠️ We found changes that cannot be executed:\n')}` - ) - for (const item of migration_.unexecutable) { - console.error(` • ${item}`) - } - - if (migration_.warnings.length) { - console.error(chalk.bold(`\n⚠️ Warnings:\n`)) - for (const warning of migration_.warnings) { - console.error(` • ${warning}`) - } - } + maybePrint(chalk.bold.red('⚠️ Some changes cannot be executed:'), migration_.unexecutable) + maybePrint(chalk.bold('⚠️ Warnings:'), migration_.warnings) console.error('\nTo apply this migration, we need to reset the database') if ( @@ -202,12 +202,7 @@ export async function dev( } if (migration_.warnings.length) { - if (migration_.warnings.length) { - console.error(chalk.bold(`\n⚠️ Warnings:\n`)) - for (const warning of migration_.warnings) { - console.error(` • ${warning}`) - } - } + maybePrint(chalk.bold('⚠️ Warnings:'), migration_.warnings) if ( !(await confirmPrompt( From deece5021ebc6b88414a336eab7f4ea07bb855f3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 24 Nov 2025 13:55:29 +0000 Subject: [PATCH 3/4] fix(deps): update dependency conf to v15 --- packages/core/package.json | 2 +- pnpm-lock.yaml | 165 +++++++++++++++++-------------------- 2 files changed, 77 insertions(+), 90 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index a46cac6e45c..52850d3793c 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -260,7 +260,7 @@ "chalk": "^4.1.2", "ci-info": "^4.0.0", "clipboard-copy": "^4.0.1", - "conf": "^10.2.0", + "conf": "^15.0.0", "cookie": "^1.0.0", "cors": "^2.8.5", "dataloader": "^2.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e01b68b57b4..d93544854a4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1928,8 +1928,8 @@ importers: specifier: ^4.0.1 version: 4.0.1 conf: - specifier: ^10.2.0 - version: 10.2.0 + specifier: ^15.0.0 + version: 15.0.2 cookie: specifier: ^1.0.0 version: 1.0.2 @@ -7055,8 +7055,8 @@ packages: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} - ajv-formats@2.1.1: - resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} peerDependencies: ajv: ^8.0.0 peerDependenciesMeta: @@ -7224,9 +7224,8 @@ packages: resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} engines: {node: '>=8.0.0'} - atomically@1.7.0: - resolution: {integrity: sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==} - engines: {node: '>=10.12.0'} + atomically@2.1.0: + resolution: {integrity: sha512-+gDffFXRW6sl/HCwbta7zK4uNqbPjv4YJEAdz7Vu+FLQHe77eZ4bvbJGi4hE0QPeJlMYMA3piXEr1UL3dAwx7Q==} auto-bind@4.0.0: resolution: {integrity: sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ==} @@ -7713,9 +7712,9 @@ packages: engines: {node: ^12.20.0 || ^14.13.0 || >=16.0.0} hasBin: true - conf@10.2.0: - resolution: {integrity: sha512-8fLl9F04EJqjSqH+QjITQfJF8BrOVaYr1jewVgSRAEWePfxT0sku4w2hrGQ60BC/TNLGQ2pgxNlTbWQmMPFvXg==} - engines: {node: '>=12'} + conf@15.0.2: + resolution: {integrity: sha512-JBSrutapCafTrddF9dH3lc7+T2tBycGF4uPkI4Js+g4vLLEhG6RZcFi3aJd5zntdf5tQxAejJt8dihkoQ/eSJw==} + engines: {node: '>=20'} confbox@0.1.8: resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} @@ -7892,9 +7891,9 @@ packages: resolution: {integrity: sha512-/6/cXqkw4LPqBVK6H0Y3L4zT7yI3pxykxPXErQ2tDCw0LJyThWL5VpBCpUOWX0vPq2OnF1pzcXvlNnvCiOQJuA==} engines: {node: '>=0.11.0'} - debounce-fn@4.0.0: - resolution: {integrity: sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ==} - engines: {node: '>=10'} + debounce-fn@6.0.0: + resolution: {integrity: sha512-rBMW+F2TXryBwB54Q0d8drNEI+TfoS9JpNTAoVpukbWEhjXQq4rySFYLaqXMFXwdv61Zb2OHtj5bviSoimqxRQ==} + engines: {node: '>=18'} debounce@1.2.1: resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==} @@ -8074,9 +8073,9 @@ packages: dot-case@3.0.4: resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} - dot-prop@6.0.1: - resolution: {integrity: sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==} - engines: {node: '>=10'} + dot-prop@10.1.0: + resolution: {integrity: sha512-MVUtAugQMOff5RnBy2d9N31iG0lNwg1qAoAOn7pOK5wf94WIaE3My2p3uwTQuvS2AcqchkcR3bHByjaM0mmi7Q==} + engines: {node: '>=20'} dotenv@16.6.1: resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} @@ -8155,9 +8154,9 @@ packages: resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} engines: {node: '>=0.12'} - env-paths@2.2.1: - resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} - engines: {node: '>=6'} + env-paths@3.0.0: + resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} error-ex@1.3.4: resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} @@ -8543,10 +8542,6 @@ packages: resolution: {integrity: sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==} engines: {node: '>=18'} - find-up@3.0.0: - resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==} - engines: {node: '>=6'} - find-up@4.1.0: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} engines: {node: '>=8'} @@ -9322,10 +9317,6 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} - is-obj@2.0.0: - resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} - engines: {node: '>=8'} - is-path-inside@3.0.3: resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} engines: {node: '>=8'} @@ -9697,8 +9688,8 @@ packages: json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - json-schema-typed@7.0.3: - resolution: {integrity: sha512-7DE8mpG+/fVw+dTpjbxnx47TaMnDfOI1jwft9g1VybltZCduyRQPJPvc+zzKY9WPHxhPWczyFuYa6I8Mw4iU5A==} + json-schema-typed@8.0.2: + resolution: {integrity: sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==} json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} @@ -9806,10 +9797,6 @@ packages: resolution: {integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==} engines: {node: '>=14'} - locate-path@3.0.0: - resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==} - engines: {node: '>=6'} - locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} @@ -10365,10 +10352,6 @@ packages: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} - mimic-fn@3.1.0: - resolution: {integrity: sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==} - engines: {node: '>=8'} - mimic-function@5.0.1: resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} engines: {node: '>=18'} @@ -10768,10 +10751,6 @@ packages: resolution: {integrity: sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==} engines: {node: '>=18'} - p-locate@3.0.0: - resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==} - engines: {node: '>=6'} - p-locate@4.1.0: resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} engines: {node: '>=8'} @@ -10889,10 +10868,6 @@ packages: path-case@3.0.4: resolution: {integrity: sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==} - path-exists@3.0.0: - resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} - engines: {node: '>=4'} - path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -10989,10 +10964,6 @@ packages: pkg-types@2.3.0: resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==} - pkg-up@3.1.0: - resolution: {integrity: sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==} - engines: {node: '>=8'} - playwright-core@1.56.1: resolution: {integrity: sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==} engines: {node: '>=18'} @@ -12064,6 +12035,12 @@ packages: strnum@2.1.1: resolution: {integrity: sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==} + stubborn-fs@2.0.0: + resolution: {integrity: sha512-Y0AvSwDw8y+nlSNFXMm2g6L51rBGdAQT20J3YSOqxC53Lo3bjWRtr2BKcfYoAf352WYpsZSTURrA0tqhfgudPA==} + + stubborn-utils@1.0.2: + resolution: {integrity: sha512-zOh9jPYI+xrNOyisSelgym4tolKTJCQd5GBhK0+0xJvcYDcwlOoxF/rnFKQ2KRZknXSG9jWAp66fwP6AxN9STg==} + style-to-object@0.4.4: resolution: {integrity: sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==} @@ -12125,6 +12102,10 @@ packages: tabbable@6.3.0: resolution: {integrity: sha512-EIHvdY5bPLuWForiR/AN2Bxngzpuwn1is4asboytXtpTgsArc+WmSJKVLlhdh71u7jFcryDqB2A8lQvj78MkyQ==} + tagged-tag@1.0.0: + resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==} + engines: {node: '>=20'} + tar-fs@2.1.4: resolution: {integrity: sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==} @@ -12332,6 +12313,10 @@ packages: resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} engines: {node: '>=16'} + type-fest@5.2.0: + resolution: {integrity: sha512-xxCJm+Bckc6kQBknN7i9fnP/xobQRsRQxR01CztFkp/h++yfVxUUcmMgfR2HttJx/dpWjS9ubVuyspJv24Q9DA==} + engines: {node: '>=20'} + type-is@1.6.18: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'} @@ -12369,6 +12354,10 @@ packages: uid2@0.0.4: resolution: {integrity: sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==} + uint8array-extras@1.5.0: + resolution: {integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==} + engines: {node: '>=18'} + unc-path-regex@0.1.2: resolution: {integrity: sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==} engines: {node: '>=0.10.0'} @@ -12801,6 +12790,9 @@ packages: whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + when-exit@2.1.5: + resolution: {integrity: sha512-VGkKJ564kzt6Ms1dbgPP/yuIoQCrsFAnRbptpC5wOEsDaNsbCB2bnfnaA8i/vRs5tjUSEOtIuvl9/MyVsvQZCg==} + which-pm-runs@1.1.0: resolution: {integrity: sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==} engines: {node: '>=4'} @@ -19267,7 +19259,7 @@ snapshots: clean-stack: 2.2.0 indent-string: 4.0.0 - ajv-formats@2.1.1(ajv@8.17.1): + ajv-formats@3.0.1(ajv@8.17.1): optionalDependencies: ajv: 8.17.1 @@ -19477,7 +19469,10 @@ snapshots: atomic-sleep@1.0.0: {} - atomically@1.7.0: {} + atomically@2.1.0: + dependencies: + stubborn-fs: 2.0.0 + when-exit: 2.1.5 auto-bind@4.0.0: {} @@ -20086,18 +20081,17 @@ snapshots: tree-kill: 1.2.2 yargs: 17.7.2 - conf@10.2.0: + conf@15.0.2: dependencies: ajv: 8.17.1 - ajv-formats: 2.1.1(ajv@8.17.1) - atomically: 1.7.0 - debounce-fn: 4.0.0 - dot-prop: 6.0.1 - env-paths: 2.2.1 - json-schema-typed: 7.0.3 - onetime: 5.1.2 - pkg-up: 3.1.0 + ajv-formats: 3.0.1(ajv@8.17.1) + atomically: 2.1.0 + debounce-fn: 6.0.0 + dot-prop: 10.1.0 + env-paths: 3.0.0 + json-schema-typed: 8.0.2 semver: 7.7.3 + uint8array-extras: 1.5.0 confbox@0.1.8: {} @@ -20271,9 +20265,9 @@ snapshots: node-addon-api: 1.7.2 optional: true - debounce-fn@4.0.0: + debounce-fn@6.0.0: dependencies: - mimic-fn: 3.1.0 + mimic-function: 5.0.1 debounce@1.2.1: {} @@ -20410,9 +20404,9 @@ snapshots: no-case: 3.0.4 tslib: 2.8.1 - dot-prop@6.0.1: + dot-prop@10.1.0: dependencies: - is-obj: 2.0.0 + type-fest: 5.2.0 dotenv@16.6.1: {} @@ -20476,7 +20470,7 @@ snapshots: entities@6.0.1: {} - env-paths@2.2.1: {} + env-paths@3.0.0: {} error-ex@1.3.4: dependencies: @@ -21090,10 +21084,6 @@ snapshots: find-up-simple@1.0.1: {} - find-up@3.0.0: - dependencies: - locate-path: 3.0.0 - find-up@4.1.0: dependencies: locate-path: 5.0.0 @@ -21985,8 +21975,6 @@ snapshots: is-number@7.0.0: {} - is-obj@2.0.0: {} - is-path-inside@3.0.3: {} is-path-inside@4.0.0: {} @@ -22556,7 +22544,7 @@ snapshots: json-schema-traverse@1.0.0: {} - json-schema-typed@7.0.3: {} + json-schema-typed@8.0.2: {} json-stable-stringify-without-jsonify@1.0.1: {} @@ -22679,11 +22667,6 @@ snapshots: pkg-types: 2.3.0 quansync: 0.2.11 - locate-path@3.0.0: - dependencies: - p-locate: 3.0.0 - path-exists: 3.0.0 - locate-path@5.0.0: dependencies: p-locate: 4.1.0 @@ -23716,8 +23699,6 @@ snapshots: mimic-fn@2.1.0: {} - mimic-fn@3.1.0: {} - mimic-function@5.0.1: {} mimic-response@1.0.1: {} @@ -24125,10 +24106,6 @@ snapshots: dependencies: yocto-queue: 1.2.2 - p-locate@3.0.0: - dependencies: - p-limit: 2.3.0 - p-locate@4.1.0: dependencies: p-limit: 2.3.0 @@ -24289,8 +24266,6 @@ snapshots: dot-case: 3.0.4 tslib: 2.8.1 - path-exists@3.0.0: {} - path-exists@4.0.0: {} path-is-absolute@1.0.1: {} @@ -24384,10 +24359,6 @@ snapshots: exsolve: 1.0.8 pathe: 2.0.3 - pkg-up@3.1.0: - dependencies: - find-up: 3.0.0 - playwright-core@1.56.1: {} playwright@1.56.1: @@ -25692,6 +25663,12 @@ snapshots: strnum@2.1.1: {} + stubborn-fs@2.0.0: + dependencies: + stubborn-utils: 1.0.2 + + stubborn-utils@1.0.2: {} + style-to-object@0.4.4: dependencies: inline-style-parser: 0.1.1 @@ -25756,6 +25733,8 @@ snapshots: tabbable@6.3.0: {} + tagged-tag@1.0.0: {} + tar-fs@2.1.4: dependencies: chownr: 1.1.4 @@ -25944,6 +25923,10 @@ snapshots: type-fest@4.41.0: {} + type-fest@5.2.0: + dependencies: + tagged-tag: 1.0.0 + type-is@1.6.18: dependencies: media-typer: 0.3.0 @@ -25984,6 +25967,8 @@ snapshots: uid2@0.0.4: {} + uint8array-extras@1.5.0: {} + unc-path-regex@0.1.2: {} undici-types@6.21.0: {} @@ -26432,6 +26417,8 @@ snapshots: tr46: 0.0.3 webidl-conversions: 3.0.1 + when-exit@2.1.5: {} + which-pm-runs@1.1.0: {} which-pm@3.0.1: From bfe3cafacb45ec349520410d46d03adc56aa9819 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Tue, 25 Nov 2025 11:43:45 +1100 Subject: [PATCH 4/4] move cli-tests to tests2/ (node) --- pnpm-lock.yaml | 9 ++ tests/cli-tests/build.test.ts | 83 --------------- tests/cli-tests/fixtures/log-node-env.ts | 2 +- tests/cli-tests/fixtures/with-ts.ts | 3 +- tests2/cli.test.ts | 125 +++++++++++++++++++++++ tests2/package.json | 5 +- tests2/utils.ts | 115 +++++++++++++++++---- 7 files changed, 236 insertions(+), 106 deletions(-) delete mode 100644 tests/cli-tests/build.test.ts create mode 100644 tests2/cli.test.ts diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d93544854a4..145597d60b5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2493,9 +2493,18 @@ importers: '@prisma/internals': specifier: 6.5.0 version: 6.5.0(typescript@5.9.3) + next: + specifier: ^15.5.2 + version: 15.5.6(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) prisma: specifier: 6.5.0 version: 6.5.0(typescript@5.9.3) + react: + specifier: ^19.0.0 + version: 19.2.0 + react-dom: + specifier: ^19.0.0 + version: 19.2.0(react@19.2.0) packages: diff --git a/tests/cli-tests/build.test.ts b/tests/cli-tests/build.test.ts deleted file mode 100644 index e99fa062c3b..00000000000 --- a/tests/cli-tests/build.test.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { readFile } from 'node:fs/promises' -import execa from 'execa' -import ms from 'ms' - -import { - basicKeystoneConfig, - cliBinPath, - cliMock, - schemas, - symlinkKeystoneDeps, - testdir, -} from './utils' - -jest.setTimeout(ms('2 minutes')) // these tests are slow - -test("start errors when a build hasn't happened", async () => { - const cwd = await testdir({ - ...symlinkKeystoneDeps, - ...schemas, - 'keystone.js': basicKeystoneConfig, - }) - await expect(cliMock(cwd, 'start')).rejects.toEqual(new Error('You need to run "keystone build"')) -}) - -test('build works with typescript without the user defining a babel config', async () => { - const cwd = await testdir({ - ...symlinkKeystoneDeps, - ...schemas, - 'keystone.ts': await readFile(`${__dirname}/fixtures/with-ts.ts`, 'utf8'), - }) - const result = await execa('node', [cliBinPath, 'build'], { - reject: false, - all: true, - cwd, - env: { - NEXT_TELEMETRY_DISABLED: '1', - } as any, - }) - expect(result.stdout.includes('Compiled successfully')).toBe(true) - expect(result.stdout.includes('Generating static pages')).toBe(true) - expect(result.stdout.includes('Finalizing page optimization')).toBe(true) - expect(result.exitCode).toBe(0) -}) - -test('process.env.NODE_ENV is production in production', async () => { - const cwd = await testdir({ - ...symlinkKeystoneDeps, - ...schemas, - 'keystone.ts': await readFile(`${__dirname}/fixtures/log-node-env.ts`, 'utf8'), - }) - const result = await execa('node', [cliBinPath, 'build'], { - reject: false, - all: true, - cwd, - buffer: true, - env: { - NEXT_TELEMETRY_DISABLED: '1', - } as any, - }) - expect(result.exitCode).toBe(0) - const startResult = execa('node', [cliBinPath, 'start'], { - reject: false, - all: true, - cwd, - env: { - NODE_ENV: 'production', - NEXT_TELEMETRY_DISABLED: '1', - } as any, - }) - let output = '' - await new Promise(resolve => { - startResult.all!.on('data', data => { - output += data - if ( - output.includes('CLI-TESTS-NODE-ENV: production') && - output.includes('CLI-TESTS-NODE-ENV-EVAL: production') - ) { - resolve() - } - }) - }) - startResult.kill() -}) diff --git a/tests/cli-tests/fixtures/log-node-env.ts b/tests/cli-tests/fixtures/log-node-env.ts index 238866cf329..da92593a37a 100644 --- a/tests/cli-tests/fixtures/log-node-env.ts +++ b/tests/cli-tests/fixtures/log-node-env.ts @@ -11,7 +11,6 @@ export default config({ url: 'file:./app.db', prismaClientPath: 'node_modules/.testprisma/client', }, - ui: { isDisabled: true }, lists: { Todo: list({ access: allowAll, @@ -20,4 +19,5 @@ export default config({ }, }), }, + ui: { isDisabled: true }, }) diff --git a/tests/cli-tests/fixtures/with-ts.ts b/tests/cli-tests/fixtures/with-ts.ts index ca31369f2c3..e7606325819 100644 --- a/tests/cli-tests/fixtures/with-ts.ts +++ b/tests/cli-tests/fixtures/with-ts.ts @@ -1,6 +1,6 @@ import { config, list } from '@keystone-6/core' -import { text } from '@keystone-6/core/fields' import { allowAll } from '@keystone-6/core/access' +import { text } from '@keystone-6/core/fields' export type something = string @@ -18,4 +18,5 @@ export default config({ }, }), }, + ui: { isDisabled: true }, }) diff --git a/tests2/cli.test.ts b/tests2/cli.test.ts new file mode 100644 index 00000000000..d85c85c1f25 --- /dev/null +++ b/tests2/cli.test.ts @@ -0,0 +1,125 @@ +import assert from 'node:assert/strict' +import { describe, test } from 'node:test' +import { collect, spawnTestEnv } from './utils' +import { finished } from 'node:stream/promises' + +describe('keystone build', () => { + test('builds with next OK', async () => { + const k = await spawnTestEnv({ + 'keystone.js': ` +import { config, list } from '@keystone-6/core' +import { allowAll } from '@keystone-6/core/access' +import { text } from '@keystone-6/core/fields' + +export default config({ + db: { + provider: 'sqlite', + url: 'file:./app.db', + prismaClientPath: 'node_modules/.testprisma/client', + }, + lists: { + Todo: list({ + access: allowAll, + fields: { + title: text(), + }, + }), + }, +}) + `, + }, ['build']) + + k.stderr.pipe(process.stderr) + const stdout = collect(k.stdout).then(b => b.toString()) + await finished(k.stdout) + await new Promise(resolve => k.on('exit', resolve)) + + assert.ok((await stdout).includes('Generated GraphQL and Prisma schemas')) + assert.ok((await stdout).includes('Compiled successfully')) + assert.ok((await stdout).includes('Generating static pages')) + assert.ok((await stdout).includes('Finalizing page optimization')) + assert.equal(k.exitCode, 0) + }) + + test('builds typescript OK', async () => { + const k = await spawnTestEnv({ + 'keystone.ts': ` +import { config, list } from '@keystone-6/core' +import { allowAll } from '@keystone-6/core/access' +import { text } from '@keystone-6/core/fields' + +type something = string // the typescript under test + +export default config({ + db: { + provider: 'sqlite', + url: 'file:./app.db', + prismaClientPath: 'node_modules/.testprisma/client', + }, + lists: { + Todo: list({ + access: allowAll, + fields: { + title: text(), + }, + }), + }, + ui: { isDisabled: true }, +}) + `, + }, ['build']) + + k.stderr.pipe(process.stderr) + const stdout = collect(k.stdout).then(b => b.toString()) + // const stderr = collect(k.stdout).then(b => b.toString()) + await finished(k.stdout) + await new Promise(resolve => k.on('exit', resolve)) + + // console.log('output', await stdout) + // console.log('output', await stderr) + assert.ok((await stdout).includes('Generated GraphQL and Prisma schemas')) + assert.equal(k.exitCode, 0) + }) + + test('process.env is retained', async () => { + const k = await spawnTestEnv({ + 'keystone.ts': ` +import { config, list } from '@keystone-6/core' +import { allowAll } from '@keystone-6/core/access' +import { text } from '@keystone-6/core/fields' + +console.log('CLI-TESTS-NODE_ENV=' + process.env.NODE_ENV) +console.log('CLI-TESTS-NEXT_TELEMETRY_DISABLED=' + process.env.NEXT_TELEMETRY_DISABLED) + +export default config({ + db: { + provider: 'sqlite', + url: 'file:./app.db', + prismaClientPath: 'node_modules/.testprisma/client', + }, + lists: { + Todo: list({ + access: allowAll, + fields: { + title: text(), + }, + }), + }, + ui: { isDisabled: true }, +}) + `, + }, ['build'], { + NODE_ENV: 'production', + NEXT_TELEMETRY_DISABLED: '1', + }) + + k.stderr.pipe(process.stderr) + const stdout = collect(k.stdout).then(b => b.toString()) + await finished(k.stdout) + await new Promise(resolve => k.on('exit', resolve)) + + assert.ok((await stdout).includes('CLI-TESTS-NODE_ENV=production')) + assert.ok((await stdout).includes('CLI-TESTS-NEXT_TELEMETRY_DISABLED=1')) + assert.equal(k.exitCode, 0) + }) +}) diff --git a/tests2/package.json b/tests2/package.json index 59fc494739c..f33e9364023 100644 --- a/tests2/package.json +++ b/tests2/package.json @@ -7,6 +7,9 @@ "@prisma/client": "6.5.0", "@prisma/engines": "6.5.0", "@prisma/internals": "6.5.0", - "prisma": "6.5.0" + "next": "^15.5.2", + "prisma": "6.5.0", + "react": "^19.0.0", + "react-dom": "^19.0.0" } } diff --git a/tests2/utils.ts b/tests2/utils.ts index 0f60c9f8e09..9c0bbb7ff1d 100644 --- a/tests2/utils.ts +++ b/tests2/utils.ts @@ -1,8 +1,9 @@ +import { spawn } from 'node:child_process' import { randomBytes } from 'node:crypto' import { readdirSync } from 'node:fs' import fs from 'node:fs/promises' import { tmpdir } from 'node:os' -import path, { join } from 'node:path' +import path, { dirname, join } from 'node:path' import { after } from 'node:test' import { getPrismaClient, objectEnumValues } from '@prisma/client/runtime/library' @@ -82,6 +83,27 @@ async function getTestPrismaModule(prismaSchemaPath: string, schema: string) { .get(schema)! } +function resolveDatabaseUrl (url: string, schema: string, cwd: string) { + if (!url) throw new TypeError('Missing DATABASE_URL') + if (url.startsWith('file:')) { + url = `file:${join(cwd, 'test.db')}` // unique files + } + + if (url.startsWith('postgres:')) { + const parsed = new URL(url) + parsed.searchParams.set('schema', schema) // unique schemas + url = parsed.toString() + } + + if (url.startsWith('mysql:')) { + const parsed = new URL(url) + parsed.pathname = schema // unique names + url = parsed.toString() + } + + return url +} + type FloatingConfig = Omit< KeystoneConfigPre, 'db' @@ -104,25 +126,7 @@ export async function setupTestEnv( await fs.mkdir(cwd) } - let dbUrl = process.env.DATABASE_URL - if (!dbUrl) throw new TypeError('Missing DATABASE_URL') - - if (dbUrl.startsWith('file:')) { - dbUrl = `file:${join(cwd, 'test.db')}` // unique database files - } - - if (dbUrl.startsWith('postgres:')) { - const parsed = new URL(dbUrl) - parsed.searchParams.set('schema', random.replace(/^pg_/g, 'p__')) // unique schema names, ^pg_ is reserved by postgres - dbUrl = parsed.toString() - } - - if (dbUrl.startsWith('mysql:')) { - const parsed = new URL(dbUrl) - parsed.pathname = random // unique database names - dbUrl = parsed.toString() - } - + const dbUrl = resolveDatabaseUrl(process.env.DATABASE_URL ?? '', random, cwd) const system = createSystem( wrap( config({ @@ -178,6 +182,77 @@ export async function setupTestEnv( } as const } +async function symlinkKeystoneDeps (cwd: string) { + for (const pkg of [ + '@keystone-6/core', + '@prisma/engines', + '@prisma/client', + '@prisma/internals', + 'next', + 'prisma', + 'react', + 'react-dom', + 'typescript', + '@types/react', + '@types/node', + ]) { + const targetPath = dirname(require.resolve(`${pkg}/package.json`)) + const outputPath = path.join(cwd, `node_modules/${pkg}`) + await fs.mkdir(dirname(outputPath), { recursive: true }) + + const symlinkType = (await fs.stat(targetPath)).isDirectory() ? 'dir' : 'file' + await fs.symlink(targetPath, outputPath, symlinkType) + } +} + +export async function spawnTestEnv( + files: { [path: string]: string }, + commands: string[] = [], + env: Record = {}, + setupDatabase: boolean = false, +) { + const random = randomBytes(10).toString('base64url').toLowerCase() + .replace(/^pg_/g, 'p__') // ^pg_ is reserved by postgres + + const cwd = join(tmpdir(), `ks6-tests-${random}`) + try { + await fs.mkdir(cwd) + } catch (err) { + if ((err as any).code !== 'EEXIST') throw err + await fs.rm(cwd, { recursive: true }) + await fs.mkdir(cwd) + } + + for (const [path, contents] of Object.entries(files)) { + await fs.writeFile(join(cwd, path), contents) + } + + const dbUrl = resolveDatabaseUrl(process.env.DATABASE_URL ?? '', random, cwd) + if (setupDatabase) await createDatabase(dbUrl, cwd) + + await symlinkKeystoneDeps(cwd) + const binPath = require.resolve('@keystone-6/core/bin/cli.js') + + return spawn('/opt/homebrew/bin/node', [binPath, ...commands], { + cwd, + env: { + NODE_ENV: 'test', + DATABASE_URL: dbUrl, + ...env, + }, + detached: false, + }) +} + +export function collect (stream: NodeJS.ReadableStream) { + const chunks: Buffer[] = [] + return new Promise((resolve, reject) => { + stream.on('data', (chunk: Buffer) => chunks.push(chunk)) + stream.on('end', () => resolve(Buffer.concat(chunks))) + stream.on('error', reject) + }) +} + export function setupTestSuite({ config: config_, identifier,