@oraclecc/dcu
Version:
Development tools for Oracle Commerce Cloud.
228 lines (186 loc) • 8.29 kB
JavaScript
const dirname = require('path').dirname
const upath = require("upath")
const elementExistsOnTarget = require("./metadata").elementExistsOnTarget
const constants = require("./constants").constants
const classify = require("./classifier").classify
const getPathsBlock = require("./puttingPathsBlock").getPathsBlock
const PuttingFileType = require("./puttingFileType").PuttingFileType
const stackExistsOnTarget = require("./metadata").stackExistsOnTarget
const themeExistsOnTarget = require("./metadata").themeExistsOnTarget
const widgetExistsOnTarget = require("./metadata").widgetExistsOnTarget
const widgetIsElementized = require("./metadata").widgetIsElementized
/**
* Handy function to filter out hidden files.
* @param fileStat
* @returns {boolean}
*/
function hidden(fileStat) {
return fileStat.name.startsWith(".")
}
/**
* Determine if file is under the tracking directory.
* @param fullPath
* @returns {boolean}
*/
function isTrackedFile(fullPath) {
return fullPath.includes(`/${constants.trackingDir}/`)
}
/**
* Figure out the base widget directory from a full path to a widget file.
* @param path
*/
function getWidgetDir(path) {
const tokens = path.split("/")
return tokens.slice(0, tokens.indexOf("widget") + 2).join("/")
}
/**
* Figure out the base element directory from a full path to a element file.
* @param path
*/
function getElementDir(path) {
const tokens = path.split("/")
return tokens.slice(0, tokens.indexOf("element") + 2).join("/")
}
/**
* Figure out the base widget directory from a full path to a widget file.
* @param path
*/
function getStackDir(path) {
const tokens = path.split("/")
return tokens.slice(0, tokens.indexOf("stack") + 2).join("/")
}
/**
* Return an object suitable for passing to the file walker for chopping up the source directory.
* @param pathTypeMap
* @param paths
* @return {{listeners: {file: listeners.file, directory: listeners.directory}}}
*/
function puttingDirectoryWalker(pathTypeMap, paths) {
return {
listeners: {
file: (root, fileStat, next) => {
// Build the full file name and keep a note of it but not if under the tracking directory or hidden.
const fullPath = upath.resolve(root, fileStat.name)
// Knock out files in the .ccc dir or that are hidden.
if (!isTrackedFile(fullPath) && !hidden(fileStat)) {
// See if we recognize the file.
const fileType = classify(fullPath)
// If the file looks OK, save the type against the path for later.
fileType && pathTypeMap.set(fullPath, fileType)
switch (fileType) {
// We want to create new themes first and then update any existing ones just after.
case PuttingFileType.THEME_STYLES:
case PuttingFileType.THEME_ADDITIONAL_STYLES:
case PuttingFileType.THEME_VARIABLES:
if (themeExistsOnTarget(fullPath)) {
// Keep existing themes together so we can do them early on.
paths.existingThemePaths.push(fullPath)
} else {
// Add our theme base path to the group of new themes to create.
paths.newThemeSet.add(dirname(fullPath))
}
break
// We want to create global elements fairly early on in the process. Existing ones can be updated later.
case PuttingFileType.GLOBAL_ELEMENT_JAVASCRIPT:
case PuttingFileType.GLOBAL_ELEMENT_METADATA:
if (elementExistsOnTarget(fullPath)) {
paths.otherPaths.push(fullPath)
} else {
paths.newElementSet.add(getElementDir(fullPath))
}
break
// New widgets have to be created before their instances. Existing widgets can be updated later.
case PuttingFileType.WIDGET_BASE_TEMPLATE:
case PuttingFileType.WIDGET_BASE_LESS:
case PuttingFileType.WIDGET_BASE_SNIPPETS:
case PuttingFileType.WIDGET_JAVASCRIPT:
case PuttingFileType.WIDGET_MODULE_JAVASCRIPT:
case PuttingFileType.WIDGET_METADATA_JSON:
case PuttingFileType.WIDGET_CONFIG_SNIPPETS:
case PuttingFileType.WIDGET_CONFIG_JSON:
case PuttingFileType.ELEMENT_METADATA:
case PuttingFileType.ELEMENT_JAVASCRIPT:
if (widgetExistsOnTarget(fullPath)) {
paths.otherPaths.push(fullPath)
} else {
paths.newWidgetSet.add(getWidgetDir(fullPath))
}
break
// If doing a putAll/transferAll on elementized widget, template will be sent with element instance json.
case PuttingFileType.WIDGET_INSTANCE_TEMPLATE:
if (!widgetIsElementized(fullPath)) {
paths.otherPaths.push(fullPath)
}
break
// We want to create new stacks fairly early on. Existing ones can be dealt with later.
case PuttingFileType.STACK_METADATA_JSON:
case PuttingFileType.STACK_BASE_LESS:
case PuttingFileType.STACK_BASE_VARIABLES_LESS:
case PuttingFileType.STACK_BASE_TEMPLATE:
case PuttingFileType.STACK_BASE_SNIPPETS:
case PuttingFileType.STACK_CONFIG_SNIPPETS:
case PuttingFileType.STACK_CONFIG_JSON:
if (stackExistsOnTarget(fullPath)) {
paths.stackBasePaths.push(fullPath)
} else {
paths.newStackSet.add(getStackDir(fullPath))
}
break
// Update stack instances separately before widgets.
case PuttingFileType.STACK_INSTANCE_METADATA_JSON:
case PuttingFileType.STACK_INSTANCE_LESS:
case PuttingFileType.STACK_INSTANCE_VARIABLES_LESS:
case PuttingFileType.STACK_INSTANCE_TEMPLATE:
paths.stackInstancePaths.push(fullPath)
break
// We need to drip feed widget instance less to stop the server being swamped by theme compiles.
// We do have an option the suppress theme compilation which speeds things up but the server may not support it.
case PuttingFileType.WIDGET_INSTANCE_LESS:
if (widgetExistsOnTarget(fullPath)) {
paths.widgetLessPaths.push(fullPath)
} else {
paths.newWidgetSet.add(getWidgetDir(fullPath))
}
break
// Element template compilation processing is not thread safe on many older versions of CC.
// Be cautious and drip feed template updates.
case PuttingFileType.ELEMENT_TEMPLATE:
if (widgetExistsOnTarget(fullPath)) {
paths.elementTemplatePaths.push(fullPath)
} else {
paths.newWidgetSet.add(getWidgetDir(fullPath))
}
break
// Element template compilation processing is not thread safe on many older versions of CC.
// Be cautious and drip feed template updates.
case PuttingFileType.GLOBAL_ELEMENT_TEMPLATE:
if (elementExistsOnTarget(fullPath)) {
paths.elementTemplatePaths.push(fullPath)
} else {
paths.newElementSet.add(getElementDir(fullPath))
}
break
// Anything we don't recognize gets ignored. If we get in here, the file gets processed at the end.
default:
if (fileType) {
paths.otherPaths.push(fullPath)
}
}
}
next()
},
directory: (root, fileStat, next) => {
const fullPath = upath.resolve(root, fileStat.name)
if (!isTrackedFile(fullPath) && !hidden(fileStat)) {
// Need to intercept widget instance directories.
classify(fullPath) === PuttingFileType.WIDGET_INSTANCE &&
paths.widgetInstanceDirs.push(fullPath)
// Same for stack instance directories.
classify(fullPath) === PuttingFileType.STACK_INSTANCE &&
paths.stackInstanceDirs.push(fullPath)
}
}
}
}
}
exports.puttingDirectoryWalker = puttingDirectoryWalker