Skip to content

Commit

Permalink
Factor out the config file compile step (#4867)
Browse files Browse the repository at this point in the history
  • Loading branch information
timleslie authored Feb 17, 2021
1 parent 36f4223 commit 370c0ee
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 17 deletions.
6 changes: 6 additions & 0 deletions .changeset/gold-houses-laugh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@keystone-next/admin-ui': major
'@keystone-next/keystone': patch
---

Removed generation of compiled configuration file from `generateAdminUI`. This is now handled by the `keystone-next build` command directly.
22 changes: 5 additions & 17 deletions packages-next/admin-ui/src/system/generateAdminUI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,23 +70,11 @@ export const generateAdminUI = async (
configFileExists,
projectAdminPath
);
const baseFiles = adminFiles.filter(x => !uniqueFiles.has(Path.normalize(x.outputPath)));

// FIXME: This path corresponds to the hardcoded value in CONFIG_PATH
const configModule = Path.join(projectAdminPath, '..', '..', 'keystone');
const outputDir = Path.join('pages', 'api');
const pathToConfig = Path.relative(Path.join(projectAdminPath, outputDir), configModule);
// this should always exist, the user should not be able to override it.
baseFiles.push({
mode: 'write',
outputPath: Path.join(outputDir, '__keystone_api_build.js'),
src: `
export { default as config } from ${serializePathForImport(pathToConfig)}
export default function (req, res) {
return res.status(500)
}`,
});
await Promise.all(baseFiles.map(file => writeAdminFile(file, projectAdminPath)));
await Promise.all(
adminFiles
.filter(x => !uniqueFiles.has(Path.normalize(x.outputPath)))
.map(file => writeAdminFile(file, projectAdminPath))
);

// Add files to pages/ which point to any files which exist in admin/pages
const userPagesDir = Path.join(process.cwd(), 'admin', 'pages');
Expand Down
37 changes: 37 additions & 0 deletions packages-next/keystone/src/scripts/build/build.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import Path from 'path';
import prettier from 'prettier';
import fs from 'fs-extra';
import { buildAdminUI, generateAdminUI } from '@keystone-next/admin-ui/system';
import { createSystem } from '../../lib/createSystem';
import { initConfig } from '../../lib/initConfig';
Expand All @@ -6,6 +9,37 @@ import { saveSchemaAndTypes } from '../../lib/saveSchemaAndTypes';
import { CONFIG_PATH } from '../utils';
import type { StaticPaths } from '..';

// FIXME: Duplicated from admin-ui package. Need to decide on a common home.
export function serializePathForImport(path: string) {
// JSON.stringify is important here because it will escape windows style paths(and any thing else that might potentionally be in there)
return JSON.stringify(
path
// Next is unhappy about imports that include .ts/tsx in them because TypeScript is unhappy with them becasue when doing a TypeScript compilation with tsc, the imports won't be written so they would be wrong there
.replace(/\.tsx?$/, '')
);
}

// FIXME: Duplicated from admin-ui package. Need to decide on a common home.
export const formatSource = (src: string, parser: 'babel' | 'babel-ts' = 'babel') =>
prettier.format(src, { parser, trailingComma: 'es5', singleQuote: true });

const reexportKeystoneConfig = async (projectAdminPath: string) => {
// We re-export the Keystone config file into the Admin UI project folder
// so that when we run the build step, we will end up with a compiled version
// of the configuration file in the .next/ directory. Even if we're not building
// an Admin UI, we still need to run the `build()` function so that this config
// file is correctly compiled.
const outputDir = Path.join(projectAdminPath, 'pages', 'api');
const pathToConfig = Path.relative(outputDir, CONFIG_PATH);
const file = `
export { default as config } from ${serializePathForImport(pathToConfig)}
export default function (req, res) {
return res.status(500)
}`;

await fs.outputFile(Path.join(outputDir, '__keystone_api_build.js'), formatSource(file));
};

export async function build({ dotKeystonePath, projectAdminPath }: StaticPaths) {
console.log('🤞 Building Keystone');

Expand All @@ -19,6 +53,9 @@ export async function build({ dotKeystonePath, projectAdminPath }: StaticPaths)
console.log('✨ Generating Admin UI code');
await generateAdminUI(config, graphQLSchema, keystone, projectAdminPath);

console.log('✨ Generating Keystone config code');
await reexportKeystoneConfig(projectAdminPath);

console.log('✨ Building Admin UI');
await buildAdminUI(projectAdminPath);

Expand Down
2 changes: 2 additions & 0 deletions packages-next/keystone/src/scripts/run/start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import * as fs from 'fs-extra';
export const start = async ({ dotKeystonePath, projectAdminPath }: StaticPaths) => {
console.log('🤞 Starting Keystone');

// This is the compiled version of the configuration which was generated during the build step.
// See reexportKeystoneConfig().
const apiFile = path.join(projectAdminPath, '.next/server/pages/api/__keystone_api_build.js');
if (!fs.existsSync(apiFile)) {
throw new Error('keystone-next build must be run before running keystone-next start');
Expand Down

1 comment on commit 370c0ee

@vercel
Copy link

@vercel vercel bot commented on 370c0ee Feb 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.