From ab739da002e3931c690554d7ab4287b456d3f3f7 Mon Sep 17 00:00:00 2001 From: mitchellhamilton Date: Tue, 2 Nov 2021 15:22:04 +1000 Subject: [PATCH 1/5] WIP --- examples/task-manager/keystone.ts | 5 +++ package.json | 3 +- packages/keystone/package.json | 4 +-- .../src/admin-ui/system/generateAdminUI.ts | 35 ++++++++++++------- yarn.lock | 2 +- 5 files changed, 32 insertions(+), 17 deletions(-) diff --git a/examples/task-manager/keystone.ts b/examples/task-manager/keystone.ts index 89001a1390f..72152380463 100644 --- a/examples/task-manager/keystone.ts +++ b/examples/task-manager/keystone.ts @@ -13,4 +13,9 @@ export default config({ }, }, lists, + ui: { + getAdditionalFiles: [ + () => [{ mode: 'write', outputPath: 'pages/api/blah/[...rest].js', src: '' }], + ], + }, }); diff --git a/package.json b/package.json index 418dcd9b877..0892e7ce8bc 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,6 @@ "@types/babel__core": "^7.1.16", "@types/jest": "^27.0.2", "@types/node-fetch": "^2.5.12", - "@types/normalize-path": "3.0.0", "@typescript-eslint/eslint-plugin": "^5.2.0", "@typescript-eslint/parser": "^5.2.0", "chalk-cli": "^5.0.0", @@ -159,4 +158,4 @@ "engines": { "node": "^12.20 || >= 14.13" } -} +} \ No newline at end of file diff --git a/packages/keystone/package.json b/packages/keystone/package.json index 0e09818416c..7335940547e 100644 --- a/packages/keystone/package.json +++ b/packages/keystone/package.json @@ -48,6 +48,7 @@ "@keystone-ui/segmented-control": "^5.0.1", "@keystone-ui/toast": "^4.0.4", "@keystone-ui/tooltip": "^4.0.3", + "@nodelib/fs.walk": "^1.2.8", "@preconstruct/next": "^3.0.1", "@prisma/client": "3.3.0", "@prisma/migrate": "3.3.0", @@ -106,7 +107,6 @@ "micro": "^9.3.4", "next": "^12.0.2", "node-fetch": "^2.6.5", - "normalize-path": "^3.0.0", "object-hash": "^2.2.0", "p-limit": "^2.3.0", "pirates": "^4.0.1", @@ -164,4 +164,4 @@ ] }, "repository": "https://github.com/keystonejs/keystone/tree/main/packages/keystone" -} +} \ No newline at end of file diff --git a/packages/keystone/src/admin-ui/system/generateAdminUI.ts b/packages/keystone/src/admin-ui/system/generateAdminUI.ts index a896a8aedff..57df486d76d 100644 --- a/packages/keystone/src/admin-ui/system/generateAdminUI.ts +++ b/packages/keystone/src/admin-ui/system/generateAdminUI.ts @@ -1,14 +1,17 @@ import Path from 'path'; +import { promisify } from 'util'; import fs from 'fs-extra'; - import fastGlob from 'fast-glob'; import resolve from 'resolve'; import { GraphQLSchema } from 'graphql'; -import normalizePath from 'normalize-path'; +import { walk as _walk } from '@nodelib/fs.walk'; +import { path } from 'filenamify'; import type { KeystoneConfig, AdminMetaRootVal, AdminFileToWrite } from '../../types'; import { writeAdminFiles } from '../templates'; import { serializePathForImport } from '../utils/serializePathForImport'; +const walk = promisify(_walk); + function getDoesAdminConfigExist() { try { const configPath = Path.join(process.cwd(), 'admin', 'config'); @@ -152,20 +155,28 @@ export const generateAdminUI = async ( // - we'll remove them when the user restarts the process if (isLiveReload) { // fast-glob expects unix style paths/globs in ignore so we need to normalize to that - const ignore = adminFiles.map(x => normalizePath(x.outputPath)); + const ignore = adminFiles.map(x => x.outputPath); ignore.push('.next'); ignore.push('next-env.d.ts'); ignore.push('public'); ignore.push('pages/api/__keystone_api_build.js'); - for (const filename of uniqueFiles) { - ignore.push(normalizePath(filename)); - } - const filesToDelete = await fastGlob(['**/*'], { - cwd: projectAdminPath, - ignore, - followSymbolicLinks: false, - absolute: true, + const ignoredDirs = new Set(['.next', 'public'].map(x => Path.resolve(projectAdminPath, x))); + const ignoredFiles = new Set( + [ + ...adminFiles.map(x => x.outputPath), + ...uniqueFiles, + 'next-env.d.ts', + 'pages/api/__keystone_api_build.js', + ].map(x => Path.resolve(projectAdminPath, x)) + ); + + const entries = await walk(projectAdminPath, { + deepFilter: entry => !ignoredDirs.has(entry.path), + entryFilter: entry => entry.dirent.isFile() && !ignoredFiles.has(entry.path), }); - await Promise.all(filesToDelete.map(filepath => fs.remove(filepath))); + + console.log(entries); + + await Promise.all(entries.map(entry => fs.remove(entry.path))); } }; diff --git a/yarn.lock b/yarn.lock index cdb4ddf85c2..298f0f2fd3c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1993,7 +1993,7 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== -"@nodelib/fs.walk@^1.2.3": +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": version "1.2.8" resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== From 4b7a94b1992a8fe8fdb7e402ccdf375af98dfbc5 Mon Sep 17 00:00:00 2001 From: mitchellhamilton Date: Tue, 2 Nov 2021 15:25:46 +1000 Subject: [PATCH 2/5] newlines --- package.json | 2 +- packages/keystone/package.json | 2 +- yarn.lock | 5 ----- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 0892e7ce8bc..5d73027a1f3 100644 --- a/package.json +++ b/package.json @@ -158,4 +158,4 @@ "engines": { "node": "^12.20 || >= 14.13" } -} \ No newline at end of file +} diff --git a/packages/keystone/package.json b/packages/keystone/package.json index 7335940547e..690f92d2be4 100644 --- a/packages/keystone/package.json +++ b/packages/keystone/package.json @@ -164,4 +164,4 @@ ] }, "repository": "https://github.com/keystonejs/keystone/tree/main/packages/keystone" -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index 298f0f2fd3c..400343b251a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2952,11 +2952,6 @@ resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw== -"@types/normalize-path@3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/normalize-path/-/normalize-path-3.0.0.tgz#bb5c46cab77b93350b4cf8d7ff1153f47189ae31" - integrity sha512-Nd8y/5t/7CRakPYiyPzr/IAfYusy1FkcZYFEAcoMZkwpJv2n4Wm+olW+e7xBdHEXhOnWdG9ddbar0gqZWS4x5Q== - "@types/parse-json@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" From 1bedb5afe98a645244c5c7a7dde221ab279dd708 Mon Sep 17 00:00:00 2001 From: mitchellhamilton Date: Tue, 2 Nov 2021 15:39:05 +1000 Subject: [PATCH 3/5] Add a test --- examples/task-manager/keystone.ts | 5 ----- .../keystone/src/admin-ui/system/generateAdminUI.ts | 8 -------- tests/admin-ui-tests/live-reloading.test.ts | 7 +++++++ tests/test-projects/live-reloading/keystone.ts | 11 +++++++++++ 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/examples/task-manager/keystone.ts b/examples/task-manager/keystone.ts index 72152380463..89001a1390f 100644 --- a/examples/task-manager/keystone.ts +++ b/examples/task-manager/keystone.ts @@ -13,9 +13,4 @@ export default config({ }, }, lists, - ui: { - getAdditionalFiles: [ - () => [{ mode: 'write', outputPath: 'pages/api/blah/[...rest].js', src: '' }], - ], - }, }); diff --git a/packages/keystone/src/admin-ui/system/generateAdminUI.ts b/packages/keystone/src/admin-ui/system/generateAdminUI.ts index 57df486d76d..7b1d18a760b 100644 --- a/packages/keystone/src/admin-ui/system/generateAdminUI.ts +++ b/packages/keystone/src/admin-ui/system/generateAdminUI.ts @@ -154,12 +154,6 @@ export const generateAdminUI = async ( // - they won't create pages in Admin UI which is really what this deleting is about avoiding // - we'll remove them when the user restarts the process if (isLiveReload) { - // fast-glob expects unix style paths/globs in ignore so we need to normalize to that - const ignore = adminFiles.map(x => x.outputPath); - ignore.push('.next'); - ignore.push('next-env.d.ts'); - ignore.push('public'); - ignore.push('pages/api/__keystone_api_build.js'); const ignoredDirs = new Set(['.next', 'public'].map(x => Path.resolve(projectAdminPath, x))); const ignoredFiles = new Set( [ @@ -175,8 +169,6 @@ export const generateAdminUI = async ( entryFilter: entry => entry.dirent.isFile() && !ignoredFiles.has(entry.path), }); - console.log(entries); - await Promise.all(entries.map(entry => fs.remove(entry.path))); } }; diff --git a/tests/admin-ui-tests/live-reloading.test.ts b/tests/admin-ui-tests/live-reloading.test.ts index 16dd335d54f..a76f213fd89 100644 --- a/tests/admin-ui-tests/live-reloading.test.ts +++ b/tests/admin-ui-tests/live-reloading.test.ts @@ -3,6 +3,7 @@ import fs from 'fs/promises'; import { Browser, Page, chromium } from 'playwright'; import { parse, print } from 'graphql'; import { ExecaChildProcess } from 'execa'; +import fetch from 'node-fetch'; import { generalStartKeystone, loadIndex, makeGqlRequest, promiseSignal } from './utils'; const gql = ([content]: TemplateStringsArray) => content; @@ -56,6 +57,12 @@ test('Creating an item with the GraphQL API and navigating to the item page for expect(value).toBe('blah'); }); +test('api routes written with getAdditionalFiles containing [...rest] work', async () => { + expect( + await fetch('http://localhost:3000/api/blah/asdasdas/das/da/sdad').then(x => x.text()) + ).toEqual('something'); +}); + test('changing the label of a field updates in the Admin UI', async () => { await replaceSchema('second'); diff --git a/tests/test-projects/live-reloading/keystone.ts b/tests/test-projects/live-reloading/keystone.ts index 8e86f606688..fc5248eeea7 100644 --- a/tests/test-projects/live-reloading/keystone.ts +++ b/tests/test-projects/live-reloading/keystone.ts @@ -8,4 +8,15 @@ export default config({ }, lists, extendGraphqlSchema, + ui: { + getAdditionalFiles: [ + () => [ + { + mode: 'write', + src: "export default function(req,res) {res.send('something')}", + outputPath: 'pages/api/blah/[...rest].js', + }, + ], + ], + }, }); From caf7f0631a6c3e5d69eb50d7cc351444e63cf790 Mon Sep 17 00:00:00 2001 From: mitchellhamilton Date: Tue, 2 Nov 2021 15:42:37 +1000 Subject: [PATCH 4/5] Changeset --- .changeset/fair-houses-kneel.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/fair-houses-kneel.md diff --git a/.changeset/fair-houses-kneel.md b/.changeset/fair-houses-kneel.md new file mode 100644 index 00000000000..4fe7353d149 --- /dev/null +++ b/.changeset/fair-houses-kneel.md @@ -0,0 +1,5 @@ +--- +'@keystone-next/keystone': patch +--- + +Fixed files with names including things like `[...rest]` created using `ui.getAdditionalFiles` being deleted after being written in dev. From e2366116256f92ea921e64cfe78ce66b6ee097bb Mon Sep 17 00:00:00 2001 From: mitchellhamilton Date: Tue, 2 Nov 2021 15:48:51 +1000 Subject: [PATCH 5/5] Remove bad import --- packages/keystone/src/admin-ui/system/generateAdminUI.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/keystone/src/admin-ui/system/generateAdminUI.ts b/packages/keystone/src/admin-ui/system/generateAdminUI.ts index 7b1d18a760b..8ab38076c70 100644 --- a/packages/keystone/src/admin-ui/system/generateAdminUI.ts +++ b/packages/keystone/src/admin-ui/system/generateAdminUI.ts @@ -5,7 +5,6 @@ import fastGlob from 'fast-glob'; import resolve from 'resolve'; import { GraphQLSchema } from 'graphql'; import { walk as _walk } from '@nodelib/fs.walk'; -import { path } from 'filenamify'; import type { KeystoneConfig, AdminMetaRootVal, AdminFileToWrite } from '../../types'; import { writeAdminFiles } from '../templates'; import { serializePathForImport } from '../utils/serializePathForImport';