From 8d9c816e2e6aed9717f7dae95ef2fe063bab7e38 Mon Sep 17 00:00:00 2001 From: Tanya Scales Date: Fri, 12 Jan 2024 10:56:03 -0500 Subject: [PATCH 1/3] moving work over from cli-lib to this repo -- adding react module support --- lang/en.json | 5 +- lib/cms/modules.ts | 130 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 114 insertions(+), 21 deletions(-) diff --git a/lang/en.json b/lang/en.json index de50a942..83c608cb 100644 --- a/lang/en.json +++ b/lang/en.json @@ -87,7 +87,10 @@ "creatingModule": "Creating module at {{ path }}", "creatingPath": "Creating {{ path }}", "errors": { - "writeModuleMeta": "The {{ path }} path already exists" + "pathExists": "The {{ path }} path already exists", + "failedToWriteMeta": "There was an problem writing the module's meta data at {{ path }}", + "fileReadFailure": "Failed to read file at {{ path }}", + "failedToWrite": "failed to write to file at {{ path }}" } } }, diff --git a/lib/cms/modules.ts b/lib/cms/modules.ts index c8ce0e2b..fae6515a 100644 --- a/lib/cms/modules.ts +++ b/lib/cms/modules.ts @@ -105,6 +105,7 @@ export async function validateSrcAndDestPaths( type ModuleDefinition = { contentTypes: Array; moduleLabel: string; + reactType: boolean; global: boolean; }; @@ -114,14 +115,58 @@ export async function createModule( moduleDefinition: ModuleDefinition, name: string, dest: string, + getInternalVersion: boolean, options = { allowExistingDir: false, }, logCallbacks?: LogCallbacksArg ) { const logger = makeTypedLogger(logCallbacks); + const { reactType: isReactModule } = moduleDefinition; + + // Ascertain the module's dest path based on module type + const parseDestPath = ( + name: string, + dest: string, + isReactModule: boolean + ) => { + const folderName = name.endsWith('.module') ? name : `${name}.module`; + + const modulePath = !isReactModule + ? path.join(dest, folderName) + : path.join(dest, `${name}`); + + return modulePath; + }; + + const destPath = parseDestPath(name, dest, isReactModule); + + // Create module directory + const createModuleDirectory = ( + allowExistingDir: boolean, + destPath: string + ) => { + if (!allowExistingDir && fs.existsSync(destPath)) { + throwErrorWithMessage(`${i18nKey}.createModule.errors.pathExists`, { + path: destPath, + }); + } else { + logger('creatingPath', `${i18nKey}.createModule.creatingPath`, { + path: destPath, + }); + fs.ensureDirSync(destPath); + } + + logger('creatingModule', `${i18nKey}.createModule.creatingModule`, { + path: destPath, + }); + }; + + createModuleDirectory(options.allowExistingDir, destPath); + + // Write module meta const writeModuleMeta = ( - { contentTypes, moduleLabel, global }: ModuleDefinition, + { moduleLabel, contentTypes, global, reactType }: ModuleDefinition, dest: string ) => { const metaData = { @@ -138,9 +183,57 @@ export async function createModule( is_available_for_new_content: false, }; - fs.writeJSONSync(dest, metaData, { spaces: 2 }); + if (!reactType) { + fs.writeJSONSync(dest, metaData, { spaces: 2 }); + } else { + const globalImportString = getInternalVersion + ? 'import "./global-samplejsr.css";' + : ''; + const defaultconfigString = getInternalVersion + ? `export const defaultModuleConfig = { + moduleName: "sample_jsr", + version: 0, +}; + ` + : ''; + + fs.readFile(`${destPath}/index.tsx`, 'utf8', function (err, data) { + if (err) { + throwErrorWithMessage( + `${i18nKey}.createModule.errors.fileReadFailure`, + { + path: `${dest}/index.tsx`, + } + ); + } + + const result = data + .replace(/\/\* import global styles \*\//g, globalImportString) + .replace(/\/\* Default config \*\//g, defaultconfigString); + + fs.writeFile(`${destPath}/index.tsx`, result, 'utf8', function (err) { + if (err) return console.log(err); + }); + + fs.appendFile( + `${dest}/index.tsx`, + 'export const meta = ' + JSON.stringify(metaData, null, ' '), + err => { + if (err) { + throwErrorWithMessage( + `${i18nKey}.createModule.errors.failedToWrite`, + { + path: `${dest}/index.tsx`, + } + ); + } + } + ); + }); + } }; + // Filter out ceratin fetched files from the response const moduleFileFilter = (src: string, dest: string) => { const emailEnabled = moduleDefinition.contentTypes.includes('EMAIL'); @@ -154,34 +247,31 @@ export async function createModule( return false; } return true; + case 'global-samplejsr.css': + case 'stories': + case 'tests': + if (getInternalVersion) { + return true; + } + return false; default: return true; } }; - const folderName = - !name || name.endsWith('.module') ? name : `${name}.module`; - const destPath = path.join(dest, folderName); - if (!options.allowExistingDir && fs.existsSync(destPath)) { - throwErrorWithMessage(`${i18nKey}.createModule.errors.writeModuleMeta`, { - path: destPath, - }); - } else { - logger('creatingPath', `${i18nKey}.createModule.creatingPath`, { - path: destPath, - }); - fs.ensureDirSync(destPath); - } - - logger('creatingModule', `${i18nKey}.createModule.creatingModule`, { - path: destPath, - }); + // Download gitHub contents to the dest directory + const sampleAssetPath = !isReactModule ? 'Sample.module' : 'SampleJSR'; await downloadGithubRepoContents( 'HubSpot/cms-sample-assets', - 'modules/Sample.module', + `modules/${sampleAssetPath}`, destPath, '', moduleFileFilter ); + + // Mutating React module files after fetch + if (isReactModule) { + writeModuleMeta(moduleDefinition, destPath); + } } From 15fb311d5dc32b43b82cc00689bba8d09dbf800c Mon Sep 17 00:00:00 2001 From: Tanya Scales Date: Fri, 12 Jan 2024 13:45:28 -0500 Subject: [PATCH 2/3] update to arrow functions, update to sample asset name --- lib/cms/modules.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/cms/modules.ts b/lib/cms/modules.ts index fae6515a..d6fe0fbf 100644 --- a/lib/cms/modules.ts +++ b/lib/cms/modules.ts @@ -197,7 +197,7 @@ export async function createModule( ` : ''; - fs.readFile(`${destPath}/index.tsx`, 'utf8', function (err, data) { + fs.readFile(`${destPath}/index.tsx`, 'utf8', (err, data) => { if (err) { throwErrorWithMessage( `${i18nKey}.createModule.errors.fileReadFailure`, @@ -211,7 +211,7 @@ export async function createModule( .replace(/\/\* import global styles \*\//g, globalImportString) .replace(/\/\* Default config \*\//g, defaultconfigString); - fs.writeFile(`${destPath}/index.tsx`, result, 'utf8', function (err) { + fs.writeFile(`${destPath}/index.tsx`, result, 'utf8', err => { if (err) return console.log(err); }); @@ -260,7 +260,9 @@ export async function createModule( }; // Download gitHub contents to the dest directory - const sampleAssetPath = !isReactModule ? 'Sample.module' : 'SampleJSR'; + const sampleAssetPath = !isReactModule + ? 'Sample.module' + : 'SampleReactModule'; await downloadGithubRepoContents( 'HubSpot/cms-sample-assets', From b9d2f779d5cb1dc333078c5dbfb2be7bc5c39483 Mon Sep 17 00:00:00 2001 From: Tanya Scales Date: Fri, 12 Jan 2024 16:28:31 -0500 Subject: [PATCH 3/3] matching cli-lib changes -- moving some code back into the main function call and moving the transformation out to separate function --- lib/cms/modules.ts | 162 +++++++++++++++++++++++---------------------- 1 file changed, 82 insertions(+), 80 deletions(-) diff --git a/lib/cms/modules.ts b/lib/cms/modules.ts index d6fe0fbf..73f56148 100644 --- a/lib/cms/modules.ts +++ b/lib/cms/modules.ts @@ -102,6 +102,72 @@ export async function validateSrcAndDestPaths( return results; } +/* createModule() helper + * Takes a file and uses the constants above to transform the contents + */ + +// Strings to replace in React module files +const MODULE_STRING_TRANSFORMATIONS = [ + { + regex: /\/\* import global styles \*\//g, + string: 'import "./global-samplejsr.css";', + fallback: '', + }, + { + regex: /\/\* Default config \*\//g, + string: + 'export const defaultModuleConfig = { \n moduleName: "sample_jsr", \n version: 0, \n};', + fallback: '', + }, +]; + +const transformFileContents = ( + file: string, + metaData: object, + getInternalVersion: boolean +) => { + fs.readFile(file, 'utf8', (err, data) => { + if (err) { + throwErrorWithMessage(`${i18nKey}.createModule.errors.fileReadFailure`, { + path: file, + }); + } + + let results = data; + + MODULE_STRING_TRANSFORMATIONS.forEach(entry => { + const replacementString = getInternalVersion + ? entry.string + : entry.fallback; + + results = results.replace(entry.regex, replacementString); + }); + + fs.writeFile(file, results, 'utf8', err => { + if (err) { + throwErrorWithMessage(`${i18nKey}.createModule.errors.failedToWrite`, { + path: file, + }); + } + }); + + fs.appendFile( + file, + 'export const meta = ' + JSON.stringify(metaData, null, ' '), + err => { + if (err) { + throwErrorWithMessage( + `${i18nKey}.createModule.errors.failedToWrite`, + { + path: file, + } + ); + } + } + ); + }); +}; + type ModuleDefinition = { contentTypes: Array; moduleLabel: string; @@ -123,46 +189,25 @@ export async function createModule( ) { const logger = makeTypedLogger(logCallbacks); const { reactType: isReactModule } = moduleDefinition; + const folderName = name.endsWith('.module') ? name : `${name}.module`; + const destPath = !isReactModule + ? path.join(dest, folderName) + : path.join(dest, `${name}`); - // Ascertain the module's dest path based on module type - const parseDestPath = ( - name: string, - dest: string, - isReactModule: boolean - ) => { - const folderName = name.endsWith('.module') ? name : `${name}.module`; - - const modulePath = !isReactModule - ? path.join(dest, folderName) - : path.join(dest, `${name}`); - - return modulePath; - }; - - const destPath = parseDestPath(name, dest, isReactModule); - - // Create module directory - const createModuleDirectory = ( - allowExistingDir: boolean, - destPath: string - ) => { - if (!allowExistingDir && fs.existsSync(destPath)) { - throwErrorWithMessage(`${i18nKey}.createModule.errors.pathExists`, { - path: destPath, - }); - } else { - logger('creatingPath', `${i18nKey}.createModule.creatingPath`, { - path: destPath, - }); - fs.ensureDirSync(destPath); - } - - logger('creatingModule', `${i18nKey}.createModule.creatingModule`, { + if (!options.allowExistingDir && fs.existsSync(destPath)) { + throwErrorWithMessage(`${i18nKey}.createModule.errors.pathExists`, { path: destPath, }); - }; + } else { + logger('creatingPath', `${i18nKey}.createModule.creatingPath`, { + path: destPath, + }); + fs.ensureDirSync(destPath); + } - createModuleDirectory(options.allowExistingDir, destPath); + logger('creatingModule', `${i18nKey}.createModule.creatingModule`, { + path: destPath, + }); // Write module meta const writeModuleMeta = ( @@ -186,50 +231,7 @@ export async function createModule( if (!reactType) { fs.writeJSONSync(dest, metaData, { spaces: 2 }); } else { - const globalImportString = getInternalVersion - ? 'import "./global-samplejsr.css";' - : ''; - const defaultconfigString = getInternalVersion - ? `export const defaultModuleConfig = { - moduleName: "sample_jsr", - version: 0, -}; - ` - : ''; - - fs.readFile(`${destPath}/index.tsx`, 'utf8', (err, data) => { - if (err) { - throwErrorWithMessage( - `${i18nKey}.createModule.errors.fileReadFailure`, - { - path: `${dest}/index.tsx`, - } - ); - } - - const result = data - .replace(/\/\* import global styles \*\//g, globalImportString) - .replace(/\/\* Default config \*\//g, defaultconfigString); - - fs.writeFile(`${destPath}/index.tsx`, result, 'utf8', err => { - if (err) return console.log(err); - }); - - fs.appendFile( - `${dest}/index.tsx`, - 'export const meta = ' + JSON.stringify(metaData, null, ' '), - err => { - if (err) { - throwErrorWithMessage( - `${i18nKey}.createModule.errors.failedToWrite`, - { - path: `${dest}/index.tsx`, - } - ); - } - } - ); - }); + transformFileContents(`${dest}/index.tsx`, metaData, getInternalVersion); } };