Diff
checker
Testo
Testo
Immagini
Documenti
Excel
Cartelle
Legal
Enterprise
Applicazione per desktop
Prezzi
Accedi
Scarica Diffchecker Desktop
Confronta il testo
Trova la differenza tra due file di testo
Strumenti
Cronologia
Editor live
Comprimi invariate
Senza a capo
Layout
Diviso
Unificato
Livello di dettaglio
Intelligente
Parola
Carattere
Evidenziazione sintassi
Scegli sintassi
Ignora
Trasforma testo
Vai alla prima modifica
Modifica input
Diffchecker Desktop
Il modo più sicuro per usare Diffchecker. Ottieni l'app Diffchecker Desktop: i tuoi diff non lasciano mai il tuo computer!
Ottieni Desktop
resultify-hubspot-cms-windows
Creato
2 anni fa
Il diff non scade mai
Eliminare
Esporta
Condividere
Spiegare
60 rimozioni
Linee
Totale
Rimosso
Caratteri
Totale
Rimosso
Per continuare a utilizzare questa funzione, aggiorna a
Diff
checker
Pro
Visualizza prezzi
424 linee
Copia tutti
38 aggiunte
Linee
Totale
Aggiunto
Caratteri
Totale
Aggiunto
Per continuare a utilizzare questa funzione, aggiorna a
Diff
checker
Pro
Visualizza prezzi
412 linee
Copia tutti
/** @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'
Copia
Copiato
Copia
Copiato
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.
*/
*/
Copia
Copiato
Copia
Copiato
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()
Copia
Copiato
Copia
Copiato
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()
Copia
Copiato
Copia
Copiato
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')) {
Copia
Copiato
Copia
Copiato
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()
Copia
Copiato
Copia
Copiato
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()
Copia
Copiato
Copia
Copiato
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')
Copia
Copiato
Copia
Copiato
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 }
Copia
Copiato
Copia
Copiato
Diff salvati
Testo originale
Apri file
/** @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 }
Testo modificato
Apri file
/** @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 }
Trovare la differenza