From c1d7ec7204eb4c6b1bf3f7cd440ad1fbfaaf77d0 Mon Sep 17 00:00:00 2001 From: Dominic Saadi Date: Fri, 8 Mar 2024 16:22:10 +0100 Subject: [PATCH 01/24] work on linting --- .../src/auth/__tests__/authFiles.test.ts | 12 +- .../src/auth/__tests__/authTasks.test.ts | 4 +- packages/cli-helpers/src/auth/authFiles.ts | 126 +++++++++--------- packages/cli-helpers/src/auth/authTasks.ts | 6 +- .../src/lib/__tests__/index.test.ts | 6 +- packages/cli-helpers/src/lib/index.ts | 14 +- .../commands/experimental/setupRscHandler.js | 2 +- .../features/fragments/fragmentsHandler.ts | 10 +- .../trustedDocumentsHandler.ts | 6 +- .../setup/monitoring/sentry/sentryHandler.ts | 8 +- packages/cli/src/lib/index.js | 13 +- .../updateBabelConfig/updateBabelConfig.ts | 2 +- .../tsconfigForRouteHooks.ts | 2 +- .../configureFastify.yargs.ts | 4 +- packages/codemods/src/lib/prettify.ts | 15 ++- packages/internal/src/ts2js.ts | 17 ++- 16 files changed, 138 insertions(+), 109 deletions(-) diff --git a/packages/cli-helpers/src/auth/__tests__/authFiles.test.ts b/packages/cli-helpers/src/auth/__tests__/authFiles.test.ts index 01a19546d988..6107f663a0c3 100644 --- a/packages/cli-helpers/src/auth/__tests__/authFiles.test.ts +++ b/packages/cli-helpers/src/auth/__tests__/authFiles.test.ts @@ -39,9 +39,9 @@ beforeEach(() => { vi.mocked(isTypeScriptProject).mockReturnValue(true) }) -it('generates a record of TS files', () => { +it('generates a record of TS files', async () => { const filePaths = Object.keys( - apiSideFiles({ + await apiSideFiles({ basedir: path.join(__dirname, 'fixtures/supertokensSetup'), webAuthn: false, }) @@ -54,11 +54,11 @@ it('generates a record of TS files', () => { ]) }) -it('generates a record of JS files', () => { +it('generates a record of JS files', async () => { vi.mocked(isTypeScriptProject).mockReturnValue(false) const filePaths = Object.keys( - apiSideFiles({ + await apiSideFiles({ basedir: path.join(__dirname, 'fixtures/supertokensSetup'), webAuthn: false, }) @@ -71,8 +71,8 @@ it('generates a record of JS files', () => { ]) }) -it('generates a record of webAuthn files', () => { - const filesRecord = apiSideFiles({ +it('generates a record of webAuthn files', async () => { + const filesRecord = await apiSideFiles({ basedir: path.join(__dirname, 'fixtures/dbAuthSetup'), webAuthn: true, }) diff --git a/packages/cli-helpers/src/auth/__tests__/authTasks.test.ts b/packages/cli-helpers/src/auth/__tests__/authTasks.test.ts index 3427788359af..1b4a04d9c404 100644 --- a/packages/cli-helpers/src/auth/__tests__/authTasks.test.ts +++ b/packages/cli-helpers/src/auth/__tests__/authTasks.test.ts @@ -644,7 +644,7 @@ describe('authTasks', () => { ).toMatchSnapshot() }) - it('writes an auth.js file for JS projects', () => { + it('writes an auth.js file for JS projects', async () => { vi.mocked(isTypeScriptProject).mockReturnValue(false) vol.fromJSON({ @@ -656,7 +656,7 @@ describe('authTasks', () => { provider: 'auth0', setupMode: 'FORCE', } - createWebAuth(getPaths().base, false).task(ctx) + await createWebAuth(getPaths().base, false).task(ctx) expect( fs.readFileSync(path.join(getPaths().web.src, 'auth.js'), 'utf-8') diff --git a/packages/cli-helpers/src/auth/authFiles.ts b/packages/cli-helpers/src/auth/authFiles.ts index c64f48f8141a..6602a9089c7d 100644 --- a/packages/cli-helpers/src/auth/authFiles.ts +++ b/packages/cli-helpers/src/auth/authFiles.ts @@ -24,76 +24,76 @@ interface FilesArgs { * } * ``` */ -export const apiSideFiles = ({ basedir, webAuthn }: FilesArgs) => { +export const apiSideFiles = async ({ basedir, webAuthn }: FilesArgs) => { const apiSrcPath = getPaths().api.src const apiBaseTemplatePath = path.join(basedir, 'templates', 'api') const templateDirectories = fs.readdirSync(apiBaseTemplatePath) - const filesRecord = templateDirectories.reduce>( - (acc, dir) => { - const templateFiles = fs.readdirSync(path.join(apiBaseTemplatePath, dir)) - const filePaths = templateFiles - .filter((fileName) => { - const fileNameParts = fileName.split('.') - // Remove all webAuthn files. We'll handle those in the next step - return ( - fileNameParts.length <= 3 || fileNameParts.at(-3) !== 'webAuthn' - ) - }) - .map((fileName) => { - // remove "template" from the end, and change from {ts,tsx} to {js,jsx} for - // JavaScript projects - let outputFileName = fileName.replace(/\.template$/, '') - if (!isTypeScriptProject()) { - outputFileName = outputFileName.replace(/\.ts(x?)$/, '.js$1') - } - - if (!webAuthn) { - return { templateFileName: fileName, outputFileName } - } - - // Insert "webAuthn." before the second to last part - const webAuthnFileName = fileName - .split('.') - .reverse() - .map((part, i) => (i === 1 ? 'webAuthn.' + part : part)) - .reverse() - .join('.') - - // Favor the abc.xyz.webAuthn.ts.template file if it exists, otherwise - // just go with the "normal" filename - if (templateFiles.includes(webAuthnFileName)) { - return { templateFileName: webAuthnFileName, outputFileName } - } else { - return { templateFileName: fileName, outputFileName } - } - }) - .map((f) => { - const templateFilePath = path.join( - apiBaseTemplatePath, - dir, - f.templateFileName - ) - const outputFilePath = path.join(apiSrcPath, dir, f.outputFileName) - - return { templateFilePath, outputFilePath } - }) - - filePaths.forEach((paths) => { - const content = fs.readFileSync(paths.templateFilePath, 'utf8') - - acc = { - ...acc, - [paths.outputFilePath]: isTypeScriptProject() - ? content - : transformTSToJS(paths.outputFilePath, content), + const filesRecord = await templateDirectories.reduce< + Promise> + >(async (accP, dir) => { + const templateFiles = fs.readdirSync(path.join(apiBaseTemplatePath, dir)) + const filePaths = templateFiles + .filter((fileName) => { + const fileNameParts = fileName.split('.') + // Remove all webAuthn files. We'll handle those in the next step + return fileNameParts.length <= 3 || fileNameParts.at(-3) !== 'webAuthn' + }) + .map((fileName) => { + // remove "template" from the end, and change from {ts,tsx} to {js,jsx} for + // JavaScript projects + let outputFileName = fileName.replace(/\.template$/, '') + if (!isTypeScriptProject()) { + outputFileName = outputFileName.replace(/\.ts(x?)$/, '.js$1') + } + + if (!webAuthn) { + return { templateFileName: fileName, outputFileName } } + + // Insert "webAuthn." before the second to last part + const webAuthnFileName = fileName + .split('.') + .reverse() + .map((part, i) => (i === 1 ? 'webAuthn.' + part : part)) + .reverse() + .join('.') + + // Favor the abc.xyz.webAuthn.ts.template file if it exists, otherwise + // just go with the "normal" filename + if (templateFiles.includes(webAuthnFileName)) { + return { templateFileName: webAuthnFileName, outputFileName } + } else { + return { templateFileName: fileName, outputFileName } + } + }) + .map((f) => { + const templateFilePath = path.join( + apiBaseTemplatePath, + dir, + f.templateFileName + ) + const outputFilePath = path.join(apiSrcPath, dir, f.outputFileName) + + return { templateFilePath, outputFilePath } }) - return acc - }, - {} - ) + const acc = await accP + let nextAcc = {} + + for (const paths of filePaths) { + const content = fs.readFileSync(paths.templateFilePath, 'utf8') + + nextAcc = { + ...acc, + [paths.outputFilePath]: isTypeScriptProject() + ? content + : await transformTSToJS(paths.outputFilePath, content), + } + } + + return nextAcc + }, Promise.resolve({})) return filesRecord } diff --git a/packages/cli-helpers/src/auth/authTasks.ts b/packages/cli-helpers/src/auth/authTasks.ts index c4d515c7e6d2..8c90351d4a93 100644 --- a/packages/cli-helpers/src/auth/authTasks.ts +++ b/packages/cli-helpers/src/auth/authTasks.ts @@ -362,7 +362,7 @@ export const createWebAuth = (basedir: string, webAuthn: boolean) => { return { title: `Creating web/src/auth.${ext}`, - task: (ctx: AuthGeneratorCtx) => { + task: async (ctx: AuthGeneratorCtx) => { // @MARK - finding unused file name here, // We should only use an unused filename, if the user is CHOOSING not to replace the existing provider @@ -399,7 +399,7 @@ export const createWebAuth = (basedir: string, webAuthn: boolean) => { template = isTSProject ? template - : transformTSToJS(authFileName, template) + : await transformTSToJS(authFileName, template) fs.writeFileSync(authFileName, template) }, @@ -448,7 +448,7 @@ export const generateAuthApiFiles = ( // The keys in `filesRecord` are the full paths to where the file contents, // which is the values in `filesRecord`, will be written. - let filesRecord = apiSideFiles({ basedir, webAuthn }) + let filesRecord = await apiSideFiles({ basedir, webAuthn }) // Always overwrite files in force mode, no need to prompt let existingFiles: ExistingFiles = 'FAIL' diff --git a/packages/cli-helpers/src/lib/__tests__/index.test.ts b/packages/cli-helpers/src/lib/__tests__/index.test.ts index e2592f4fac2d..b58cd68274f8 100644 --- a/packages/cli-helpers/src/lib/__tests__/index.test.ts +++ b/packages/cli-helpers/src/lib/__tests__/index.test.ts @@ -12,7 +12,7 @@ vi.mock('../paths', () => { } }) -test('prettify formats tsx content', () => { +test('prettify formats tsx content', async () => { const content = `import React from 'react' interface Props { foo: number, bar: number } @@ -30,5 +30,7 @@ test('prettify formats tsx content', () => { return <>{foo}, {bar}}` - expect(prettify('FooBarComponent.template.tsx', content)).toMatchSnapshot() + expect( + await prettify('FooBarComponent.template.tsx', content) + ).toMatchSnapshot() }) diff --git a/packages/cli-helpers/src/lib/index.ts b/packages/cli-helpers/src/lib/index.ts index 1bc77ed61bea..a90bce84bdc3 100644 --- a/packages/cli-helpers/src/lib/index.ts +++ b/packages/cli-helpers/src/lib/index.ts @@ -52,9 +52,11 @@ export const transformTSToJS = (filename: string, content: string) => { /** * This returns the config present in `prettier.config.js` of a Redwood project. */ -export const prettierOptions = () => { +export const getPrettierOptions = async () => { try { - const options = require(path.join(getPaths().base, 'prettier.config.js')) + const options = await import( + path.join(getPaths().base, 'prettier.config.js') + ) if (options.tailwindConfig?.startsWith('.')) { // Make this work with --cwd @@ -70,10 +72,10 @@ export const prettierOptions = () => { } } -export const prettify = ( +export const prettify = async ( templateFilename: string, renderedTemplate: string -): string => { +): Promise => { // We format .js and .css templates, we need to tell prettier which parser // we're using. // https://prettier.io/docs/en/options.html#parser @@ -88,8 +90,10 @@ export const prettify = ( return renderedTemplate } + const prettierOptions = await getPrettierOptions() + return format(renderedTemplate, { - ...prettierOptions(), + ...prettierOptions, parser, }) } diff --git a/packages/cli/src/commands/experimental/setupRscHandler.js b/packages/cli/src/commands/experimental/setupRscHandler.js index b0ae3a54959c..2dbddc3eb0ce 100644 --- a/packages/cli/src/commands/experimental/setupRscHandler.js +++ b/packages/cli/src/commands/experimental/setupRscHandler.js @@ -303,7 +303,7 @@ export const handler = async ({ force, verbose }) => { writeFile( tsconfigPath, - prettify('tsconfig.json', JSON.stringify(tsconfig, null, 2)), + await prettify('tsconfig.json', JSON.stringify(tsconfig, null, 2)), { overwriteExisting: true, } diff --git a/packages/cli/src/commands/setup/graphql/features/fragments/fragmentsHandler.ts b/packages/cli/src/commands/setup/graphql/features/fragments/fragmentsHandler.ts index b9bb28c41b50..fc7ec0b03670 100644 --- a/packages/cli/src/commands/setup/graphql/features/fragments/fragmentsHandler.ts +++ b/packages/cli/src/commands/setup/graphql/features/fragments/fragmentsHandler.ts @@ -5,7 +5,11 @@ import execa from 'execa' import { Listr } from 'listr2' import { format } from 'prettier' -import { colors, prettierOptions, setTomlSetting } from '@redwoodjs/cli-helpers' +import { + colors, + getPrettierOptions, + setTomlSetting, +} from '@redwoodjs/cli-helpers' import { getConfig, getPaths } from '@redwoodjs/project-config' import type { Args } from './fragments' @@ -67,8 +71,10 @@ export async function handler({ force }: Args) { const appPath = getPaths().web.app const source = fs.readFileSync(appPath, 'utf-8') + const prettierOptions = await getPrettierOptions() + const prettifiedApp = format(source, { - ...prettierOptions(), + ...prettierOptions, parser: 'babel-ts', }) diff --git a/packages/cli/src/commands/setup/graphql/features/trustedDocuments/trustedDocumentsHandler.ts b/packages/cli/src/commands/setup/graphql/features/trustedDocuments/trustedDocumentsHandler.ts index e3e959ee9493..a3a60a9d2d09 100644 --- a/packages/cli/src/commands/setup/graphql/features/trustedDocuments/trustedDocumentsHandler.ts +++ b/packages/cli/src/commands/setup/graphql/features/trustedDocuments/trustedDocumentsHandler.ts @@ -5,7 +5,7 @@ import execa from 'execa' import { Listr } from 'listr2' import { format } from 'prettier' -import { prettierOptions, setTomlSetting } from '@redwoodjs/cli-helpers' +import { getPrettierOptions, setTomlSetting } from '@redwoodjs/cli-helpers' import { getConfig, getPaths, resolveFile } from '@redwoodjs/project-config' import { runTransform } from '../fragments/runTransform.js' @@ -62,8 +62,10 @@ export async function handler({ force }: { force: boolean }) { const source = fs.readFileSync(graphqlPath, 'utf-8') + const prettierOptions = await getPrettierOptions() + const prettifiedApp = format(source, { - ...prettierOptions(), + ...prettierOptions, parser: 'babel-ts', }) diff --git a/packages/cli/src/commands/setup/monitoring/sentry/sentryHandler.ts b/packages/cli/src/commands/setup/monitoring/sentry/sentryHandler.ts index 607a6d28a506..f0db2436f939 100644 --- a/packages/cli/src/commands/setup/monitoring/sentry/sentryHandler.ts +++ b/packages/cli/src/commands/setup/monitoring/sentry/sentryHandler.ts @@ -54,7 +54,7 @@ export const handler = async ({ force }: Args) => { }, { title: 'Implementing the Envelop plugin', - task: (ctx) => { + task: async (ctx) => { const graphqlHandlerPath = path.join( rwPaths.api.functions, `graphql.${extension}` @@ -95,13 +95,13 @@ export const handler = async ({ force }: Args) => { fs.writeFileSync( graphqlHandlerPath, - prettify('graphql.ts', contentLines.join('\n')) + await prettify('graphql.ts', contentLines.join('\n')) ) }, }, { title: "Replacing Redwood's Error boundary", - task: () => { + task: async () => { const contentLines = fs .readFileSync(rwPaths.web.app) .toString() @@ -136,7 +136,7 @@ export const handler = async ({ force }: Args) => { fs.writeFileSync( rwPaths.web.app, - prettify('App.tsx', contentLines.join('\n')) + await prettify('App.tsx', contentLines.join('\n')) ) }, }, diff --git a/packages/cli/src/lib/index.js b/packages/cli/src/lib/index.js index 835b6ea8d7a7..f5ccb4bb0353 100644 --- a/packages/cli/src/lib/index.js +++ b/packages/cli/src/lib/index.js @@ -81,7 +81,7 @@ export const generateTemplate = (templateFilename, { name, ...rest }) => { } } -export const prettify = (templateFilename, renderedTemplate) => { +export const prettify = async (templateFilename, renderedTemplate) => { // We format .js and .css templates, we need to tell prettier which parser // we're using. // https://prettier.io/docs/en/options.html#parser @@ -97,8 +97,10 @@ export const prettify = (templateFilename, renderedTemplate) => { return renderedTemplate } + const prettierOptions = await getPrettierOptions() + return format(renderedTemplate, { - ...prettierOptions(), + ...prettierOptions, parser, }) } @@ -228,9 +230,12 @@ export const getConfig = () => { /** * This returns the config present in `prettier.config.js` of a Redwood project. */ -export const prettierOptions = () => { +export const getPrettierOptions = async () => { try { - return require(path.join(getPaths().base, 'prettier.config.js')) + const prettierOptions = await import( + path.join(getPaths().base, 'prettier.config.js') + ) + return prettierOptions } catch (e) { // If we're in our vitest environment we want to return a consistent set of prettier options // such that snapshots don't change unexpectedly. diff --git a/packages/codemods/src/codemods/v0.39.x/updateBabelConfig/updateBabelConfig.ts b/packages/codemods/src/codemods/v0.39.x/updateBabelConfig/updateBabelConfig.ts index 863bfb8aad61..b1325c779f0e 100644 --- a/packages/codemods/src/codemods/v0.39.x/updateBabelConfig/updateBabelConfig.ts +++ b/packages/codemods/src/codemods/v0.39.x/updateBabelConfig/updateBabelConfig.ts @@ -51,7 +51,7 @@ export const removeBabelConfig = async () => { const newConfig = `module.exports = ${JSON.stringify(otherConfig)}` - fs.writeFileSync(webBabelConfigPath, prettify(newConfig)) + fs.writeFileSync(webBabelConfigPath, await prettify(newConfig)) } } } diff --git a/packages/codemods/src/codemods/v2.3.x/tsconfigForRouteHooks/tsconfigForRouteHooks.ts b/packages/codemods/src/codemods/v2.3.x/tsconfigForRouteHooks/tsconfigForRouteHooks.ts index bd30a857a289..d081b8d8d097 100644 --- a/packages/codemods/src/codemods/v2.3.x/tsconfigForRouteHooks/tsconfigForRouteHooks.ts +++ b/packages/codemods/src/codemods/v2.3.x/tsconfigForRouteHooks/tsconfigForRouteHooks.ts @@ -41,7 +41,7 @@ export default async function addApiAliasToTsConfig() { ts.sys.writeFile( webConfigPath, // @NOTE: prettier will remove trailing commas, but whatever - prettify(JSON.stringify(updatedConfig), { parser: 'json' }) + await prettify(JSON.stringify(updatedConfig), { parser: 'json' }) ) } else { throw new Error( diff --git a/packages/codemods/src/codemods/v2.x.x/configureFastify/configureFastify.yargs.ts b/packages/codemods/src/codemods/v2.x.x/configureFastify/configureFastify.yargs.ts index 8180f0901c6e..a55f573bf45a 100644 --- a/packages/codemods/src/codemods/v2.x.x/configureFastify/configureFastify.yargs.ts +++ b/packages/codemods/src/codemods/v2.x.x/configureFastify/configureFastify.yargs.ts @@ -36,7 +36,7 @@ export const handler = () => { // They don't show up in tests cause we run prettier. Let's do the same here. fs.writeFileSync( API_SERVER_CONFIG_PATH, - prettify(fs.readFileSync(API_SERVER_CONFIG_PATH, 'utf-8')) + await prettify(fs.readFileSync(API_SERVER_CONFIG_PATH, 'utf-8')) ) setOutput('All done!') @@ -51,7 +51,7 @@ export const handler = () => { 'server.config.js' ) - fs.writeFileSync(NEW_API_SERVER_CONFIG_PATH, prettify(text)) + fs.writeFileSync(NEW_API_SERVER_CONFIG_PATH, await prettify(text)) setOutput( 'Done! No server.config.js found, so we updated your project to use the latest version.' diff --git a/packages/codemods/src/lib/prettify.ts b/packages/codemods/src/lib/prettify.ts index 7a2927f24e85..273931c2d66e 100644 --- a/packages/codemods/src/lib/prettify.ts +++ b/packages/codemods/src/lib/prettify.ts @@ -4,21 +4,26 @@ import { format } from 'prettier' import { getPaths } from '@redwoodjs/project-config' -const getPrettierConfig = () => { +const getPrettierConfig = async () => { try { - return require(path.join(getPaths().base, 'prettier.config.js')) + const prettierConfig = await import( + path.join(getPaths().base, 'prettier.config.js') + ) + return prettierConfig } catch (e) { return undefined } } -const prettify = (code: string, options: Record = {}) => - format(code, { +const prettify = async (code: string, options: Record = {}) => { + const prettierConfig = await getPrettierConfig() + return format(code, { singleQuote: true, semi: false, - ...getPrettierConfig(), + ...prettierConfig, parser: 'babel', ...options, }) +} export default prettify diff --git a/packages/internal/src/ts2js.ts b/packages/internal/src/ts2js.ts index 31e483801e00..fb2a05a56e5e 100644 --- a/packages/internal/src/ts2js.ts +++ b/packages/internal/src/ts2js.ts @@ -33,12 +33,12 @@ export const convertTsScriptsToJs = (cwd = getPaths().base) => { * @param {string} cwd - Current directory * @param {string[]} files - Collection of files to convert */ -export const convertTsFilesToJs = (cwd: string, files: string[]) => { +export const convertTsFilesToJs = async (cwd: string, files: string[]) => { if (files.length === 0) { console.log('No TypeScript files found to convert to JS in this project.') } for (const f of files) { - const code = transformTSToJS(f) + const code = await transformTSToJS(f) if (code) { fs.writeFileSync( path.join(cwd, f.replace('.tsx', '.jsx').replace('.ts', '.js')), @@ -117,9 +117,12 @@ export const transformTSToJS = (file: string) => { return prettify(result.code, filename.replace(/\.ts$/, '.js')) } -export const prettierConfig = () => { +export const getPrettierConfig = async () => { try { - return require(path.join(getPaths().base, 'prettier.config.js')) + const prettierConfig = await import( + path.join(getPaths().base, 'prettier.config.js') + ) + return prettierConfig } catch (e) { return undefined } @@ -152,15 +155,17 @@ const prettierParser = (filename: string) => { * @param {string} code * @param {string} filename */ -export const prettify = (code: string, filename: string) => { +export const prettify = async (code: string, filename: string) => { const parser = prettierParser(filename) // Return unformatted code if we could not determine the parser. if (typeof parser === 'undefined') { return code } + const prettierConfig = await getPrettierConfig() + return format(code, { - ...prettierConfig(), + ...prettierConfig, parser, }) } From d840b97a6aed4e5b00eea79178e5043ccd3c71a2 Mon Sep 17 00:00:00 2001 From: Dominic Saadi Date: Fri, 8 Mar 2024 16:31:47 +0100 Subject: [PATCH 02/24] refactor out reduce --- packages/cli-helpers/src/auth/authFiles.ts | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/packages/cli-helpers/src/auth/authFiles.ts b/packages/cli-helpers/src/auth/authFiles.ts index 6602a9089c7d..2ba0efbd3f08 100644 --- a/packages/cli-helpers/src/auth/authFiles.ts +++ b/packages/cli-helpers/src/auth/authFiles.ts @@ -29,9 +29,9 @@ export const apiSideFiles = async ({ basedir, webAuthn }: FilesArgs) => { const apiBaseTemplatePath = path.join(basedir, 'templates', 'api') const templateDirectories = fs.readdirSync(apiBaseTemplatePath) - const filesRecord = await templateDirectories.reduce< - Promise> - >(async (accP, dir) => { + let filesRecord = {} + + for (const dir of templateDirectories) { const templateFiles = fs.readdirSync(path.join(apiBaseTemplatePath, dir)) const filePaths = templateFiles .filter((fileName) => { @@ -78,22 +78,17 @@ export const apiSideFiles = async ({ basedir, webAuthn }: FilesArgs) => { return { templateFilePath, outputFilePath } }) - const acc = await accP - let nextAcc = {} - for (const paths of filePaths) { const content = fs.readFileSync(paths.templateFilePath, 'utf8') - nextAcc = { - ...acc, + filesRecord = { + ...filesRecord, [paths.outputFilePath]: isTypeScriptProject() ? content : await transformTSToJS(paths.outputFilePath, content), } } - - return nextAcc - }, Promise.resolve({})) + } return filesRecord } From 1d9ceb624753b2396178e918b8a949228a8d1c5a Mon Sep 17 00:00:00 2001 From: Dominic Saadi Date: Fri, 8 Mar 2024 16:45:23 +0100 Subject: [PATCH 03/24] get db auth tests passing --- .../generate/dbAuth/__tests__/dbAuth.test.js | 12 ++--- .../src/commands/generate/dbAuth/dbAuth.js | 51 ++++++++++--------- packages/cli/src/commands/generate/helpers.js | 4 +- 3 files changed, 34 insertions(+), 33 deletions(-) diff --git a/packages/cli/src/commands/generate/dbAuth/__tests__/dbAuth.test.js b/packages/cli/src/commands/generate/dbAuth/__tests__/dbAuth.test.js index 0050ee66add4..a1e3e621b144 100644 --- a/packages/cli/src/commands/generate/dbAuth/__tests__/dbAuth.test.js +++ b/packages/cli/src/commands/generate/dbAuth/__tests__/dbAuth.test.js @@ -67,22 +67,22 @@ describe('dbAuth', () => { vol.fromJSON(mockFiles) }) - it('creates a login page', () => { - expect(dbAuth.files(true, false)).toHaveProperty([ + it('creates a login page', async () => { + expect(await dbAuth.files(true, false)).toHaveProperty([ path.normalize('/path/to/project/web/src/pages/LoginPage/LoginPage.jsx'), ]) }) - it('creates a signup page', () => { - expect(dbAuth.files(true, false)).toHaveProperty([ + it('creates a signup page', async () => { + expect(await dbAuth.files(true, false)).toHaveProperty([ path.normalize( '/path/to/project/web/src/pages/SignupPage/SignupPage.jsx' ), ]) }) - it('creates a scaffold CSS file', () => { - expect(dbAuth.files(true, false)).toHaveProperty([ + it('creates a scaffold CSS file', async () => { + expect(await dbAuth.files(true, false)).toHaveProperty([ path.normalize('/path/to/project/web/src/scaffold.css'), ]) }) diff --git a/packages/cli/src/commands/generate/dbAuth/dbAuth.js b/packages/cli/src/commands/generate/dbAuth/dbAuth.js index 00924554e756..94581d256932 100644 --- a/packages/cli/src/commands/generate/dbAuth/dbAuth.js +++ b/packages/cli/src/commands/generate/dbAuth/dbAuth.js @@ -123,7 +123,7 @@ export const builder = (yargs) => { }) } -export const files = ({ +export const files = async ({ _tests, typescript, skipForgot, @@ -150,7 +150,7 @@ export const files = ({ if (!skipForgot) { files.push( - templateForComponentFile({ + await templateForComponentFile({ name: 'ForgotPassword', suffix: 'Page', extension: typescript ? '.tsx' : '.jsx', @@ -164,7 +164,7 @@ export const files = ({ if (!skipLogin) { files.push( - templateForComponentFile({ + await templateForComponentFile({ name: 'Login', suffix: 'Page', extension: typescript ? '.tsx' : '.jsx', @@ -180,7 +180,7 @@ export const files = ({ if (!skipReset) { files.push( - templateForComponentFile({ + await templateForComponentFile({ name: 'ResetPassword', suffix: 'Page', extension: typescript ? '.tsx' : '.jsx', @@ -194,7 +194,7 @@ export const files = ({ if (!skipSignup) { files.push( - templateForComponentFile({ + await templateForComponentFile({ name: 'Signup', suffix: 'Page', extension: typescript ? '.tsx' : '.jsx', @@ -214,7 +214,7 @@ export const files = ({ // add scaffold CSS file if it doesn't exist already const scaffoldOutputPath = path.join(getPaths().web.src, 'scaffold.css') if (!fs.existsSync(scaffoldOutputPath)) { - const scaffoldTemplate = generateTemplate( + const scaffoldTemplate = await generateTemplate( path.join( __dirname, '../scaffold/templates/assets/scaffold.css.template' @@ -225,18 +225,20 @@ export const files = ({ files.push([scaffoldOutputPath, scaffoldTemplate]) } - return files.reduce((acc, [outputPath, content]) => { + return files.reduce(async (accP, [outputPath, content]) => { + const acc = await accP + let template = content if (outputPath.match(/\.[jt]sx?/) && !typescript) { - template = transformTSToJS(outputPath, content) + template = await transformTSToJS(outputPath, content) } return { [outputPath]: template, ...acc, } - }, {}) + }, Promise.resolve({})) } const tasks = ({ @@ -327,22 +329,21 @@ const tasks = ({ { title: 'Creating pages...', task: async () => { - return writeFilesTask( - files({ - tests, - typescript, - skipForgot, - skipLogin, - skipReset, - skipSignup, - webauthn, - usernameLabel, - passwordLabel, - }), - { - overwriteExisting: force, - } - ) + const filesObj = await files({ + tests, + typescript, + skipForgot, + skipLogin, + skipReset, + skipSignup, + webauthn, + usernameLabel, + passwordLabel, + }) + + return writeFilesTask(filesObj, { + overwriteExisting: force, + }) }, }, { diff --git a/packages/cli/src/commands/generate/helpers.js b/packages/cli/src/commands/generate/helpers.js index c17bb6eb2985..0b8ad76e3518 100644 --- a/packages/cli/src/commands/generate/helpers.js +++ b/packages/cli/src/commands/generate/helpers.js @@ -48,7 +48,7 @@ export const customOrDefaultTemplatePath = ({ */ // TODO: Make this read all the files in a template directory instead of // manually passing in each file. -export const templateForComponentFile = ({ +export const templateForComponentFile = async ({ name, suffix = '', extension = '.js', @@ -72,7 +72,7 @@ export const templateForComponentFile = ({ templatePath, side: webPathSection ? 'web' : 'api', }) - const content = generateTemplate(fullTemplatePath, { + const content = await generateTemplate(fullTemplatePath, { name, outputPath: ensurePosixPath( `./${path.relative(getPaths().base, componentOutputPath)}` From 9ba84c518474b7612e07a8dea5da58fba8df4776 Mon Sep 17 00:00:00 2001 From: Dominic Saadi Date: Fri, 8 Mar 2024 16:49:55 +0100 Subject: [PATCH 04/24] get helpers tests passing --- .../generate/__tests__/helpers.test.js | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/packages/cli/src/commands/generate/__tests__/helpers.test.js b/packages/cli/src/commands/generate/__tests__/helpers.test.js index 5383ea2156fc..f9a86508de90 100644 --- a/packages/cli/src/commands/generate/__tests__/helpers.test.js +++ b/packages/cli/src/commands/generate/__tests__/helpers.test.js @@ -79,11 +79,11 @@ test('customOrDefaultTemplatePath returns the app path with proper side, generat ) }) -test('templateForComponentFile creates a proper output path for files', () => { +test('templateForComponentFile creates a proper output path for files', async () => { const names = ['FooBar', 'fooBar', 'foo-bar', 'foo_bar'] - names.forEach((name) => { - const output = helpers.templateForComponentFile({ + for (const name of names) { + const output = await helpers.templateForComponentFile({ name: name, suffix: 'Page', webPathSection: 'pages', @@ -95,14 +95,14 @@ test('templateForComponentFile creates a proper output path for files', () => { expect(output[0]).toEqual( path.normalize('/path/to/project/web/src/pages/FooBarPage/FooBarPage.js') ) - }) + } }) -test('templateForComponentFile creates a proper output path for files with all caps in component name', () => { +test('templateForComponentFile creates a proper output path for files with all caps in component name', async () => { const names = ['FOO_BAR', 'FOO-BAR', 'FOOBAR'] - names.forEach((name) => { - const output = helpers.templateForComponentFile({ + for (const name of names) { + const output = await helpers.templateForComponentFile({ name: name, suffix: 'Page', webPathSection: 'pages', @@ -114,14 +114,14 @@ test('templateForComponentFile creates a proper output path for files with all c expect(output[0]).toEqual( path.normalize('/path/to/project/web/src/pages/FOOBARPage/FOOBARPage.js') ) - }) + } }) -test('templateForComponentFile creates a proper output path for files for starting with uppercase and ending with lowercase', () => { +test('templateForComponentFile creates a proper output path for files for starting with uppercase and ending with lowercase', async () => { const names = ['FOOBar', 'FOO-Bar', 'FOO_Bar'] - names.forEach((name) => { - const output = helpers.templateForComponentFile({ + for (const name of names) { + const output = await helpers.templateForComponentFile({ name: name, suffix: 'Page', webPathSection: 'pages', @@ -133,14 +133,14 @@ test('templateForComponentFile creates a proper output path for files for starti expect(output[0]).toEqual( path.normalize('/path/to/project/web/src/pages/FOOBarPage/FOOBarPage.js') ) - }) + } }) -test('templateForComponentFile creates a proper output path for files with uppercase after special characters in component name', () => { +test('templateForComponentFile creates a proper output path for files with uppercase after special characters in component name', async () => { const names = ['ABtest', 'aBtest', 'a-Btest', 'a_Btest'] - names.forEach((name) => { - const output = helpers.templateForComponentFile({ + for (const name of names) { + const output = await helpers.templateForComponentFile({ name: name, suffix: 'Page', webPathSection: 'pages', @@ -152,11 +152,11 @@ test('templateForComponentFile creates a proper output path for files with upper expect(output[0]).toEqual( path.normalize('/path/to/project/web/src/pages/ABtestPage/ABtestPage.js') ) - }) + } }) -test('templateForComponentFile can create a path in /web', () => { - const output = helpers.templateForComponentFile({ +test('templateForComponentFile can create a path in /web', async () => { + const output = await helpers.templateForComponentFile({ name: 'Home', suffix: 'Page', webPathSection: 'pages', @@ -170,8 +170,8 @@ test('templateForComponentFile can create a path in /web', () => { ) }) -test('templateForComponentFile can create a path in /api', () => { - const output = helpers.templateForComponentFile({ +test('templateForComponentFile can create a path in /api', async () => { + const output = await helpers.templateForComponentFile({ name: 'Home', suffix: 'Page', apiPathSection: 'services', @@ -185,8 +185,8 @@ test('templateForComponentFile can create a path in /api', () => { ) }) -test('templateForComponentFile can override generated component name', () => { - const output = helpers.templateForComponentFile({ +test('templateForComponentFile can override generated component name', async () => { + const output = await helpers.templateForComponentFile({ name: 'Home', componentName: 'Hobbiton', webPathSection: 'pages', @@ -200,8 +200,8 @@ test('templateForComponentFile can override generated component name', () => { ) }) -test('templateForComponentFile can override file extension', () => { - const output = helpers.templateForComponentFile({ +test('templateForComponentFile can override file extension', async () => { + const output = await helpers.templateForComponentFile({ name: 'Home', suffix: 'Page', extension: '.txt', @@ -216,8 +216,8 @@ test('templateForComponentFile can override file extension', () => { ) }) -test('templateForComponentFile can override output path', () => { - const output = helpers.templateForComponentFile({ +test('templateForComponentFile can override output path', async () => { + const output = await helpers.templateForComponentFile({ name: 'func', apiPathSection: 'functions', generator: 'function', @@ -231,8 +231,8 @@ test('templateForComponentFile can override output path', () => { ) }) -test('templateForComponentFile creates a template', () => { - const output = helpers.templateForComponentFile({ +test('templateForComponentFile creates a template', async () => { + const output = await helpers.templateForComponentFile({ name: 'FooBar', suffix: 'Page', webPathSection: 'pages', From 2777c270e739febe2fe9ce7eb7fc5c317b724fcf Mon Sep 17 00:00:00 2001 From: Dominic Saadi Date: Fri, 8 Mar 2024 16:55:55 +0100 Subject: [PATCH 05/24] get functions tests passing --- .../function/__tests__/function.test.ts | 16 ++++++++-------- .../src/commands/generate/function/function.js | 18 ++++++++++-------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/packages/cli/src/commands/generate/function/__tests__/function.test.ts b/packages/cli/src/commands/generate/function/__tests__/function.test.ts index 03ac2ddcd248..442b8aa5f1a9 100644 --- a/packages/cli/src/commands/generate/function/__tests__/function.test.ts +++ b/packages/cli/src/commands/generate/function/__tests__/function.test.ts @@ -12,8 +12,8 @@ import * as functionGenerator from '../function' // Should be refactored as it's repeated type WordFilesType = { [key: string]: string } -describe('Single word default files', () => { - const singleWordDefaultFiles: WordFilesType = functionGenerator.files({ +describe('Single word default files', async () => { + const singleWordDefaultFiles: WordFilesType = await functionGenerator.files({ name: 'foo', tests: true, }) @@ -63,8 +63,8 @@ test('Keeps Function in name', () => { expect(name).toEqual('BazingaFunction') }) -test('creates a multi word function file', () => { - const multiWordDefaultFiles = functionGenerator.files({ +test('creates a multi word function file', async () => { + const multiWordDefaultFiles = await functionGenerator.files({ name: 'send-mail', }) @@ -75,8 +75,8 @@ test('creates a multi word function file', () => { ).toMatchSnapshot() }) -test('creates a .js file if --javascript=true', () => { - const javascriptFiles = functionGenerator.files({ +test('creates a .js file if --javascript=true', async () => { + const javascriptFiles = await functionGenerator.files({ name: 'javascript-function', }) @@ -91,8 +91,8 @@ test('creates a .js file if --javascript=true', () => { // https://babeljs.io/docs/en/babel-plugin-transform-typescript }) -test('creates a .ts file if --typescript=true', () => { - const typescriptFiles = functionGenerator.files({ +test('creates a .ts file if --typescript=true', async () => { + const typescriptFiles = await functionGenerator.files({ name: 'typescript-function', typescript: true, }) diff --git a/packages/cli/src/commands/generate/function/function.js b/packages/cli/src/commands/generate/function/function.js index 24559c7121d5..eba8a117b596 100644 --- a/packages/cli/src/commands/generate/function/function.js +++ b/packages/cli/src/commands/generate/function/function.js @@ -13,7 +13,7 @@ import { prepareForRollback } from '../../../lib/rollback' import { yargsDefaults } from '../helpers' import { validateName, templateForComponentFile } from '../helpers' -export const files = ({ +export const files = async ({ name, typescript: generateTypescript = false, tests: generateTests = true, @@ -25,7 +25,7 @@ export const files = ({ const outputFiles = [] - const functionFiles = templateForComponentFile({ + const functionFiles = await templateForComponentFile({ name: functionName, componentName: functionName, extension, @@ -43,7 +43,7 @@ export const files = ({ outputFiles.push(functionFiles) if (generateTests) { - const testFile = templateForComponentFile({ + const testFile = await templateForComponentFile({ name: functionName, componentName: functionName, extension, @@ -58,7 +58,7 @@ export const files = ({ ), }) - const scenarioFile = templateForComponentFile({ + const scenarioFile = await templateForComponentFile({ name: functionName, componentName: functionName, extension, @@ -77,16 +77,18 @@ export const files = ({ outputFiles.push(scenarioFile) } - return outputFiles.reduce((acc, [outputPath, content]) => { + return outputFiles.reduce(async (accP, [outputPath, content]) => { + const acc = await accP + const template = generateTypescript ? content - : transformTSToJS(outputPath, content) + : await transformTSToJS(outputPath, content) return { [outputPath]: template, ...acc, } - }, {}) + }, Promise.resolve({})) } export const command = 'function ' @@ -136,7 +138,7 @@ export const handler = async ({ name, force, ...rest }) => { { title: 'Generating function files...', task: async () => { - return writeFilesTask(files({ name, ...rest }), { + return writeFilesTask(await files({ name, ...rest }), { overwriteExisting: force, }) }, From 3d563e75fae480e019551a2cad41375d7b3760fb Mon Sep 17 00:00:00 2001 From: Dominic Saadi Date: Fri, 8 Mar 2024 17:01:32 +0100 Subject: [PATCH 06/24] get sdl tests passing --- packages/cli/src/commands/generate/sdl/sdl.js | 4 ++-- .../src/commands/generate/service/service.js | 20 ++++++++++--------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/packages/cli/src/commands/generate/sdl/sdl.js b/packages/cli/src/commands/generate/sdl/sdl.js index 53625a5fdaf1..f3baf1f25c54 100644 --- a/packages/cli/src/commands/generate/sdl/sdl.js +++ b/packages/cli/src/commands/generate/sdl/sdl.js @@ -212,7 +212,7 @@ export const files = async ({ templatePath: 'sdl.ts.template', }) - let template = generateTemplate(templatePath, { + let template = await generateTemplate(templatePath, { docs, modelName, modelDescription, @@ -233,7 +233,7 @@ export const files = async ({ ) if (typescript) { - template = transformTSToJS(outputPath, template) + template = await transformTSToJS(outputPath, template) } return { diff --git a/packages/cli/src/commands/generate/service/service.js b/packages/cli/src/commands/generate/service/service.js index b3df5afac1cd..0576182e155e 100644 --- a/packages/cli/src/commands/generate/service/service.js +++ b/packages/cli/src/commands/generate/service/service.js @@ -304,7 +304,7 @@ export const files = async ({ const model = name const idName = await getIdName(model) const extension = 'ts' - const serviceFile = templateForComponentFile({ + const serviceFile = await templateForComponentFile({ name, componentName: componentName, extension: `.${extension}`, @@ -314,7 +314,7 @@ export const files = async ({ templateVars: { relations: relations || [], idName, ...rest }, }) - const testFile = templateForComponentFile({ + const testFile = await templateForComponentFile({ name, componentName: componentName, extension: `.test.${extension}`, @@ -326,16 +326,16 @@ export const files = async ({ create: await fieldsToInput(model), update: await fieldsToUpdate(model), types: await fieldTypes(model), - prismaImport: (await parseSchema(model)).scalarFields.some( - (field) => field.type === 'Decimal' - ), + prismaImport: ( + await parseSchema(model) + ).scalarFields.some((field) => field.type === 'Decimal'), prismaModel: model, idName, ...rest, }, }) - const scenariosFile = templateForComponentFile({ + const scenariosFile = await templateForComponentFile({ name, componentName: componentName, extension: `.scenarios.${extension}`, @@ -362,9 +362,11 @@ export const files = async ({ // "path/to/fileA": "<<