Source: hubspot/upload.js

/** @module hubspot/upload */
/// <reference path="../types/types.js" />
import uploadFolder from '@hubspot/local-dev-lib/cms/uploadFolder'
import { deleteFile, getDirectoryContentsByPath } from '@hubspot/local-dev-lib/api/fileMapper'
import { setLogLevel, LOG_LEVEL } from '@hubspot/local-dev-lib/logger'
import { isAllowedExtension } from '@hubspot/local-dev-lib/path'
import { createIgnoreFilter } from '@hubspot/local-dev-lib/ignoreRules'
import { walk } from '@hubspot/local-dev-lib/fs'
import * as ui from '../utils/ui.js'
import { getThemeOptions } from '../utils/options.js'
import { throwErrorIfMissingScope } from './auth/scopes.js'
import ora from 'ora'

/**
 * @type {"draft" | "publish"}
 */
let cmsMode = 'publish'
if (process.env.HUB_MODE === 'draft') {
  cmsMode = 'draft'
}

/**
 * #### Walks the src folder for files, filters them based on ignore filter.
 * @async
 * @private
 * @param {string} src - src folder
 * @returns {Promise<Array<string>>} src file list
 */
const getUploadableFileList = async (src) => {
  /**
   * @type {Array<string>}
   */
  let filePaths = []
  try {
    filePaths = await walk(src)
  } catch (error) {
    console.error(error)
  }
  const allowedFiles = filePaths.filter((/** @type {any} */ file) => {
    if (!isAllowedExtension(file)) {
      return false
    }
    return true
    // @ts-ignore
  }).filter(createIgnoreFilter())
  return allowedFiles
}

/**
 * #### upload all HubSpot theme files
 * @async
 * @param {HUBSPOT_AUTH_CONFIG} config - hubspot authentication config
 * @param {string} themeName - theme name
 * @returns undefined
 */
async function uploadTheme (config, themeName) {
  try {
    const timeStart = ui.startTask('uploadTheme')
    const cmslibOptions = getThemeOptions()
    const src = `${process.cwd()}/${cmslibOptions.themeFolder}`
    const dest = themeName
    const portalId = config.portals[0].portalId

    throwErrorIfMissingScope(config, 'design_manager')
    setLogLevel(LOG_LEVEL.LOG)
    const uploadableFileList = await getUploadableFileList(src)
    await uploadFolder.uploadFolder(
      portalId,
      src,
      dest,
      { overwrite: false },
      { saveOutput: true, convertFields: false },
      uploadableFileList,
      cmsMode
    )
    ui.endTask({ taskName: 'uploadTheme', timeStart })
  } catch (error) {
    console.error(error)
    process.exit(1)
  }
}

/**
 * #### delete all templates in theme and reupload them
 * @async
 * @param {HUBSPOT_AUTH_CONFIG} config - hubspot authentication config
 * @param {string} themeName - theme name
 * @returns undefined
 */
async function cleanUploadThemeTemplates (config, themeName) {
  const timeStart = ui.startTask('cleanUploadThemeTemplates')
  const spinner = ora('Reupload all templates').start()
  try {
    const cmslibOptions = getThemeOptions()
    const src = `${process.cwd()}/${cmslibOptions.themeFolder}/templates`
    const dest = `${themeName}/templates`
    const portalId = config.portals[0].portalId

    throwErrorIfMissingScope(config, 'design_manager')
    setLogLevel(LOG_LEVEL.NONE)
    const uploadableFileList = await getUploadableFileList(src)
    const filesToDelete = await getDirectoryContentsByPath(portalId, dest)
    if (filesToDelete !== undefined && filesToDelete.children.length > 0) {
      for await (const file of filesToDelete.children) {
        // @ts-ignore
        if (file.includes('.html')) {
          await deleteFile(portalId, `${dest}/${file}`)
        }
      }
    }
    await uploadFolder.uploadFolder(
      portalId,
      src,
      dest,
      { overwrite: false },
      { saveOutput: true, convertFields: false },
      uploadableFileList,
      cmsMode
    )
    spinner.succeed()
    ui.endTask({ taskName: 'cleanUploadThemeTemplates', timeStart })
  } catch (error) {
    spinner.fail()
    console.error(error)
    process.exit(1)
  }
}

/**
 * #### clean theme and reupload it
 * @async
 * @param {HUBSPOT_AUTH_CONFIG} config - hubspot authentication config
 * @param {string} themeName - theme name
 * @returns undefined
 */
async function cleanUploadTheme (config, themeName) {
  const timeStart = ui.startTask('cleanUploadTheme')
  const dest = themeName
  const spinner = ora(`Clean ${dest} folder before upload`)
  try {
    const cmslibOptions = getThemeOptions()
    const src = `${process.cwd()}/${cmslibOptions.themeFolder}`
    const portalId = config.portals[0].portalId

    throwErrorIfMissingScope(config, 'design_manager')
    setLogLevel(LOG_LEVEL.LOG)
    const uploadableFileList = await getUploadableFileList(src)
    spinner.start()
    const filesToDelete = await getDirectoryContentsByPath(portalId, '/')
    if (filesToDelete !== undefined && filesToDelete.children.length > 0) {
      for await (const file of filesToDelete.children) {
        // @ts-ignore
        if (file === dest) {
          await deleteFile(portalId, file)
        }
      }
    }
    spinner.succeed()
    await uploadFolder.uploadFolder(
      portalId,
      src,
      dest,
      { overwrite: false },
      { saveOutput: true, convertFields: false },
      uploadableFileList,
      cmsMode
    )
    ui.endTask({ taskName: 'cleanUploadTheme', timeStart })
  } catch (error) {
    spinner.fail()
    console.error(error)
    process.exit(1)
  }
}

export { uploadTheme, cleanUploadThemeTemplates, cleanUploadTheme }

Table of contents