From 70941c6846a5613a8d76f2bd8f9ebe21fc41a601 Mon Sep 17 00:00:00 2001 From: Saad Jutt Date: Fri, 2 Jul 2021 15:28:06 +0500 Subject: [PATCH] feat(web): process all files under webSourcePath nested --- src/commands/build/build.ts | 22 +++- src/commands/web/index.ts | 238 ++++++++++++++++++------------------ 2 files changed, 136 insertions(+), 124 deletions(-) diff --git a/src/commands/build/build.ts b/src/commands/build/build.ts index 7cb128223..2ae57676e 100644 --- a/src/commands/build/build.ts +++ b/src/commands/build/build.ts @@ -211,7 +211,7 @@ async function getFolderContent(serverType: ServerType) { await asyncForEach(buildSubFolders, async (subFolder) => { const { content, contentJSON } = await getContentFor( path.join(buildDestinationFolder, subFolder), - subFolder, + path.join(buildDestinationFolder, subFolder), serverType ) @@ -234,21 +234,23 @@ async function getDependencies(filePaths: string[]): Promise { } async function getContentFor( + rootDirectory: string, folderPath: string, - folderName: string, serverType: ServerType, testPath: string | undefined = undefined ) { + const folderName = path.basename(folderPath) if (!testPath && folderName === 'tests') { testPath = '' } + const isRootDir = folderPath === rootDirectory let content = `\n%let path=${ - folderName === 'services' + isRootDir ? '' : testPath !== undefined ? testPath - : folderName + : folderPath.replace(rootDirectory, '').substr(1) };\n` const contentJSON: any = { @@ -294,8 +296,8 @@ async function getContentFor( await asyncForEach(subFolders, async (subFolder) => { const { content: childContent, contentJSON: childContentJSON } = await getContentFor( + rootDirectory, path.join(folderPath, subFolder), - subFolder, serverType, testPath !== undefined ? testPath === '' @@ -367,7 +369,15 @@ async function getWebFileContent(filePath: string, type: string) { let lines, encoded = false - const typesToEncode: string[] = ['ICO', 'PNG', 'JPG', 'JPEG', 'MP3'] + const typesToEncode: string[] = [ + 'ICO', + 'PNG', + 'JPG', + 'JPEG', + 'MP3', + 'OGG', + 'WAV' + ] if (typesToEncode.includes(type)) { encoded = true diff --git a/src/commands/web/index.ts b/src/commands/web/index.ts index e9c35f44b..412e27c86 100644 --- a/src/commands/web/index.ts +++ b/src/commands/web/index.ts @@ -12,7 +12,8 @@ import { listFilesInFolder, ServerType, Target, - asyncForEach + asyncForEach, + listSubFoldersInFolder } from '@sasjs/utils' import { getLocalConfig } from '../../utils/config' import path from 'path' @@ -22,6 +23,7 @@ import { adjustIframeScript } from './adjustIframeScript' import btoa from 'btoa' import { getConstants } from '../../constants' import { StreamConfig } from '@sasjs/utils/types/config' +import uniqBy from 'lodash.uniqby' const permittedServerTypes = { SAS9: 'SAS9', @@ -126,7 +128,8 @@ export async function createWebAppServices(target: Target) { webSourcePath, destinationPath, target, - streamConfig + streamConfig, + assetPathMap ) }) @@ -137,7 +140,8 @@ export async function createWebAppServices(target: Target) { webSourcePath, destinationPath, target, - streamConfig + streamConfig, + assetPathMap ) }) @@ -159,64 +163,107 @@ async function createAssetServices( target: Target, destinationPath: string, streamConfig: StreamConfig -) { +): Promise<{ source: string; target: string }[]> { const { webSourcePath, streamWebFolder, assetPaths } = streamConfig const assetPathMap: { source: string; target: string }[] = [] - await asyncForEach(assetPaths, async (assetPath) => { - const fullAssetPath = path.isAbsolute(assetPath) - ? assetPath - : path.isAbsolute(webSourcePath) - ? path.join(webSourcePath, assetPath) - : path.join(process.projectDir, webSourcePath, assetPath) - const assetPathExists = await folderExists(fullAssetPath) - - if (!assetPathExists) { - process.logger?.warn( - `Assets path '${fullAssetPath}' present in 'streamConfig' doesn't exist.` + + await asyncForEach( + [path.join(process.projectDir, webSourcePath), ...(assetPaths ?? [])], + async (assetPath) => { + const fullAssetPath = path.isAbsolute(assetPath) + ? assetPath + : path.isAbsolute(webSourcePath) + ? path.join(webSourcePath, assetPath) + : path.join(process.projectDir, webSourcePath, assetPath) + const assetPathExists = await folderExists(fullAssetPath) + + if (!assetPathExists) { + process.logger?.warn( + `Assets path '${fullAssetPath}' present in 'streamConfig' doesn't exist.` + ) + return + } + const assetPathMapNested = await createAssetsServicesNested( + target, + streamWebFolder, + fullAssetPath, + destinationPath ) - return + assetPathMap.push(...assetPathMapNested) } - const filePaths = await listFilesInFolder(fullAssetPath) - await asyncForEach(filePaths, async (filePath) => { - const fullFileName = path.basename(filePath) - const fileName = fullFileName.substring(0, fullFileName.lastIndexOf('.')) - const fileExtension = path - .basename(filePath) - .substring(fullFileName.lastIndexOf('.') + 1, fullFileName.length) - if (fileName && fileExtension) { - const sourcePath = path.join(fullAssetPath, filePath) - if (target.serverType === ServerType.SasViya) { - await copy(sourcePath, path.join(destinationPath, fullFileName)) - const assetServiceUrl = getAssetPath( - target.appLoc, - target.serverType, - streamWebFolder, - fullFileName - ) - assetPathMap.push({ - source: fullFileName, - target: assetServiceUrl - }) - } else { - const base64string = await base64EncodeFile(sourcePath) - const fileName = await generateAssetService( - base64string, - filePath, - destinationPath, - target.serverType - ) - const assetServiceUrl = getAssetPath( - target.appLoc, - target.serverType, - streamWebFolder, - fileName.replace('.sas', '') - ) - assetPathMap.push({ - source: path.join(fullAssetPath, filePath), - target: assetServiceUrl - }) - } + ) + return uniqBy(assetPathMap, 'source') +} + +async function createAssetsServicesNested( + target: Target, + streamWebFolder: string, + fullAssetPath: string, + destinationPath: string +) { + const assetPathMap: { source: string; target: string }[] = [] + const filePaths = await listFilesInFolder(fullAssetPath) + await asyncForEach(filePaths, async (filePath) => { + const fullFileName = path.basename(filePath) + const fileName = fullFileName.substring(0, fullFileName.lastIndexOf('.')) + const fileExtension = path + .basename(filePath) + .substring(fullFileName.lastIndexOf('.') + 1, fullFileName.length) + if (fileName && fileExtension) { + const sourcePath = path.join(fullAssetPath, filePath) + if (target.serverType === ServerType.SasViya) { + await copy(sourcePath, path.join(destinationPath, fullFileName)) + const assetServiceUrl = getAssetPath( + target.appLoc, + target.serverType, + streamWebFolder, + fullFileName + ) + assetPathMap.push({ + source: fullFileName, + target: assetServiceUrl + }) + } else { + const base64string = await base64EncodeFile(sourcePath) + const fileName = await generateAssetService( + base64string, + filePath, + destinationPath, + target.serverType + ) + const assetServiceUrl = getAssetPath( + target.appLoc, + target.serverType, + streamWebFolder, + fileName.replace('.sas', '') + ) + assetPathMap.push({ + source: fullFileName, + target: assetServiceUrl + }) } + } + }) + + const folderNames = await listSubFoldersInFolder(fullAssetPath) + await asyncForEach(folderNames, async (folderName) => { + const destinationPathNested = path.join(destinationPath, folderName) + const fullAssetPathNested = path.join(fullAssetPath, folderName) + + await createFolder(destinationPathNested) + + const assetFolderMap: { source: string; target: string }[] = + await createAssetsServicesNested( + target, + `${streamWebFolder}/${folderName}`, + fullAssetPathNested, + destinationPathNested + ) + assetFolderMap.forEach((entry) => { + assetPathMap.push({ + source: `${folderName}/${entry.source}`, + target: entry.target + }) }) }) return assetPathMap @@ -257,10 +304,6 @@ async function updateTagSource( scriptPath && (scriptPath.startsWith('http') || scriptPath.startsWith('//')) if (scriptPath) { - const fileName = - target.serverType === ServerType.SasViya - ? path.basename(scriptPath) - : `${path.basename(scriptPath).replace(/\./g, '')}` if (!isUrl) { let content = await readFile( path.join(process.projectDir, webAppSourcePath, scriptPath) @@ -274,7 +317,7 @@ async function updateTagSource( }) if (target.serverType === ServerType.SasViya) { - await createFile(path.join(destinationPath, fileName), content) + await createFile(path.join(destinationPath, scriptPath), content) } else { const serviceContent = await getWebServiceContent( content, @@ -282,19 +325,14 @@ async function updateTagSource( target.serverType ) await createFile( - path.join(destinationPath, `${fileName}.sas`), + path.join(destinationPath, `${scriptPath.replace('.', '-')}.sas`), serviceContent ) } tag.setAttribute( 'src', - getAssetPath( - target.appLoc, - target.serverType, - streamConfig.streamWebFolder!, - fileName - ) + assetPathMap.find((entry) => entry.source === scriptPath)!.target ) } } @@ -305,45 +343,17 @@ async function updateLinkHref( webAppSourcePath: string, destinationPath: string, target: Target, - streamConfig: StreamConfig + streamConfig: StreamConfig, + assetPathMap: { source: string; target: string }[] ) { const linkSourcePath = linkTag.getAttribute('href') || '' const isUrl = linkSourcePath.startsWith('http') || linkSourcePath.startsWith('//') - const fileName = - target.serverType === ServerType.SasViya - ? path.basename(linkSourcePath) - : `${path.basename(linkSourcePath).replace(/\./g, '')}` if (!isUrl) { - const sourcePath = path.join( - process.projectDir, - webAppSourcePath, - linkSourcePath + linkTag.setAttribute( + 'href', + assetPathMap.find((entry) => entry.source === linkSourcePath)!.target ) - - if (target.serverType === ServerType.SasViya) { - await copy(sourcePath, path.join(destinationPath, fileName)) - } else { - const content = await readFile(sourcePath) - const serviceContent = await getWebServiceContent( - content, - 'CSS', - target.serverType - ) - - await createFile( - path.join(destinationPath, `${fileName}.sas`), - serviceContent - ) - } - - const linkHref = getAssetPath( - target.appLoc, - target.serverType, - streamConfig.streamWebFolder!, - fileName - ) - linkTag.setAttribute('href', linkHref) } } @@ -352,30 +362,22 @@ async function updateFaviconHref( webAppSourcePath: string, destinationPath: string, target: Target, - streamConfig: StreamConfig + streamConfig: StreamConfig, + assetPathMap: { source: string; target: string }[] ) { const linkSourcePath = linkTag.getAttribute('href') || '' const isUrl = linkSourcePath.startsWith('http') || linkSourcePath.startsWith('//') if (!isUrl) { - const sourcePath = path.join( - process.projectDir, - webAppSourcePath, - linkSourcePath - ) if (target.serverType === ServerType.SasViya) { - const fileName = path.basename(linkSourcePath) - await copy(sourcePath, path.join(destinationPath, fileName)) - - const linkHref = getAssetPath( - target.appLoc, - target.serverType, - streamConfig.streamWebFolder!, - fileName + linkTag.setAttribute( + 'href', + assetPathMap.find((entry) => entry.source === linkSourcePath)!.target ) - linkTag.setAttribute('href', linkHref) } else { - const base64string = await base64EncodeImageFile(sourcePath) + const base64string = await base64EncodeImageFile( + path.join(process.projectDir, webAppSourcePath, linkSourcePath) + ) linkTag.setAttribute('href', base64string) } } @@ -396,7 +398,7 @@ function getAssetPath( // the appLoc is inserted dynamically by SAS serverType === ServerType.SasViya ? `/SASJobExecution?_FILE=${appLoc}/services/${streamWebFolder}` - : `/SASStoredProcess/?_PROGRAM=/services/${streamWebFolder}` + : `/SASStoredProcess/?_PROGRAM=${appLoc}/services/${streamWebFolder}` return `${storedProcessPath}/${fileName}` }