Diff
checker
Texto
Texto
Imagens
Documentos
Excel
Pastas
Legal
Enterprise
Aplicativo para desktop
Preços
Fazer login
Baixar o Diffchecker Desktop
Comparar texto
Encontre a diferença entre dois arquivos de texto
Ferramentas
Histórico
Editor live
Recolher inalteradas
Sem quebra de linha
Layout
Dividido
Unificado
Nível de detalhe
Inteligente
Palavra
Caractere
Realce de sintaxe
Escolher sintaxe
Ignorar
Transformar texto
Ir à primeira mudança
Editar entrada
Diffchecker Desktop
A maneira mais segura de usar o Diffchecker. Obtenha o aplicativo Diffchecker Desktop: seus diffs nunca saem do seu computador!
Obter Desktop
resultify-hubspot-cms-windows
Criado
há 2 anos
O diff nunca expira
Limpar
Exportar
Compartilhar
Explicar
60 remoções
Linhas
Total
Removido
Caracteres
Total
Removido
Para continuar usando este recurso, atualize para
Diff
checker
Pro
Ver preços
424 linhas
Copiar tudo
38 adições
Linhas
Total
Adicionado
Caracteres
Total
Adicionado
Para continuar usando este recurso, atualize para
Diff
checker
Pro
Ver preços
412 linhas
Copiar tudo
/** @module hubspot/upload */
/** @module hubspot/upload */
/// <reference path="../types/types.js" />
/// <reference path="../types/types.js" />
import fsPromises from 'fs/promises'
import fsPromises from 'fs/promises'
import uploadFolder from '@hubspot/local-dev-lib/cms/uploadFolder'
import uploadFolder from '@hubspot/local-dev-lib/cms/uploadFolder'
import { deleteFile, getDirectoryContentsByPath } from '@hubspot/local-dev-lib/api/fileMapper'
import { deleteFile, getDirectoryContentsByPath } from '@hubspot/local-dev-lib/api/fileMapper'
import { setLogLevel, LOG_LEVEL } from '@hubspot/local-dev-lib/logger'
import { setLogLevel, LOG_LEVEL } from '@hubspot/local-dev-lib/logger'
import { isAllowedExtension } from '@hubspot/local-dev-lib/path'
import { isAllowedExtension } from '@hubspot/local-dev-lib/path'
import { createIgnoreFilter } from '@hubspot/local-dev-lib/ignoreRules'
import { createIgnoreFilter } from '@hubspot/local-dev-lib/ignoreRules'
import { walk } from '@hubspot/local-dev-lib/fs'
import { walk } from '@hubspot/local-dev-lib/fs'
import * as ui from '../utils/ui.js'
import * as ui from '../utils/ui.js'
import { getThemeOptions } from '../utils/options.js'
import { getThemeOptions } from '../utils/options.js'
import { throwErrorIfMissingScope } from './auth/scopes.js'
import { throwErrorIfMissingScope } from './auth/scopes.js'
import ora from 'ora'
import ora from 'ora'
import chalk from 'chalk'
import chalk from 'chalk'
import checkbox from '@inquirer/checkbox'
import checkbox from '@inquirer/checkbox'
import confirm from '@inquirer/confirm'
import confirm from '@inquirer/confirm'
import { getFileList, isFileDir } from '../utils/fs.js'
import { getFileList, isFileDir } from '../utils/fs.js'
Copiar
Copiado
Copiar
Copiado
import path from 'path'
/**
/**
* @type {"draft" | "publish"}
* @type {"draft" | "publish"}
*/
*/
let cmsMode = 'publish'
let cmsMode = 'publish'
if (process.env.HUB_MODE === 'draft') {
if (process.env.HUB_MODE === 'draft') {
cmsMode = 'draft'
cmsMode = 'draft'
}
}
/**
/**
* #### Walks the src folder for files, filters them based on ignore filter.
* #### Walks the src folder for files, filters them based on ignore filter.
* @async
* @async
* @private
* @private
* @param {string} src - src folder
* @param {string} src - src folder
* @returns {Promise<Array<string>>} src file list
* @returns {Promise<Array<string>>} src file list
*/
*/
const getUploadableFileList = async (src) => {
const getUploadableFileList = async (src) => {
/**
/**
* @type {Array<string>}
* @type {Array<string>}
*/
*/
let filePaths = []
let filePaths = []
try {
try {
filePaths = await walk(src)
filePaths = await walk(src)
} catch (error) {
} catch (error) {
console.error(error)
console.error(error)
}
}
const allowedFiles = filePaths.filter((/** @type {any} */ file) => {
const allowedFiles = filePaths.filter((/** @type {any} */ file) => {
if (!isAllowedExtension(file)) {
if (!isAllowedExtension(file)) {
return false
return false
}
}
return true
return true
// @ts-ignore
// @ts-ignore
}).filter(createIgnoreFilter())
}).filter(createIgnoreFilter())
return allowedFiles
return allowedFiles
}
}
/**
/**
* #### Reads the .cihsignore file and returns the list of files to ignore.
* #### Reads the .cihsignore file and returns the list of files to ignore.
* @private
* @private
* @async
* @async
* @returns {Promise<string[]>} List of files to ignore.
* @returns {Promise<string[]>} List of files to ignore.
*/
*/
Copiar
Copiado
Copiar
Copiado
async function readCihsIgnore
() {
async function readCihsIgnore
() {
return new Promise((resolve) =>
{
try
{
const cihsignorePath = path.join(
process.cwd()
, '
.cihsignore
');
if (await isFileDir(`${
process.cwd()
}/
.cihsignore
`)) {
const ignoreContent = await
fsPromises.readFile(
`${process.cwd()}/.
cihsignore
`
, 'utf8'
)
fsPromises.access(cihsignorePath)
return
ignoreContent
.split(
'\n')
.map(line => line.trim())
.filter(line => line && !line.startsWith('#'))
.then(() =>
fsPromises.readFile(
cihsignore
Path
, 'utf8'
)
)
} else {
.then(ignoreContent => {
return []
const ignoredPaths =
ignoreContent
}
.split(
/\r?\n/)
}
catch
(error
)
{
.map(line => line.trim())
console.error('Error reading .cihsignore file:', error)
.filter(line => line && !line.startsWith('#'))
;
return []
resolve(ignoredPaths);
}
})
.
catch
(error
=>
{
console.error('Error reading .cihsignore file:', error)
;
resolve([]);
});
}
);
}
}
/**
/**
* #### Walks the src folder for files, filters them based on ignore filter and CI .cihsignore file.
* #### Walks the src folder for files, filters them based on ignore filter and CI .cihsignore file.
* @async
* @async
* @private
* @private
* @param {string} src - src folder
* @param {string} src - src folder
* @returns {Promise<Array<string>>} src file list
* @returns {Promise<Array<string>>} src file list
*/
*/
const getCiUploadableFileList = async (src) => {
const getCiUploadableFileList = async (src) => {
/**
/**
* @type {Array<string>}
* @type {Array<string>}
*/
*/
let filePaths = []
let filePaths = []
try {
try {
filePaths = await walk(src)
filePaths = await walk(src)
} catch (error) {
} catch (error) {
console.error(error)
console.error(error)
}
}
let allowedFiles = filePaths.filter((/** @type {any} */ file) => {
let allowedFiles = filePaths.filter((/** @type {any} */ file) => {
if (!isAllowedExtension(file)) {
if (!isAllowedExtension(file)) {
return false
return false
}
}
return true
return true
// @ts-ignore
// @ts-ignore
}).filter(createIgnoreFilter())
}).filter(createIgnoreFilter())
async function filterFiles (/** @type {any} */ files) {
async function filterFiles (/** @type {any} */ files) {
const ignoredPaths = await readCihsIgnore()
const ignoredPaths = await readCihsIgnore()
return files.filter((/** @type {any} */ file) => !ignoredPaths.some(ignoredPath => file.includes(ignoredPath)))
return files.filter((/** @type {any} */ file) => !ignoredPaths.some(ignoredPath => file.includes(ignoredPath)))
}
}
allowedFiles = await filterFiles(allowedFiles)
allowedFiles = await filterFiles(allowedFiles)
return allowedFiles
return allowedFiles
}
}
/**
/**
* #### upload all HubSpot theme files
* #### upload all HubSpot theme files
* @async
* @async
* @param {HUBSPOT_AUTH_CONFIG} config - hubspot authentication config
* @param {HUBSPOT_AUTH_CONFIG} config - hubspot authentication config
* @param {string} themeName - theme name
* @param {string} themeName - theme name
* @returns undefined
* @returns undefined
*/
*/
async function uploadTheme (config, themeName) {
async function uploadTheme (config, themeName) {
try {
try {
const timeStart = ui.startTask('uploadTheme')
const timeStart = ui.startTask('uploadTheme')
const cmslibOptions = getThemeOptions()
const cmslibOptions = getThemeOptions()
Copiar
Copiado
Copiar
Copiado
const src =
path.join(
process.cwd()
,
cmslibOptions.themeFolder
)
const src =
`${
process.cwd()
}/${
cmslibOptions.themeFolder
}`
const dest = themeName
const dest = themeName
const portalId = config.portals[0].portalId
const portalId = config.portals[0].portalId
throwErrorIfMissingScope(config, 'design_manager')
throwErrorIfMissingScope(config, 'design_manager')
setLogLevel(LOG_LEVEL.LOG)
setLogLevel(LOG_LEVEL.LOG)
const uploadableFileList = await getUploadableFileList(src)
const uploadableFileList = await getUploadableFileList(src)
await uploadFolder.uploadFolder(
await uploadFolder.uploadFolder(
portalId,
portalId,
src,
src,
dest,
dest,
{ overwrite: false },
{ overwrite: false },
{ saveOutput: true, convertFields: false },
{ saveOutput: true, convertFields: false },
uploadableFileList,
uploadableFileList,
cmsMode
cmsMode
)
)
ui.endTask({ taskName: 'uploadTheme', timeStart })
ui.endTask({ taskName: 'uploadTheme', timeStart })
} catch (error) {
} catch (error) {
console.error(chalk.red('Error:'))
console.error(chalk.red('Error:'))
console.error(error.message)
console.error(error.message)
process.exitCode = 1
process.exitCode = 1
if (process.env.DEBUG_MODE === 'debug') {
if (process.env.DEBUG_MODE === 'debug') {
console.error(error)
console.error(error)
process.exitCode = 1
process.exitCode = 1
}
}
}
}
}
}
/**
/**
* #### delete all templates in theme and reupload them
* #### delete all templates in theme and reupload them
* @async
* @async
* @param {HUBSPOT_AUTH_CONFIG} config - hubspot authentication config
* @param {HUBSPOT_AUTH_CONFIG} config - hubspot authentication config
* @param {string} themeName - theme name
* @param {string} themeName - theme name
* @returns undefined
* @returns undefined
*/
*/
async function cleanUploadThemeTemplates (config, themeName) {
async function cleanUploadThemeTemplates (config, themeName) {
const timeStart = ui.startTask('cleanUploadThemeTemplates')
const timeStart = ui.startTask('cleanUploadThemeTemplates')
const spinner = ora('Reupload all templates').start()
const spinner = ora('Reupload all templates').start()
try {
try {
const cmslibOptions = getThemeOptions()
const cmslibOptions = getThemeOptions()
Copiar
Copiado
Copiar
Copiado
const src =
path.join(
process.cwd()
,
cmslibOptions.themeFolder
, '
templates
')
const src =
`${
process.cwd()
}/${
cmslibOptions.themeFolder
}/
templates
`
const dest =
path.join(
themeName
, '
templates
')
const dest =
`${
themeName
}/
templates
`
const portalId = config.portals[0].portalId
const portalId = config.portals[0].portalId
throwErrorIfMissingScope(config, 'design_manager')
throwErrorIfMissingScope(config, 'design_manager')
setLogLevel(LOG_LEVEL.NONE)
setLogLevel(LOG_LEVEL.NONE)
const uploadableFileList = await getUploadableFileList(src)
const uploadableFileList = await getUploadableFileList(src)
const filesToDelete = await getDirectoryContentsByPath(portalId, dest)
const filesToDelete = await getDirectoryContentsByPath(portalId, dest)
if (filesToDelete !== undefined && filesToDelete.data.children.length > 0) {
if (filesToDelete !== undefined && filesToDelete.data.children.length > 0) {
for await (const file of filesToDelete.data.children) {
for await (const file of filesToDelete.data.children) {
// @ts-ignore
// @ts-ignore
if (file.includes('.html')) {
if (file.includes('.html')) {
Copiar
Copiado
Copiar
Copiado
await deleteFile(portalId,
path.join(
dest
,
file
)
)
await deleteFile(portalId,
`${
dest
}/${
file
}`
)
}
}
}
}
}
}
await uploadFolder.uploadFolder(
await uploadFolder.uploadFolder(
portalId,
portalId,
src,
src,
dest,
dest,
{ overwrite: false },
{ overwrite: false },
{ saveOutput: true, convertFields: false },
{ saveOutput: true, convertFields: false },
uploadableFileList,
uploadableFileList,
cmsMode
cmsMode
)
)
spinner.succeed()
spinner.succeed()
ui.endTask({ taskName: 'cleanUploadThemeTemplates', timeStart })
ui.endTask({ taskName: 'cleanUploadThemeTemplates', timeStart })
} catch (error) {
} catch (error) {
spinner.fail()
spinner.fail()
console.error(chalk.red('Error:'))
console.error(chalk.red('Error:'))
console.error(error.message)
console.error(error.message)
process.exitCode = 1
process.exitCode = 1
if (process.env.DEBUG_MODE === 'debug') {
if (process.env.DEBUG_MODE === 'debug') {
console.error(error)
console.error(error)
process.exitCode = 1
process.exitCode = 1
}
}
}
}
}
}
/**
/**
* #### clean theme and reupload it
* #### clean theme and reupload it
* @async
* @async
* @param {HUBSPOT_AUTH_CONFIG} config - hubspot authentication config
* @param {HUBSPOT_AUTH_CONFIG} config - hubspot authentication config
* @param {string} themeName - theme name
* @param {string} themeName - theme name
* @returns undefined
* @returns undefined
*/
*/
async function cleanUploadTheme (config, themeName) {
async function cleanUploadTheme (config, themeName) {
const timeStart = ui.startTask('cleanUploadTheme')
const timeStart = ui.startTask('cleanUploadTheme')
const dest = themeName
const dest = themeName
const spinner = ora(`Clean ${dest} folder before upload`)
const spinner = ora(`Clean ${dest} folder before upload`)
try {
try {
const cmslibOptions = getThemeOptions()
const cmslibOptions = getThemeOptions()
Copiar
Copiado
Copiar
Copiado
const src =
path.join(
process.cwd()
,
cmslibOptions.themeFolder
)
const src =
`${
process.cwd()
}/${
cmslibOptions.themeFolder
}`
const portalId = config.portals[0].portalId
const portalId = config.portals[0].portalId
throwErrorIfMissingScope(config, 'design_manager')
throwErrorIfMissingScope(config, 'design_manager')
setLogLevel(LOG_LEVEL.LOG)
setLogLevel(LOG_LEVEL.LOG)
const uploadableFileList = await getUploadableFileList(src)
const uploadableFileList = await getUploadableFileList(src)
spinner.start()
spinner.start()
const filesToDelete = await getDirectoryContentsByPath(portalId, '/')
const filesToDelete = await getDirectoryContentsByPath(portalId, '/')
if (filesToDelete !== undefined && filesToDelete.data.children.length > 0) {
if (filesToDelete !== undefined && filesToDelete.data.children.length > 0) {
for await (const file of filesToDelete.data.children) {
for await (const file of filesToDelete.data.children) {
// @ts-ignore
// @ts-ignore
if (file === dest) {
if (file === dest) {
await deleteFile(portalId, file)
await deleteFile(portalId, file)
}
}
}
}
}
}
spinner.succeed()
spinner.succeed()
await uploadFolder.uploadFolder(
await uploadFolder.uploadFolder(
portalId,
portalId,
src,
src,
dest,
dest,
{ overwrite: false },
{ overwrite: false },
{ saveOutput: true, convertFields: false },
{ saveOutput: true, convertFields: false },
uploadableFileList,
uploadableFileList,
cmsMode
cmsMode
)
)
ui.endTask({ taskName: 'cleanUploadTheme', timeStart })
ui.endTask({ taskName: 'cleanUploadTheme', timeStart })
} catch (error) {
} catch (error) {
spinner.fail()
spinner.fail()
console.error(chalk.red('Error:'))
console.error(chalk.red('Error:'))
console.error(error.message)
console.error(error.message)
process.exitCode = 1
process.exitCode = 1
if (process.env.DEBUG_MODE === 'debug') {
if (process.env.DEBUG_MODE === 'debug') {
console.error(error)
console.error(error)
process.exitCode = 1
process.exitCode = 1
}
}
}
}
}
}
/**
/**
* #### CI clean theme upload
* #### CI clean theme upload
* @async
* @async
* @param {HUBSPOT_AUTH_CONFIG} config - hubspot authentication config
* @param {HUBSPOT_AUTH_CONFIG} config - hubspot authentication config
* @param {string} themeName - theme name
* @param {string} themeName - theme name
* @returns undefined
* @returns undefined
*/
*/
async function ciUploadTheme (config, themeName) {
async function ciUploadTheme (config, themeName) {
const timeStart = ui.startTask('ciUpload')
const timeStart = ui.startTask('ciUpload')
const dest = themeName
const dest = themeName
const spinner = ora(`Clean ${dest} folder before upload`)
const spinner = ora(`Clean ${dest} folder before upload`)
try {
try {
const cmslibOptions = getThemeOptions()
const cmslibOptions = getThemeOptions()
Copiar
Copiado
Copiar
Copiado
const src =
path.join(
process.cwd()
,
cmslibOptions.themeFolder
)
const src =
`${
process.cwd()
}/${
cmslibOptions.themeFolder
}`
const portalId = config.portals[0].portalId
const portalId = config.portals[0].portalId
throwErrorIfMissingScope(config, 'design_manager')
throwErrorIfMissingScope(config, 'design_manager')
setLogLevel(LOG_LEVEL.LOG)
setLogLevel(LOG_LEVEL.LOG)
const uploadableFileList = await getCiUploadableFileList(src)
const uploadableFileList = await getCiUploadableFileList(src)
spinner.start()
spinner.start()
const filesToDelete = await getDirectoryContentsByPath(portalId, '/')
const filesToDelete = await getDirectoryContentsByPath(portalId, '/')
if (filesToDelete !== undefined && filesToDelete.data.children.length > 0) {
if (filesToDelete !== undefined && filesToDelete.data.children.length > 0) {
for await (const file of filesToDelete.data.children) {
for await (const file of filesToDelete.data.children) {
// @ts-ignore
// @ts-ignore
if (file === dest) {
if (file === dest) {
await deleteFile(portalId, file)
await deleteFile(portalId, file)
}
}
}
}
}
}
spinner.succeed()
spinner.succeed()
await uploadFolder.uploadFolder(
await uploadFolder.uploadFolder(
portalId,
portalId,
src,
src,
dest,
dest,
{ overwrite: false },
{ overwrite: false },
{ saveOutput: true, convertFields: false },
{ saveOutput: true, convertFields: false },
uploadableFileList,
uploadableFileList,
cmsMode
cmsMode
)
)
ui.endTask({ taskName: 'ciUpload', timeStart })
ui.endTask({ taskName: 'ciUpload', timeStart })
} catch (error) {
} catch (error) {
spinner.fail()
spinner.fail()
console.error(chalk.red('Error:'))
console.error(chalk.red('Error:'))
console.error(error.message)
console.error(error.message)
process.exitCode = 1
process.exitCode = 1
if (process.env.DEBUG_MODE === 'debug') {
if (process.env.DEBUG_MODE === 'debug') {
console.error(error)
console.error(error)
process.exitCode = 1
process.exitCode = 1
}
}
}
}
}
}
/**
/**
* #### prepare file choices for prompt
* #### prepare file choices for prompt
* @private
* @private
* @param {Array<FILE_LIST>} files - hubdb files
* @param {Array<FILE_LIST>} files - hubdb files
* @returns {Array<{name:string, value:{path:string, name:string, label:string}}>} files choices
* @returns {Array<{name:string, value:{path:string, name:string, label:string}}>} files choices
*/
*/
function prepareFileChoices (files) {
function prepareFileChoices (files) {
const fileChoices = []
const fileChoices = []
for (const file of files) {
for (const file of files) {
fileChoices.push({ name: file.name, value: { path: file.path, name: file.name, label: file.name.slice(0, -7) } })
fileChoices.push({ name: file.name, value: { path: file.path, name: file.name, label: file.name.slice(0, -7) } })
}
}
return fileChoices
return fileChoices
}
}
/**
/**
* #### select standalome modules to upload
* #### select standalome modules to upload
* @async
* @async
* @private
* @private
* @param {Array<FILE_LIST>} dirs - files
* @param {Array<FILE_LIST>} dirs - files
* @returns {Promise<Array<{path:string, name:string, label:string}>>} selected files
* @returns {Promise<Array<{path:string, name:string, label:string}>>} selected files
*/
*/
async function selectModules (dirs) {
async function selectModules (dirs) {
const selectFiles = {
const selectFiles = {
message: 'Pick modules:',
message: 'Pick modules:',
choices: prepareFileChoices(dirs),
choices: prepareFileChoices(dirs),
pageSize: 5,
pageSize: 5,
loop: false
loop: false
}
}
const confirmPortal = (/** @type {any} */ selectedFiles) => {
const confirmPortal = (/** @type {any} */ selectedFiles) => {
const filesNameList = []
const filesNameList = []
for (const file of selectedFiles) {
for (const file of selectedFiles) {
filesNameList.push(file.name)
filesNameList.push(file.name)
}
}
if (filesNameList.length === 1) {
if (filesNameList.length === 1) {
return {
return {
message: `Continue with ${chalk.cyan.bold(filesNameList.join(','))} module?`
message: `Continue with ${chalk.cyan.bold(filesNameList.join(','))} module?`
}
}
} else {
} else {
return {
return {
message: `Continue with ${chalk.cyan.bold(filesNameList.join(','))} modules?`
message: `Continue with ${chalk.cyan.bold(filesNameList.join(','))} modules?`
}
}
}
}
}
}
// select files
// select files
let selectedTables = await checkbox(selectFiles)
let selectedTables = await checkbox(selectFiles)
if (!selectedTables.length) {
if (!selectedTables.length) {
console.log(chalk.yellow('No modules selected'))
console.log(chalk.yellow('No modules selected'))
process.exit(0)
process.exit(0)
}
}
// confirm selection
// confirm selection
let confirmed = await confirm(confirmPortal(selectedTables))
let confirmed = await confirm(confirmPortal(selectedTables))
if (!confirmed) {
if (!confirmed) {
// try again one more time
// try again one more time
selectedTables = await checkbox(selectFiles)
selectedTables = await checkbox(selectFiles)
if (!selectedTables.length) {
if (!selectedTables.length) {
console.log(chalk.yellow('No modules selected'))
console.log(chalk.yellow('No modules selected'))
process.exit(0)
process.exit(0)
}
}
confirmed = await confirm(confirmPortal(selectedTables))
confirmed = await confirm(confirmPortal(selectedTables))
if (!confirmed) {
if (!confirmed) {
process.exit(0)
process.exit(0)
}
}
}
}
return selectedTables
return selectedTables
}
}
/**
/**
* #### upload module to HubSpot
* #### upload module to HubSpot
* @async
* @async
* @param {HUBSPOT_AUTH_CONFIG} config - hubspot authentication config
* @param {HUBSPOT_AUTH_CONFIG} config - hubspot authentication config
* @returns undefined
* @returns undefined
*/
*/
async function uploadSelectedModules (config) {
async function uploadSelectedModules (config) {
try {
try {
const timeStart = ui.startTask('uploadModules')
const timeStart = ui.startTask('uploadModules')
Copiar
Copiado
Copiar
Copiado
const modulesToUpload = await getFileList(
path.normalize(
'standalone-modules/*.module'
)
, {
const modulesToUpload = await getFileList(
'standalone-modules/*.module'
, {
objectMode: true,
onlyDirectories: true,
deep: 1
})
objectMode: true,
onlyDirectories: true,
deep: 1
})
const selectedModules = await selectModules(modulesToUpload)
const selectedModules = await selectModules(modulesToUpload)
const portalId = config.portals[0].portalId
const portalId = config.portals[0].portalId
throwErrorIfMissingScope(config, 'design_manager')
throwErrorIfMissingScope(config, 'design_manager')
setLogLevel(LOG_LEVEL.LOG)
setLogLevel(LOG_LEVEL.LOG)
for (const module of selectedModules) {
for (const module of selectedModules) {
const src = module.path
const src = module.path
const dest = module.name
const dest = module.name
if (await isFileDir(src) === false) {
if (await isFileDir(src) === false) {
throw new Error(`${chalk.red('Error')}: Module ${chalk.green(src)} does not exist`)
throw new Error(`${chalk.red('Error')}: Module ${chalk.green(src)} does not exist`)
}
}
const uploadableFileList = await getUploadableFileList(src)
const uploadableFileList = await getUploadableFileList(src)
await uploadFolder.uploadFolder(
await uploadFolder.uploadFolder(
portalId,
portalId,
src,
src,
dest,
dest,
{ overwrite: false },
{ overwrite: false },
{ saveOutput: true, convertFields: false },
{ saveOutput: true, convertFields: false },
uploadableFileList,
uploadableFileList,
cmsMode
cmsMode
)
)
}
}
ui.endTask({ taskName: 'uploadModules', timeStart })
ui.endTask({ taskName: 'uploadModules', timeStart })
} catch (error) {
} catch (error) {
console.error(chalk.red('Error:'))
console.error(chalk.red('Error:'))
console.error(error.message)
console.error(error.message)
process.exitCode = 1
process.exitCode = 1
if (process.env.DEBUG_MODE === 'debug') {
if (process.env.DEBUG_MODE === 'debug') {
console.error(error)
console.error(error)
process.exitCode = 1
process.exitCode = 1
}
}
}
}
}
}
export { uploadTheme, cleanUploadThemeTemplates, cleanUploadTheme, ciUploadTheme, uploadSelectedModules }
export { uploadTheme, cleanUploadThemeTemplates, cleanUploadTheme, ciUploadTheme, uploadSelectedModules }
Copiar
Copiado
Copiar
Copiado
Diferenças salvas
Texto original
Abrir arquivo
/** @module hubspot/upload */ /// <reference path="../types/types.js" /> import fsPromises from 'fs/promises' 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' import chalk from 'chalk' import checkbox from '@inquirer/checkbox' import confirm from '@inquirer/confirm' import { getFileList, isFileDir } from '../utils/fs.js' import path from 'path' /** * @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 } /** * #### Reads the .cihsignore file and returns the list of files to ignore. * @private * @async * @returns {Promise<string[]>} List of files to ignore. */ async function readCihsIgnore() { return new Promise((resolve) => { const cihsignorePath = path.join(process.cwd(), '.cihsignore'); fsPromises.access(cihsignorePath) .then(() => fsPromises.readFile(cihsignorePath, 'utf8')) .then(ignoreContent => { const ignoredPaths = ignoreContent .split(/\r?\n/) .map(line => line.trim()) .filter(line => line && !line.startsWith('#')); resolve(ignoredPaths); }) .catch(error => { console.error('Error reading .cihsignore file:', error); resolve([]); }); }); } /** * #### Walks the src folder for files, filters them based on ignore filter and CI .cihsignore file. * @async * @private * @param {string} src - src folder * @returns {Promise<Array<string>>} src file list */ const getCiUploadableFileList = async (src) => { /** * @type {Array<string>} */ let filePaths = [] try { filePaths = await walk(src) } catch (error) { console.error(error) } let allowedFiles = filePaths.filter((/** @type {any} */ file) => { if (!isAllowedExtension(file)) { return false } return true // @ts-ignore }).filter(createIgnoreFilter()) async function filterFiles (/** @type {any} */ files) { const ignoredPaths = await readCihsIgnore() return files.filter((/** @type {any} */ file) => !ignoredPaths.some(ignoredPath => file.includes(ignoredPath))) } allowedFiles = await filterFiles(allowedFiles) 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 = path.join(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(chalk.red('Error:')) console.error(error.message) process.exitCode = 1 if (process.env.DEBUG_MODE === 'debug') { console.error(error) process.exitCode = 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 = path.join(process.cwd(), cmslibOptions.themeFolder, 'templates') const dest = path.join(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.data.children.length > 0) { for await (const file of filesToDelete.data.children) { // @ts-ignore if (file.includes('.html')) { await deleteFile(portalId, path.join(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(chalk.red('Error:')) console.error(error.message) process.exitCode = 1 if (process.env.DEBUG_MODE === 'debug') { console.error(error) process.exitCode = 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 = path.join(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.data.children.length > 0) { for await (const file of filesToDelete.data.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(chalk.red('Error:')) console.error(error.message) process.exitCode = 1 if (process.env.DEBUG_MODE === 'debug') { console.error(error) process.exitCode = 1 } } } /** * #### CI clean theme upload * @async * @param {HUBSPOT_AUTH_CONFIG} config - hubspot authentication config * @param {string} themeName - theme name * @returns undefined */ async function ciUploadTheme (config, themeName) { const timeStart = ui.startTask('ciUpload') const dest = themeName const spinner = ora(`Clean ${dest} folder before upload`) try { const cmslibOptions = getThemeOptions() const src = path.join(process.cwd(), cmslibOptions.themeFolder) const portalId = config.portals[0].portalId throwErrorIfMissingScope(config, 'design_manager') setLogLevel(LOG_LEVEL.LOG) const uploadableFileList = await getCiUploadableFileList(src) spinner.start() const filesToDelete = await getDirectoryContentsByPath(portalId, '/') if (filesToDelete !== undefined && filesToDelete.data.children.length > 0) { for await (const file of filesToDelete.data.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: 'ciUpload', timeStart }) } catch (error) { spinner.fail() console.error(chalk.red('Error:')) console.error(error.message) process.exitCode = 1 if (process.env.DEBUG_MODE === 'debug') { console.error(error) process.exitCode = 1 } } } /** * #### prepare file choices for prompt * @private * @param {Array<FILE_LIST>} files - hubdb files * @returns {Array<{name:string, value:{path:string, name:string, label:string}}>} files choices */ function prepareFileChoices (files) { const fileChoices = [] for (const file of files) { fileChoices.push({ name: file.name, value: { path: file.path, name: file.name, label: file.name.slice(0, -7) } }) } return fileChoices } /** * #### select standalome modules to upload * @async * @private * @param {Array<FILE_LIST>} dirs - files * @returns {Promise<Array<{path:string, name:string, label:string}>>} selected files */ async function selectModules (dirs) { const selectFiles = { message: 'Pick modules:', choices: prepareFileChoices(dirs), pageSize: 5, loop: false } const confirmPortal = (/** @type {any} */ selectedFiles) => { const filesNameList = [] for (const file of selectedFiles) { filesNameList.push(file.name) } if (filesNameList.length === 1) { return { message: `Continue with ${chalk.cyan.bold(filesNameList.join(','))} module?` } } else { return { message: `Continue with ${chalk.cyan.bold(filesNameList.join(','))} modules?` } } } // select files let selectedTables = await checkbox(selectFiles) if (!selectedTables.length) { console.log(chalk.yellow('No modules selected')) process.exit(0) } // confirm selection let confirmed = await confirm(confirmPortal(selectedTables)) if (!confirmed) { // try again one more time selectedTables = await checkbox(selectFiles) if (!selectedTables.length) { console.log(chalk.yellow('No modules selected')) process.exit(0) } confirmed = await confirm(confirmPortal(selectedTables)) if (!confirmed) { process.exit(0) } } return selectedTables } /** * #### upload module to HubSpot * @async * @param {HUBSPOT_AUTH_CONFIG} config - hubspot authentication config * @returns undefined */ async function uploadSelectedModules (config) { try { const timeStart = ui.startTask('uploadModules') const modulesToUpload = await getFileList(path.normalize('standalone-modules/*.module'), { objectMode: true, onlyDirectories: true, deep: 1 }) const selectedModules = await selectModules(modulesToUpload) const portalId = config.portals[0].portalId throwErrorIfMissingScope(config, 'design_manager') setLogLevel(LOG_LEVEL.LOG) for (const module of selectedModules) { const src = module.path const dest = module.name if (await isFileDir(src) === false) { throw new Error(`${chalk.red('Error')}: Module ${chalk.green(src)} does not exist`) } const uploadableFileList = await getUploadableFileList(src) await uploadFolder.uploadFolder( portalId, src, dest, { overwrite: false }, { saveOutput: true, convertFields: false }, uploadableFileList, cmsMode ) } ui.endTask({ taskName: 'uploadModules', timeStart }) } catch (error) { console.error(chalk.red('Error:')) console.error(error.message) process.exitCode = 1 if (process.env.DEBUG_MODE === 'debug') { console.error(error) process.exitCode = 1 } } } export { uploadTheme, cleanUploadThemeTemplates, cleanUploadTheme, ciUploadTheme, uploadSelectedModules }
Texto alterado
Abrir arquivo
/** @module hubspot/upload */ /// <reference path="../types/types.js" /> import fsPromises from 'fs/promises' 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' import chalk from 'chalk' import checkbox from '@inquirer/checkbox' import confirm from '@inquirer/confirm' import { getFileList, isFileDir } from '../utils/fs.js' /** * @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 } /** * #### Reads the .cihsignore file and returns the list of files to ignore. * @private * @async * @returns {Promise<string[]>} List of files to ignore. */ async function readCihsIgnore () { try { if (await isFileDir(`${process.cwd()}/.cihsignore`)) { const ignoreContent = await fsPromises.readFile(`${process.cwd()}/.cihsignore`, 'utf8') return ignoreContent.split('\n').map(line => line.trim()).filter(line => line && !line.startsWith('#')) } else { return [] } } catch (error) { console.error('Error reading .cihsignore file:', error) return [] } } /** * #### Walks the src folder for files, filters them based on ignore filter and CI .cihsignore file. * @async * @private * @param {string} src - src folder * @returns {Promise<Array<string>>} src file list */ const getCiUploadableFileList = async (src) => { /** * @type {Array<string>} */ let filePaths = [] try { filePaths = await walk(src) } catch (error) { console.error(error) } let allowedFiles = filePaths.filter((/** @type {any} */ file) => { if (!isAllowedExtension(file)) { return false } return true // @ts-ignore }).filter(createIgnoreFilter()) async function filterFiles (/** @type {any} */ files) { const ignoredPaths = await readCihsIgnore() return files.filter((/** @type {any} */ file) => !ignoredPaths.some(ignoredPath => file.includes(ignoredPath))) } allowedFiles = await filterFiles(allowedFiles) 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(chalk.red('Error:')) console.error(error.message) process.exitCode = 1 if (process.env.DEBUG_MODE === 'debug') { console.error(error) process.exitCode = 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.data.children.length > 0) { for await (const file of filesToDelete.data.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(chalk.red('Error:')) console.error(error.message) process.exitCode = 1 if (process.env.DEBUG_MODE === 'debug') { console.error(error) process.exitCode = 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.data.children.length > 0) { for await (const file of filesToDelete.data.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(chalk.red('Error:')) console.error(error.message) process.exitCode = 1 if (process.env.DEBUG_MODE === 'debug') { console.error(error) process.exitCode = 1 } } } /** * #### CI clean theme upload * @async * @param {HUBSPOT_AUTH_CONFIG} config - hubspot authentication config * @param {string} themeName - theme name * @returns undefined */ async function ciUploadTheme (config, themeName) { const timeStart = ui.startTask('ciUpload') 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 getCiUploadableFileList(src) spinner.start() const filesToDelete = await getDirectoryContentsByPath(portalId, '/') if (filesToDelete !== undefined && filesToDelete.data.children.length > 0) { for await (const file of filesToDelete.data.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: 'ciUpload', timeStart }) } catch (error) { spinner.fail() console.error(chalk.red('Error:')) console.error(error.message) process.exitCode = 1 if (process.env.DEBUG_MODE === 'debug') { console.error(error) process.exitCode = 1 } } } /** * #### prepare file choices for prompt * @private * @param {Array<FILE_LIST>} files - hubdb files * @returns {Array<{name:string, value:{path:string, name:string, label:string}}>} files choices */ function prepareFileChoices (files) { const fileChoices = [] for (const file of files) { fileChoices.push({ name: file.name, value: { path: file.path, name: file.name, label: file.name.slice(0, -7) } }) } return fileChoices } /** * #### select standalome modules to upload * @async * @private * @param {Array<FILE_LIST>} dirs - files * @returns {Promise<Array<{path:string, name:string, label:string}>>} selected files */ async function selectModules (dirs) { const selectFiles = { message: 'Pick modules:', choices: prepareFileChoices(dirs), pageSize: 5, loop: false } const confirmPortal = (/** @type {any} */ selectedFiles) => { const filesNameList = [] for (const file of selectedFiles) { filesNameList.push(file.name) } if (filesNameList.length === 1) { return { message: `Continue with ${chalk.cyan.bold(filesNameList.join(','))} module?` } } else { return { message: `Continue with ${chalk.cyan.bold(filesNameList.join(','))} modules?` } } } // select files let selectedTables = await checkbox(selectFiles) if (!selectedTables.length) { console.log(chalk.yellow('No modules selected')) process.exit(0) } // confirm selection let confirmed = await confirm(confirmPortal(selectedTables)) if (!confirmed) { // try again one more time selectedTables = await checkbox(selectFiles) if (!selectedTables.length) { console.log(chalk.yellow('No modules selected')) process.exit(0) } confirmed = await confirm(confirmPortal(selectedTables)) if (!confirmed) { process.exit(0) } } return selectedTables } /** * #### upload module to HubSpot * @async * @param {HUBSPOT_AUTH_CONFIG} config - hubspot authentication config * @returns undefined */ async function uploadSelectedModules (config) { try { const timeStart = ui.startTask('uploadModules') const modulesToUpload = await getFileList('standalone-modules/*.module', { objectMode: true, onlyDirectories: true, deep: 1 }) const selectedModules = await selectModules(modulesToUpload) const portalId = config.portals[0].portalId throwErrorIfMissingScope(config, 'design_manager') setLogLevel(LOG_LEVEL.LOG) for (const module of selectedModules) { const src = module.path const dest = module.name if (await isFileDir(src) === false) { throw new Error(`${chalk.red('Error')}: Module ${chalk.green(src)} does not exist`) } const uploadableFileList = await getUploadableFileList(src) await uploadFolder.uploadFolder( portalId, src, dest, { overwrite: false }, { saveOutput: true, convertFields: false }, uploadableFileList, cmsMode ) } ui.endTask({ taskName: 'uploadModules', timeStart }) } catch (error) { console.error(chalk.red('Error:')) console.error(error.message) process.exitCode = 1 if (process.env.DEBUG_MODE === 'debug') { console.error(error) process.exitCode = 1 } } } export { uploadTheme, cleanUploadThemeTemplates, cleanUploadTheme, ciUploadTheme, uploadSelectedModules }
Encontrar Diferença