@griddo/cx 11.10.11 → 11.10.12-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/commands/end-render.js +1 -1
- package/build/commands/end-render.js.map +2 -2
- package/build/commands/prepare-assets-directory.js +1 -1
- package/build/commands/prepare-assets-directory.js.map +2 -2
- package/build/commands/prepare-domains-render.js +4 -4
- package/build/commands/prepare-domains-render.js.map +2 -2
- package/build/commands/reset-render.js +1 -1
- package/build/commands/reset-render.js.map +2 -2
- package/build/commands/start-render.js +1 -1
- package/build/commands/start-render.js.map +2 -2
- package/build/commands/upload-search-content.js +11 -11
- package/build/commands/upload-search-content.js.map +2 -2
- package/build/index.js +2 -2
- package/package.json +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../exporter/core/errors.ts", "../../exporter/shared/npm-modules/brush.ts", "../../exporter/shared/types/render.ts", "../../exporter/core/db.ts", "../../exporter/shared/npm-modules/pkg-dir.ts", "../../exporter/shared/npm-modules/find-up-simple.ts", "../../exporter/shared/envs.ts", "../../exporter/core/GriddoLog.ts", "../../exporter/core/dist-rollback.ts", "../../exporter/core/fs.ts", "../../exporter/shared/errors.ts", "../../exporter/core/print-logos.ts", "../../exporter/shared/endpoints.ts", "../../package.json", "../../exporter/shared/headers.ts", "../../exporter/services/auth.ts", "../../exporter/ssg-adapters/gatsby/index.ts", "../../exporter/core/life-cycle.ts", "../../exporter/core/logger.ts", "../../exporter/services/render.ts", "../../exporter/services/manage-store.ts", "../../exporter/services/render-artifacts.ts", "../../exporter/shared/context.ts", "../../exporter/ssg-adapters/gatsby/actions/clean.ts", "../../exporter/ssg-adapters/gatsby/actions/close.ts", "../../exporter/services/store.ts", "../../node_modules/yocto-queue/index.js", "../../node_modules/p-limit/index.js", "../../exporter/services/api.ts", "../../exporter/services/manage-sites.ts", "../../exporter/services/sites.ts", "../../exporter/services/navigation.ts", "../../exporter/core/images.ts", "../../exporter/services/pages.ts", "../../exporter/services/reference-fields.ts", "../../exporter/ssg-adapters/gatsby/actions/data.ts", "../../exporter/ssg-adapters/gatsby/actions/healthCheck.ts", "../../exporter/ssg-adapters/gatsby/actions/init.ts", "../../exporter/ssg-adapters/gatsby/actions/logs.ts", "../../exporter/services/robots.ts", "../../exporter/services/sitemaps.ts", "../../exporter/shared/npm-modules/xml-parser.ts", "../../exporter/ssg-adapters/gatsby/actions/meta.ts", "../../exporter/ssg-adapters/gatsby/actions/prepare.ts", "../../exporter/ssg-adapters/gatsby/actions/relocation.ts", "../../exporter/ssg-adapters/gatsby/actions/restore.ts", "../../exporter/ssg-adapters/gatsby/shared/gatsby-build.ts", "../../exporter/ssg-adapters/gatsby/actions/ssg.ts", "../../exporter/ssg-adapters/gatsby/actions/sync.ts", "../../exporter/ssg-adapters/gatsby/shared/extract-assets.ts", "../../exporter/ssg-adapters/gatsby/shared/sync-render.ts", "../../exporter/ssg-adapters/gatsby/shared/diff-assets.ts", "../../exporter/ssg-adapters/gatsby/shared/artifacts.ts", "../../exporter/ssg-adapters/gatsby/shared/render-rollback.ts", "../../exporter/commands/start-render.ts"],
|
|
4
|
-
"sourcesContent": ["import type { ErrorsType } from \"../shared/errors\";\n\nimport path from \"node:path\";\n\nimport { brush } from \"../shared/npm-modules/brush\";\nimport { RENDER_MODE } from \"../shared/types/render\";\nimport { readDB, writeDB } from \"./db\";\nimport { distRollback } from \"./dist-rollback\";\nimport { GriddoLog } from \"./GriddoLog\";\n\nexport type ErrorData = {\n\terror: ErrorsType;\n\tmessage: string;\n\texpected?: string;\n\thint?: string;\n};\n\nexport class RenderError extends Error {\n\tconstructor(originalError?: unknown) {\n\t\tsuper(originalError instanceof Error ? originalError.message : String(originalError));\n\n\t\tthis.name = \"InternalCXError\";\n\t\tthis.stack = originalError instanceof Error ? originalError.stack : \"\";\n\t}\n}\n\n/**\n * Throws an error with the provided error message, expected value, and hint.\n */\nfunction throwError(options: ErrorData, stack?: unknown): never {\n\tconst { error, message, expected, hint } = options;\n\n\tconst errorColor = GriddoLog.log(brush.red(`[ ${error} ]`));\n\tconst extraText = [expected, hint].filter(Boolean).join(\"\\n\");\n\n\tGriddoLog.log(`\n${errorColor}\n${message}\n${extraText}\n\n${brush.red(\"stack\")}\n${JSON.stringify(stack, null, 2)}`);\n\n\tthrow new RenderError(stack);\n}\n\n/**\n * Executes the provided asynchronous function and handles errors that occur during execution.\n *\n * - If an error is thrown, attempts to log the error and, if necessary, rolls back the exports directory.\n * - Updates the render database to set the domain's rendering state to \"ERROR\" if an error occurs.\n *\n * @param fn - The asynchronous function to execute within the error handler.\n * @returns A promise that resolves when the function is executed successfully.\n * @throws RenderError | unknown - Rethrows the original error after handling and database state update.\n */\nasync function withErrorHandler(fn: () => Promise<void>) {\n\ttry {\n\t\tawait fn();\n\t} catch (error) {\n\t\tif (error instanceof RenderError) {\n\t\t\tGriddoLog.error(\"Internal Griddo RenderError\");\n\t\t} else if (error instanceof Error) {\n\t\t\tGriddoLog.error(error.message);\n\t\t} else {\n\t\t\tGriddoLog.error(`An unexpected error occurred ${error}`);\n\t\t}\n\n\t\t// Try to rollback the exports directory if needed\n\t\ttry {\n\t\t\tconst data = await readDB();\n\t\t\tconst { root } = data.paths;\n\t\t\tif (data.needsRollbackOnError) {\n\t\t\t\tGriddoLog.info(\"Cleaning exports dir...\");\n\t\t\t\tGriddoLog.verbose(`Deleting ${path.join(root, \"exports\")}...`);\n\n\t\t\t\tawait distRollback(data.currentRenderingDomain!);\n\t\t\t} else {\n\t\t\t\tGriddoLog.info(\"No rollback needed, skipping...\");\n\t\t\t}\n\t\t} catch (_e) {\n\t\t\tGriddoLog.info(\"Early render stage, no db.json created yet...\");\n\t\t}\n\n\t\tconst data = await readDB();\n\t\tdata.domains[data.currentRenderingDomain!].isRendering = false;\n\t\tdata.domains[data.currentRenderingDomain!].renderMode = RENDER_MODE.ERROR;\n\t\tawait writeDB(data);\n\t\tthrow error;\n\t}\n}\n\nexport { throwError, withErrorHandler };\n", "//\n// Brush adds color to a string|number, it does not print it!\n// Its simple, no log, no chains, just color in a string|number\n// usage:\n// console.log(brush.green(\"sucess!\"))\n//\n\nconst RESET = \"\\x1b[0m\";\nconst CODES = {\n\tblack: \"\\x1b[30m\",\n\tred: \"\\x1b[31m\",\n\tgreen: \"\\x1b[32m\",\n\tyellow: \"\\x1b[33m\",\n\tblue: \"\\x1b[34m\",\n\tmagenta: \"\\x1b[35m\",\n\tcyan: \"\\x1b[36m\",\n\twhite: \"\\x1b[37m\",\n\tgray: \"\\x1b[90m\",\n\tbold: \"\\x1b[1m\",\n\tdim: \"\\x1b[2m\",\n} as const;\n\ntype ColorFunction = (text: string | number) => string;\ntype ColorName = keyof typeof CODES;\ntype Brush = Record<ColorName, ColorFunction>;\n\nconst brush = {} as Brush;\n\nfor (const color in CODES) {\n\tconst key = color as ColorName;\n\tbrush[key] = (text: string | number) => `${CODES[key]}${text}${RESET}`;\n}\n\nexport { brush };\n", "import type { RenderInfo } from \"./global\";\n\nconst RENDER_MODE = {\n\tFROM_SCRATCH: \"FROM_SCRATCH\",\n\tINCREMENTAL: \"INCREMENTAL\",\n\tIDLE: \"IDLE\",\n\tERROR: \"ERROR\",\n\tCOMPLETED: \"COMPLETED\",\n} as const;\n\ntype RenderMode = (typeof RENDER_MODE)[keyof typeof RENDER_MODE];\n\nexport interface RenderModeTuple {\n\trenderMode: RenderMode;\n\treason?: string;\n}\n\ntype DomainLike = string;\n\ntype RenderDB = {\n\tgriddoVersion: string;\n\tbuildReportFileName: string;\n\tsortedDomains: DomainLike[];\n\tneedsRollbackOnError: boolean;\n\tcurrentRenderingDomain: string | null;\n\tcommitHash: string;\n\tcommitMessage: string;\n\tpaths: {\n\t\troot: string;\n\t\tcx: string;\n\t\tssg: string;\n\t\tcxCache: string;\n\t\tcomponents: string;\n\t\texportsDir: string;\n\t\texportsDirBackup: string;\n\t};\n\tdomains: {\n\t\t[key: DomainLike]: {\n\t\t\trenderMode?: RenderMode;\n\t\t\tshouldBeRendered?: boolean;\n\t\t\tisRendering?: boolean;\n\t\t\trenderInfo?: RenderInfo;\n\t\t\trenderModeReason?: string;\n\t\t};\n\t};\n};\n\ninterface Report {\n\tauthControl:\n\t\t| {\n\t\t\t\tAuthorization: string;\n\t\t\t\t\"Cache-Control\": string;\n\t\t\t\tlang?: string | undefined;\n\t\t }\n\t\t| undefined;\n\tsites: {\n\t\tsiteId: number;\n\t\tpublishHashes: string[];\n\t\tsiteHash: string | null;\n\t\tunpublishHashes: string[];\n\t\tpublishPagesIds: number[];\n\t}[];\n}\n\nexport { RENDER_MODE, type RenderDB, type RenderMode, type Report };\n", "import type { RenderDB } from \"../shared/types/render\";\n\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { pkgDirSync } from \"../shared/npm-modules/pkg-dir\";\nimport { GriddoLog } from \"./GriddoLog\";\n\nconst root = pkgDirSync({ cwd: path.resolve(__dirname, \"../../..\") }) || \"\";\nconst cache = path.join(root, \".griddo/cache\");\nconst dbFilePath = path.join(cache, \"db.json\");\n\nasync function readDB(customDBPath = \"\") {\n\tconst file = customDBPath || dbFilePath;\n\ttry {\n\t\treturn JSON.parse(await fsp.readFile(file, \"utf-8\")) as RenderDB;\n\t} catch (error) {\n\t\tGriddoLog.error(`Failed to read DB file at ${file}:`, error);\n\t\tthrow error;\n\t}\n}\n\nasync function writeDB(renderDB: RenderDB, customDBPath = \"\") {\n\tconst file = customDBPath || dbFilePath;\n\ttry {\n\t\tawait fsp.writeFile(file, JSON.stringify(renderDB, null, \"\\t\"));\n\t} catch (error) {\n\t\tGriddoLog.error(`Failed to write DB file at ${file}:`, error);\n\t\tthrow error;\n\t}\n}\n\nexport { readDB, writeDB };\n", "import path from \"node:path\";\n\nimport { findUp, findUpSync } from \"./find-up-simple\";\n\nasync function pkgDir(options?: { readonly cwd?: string }) {\n\tconst { cwd } = options || {};\n\tconst filePath = await findUp(\"package.json\", { cwd });\n\treturn filePath && path.dirname(filePath);\n}\n\nfunction pkgDirSync(options?: { readonly cwd?: string }) {\n\tconst { cwd } = options || {};\n\tconst filePath = findUpSync(\"package.json\", { cwd });\n\treturn filePath && path.dirname(filePath);\n}\n\nexport { pkgDir, pkgDirSync };\n", "import fs from \"node:fs\";\nimport fsPromises from \"node:fs/promises\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport { fileURLToPath } from \"node:url\";\n\n/**\n * Opciones para controlar el comportamiento de la b\u00FAsqueda.\n */\nexport type Options = {\n\t/**\n\tEl directorio desde donde empezar a buscar.\n\t@default process.cwd()\n\t*/\n\treadonly cwd?: URL | string;\n\n\t/**\n\tEl tipo de ruta a buscar.\n\t@default 'file'\n\t*/\n\treadonly type?: \"file\" | \"directory\";\n\n\t/**\n\tUn directorio en el que la b\u00FAsqueda se detiene si no se encuentran coincidencias.\n\t@default El directorio ra\u00EDz del sistema\n\t*/\n\treadonly stopAt?: URL | string;\n};\n\n// Funci\u00F3n auxiliar para convertir una URL en una ruta de archivo de tipo string.\nconst toPath = (urlOrPath: URL | string | undefined): string | undefined =>\n\turlOrPath instanceof URL ? fileURLToPath(urlOrPath) : urlOrPath;\n\n/**\n * Encuentra un archivo o directorio de forma as\u00EDncrona subiendo por los directorios padre.\n * @param name - El nombre del archivo o directorio a buscar.\n * @param options - Opciones de b\u00FAsqueda.\n * @returns La ruta encontrada o `undefined` si no se pudo encontrar.\n */\nexport async function findUp(name: string, options: Options = {}): Promise<string | undefined> {\n\tconst { cwd = process.cwd(), type = \"file\", stopAt: stopAtOption } = options;\n\n\tlet directory = path.resolve(toPath(cwd) ?? \"\");\n\tconst { root } = path.parse(directory);\n\tconst stopAt = stopAtOption ? path.resolve(directory, toPath(stopAtOption)!) : root;\n\tconst isAbsoluteName = path.isAbsolute(name);\n\n\twhile (true) {\n\t\tconst filePath = isAbsoluteName ? name : path.join(directory, name);\n\t\ttry {\n\t\t\t// eslint-disable-next-line no-await-in-loop\n\t\t\tconst stats = await fsPromises.stat(filePath);\n\t\t\tif ((type === \"file\" && stats.isFile()) || (type === \"directory\" && stats.isDirectory())) {\n\t\t\t\treturn filePath;\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignora errores (ej. el archivo no existe) y contin\u00FAa la b\u00FAsqueda.\n\t\t}\n\n\t\tif (directory === stopAt || directory === root) {\n\t\t\tbreak;\n\t\t}\n\n\t\tdirectory = path.dirname(directory);\n\t}\n}\n\n/**\n * Encuentra un archivo o directorio de forma s\u00EDncrona subiendo por los directorios padre.\n * @param name - El nombre del archivo o directorio a buscar.\n * @param options - Opciones de b\u00FAsqueda.\n * @returns La ruta encontrada o `undefined` si no se pudo encontrar.\n */\nexport function findUpSync(name: string, options: Options = {}): string | undefined {\n\tconst { cwd = process.cwd(), type = \"file\", stopAt: stopAtOption } = options;\n\n\tlet directory = path.resolve(toPath(cwd) ?? \"\");\n\tconst { root } = path.parse(directory);\n\tconst stopAt = stopAtOption ? path.resolve(directory, toPath(stopAtOption)!) : root;\n\tconst isAbsoluteName = path.isAbsolute(name);\n\n\twhile (true) {\n\t\tconst filePath = isAbsoluteName ? name : path.join(directory, name);\n\t\ttry {\n\t\t\tconst stats = fs.statSync(filePath, { throwIfNoEntry: false });\n\t\t\tif ((type === \"file\" && stats?.isFile()) || (type === \"directory\" && stats?.isDirectory())) {\n\t\t\t\treturn filePath;\n\t\t\t}\n\t\t} catch {\n\t\t\t// En teor\u00EDa, statSync con `throwIfNoEntry: false` no deber\u00EDa lanzar un error,\n\t\t\t// pero se mantiene por seguridad.\n\t\t}\n\n\t\tif (directory === stopAt || directory === root) {\n\t\t\tbreak;\n\t\t}\n\n\t\tdirectory = path.dirname(directory);\n\t}\n}\n", "const { env } = process;\n\n/**\n * Returns true/false from string\n */\nfunction envIsTruthy(value?: string): boolean {\n\tif (!value) return false;\n\n\tswitch (value.trim().toLowerCase()) {\n\t\tcase \"1\":\n\t\tcase \"true\":\n\t\tcase \"yes\":\n\t\tcase \"y\":\n\t\tcase \"on\":\n\t\t\treturn true;\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\n// Credentials\nconst GRIDDO_API_URL = env.GRIDDO_API_URL || env.API_URL;\nconst GRIDDO_PUBLIC_API_URL = env.GRIDDO_PUBLIC_API_URL || env.PUBLIC_API_URL;\nconst GRIDDO_BOT_USER = env.botEmail || env.GRIDDO_BOT_USER;\nconst GRIDDO_BOT_PASSWORD = env.botPassword || env.GRIDDO_BOT_PASSWORD;\n\n// Rendering\nconst GRIDDO_API_CONCURRENCY_COUNT = Number.parseInt(env.GRIDDO_API_CONCURRENCY_COUNT || \"10\");\nconst GRIDDO_SKIP_BUILD_CHECKS = envIsTruthy(env.GRIDDO_SKIP_BUILD_CHECKS);\nconst GRIDDO_BUILD_LOGS = envIsTruthy(env.GRIDDO_BUILD_LOGS);\nconst GRIDDO_BUILD_LOGS_BUFFER_SIZE = Number.parseInt(env.GRIDDO_BUILD_LOGS_BUFFER_SIZE || \"500\");\nconst GRIDDO_SSG_VERBOSE_LOGS = envIsTruthy(env.GRIDDO_SSG_VERBOSE_LOGS);\nconst GRIDDO_SEARCH_FEATURE = envIsTruthy(env.GRIDDO_SEARCH_FEATURE);\nconst GRIDDO_ASSET_PREFIX = env.GRIDDO_ASSET_PREFIX || env.ASSET_PREFIX;\nconst GRIDDO_REACT_APP_INSTANCE = env.GRIDDO_REACT_APP_INSTANCE || env.REACT_APP_INSTANCE;\nconst GRIDDO_AI_EMBEDDINGS = envIsTruthy(env.GRIDDO_AI_EMBEDDINGS);\nconst GRIDDO_VERBOSE_LOGS = envIsTruthy(env.GRIDDO_VERBOSE_LOGS);\nconst GRIDDO_USE_DIST_BACKUP = envIsTruthy(env.GRIDDO_USE_DIST_BACKUP);\nconst GRIDDO_SSG_BUNDLE_ANALYZER = envIsTruthy(env.GRIDDO_SSG_BUNDLE_ANALYZER);\n\nexport {\n\tGRIDDO_AI_EMBEDDINGS,\n\tGRIDDO_API_CONCURRENCY_COUNT,\n\tGRIDDO_API_URL,\n\tGRIDDO_ASSET_PREFIX,\n\tGRIDDO_BOT_PASSWORD,\n\tGRIDDO_BOT_USER,\n\tGRIDDO_BUILD_LOGS,\n\tGRIDDO_BUILD_LOGS_BUFFER_SIZE,\n\tGRIDDO_PUBLIC_API_URL,\n\tGRIDDO_REACT_APP_INSTANCE,\n\tGRIDDO_SEARCH_FEATURE,\n\tGRIDDO_SKIP_BUILD_CHECKS,\n\tGRIDDO_SSG_BUNDLE_ANALYZER,\n\tGRIDDO_SSG_VERBOSE_LOGS,\n\tGRIDDO_USE_DIST_BACKUP,\n\tGRIDDO_VERBOSE_LOGS,\n};\n", "import { GRIDDO_BUILD_LOGS, GRIDDO_VERBOSE_LOGS } from \"../shared/envs\";\nimport { brush } from \"../shared/npm-modules/brush\";\n\n/**\n * Clase est\u00E1tica para gestionar los logs de la aplicaci\u00F3n.\n * No se puede instanciar, se usa directamente: GriddoLogs.info(\"mensaje\").\n */\nclass GriddoLog {\n\t/** El constructor es privado para prevenir la instanciaci\u00F3n de la clase. */\n\tprivate constructor() {}\n\n\tpublic static verbose(...str: unknown[]): void {\n\t\tif (GRIDDO_VERBOSE_LOGS) {\n\t\t\tconsole.log(brush.yellow(\"verbose\"), brush.dim(str.join(\" \")));\n\t\t}\n\t}\n\n\tpublic static build(...str: unknown[]): void {\n\t\tif (GRIDDO_BUILD_LOGS) {\n\t\t\tGriddoLog.log(...str);\n\t\t}\n\t}\n\n\tpublic static info(...str: unknown[]): void {\n\t\tconsole.log(`${brush.blue(\"info\")} ${str.join(\" \")}`);\n\t}\n\n\tpublic static success(...str: unknown[]): void {\n\t\tconsole.log(`${brush.green(\"success\")} ${str.join(\" \")}`);\n\t}\n\n\tpublic static error(...str: unknown[]): void {\n\t\tconsole.error(`${brush.red(\"error\")} ${str.join(\" \")}`);\n\t}\n\n\tpublic static warn(...str: unknown[]): void {\n\t\tconsole.warn(`${brush.yellow(\"warn\")} ${str.join(\" \")}`);\n\t}\n\n\tpublic static log(...args: Parameters<typeof console.log>): void {\n\t\tconsole.log(...args);\n\t}\n}\n\nexport { GriddoLog };\n", "import fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { readDB } from \"./db\";\nimport { pathExists } from \"./fs\";\nimport { GriddoLog } from \"./GriddoLog\";\n\n/**\n * Rolls back the exports directory for the given domain.\n *\n * - Deletes the potentially corrupt exports directory for the domain.\n * - If a backup exists, it restores the directory from the backup location.\n * - If no backup is found, it informs that a fresh exports directory will be created on the next render.\n *\n * @param domain The domain for which to rollback the exports directory.\n */\nasync function distRollback(domain: string): Promise<void> {\n\tconst data = await readDB();\n\tconst { exportsDir, exportsDirBackup } = data.paths;\n\n\tGriddoLog.info(`Cleaning exports dir for the domain ${domain}`);\n\tGriddoLog.verbose(`Deleting ${path.join(exportsDir, domain)}...`);\n\n\t// TODO: Probar rsync en lugar de borrar y copiar\n\n\t// 1 - Borrar dist corrupto\n\tawait fsp.rm(path.join(exportsDir, domain), {\n\t\trecursive: true,\n\t\tforce: true,\n\t});\n\n\t// 2 - Si hay backup, restaurar\n\tif (await pathExists(path.join(exportsDirBackup, domain))) {\n\t\tawait fsp.cp(path.join(exportsDirBackup, domain), path.join(exportsDir, domain), {\n\t\t\trecursive: true,\n\t\t});\n\n\t\tGriddoLog.info(`export-backup dir for the domain ${domain} found. Restoring before exit...`);\n\t\tGriddoLog.verbose(\n\t\t\t`Copying ${path.join(exportsDirBackup, domain)} -> ${path.join(exportsDir, domain)}...`,\n\t\t);\n\t} else {\n\t\tGriddoLog.info(\n\t\t\t\"No export-backup found, skipping rollback. Next render will create a new exports dir from scratch...\",\n\t\t);\n\t}\n}\n\nexport { distRollback };\n", "import type { MakeDirectoryOptions } from \"node:fs\";\n\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { ArtifactError } from \"../shared/errors\";\nimport { throwError } from \"./errors\";\nimport { GriddoLog } from \"./GriddoLog\";\n\n/**\n * Remove an empty directory from the basePath recursively.\n * If the directory has only .xml files it will handle as empty too (empty site)\n *\n * @param baseDir - The base directory.\n */\nasync function deleteDisposableSiteDirs(baseDir: string) {\n\tif (!(await pathExists(baseDir))) {\n\t\treturn;\n\t}\n\n\tconst sitesDirs = (await fsp.readdir(baseDir, { withFileTypes: true })).filter((file) =>\n\t\tfile.isDirectory(),\n\t);\n\n\tfor (const siteDir of sitesDirs) {\n\t\tconst sitePath = path.join(baseDir, siteDir.name);\n\t\tif (await siteIsEmpty(sitePath)) {\n\t\t\tawait fsp.rm(sitePath, { recursive: true });\n\t\t}\n\t}\n}\n\n/**\n * Creates multiple artifact directories.\n *\n * @param dirs - An array of directory paths.\n * @param options - Same option as `fs.mkdirSync()`\n */\nasync function mkDirs(dirs: string[], options?: MakeDirectoryOptions) {\n\tfor (const dir of dirs) {\n\t\ttry {\n\t\t\tif (!(await pathExists(dir))) {\n\t\t\t\tawait fsp.mkdir(dir, { recursive: true, ...options });\n\t\t\t\tGriddoLog.verbose(`create directory: ${dir}`);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthrowError(ArtifactError, error);\n\t\t}\n\t}\n}\n\nasync function renamePath(src: string, dst: string) {\n\ttry {\n\t\tif (await pathExists(src)) {\n\t\t\tawait fsp.rename(src, dst);\n\t\t\tGriddoLog.verbose(`rename ${src} to ${dst}`);\n\t\t}\n\t} catch (error) {\n\t\tthrowError(ArtifactError, error);\n\t}\n}\n\n/**\n * Copy multiple directories with backup option.\n *\n * @param src - Source directory.\n * @param dst - Destination directory.\n * @param dirs - Directories to copy.\n * @param options.withBackup - Create a previous backup before copy.\n */\nasync function cpDirs(\n\tsrc: string,\n\tdst: string,\n\tdirs: string[],\n\toptions = {\n\t\twithBackup: false,\n\t},\n) {\n\tconst { withBackup } = options;\n\tfor (const dir of dirs) {\n\t\tconst srcCompose = path.join(src, dir);\n\t\tconst dstCompose = path.join(dst, dir);\n\n\t\t// The dir we want to copy, doesn't exist.\n\t\tif (!(await pathExists(srcCompose))) {\n\t\t\tGriddoLog.info(`(Maybe first render) Source directory does not exist: ${srcCompose}`);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Create the backup\n\t\tif (withBackup) {\n\t\t\tawait createBackup(dstCompose);\n\t\t\tGriddoLog.verbose(`create backup: ${dstCompose}`);\n\t\t}\n\n\t\t// Copy directory\n\t\ttry {\n\t\t\t// First clean destination\n\t\t\tif (await pathExists(dstCompose)) {\n\t\t\t\tawait fsp.rm(dstCompose, { recursive: true, force: true });\n\t\t\t\tGriddoLog.verbose(`clean destination: ${dstCompose}`);\n\t\t\t}\n\n\t\t\t// Then copy src to dst\n\t\t\tawait fsp.cp(srcCompose, dstCompose, {\n\t\t\t\trecursive: true,\n\t\t\t\tpreserveTimestamps: true,\n\t\t\t});\n\t\t\tGriddoLog.verbose(`copy: ${srcCompose} to ${dstCompose}`);\n\n\t\t\tif (withBackup) {\n\t\t\t\tawait deleteBackup(dstCompose);\n\t\t\t\tGriddoLog.verbose(`delete backup: ${dstCompose}`);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (withBackup) {\n\t\t\t\tawait restoreBackup(dstCompose);\n\t\t\t\tGriddoLog.verbose(\"Backup has been restored.\");\n\t\t\t}\n\n\t\t\tthrowError(ArtifactError, error);\n\t\t}\n\t}\n}\n\n/**\n * Move artifacts between cx-paths\n *\n * @param src - Source directory.\n * @param dst - Destination directory.\n * @param dirs - Directories to move.\n * @param options - Options.\n */\nasync function mvDirs(\n\tsrc: string,\n\tdst: string,\n\tdirs: string[],\n\toptions?: { withBackup?: boolean; override?: boolean },\n) {\n\tconst { override, withBackup } = options || {};\n\n\tfor (const dir of dirs) {\n\t\tconst srcCompose = path.join(src, dir);\n\t\tconst dstCompose = path.join(dst, dir);\n\n\t\tif (!(await pathExists(srcCompose))) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (withBackup) {\n\t\t\tawait createBackup(dstCompose);\n\t\t}\n\n\t\ttry {\n\t\t\t// Clean destination\n\t\t\tif (override && (await pathExists(dstCompose))) {\n\t\t\t\tawait fsp.rm(dstCompose, { recursive: true, force: true });\n\t\t\t}\n\n\t\t\tawait fsp.rename(srcCompose, dstCompose);\n\t\t\tGriddoLog.verbose(`moved: ${srcCompose} to ${dstCompose}`);\n\n\t\t\tif (withBackup) {\n\t\t\t\tawait deleteBackup(dstCompose);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (withBackup) {\n\t\t\t\tawait restoreBackup(dstCompose);\n\t\t\t\tGriddoLog.info(\"Backup has been restored.\");\n\t\t\t}\n\n\t\t\tthrowError(ArtifactError, error);\n\t\t}\n\t}\n}\n\n/**\n * Removes multiple artifact directories.\n *\n * @param dirs - An array of directory paths.\n */\nasync function rmDirs(dirs: string[]) {\n\tfor (const dir of dirs) {\n\t\ttry {\n\t\t\tawait fsp.rm(dir, { recursive: true, force: true });\n\t\t\tGriddoLog.verbose(`artifact removed: ${dir}`);\n\t\t} catch (error) {\n\t\t\tthrowError(ArtifactError, error);\n\t\t}\n\t}\n}\n\nasync function restoreBackup(src: string, suffix = \"-BACKUP\") {\n\tconst dst = src + suffix;\n\ttry {\n\t\tawait fsp.rename(dst, src);\n\t\tGriddoLog.info(`Backup ${dst} has been restored`);\n\t} catch (_error) {\n\t\tthrow new Error(`Error while delete ${dst} backup`);\n\t}\n}\n\nasync function deleteBackup(src: string, suffix = \"-BACKUP\") {\n\tconst dst = src + suffix;\n\n\tif (!(await pathExists(dst))) {\n\t\treturn;\n\t}\n\n\ttry {\n\t\tawait fsp.rm(dst, { recursive: true, force: true });\n\t\tGriddoLog.verbose(`Backup ${dst} has been deleted`);\n\t} catch (_error) {\n\t\tthrow new Error(`Error while delete ${dst} backup`);\n\t}\n}\n\nasync function createBackup(src: string, suffix = \"-BACKUP\") {\n\tconst dst = src + suffix;\n\n\tif (!(await pathExists(src))) {\n\t\treturn;\n\t}\n\n\tif (await pathExists(dst)) {\n\t\tGriddoLog.warn(`Destination ${dst} already exists`);\n\t\treturn;\n\t}\n\n\ttry {\n\t\tawait fsp.rename(src, dst);\n\t\tGriddoLog.verbose(`Backup of ${src} has been created in ${dst}`);\n\t} catch (error) {\n\t\tGriddoLog.error(`Error while coping ${src} to ${dst} backup`);\n\t\tthrowError(ArtifactError, error);\n\t}\n}\n\n/**\n * Return true if the site folder is empty or only has xml files. (Recursively)\n */\nasync function siteIsEmpty(sitePath: string) {\n\tconst siteFiles = (\n\t\tawait fsp.readdir(sitePath, {\n\t\t\twithFileTypes: true,\n\t\t\trecursive: true,\n\t\t})\n\t).filter((file) => file.isFile() && !path.basename(file.name).startsWith(\".\"));\n\n\tconst xmlFiles = siteFiles.filter((file) => file.name.endsWith(\".xml\"));\n\n\tif (siteFiles.length === xmlFiles.length) {\n\t\treturn true;\n\t}\n}\n\n/**\n * Delete empty directories from the given directory in a recursive way.\n */\nasync function deleteEmptyDirectories(dirPath: string) {\n\ttry {\n\t\tconst stats = await fsp.stat(dirPath);\n\n\t\t// Si no es un directorio, no hacemos nada\n\t\tif (!stats.isDirectory()) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet filesInDirectory: string[];\n\t\ttry {\n\t\t\tfilesInDirectory = await fsp.readdir(dirPath);\n\t\t} catch (err: any) {\n\t\t\t// Si el directorio no existe o no se puede leer (ej. permisos), lo saltamos.\n\t\t\tif (err.code === \"ENOENT\") {\n\t\t\t\tGriddoLog.warn(`The directory \"${dirPath}\" does not exist, skipping it.`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tGriddoLog.error(`Error al leer el directorio \"${dirPath}\":`, err);\n\t\t\tthrow err; // Re-lanza el error para que sea manejado por el llamador\n\t\t}\n\n\t\t// Recorrer los contenidos del directorio\n\t\tfor (const file of filesInDirectory) {\n\t\t\tconst fullPath = path.join(dirPath, file);\n\t\t\tawait deleteEmptyDirectories(fullPath); // Llamada recursiva s\u00EDncrona\n\t\t}\n\n\t\t// Despu\u00E9s de procesar todos los subdirectorios, verifica si el directorio actual est\u00E1 vac\u00EDo\n\t\tconst remainingFiles = await fsp.readdir(dirPath);\n\n\t\tif (remainingFiles.length === 0) {\n\t\t\ttry {\n\t\t\t\tawait fsp.rmdir(dirPath);\n\t\t\t\tGriddoLog.verbose(`Remove empty directory: ${dirPath}`);\n\t\t\t} catch (err: any) {\n\t\t\t\t// Puede que haya habido un problema de concurrencia o permisos\n\t\t\t\tif (err.code === \"ENOENT\") {\n\t\t\t\t\tGriddoLog.warn(\n\t\t\t\t\t\t`El directorio \"${dirPath}\" ya no existe. Posiblemente fue borrado por otra operaci\u00F3n.`,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tGriddoLog.error(`Error al borrar el directorio \"${dirPath}\":`, err);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch (err: any) {\n\t\tif (err.code === \"ENOENT\") {\n\t\t\t// El directorio ya no existe, no es un error para nosotros en este contexto\n\t\t\tGriddoLog.warn(`The directory \"${dirPath}\" does not exist or has already been processed.`);\n\t\t} else {\n\t\t\tGriddoLog.error(`General error general while processing \"${dirPath}\":`, err);\n\t\t\tthrow err;\n\t\t}\n\t}\n}\n\nasync function pathExists(dir: string) {\n\ttry {\n\t\tawait fsp.access(dir);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Busca recursivamente archivos que terminen con un sufijo espec\u00EDfico dentro de un directorio.\n * Esta funci\u00F3n es un generador as\u00EDncrono, lo que la hace muy eficiente en uso de memoria.\n *\n * @param dir El directorio base para comenzar la b\u00FAsqueda.\n * @param suffix El sufijo con el que deben terminar los nombres de archivo (ej: 'page-data.json').\n * @returns Un generador as\u00EDncrono que produce la ruta completa de cada archivo encontrado.\n * @throws Si el directorio inicial `dir` no existe o no se puede leer.\n */\nasync function* findFilesBySuffix(dir: string, suffix: string): AsyncGenerator<string> {\n\tconst dirHandle = await fsp.opendir(dir);\n\tfor await (const item of dirHandle) {\n\t\tconst fullPath = path.join(dir, item.name);\n\t\tif (item.isDirectory()) {\n\t\t\t// yield* para encadenar otro generator.\n\t\t\tyield* findFilesBySuffix(fullPath, suffix);\n\t\t} else if (item.isFile() && item.name.endsWith(suffix)) {\n\t\t\tyield fullPath;\n\t\t}\n\t}\n}\n\n/**\n * Walk a directory and returns the JSON file absolute paths with one level of depth.\n * /abs/.../sotre/331/158.json\n * /abs/.../sotre/114/443.json\n * /abs/.../sotre/131/217.json\n * /abs/.../sotre/191/281.json\n */\nasync function* walkStore(storeDir: string): AsyncGenerator<string> {\n\tconst storeDirHandle = await fsp.opendir(storeDir);\n\n\tfor await (const siteDirent of storeDirHandle) {\n\t\tif (siteDirent.isDirectory()) {\n\t\t\tconst siteDirPath = path.join(storeDir, siteDirent.name);\n\t\t\tconst siteDirHandle = await fsp.opendir(siteDirPath);\n\n\t\t\tfor await (const fileDirent of siteDirHandle) {\n\t\t\t\tconst filePath = path.join(siteDirPath, fileDirent.name);\n\n\t\t\t\tif (fileDirent.isFile() && path.extname(filePath) === \".json\") {\n\t\t\t\t\tyield filePath;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport {\n\tcpDirs,\n\tdeleteDisposableSiteDirs,\n\tdeleteEmptyDirectories,\n\tfindFilesBySuffix,\n\tmkDirs,\n\tmvDirs,\n\tpathExists,\n\trenamePath,\n\trmDirs,\n\twalkStore,\n};\n", "/**\n * Do you want to add a new error to the list?\n *\n * 1 - Add the new error type name to the `ErrorsType` union type.\n * 2 - Export a new ErrorData object (or a function that returns one) in this\n * file by completing the `error` (ErrosType) and `message` (string) properties\n * obligatorily.\n */\n\nimport type { SpawnSyncReturns } from \"node:child_process\";\nimport type { ErrorData } from \"../core/errors\";\n\ntype ErrorsType =\n\t| \"ArtifactError\"\n\t| \"BundlesInconsistencyError\"\n\t| \"CheckHealthError\"\n\t| \"ErrorInSSGBuildProcess\"\n\t| \"LifecycleExecutionError\"\n\t| \"LoginError\"\n\t| \"NoDomainsFoundError\"\n\t| \"NoJSConfigFileFound\"\n\t| \"ReadFromStoreError\"\n\t| \"ReferenceFieldSourcesNotFoundError\"\n\t| \"RenderUUIDError\"\n\t| \"UploadSearchError\"\n\t| \"WriteToStoreError\";\n\nconst ArtifactError: ErrorData = {\n\terror: \"ArtifactError\",\n\tmessage: \"There was a problem with an artifact\",\n\texpected:\n\t\t\"An external process may have has modified or deleted one of the artifacts (files and directories).\",\n\thint: \"Have there been any recent deployments? These can delete directories from the current render.\",\n};\n\nconst ErrorInSSGBuildProcess = (command: SpawnSyncReturns<string>): ErrorData => ({\n\terror: \"ErrorInSSGBuildProcess\",\n\tmessage: `Error in SSG build process: ${JSON.stringify(command)}`,\n\texpected: \"This can happen if there was a problem with the SSG build process.\",\n});\n\nconst LifecycleExecutionError = (attempts: number, name: string): ErrorData => ({\n\terror: \"LifecycleExecutionError\",\n\tmessage: `Exceeded maximum retry attempts (${attempts}) for ${name} LifeCycle`,\n});\n\nconst LoginError: ErrorData = {\n\terror: \"LoginError\",\n\tmessage: \"There was a problem logging in to the API\",\n\texpected: \"This happens if the API is currently not working or the credentials are incorrect.\",\n};\n\nconst NoDomainsFoundError: ErrorData = {\n\terror: \"NoDomainsFoundError\",\n\tmessage: \"No domains were found in this instance. The process cannot continue.\",\n\texpected:\n\t\t\"This may happen if the API is not functioning, or the site is not properly configured, or the domains are not registered.\",\n\thint: \"You can contact the instance administrator.\",\n};\n\nconst NoJSConfigFileFound: ErrorData = {\n\terror: \"NoJSConfigFileFound\",\n\tmessage: \"Could not find jsconfig.json or tsconfig.json\",\n\texpected:\n\t\t\"This can happen if the instance is not properly configured with a jsconfig.json or tsconfig.json file.\",\n};\n\nconst ReadFromStoreError: ErrorData = {\n\terror: \"ReadFromStoreError\",\n\tmessage: \"There was an error reading a file to the Store directory\",\n\thint: \"There may be an issue such as permissions preventing the file from being read.\",\n};\n\nconst ReferenceFieldSourcesNotFoundError: ErrorData = {\n\terror: \"ReferenceFieldSourcesNotFoundError\",\n\tmessage: \"The distributor has no sources defined.\",\n\texpected:\n\t\t\"It is expected to have at least one data source in the `sources` property, even if it is empty.\",\n};\n\nconst RenderUUIDError: ErrorData = {\n\terror: \"RenderUUIDError\",\n\tmessage: `Render sentinel file does not exist.\nThe rendering UUID cannot be read safely.\nThere was probably an instance deployment during the render, and files were deleted.\n\nThe files generated in this render will not be published.`,\n};\n\nconst WriteToStoreError: ErrorData = {\n\terror: \"WriteToStoreError\",\n\tmessage: \"There was an error writing a file to the Store directory\",\n\thint: \"There may be an issue such as lack of space or permissions preventing the file from being written.\",\n};\n\nconst UploadSearchError: ErrorData = {\n\terror: \"UploadSearchError\",\n\tmessage: \"There was an error uploading content to API for search\",\n\thint: \"This happens if the API is currently not working or the credentials are incorrect.\",\n};\n\nconst CheckHealthError: ErrorData = {\n\terror: \"CheckHealthError\",\n\tmessage: \"There was a problem with environment vars configuration.\",\n\texpected: \"Some of the required environment variables are not set correctly or are missing\",\n\thint: \"Are the environment variables correctly set?\",\n};\n\nexport {\n\tArtifactError,\n\tCheckHealthError,\n\tErrorInSSGBuildProcess,\n\tLifecycleExecutionError,\n\tLoginError,\n\tNoDomainsFoundError,\n\tNoJSConfigFileFound,\n\tReadFromStoreError,\n\tReferenceFieldSourcesNotFoundError,\n\tRenderUUIDError,\n\tUploadSearchError,\n\tWriteToStoreError,\n\ttype ErrorsType,\n};\n", "import fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { brush } from \"../shared/npm-modules/brush\";\nimport { GriddoLog } from \"./GriddoLog\";\n\n/**\n * Console log the Griddo exporter version.\n */\nasync function showExporterVersion() {\n\t// console.clear();\n\tconst { version } = JSON.parse(\n\t\tawait fsp.readFile(path.resolve(__dirname, \"../..\", \"package.json\"), \"utf-8\"),\n\t) as { version: string };\n\tconst logo = `\\n${brush.yellow(`Griddo Exporter ${version}`)}\n${brush.dim(`Node ${process.version.slice(1)}`)}\\n`;\n\n\tGriddoLog.log(logo);\n}\n\nexport { showExporterVersion };\n", "const GRIDDO_API_URL = process.env.GRIDDO_API_URL;\nconst GRIDDO_PUBLIC_API_URL = process.env.GRIDDO_PUBLIC_API_URL;\n\nconst AI_EMBEDDINGS = `${GRIDDO_API_URL}/ai/embeddings`;\nconst ALERT = `${GRIDDO_PUBLIC_API_URL}/alert`;\nconst DOMAINS = `${GRIDDO_API_URL}/domains`;\nconst GET_ALL = `${GRIDDO_API_URL}/sites/all`;\nconst GET_PAGE = `${GRIDDO_API_URL}/page`;\nconst LOGIN = `${GRIDDO_API_URL}/login_check`;\nconst RESET_RENDER = `${GRIDDO_API_URL}/debug/reset-render`;\nconst ROBOTS = `${GRIDDO_API_URL}/domains/robots`;\nconst SEARCH = `${GRIDDO_API_URL}/search`;\nconst SETTINGS = `${GRIDDO_API_URL}/settings`;\n\n// Site\nconst SITE_URI = `${GRIDDO_API_URL}/site/`;\nconst BUILD_END = [SITE_URI, \"/build/end\"];\nconst BUILD_START = [SITE_URI, \"/build/start\"];\nconst GET_REFERENCE_FIELD_DATA = [SITE_URI, \"/distributor\"];\nconst GET_SITEMAP = [SITE_URI, \"/sitemap\"];\nconst INFO = [SITE_URI, \"/all\"];\nconst LANGUAGES = [SITE_URI, \"/languages\"];\nconst SOCIALS = [SITE_URI, \"/socials\"];\n\nexport {\n\tAI_EMBEDDINGS,\n\tALERT,\n\tBUILD_END,\n\tBUILD_START,\n\tDOMAINS,\n\tGET_ALL,\n\tGET_PAGE,\n\tGET_REFERENCE_FIELD_DATA,\n\tGET_SITEMAP,\n\tINFO,\n\tLANGUAGES,\n\tLOGIN,\n\tRESET_RENDER,\n\tROBOTS,\n\tSEARCH,\n\tSETTINGS,\n\tSOCIALS,\n};\n", "{\n\t\"name\": \"@griddo/cx\",\n\t\"description\": \"Griddo SSG based on Gatsby\",\n\t\"version\": \"11.10.11\",\n\t\"authors\": [\n\t\t\"Hisco <francis.vega@griddo.io>\"\n\t],\n\t\"license\": \"UNLICENSED\",\n\t\"homepage\": \"https://griddo.io\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/griddo/griddo\"\n\t},\n\t\"bin\": {\n\t\t\"griddo-render\": \"cli.mjs\"\n\t},\n\t\"exports\": {\n\t\t\".\": {\n\t\t\t\"import\": \"./build/index.js\",\n\t\t\t\"require\": \"./build/index.js\",\n\t\t\t\"types\": \"./build/index.d.ts\"\n\t\t},\n\t\t\"./react\": {\n\t\t\t\"import\": \"./build/react/index.js\",\n\t\t\t\"require\": \"./build/react/index.js\",\n\t\t\t\"types\": \"./build/react/index.d.ts\"\n\t\t}\n\t},\n\t\"scripts\": {\n\t\t\"// NPM\": \"\",\n\t\t\"prepare\": \"yarn run build\",\n\t\t\"// BUILD\": \"\",\n\t\t\"build\": \"rm -rf build && sh ./exporter/build.sh\",\n\t\t\"build:debug\": \"rm -rf build && sh ./exporter/build.sh --debug\",\n\t\t\"// TESTS\": \"\",\n\t\t\"test\": \"npm run test:compile && npm run test:create-render-fixtures && node --env-file=.env --test ./build/__tests__/* && npm run test:remove-render-fixtures\",\n\t\t\"test-exporter\": \"npm run test:compile && node --env-file=.env --test ./build/__tests__exporter__/\",\n\t\t\"test:create-render-fixtures\": \"node --env-file=.env ./build/__tests__/utils/create-fixtures\",\n\t\t\"test:remove-render-fixtures\": \"node --env-file=.env ./build/__tests__/utils/remove-fixtures\",\n\t\t\"test:compile\": \"tsgo --project tsconfig.tests.json\",\n\t\t\"// INFRA SCRIPTS\": \"\",\n\t\t\"prepare-domains-render\": \"node ./build/commands/prepare-domains-render\",\n\t\t\"start-render\": \"node ./build/commands/start-render\",\n\t\t\"end-render\": \"node ./build/commands/end-render\",\n\t\t\"upload-search-content\": \"node ./build/commands/upload-search-content\",\n\t\t\"reset-render\": \"node ./build/commands/reset-render\",\n\t\t\"// ONLY LOCAL SCRIPTS\": \"\",\n\t\t\"prepare-assets-directory\": \"node ./build/commands/prepare-assets-directory\",\n\t\t\"create-rollback-copy\": \"rm -rf ../../exports-backup && cp -r ../../exports ../../exports-backup\",\n\t\t\"render\": \"npm run build && node --env-file=.env cli.mjs render --root=../..\",\n\t\t\"// LINTER & FORMATTER\": \"\",\n\t\t\"lint\": \"biome check --write\",\n\t\t\"format\": \"biome format --write\",\n\t\t\"flint\": \"npm run lint && npm run format\",\n\t\t\"ts-lint\": \"tsgo --noEmit\",\n\t\t\"watch:ts-lint\": \"tsc --noEmit --watch\"\n\t},\n\t\"dependencies\": {\n\t\t\"gatsby\": \"5.15.0\",\n\t\t\"html-react-parser\": \"^5.2.10\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@biomejs/biome\": \"2.3.4\",\n\t\t\"@types/node\": \"20.19.4\",\n\t\t\"@typescript/native-preview\": \"latest\",\n\t\t\"cheerio\": \"1.1.2\",\n\t\t\"esbuild\": \"0.25.12\",\n\t\t\"p-limit\": \"7.2.0\",\n\t\t\"typescript\": \"5.9.3\"\n\t},\n\t\"peerDependencies\": {\n\t\t\"@griddo/core\": \"11.9.16\",\n\t\t\"react\": \">=18 <19\",\n\t\t\"react-dom\": \">=18 <19\"\n\t},\n\t\"engines\": {\n\t\t\"node\": \">=20.19\"\n\t},\n\t\"files\": [\n\t\t\"build\",\n\t\t\"exporter\",\n\t\t\"src\",\n\t\t\"gatsby-browser.tsx\",\n\t\t\"gatsby-config.ts\",\n\t\t\"gatsby-node.ts\",\n\t\t\"gatsby-ssr.tsx\",\n\t\t\"global.d.ts\",\n\t\t\"tsconfig.commands.json\",\n\t\t\"tsconfig.exporter.json\",\n\t\t\"tsconfig.json\",\n\t\t\"plugins\",\n\t\t\"cli.mjs\"\n\t],\n\t\"publishConfig\": {\n\t\t\"access\": \"public\"\n\t},\n\t\"gitHead\": \"cbfc6265bef5216b8f34bef05fc6f122826c1dd8\"\n}\n", "import packageJson from \"../../package.json\";\n\nexport const DEFAULT_HEADERS = {\n\t\"x-application-id\": \"griddo-cx\",\n\t\"x-client-version\": packageJson.version,\n\t\"x-client-name\": \"CX\",\n} as const;\n", "import type { AuthHeaders } from \"../shared/types/api\";\n\nimport { throwError } from \"../core/errors\";\nimport { LOGIN } from \"../shared/endpoints\";\nimport { GRIDDO_BOT_PASSWORD, GRIDDO_BOT_USER } from \"../shared/envs\";\nimport { LoginError } from \"../shared/errors\";\nimport { DEFAULT_HEADERS } from \"../shared/headers\";\n\nclass AuthService {\n\theaders: AuthHeaders | undefined;\n\n\tasync login() {\n\t\ttry {\n\t\t\tconst response = await fetch(LOGIN, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: Object.assign({}, DEFAULT_HEADERS, {\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\tConnection: \"close\",\n\t\t\t\t}),\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tusername: GRIDDO_BOT_USER,\n\t\t\t\t\tpassword: GRIDDO_BOT_PASSWORD,\n\t\t\t\t}),\n\t\t\t});\n\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow new Error(\"Error while login in the API\");\n\t\t\t}\n\n\t\t\tconst { token } = await response.json();\n\t\t\tthis.headers = {\n\t\t\t\tAuthorization: `bearer ${token}`,\n\t\t\t\t\"Cache-Control\": \"no-store\",\n\t\t\t};\n\n\t\t\treturn this.headers;\n\t\t} catch (e) {\n\t\t\tthrowError(LoginError, e);\n\t\t}\n\t}\n}\n\nconst authService = new AuthService();\n\nexport { authService as AuthService };\n", "import type { SSG } from \"./shared/types\";\n\nimport path from \"node:path\";\n\nimport { readDB, writeDB } from \"../../core/db\";\nimport { pathExists } from \"../../core/fs\";\nimport { GriddoLog } from \"../../core/GriddoLog\";\nimport { doLifeCycle } from \"../../core/life-cycle\";\nimport { initializeLogFile } from \"../../core/logger\";\nimport {\n\tgetRenderMetadataFromDB,\n\tgetRenderModeFromDB,\n\tgetRenderPathsHydratedWithDomainFromDB,\n} from \"../../services/render\";\nimport { getRenderArtifacts } from \"../../services/render-artifacts\";\nimport { RenderContext } from \"../../shared/context\";\nimport { GRIDDO_ASSET_PREFIX, GRIDDO_BUILD_LOGS } from \"../../shared/envs\";\nimport { RENDER_MODE } from \"../../shared/types/render\";\nimport { cleanAction } from \"./actions/clean\";\nimport { closeAction } from \"./actions/close\";\nimport { dataAction } from \"./actions/data\";\nimport { healthCheckAction } from \"./actions/healthCheck\";\nimport { initAction } from \"./actions/init\";\nimport { logsAction } from \"./actions/logs\";\nimport { metaAction } from \"./actions/meta\";\nimport { prepareAction } from \"./actions/prepare\";\nimport { relocationAction } from \"./actions/relocation\";\nimport { restoreAction } from \"./actions/restore\";\nimport { ssgAction } from \"./actions/ssg\";\nimport { syncAction } from \"./actions/sync\";\nimport { getGatsbyArtifacts } from \"./shared/artifacts\";\nimport { disableRollbackOnError, enableRollbackOnError } from \"./shared/render-rollback\";\n\n/**\n * Executes a complete Gatsby render process for a given domain.\n *\n * The render process consists of multiple lifecycle steps that handle cleaning,\n * preparing, building and syncing the site. It can run in two modes:\n * - FROM_SCRATCH: Performs a complete rebuild of the domains sites.\n * - INCREMENTAL: Only rebuilds changed pages while preserving the rest.\n */\nexport async function gatsbyRenderDomain(domain: string) {\n\t// Init render log\n\tawait initializeLogFile();\n\n\t// Render data\n\tconst { renderMode, reason } = await getRenderModeFromDB(domain);\n\tconst renderMetadata = await getRenderMetadataFromDB();\n\tconst pathsHydratedWithDomain = await getRenderPathsHydratedWithDomainFromDB({ domain });\n\tconst { __ssg } = pathsHydratedWithDomain;\n\n\t// Artifacts\n\tconst renderArtifacts = await getRenderArtifacts(domain);\n\tconst ssgArtifacts = await getGatsbyArtifacts();\n\n\t// SSG Gatsby assetPrefix\n\tconst assetPrefix = GRIDDO_ASSET_PREFIX ? `${GRIDDO_ASSET_PREFIX}/${domain}` : \"\";\n\n\t// Previous render error management\n\tconst domainSentinelFile = await pathExists(path.join(__ssg, `.render-sentinel-${domain}`));\n\tconst derivedRenderMode = domainSentinelFile ? RENDER_MODE.FROM_SCRATCH : renderMode;\n\tconst derivedRenderModeReason = domainSentinelFile ? \"previous render error\" : reason;\n\n\tconst data = await readDB();\n\tdata.domains[domain].renderMode = derivedRenderMode;\n\tdata.domains[domain].renderModeReason = derivedRenderModeReason;\n\tdata.domains[domain].isRendering = false;\n\n\tif (renderMode === RENDER_MODE.IDLE && derivedRenderMode === RENDER_MODE.IDLE) {\n\t\tGriddoLog.info(\n\t\t\t`(From Current Render) [${domain}]: Skipping start-render as it is marked as IDLE with the reason ${reason}.`,\n\t\t);\n\t\treturn;\n\t}\n\n\tdata.domains[domain].isRendering = true;\n\tdata.currentRenderingDomain = domain;\n\tawait writeDB(data);\n\n\t// Render mode reason to log information to the terminal\n\tconst renderModeReason = derivedRenderModeReason ? ` <${derivedRenderModeReason}>` : \"\";\n\tGriddoLog.info(`Init render (${derivedRenderMode})${renderModeReason} for domain ${domain}\\n`);\n\n\t// Render context\n\tconst context = new RenderContext<SSG>({\n\t\tdomain,\n\t\tpathsHydratedWithDomain,\n\t\trenderArtifacts,\n\t\trenderMetadata,\n\t\trenderMode: derivedRenderMode,\n\t\tssg: { assetPrefix, ssgArtifacts },\n\t});\n\n\t// A las actions se les pasa siempre `context` y cada action ya utiliza lo que necesita.\n\t// Si una action necesita devolver algo para otra, se guarda en el context.\n\t// Ejemplo: el dataAction obtiene los ids de p\u00E1ginas para renderizar y\n\t// borrar y los guarda en context.pathsToRender y context.pathsToDelete.\n\tawait doLifeCycle(\"Init\", async () => initAction(context));\n\tawait doLifeCycle(\"Clean\", async () => cleanAction(context));\n\tawait doLifeCycle(\"Prepare\", async () => prepareAction(context));\n\tawait doLifeCycle(\"Restore\", async () => restoreAction(context));\n\n\tawait enableRollbackOnError();\n\n\tawait doLifeCycle(\"Data\", async () => dataAction(context));\n\tawait doLifeCycle(\"SSG\", async () => ssgAction(context));\n\tawait doLifeCycle(\"Relocation\", async () => relocationAction(context));\n\tawait doLifeCycle(\"Meta\", async () => metaAction(context));\n\tawait doLifeCycle(\"Sync\", async () => syncAction(context));\n\tawait doLifeCycle(\"HealthCheck\", async () => healthCheckAction(context));\n\tawait doLifeCycle(\"Logs\", async () => logsAction(context), {\n\t\tskip: !GRIDDO_BUILD_LOGS ? \"Build logs to file are disabled\" : false,\n\t});\n\tawait doLifeCycle(\"Close\", async () => closeAction(context));\n\n\tawait disableRollbackOnError();\n}\n", "import type { LifeCycleAction } from \"../shared/types/global\";\n\nimport { LifecycleExecutionError } from \"../shared/errors\";\nimport { brush } from \"../shared/npm-modules/brush\";\nimport { throwError } from \"./errors\";\nimport { GriddoLog } from \"./GriddoLog\";\n\n/**\n * Measures the execution time of a series of sync or async functions.\n *\n * @async\n * @param functions - Functions to be executed to measure their execution time.\n * @returns A promise that resolves with the total execution time in seconds.\n */\nasync function executeAndReturnExecutionTime<T>(func: () => T | Promise<T>): Promise<number> {\n\tconst start = process.hrtime.bigint();\n\tawait Promise.resolve(func());\n\tconst end = process.hrtime.bigint();\n\treturn Number((Number(end - start) / 1e9).toFixed(3));\n}\n\n/**\n * Executes a life cycle process, which involves executing a callback\n * function, printing to the console, and handling errors with optional retries.\n *\n * @async\n * @param name - The name of the life cycle.\n * @param action - A callback function to execute.\n * @param options - Optional configuration for the life cycle process.\n * @param options.maxRetrys - The maximum number of retries for the life cycle.\n * @param options.enabled - Whether the life cycle process should be executed.\n * @returns - A promise that resolves when the life cycle process is completed.\n */\nasync function doLifeCycle(\n\tname: string,\n\taction: LifeCycleAction,\n\toptions?: {\n\t\tmaxRetrys?: number;\n\t\tskip?: undefined | false | string;\n\t},\n) {\n\tconst { maxRetrys = 3, skip } = options || {};\n\n\tif (skip) {\n\t\tGriddoLog.info(`Skiping life-cycle ${name}. Reason: ${skip}\\n`);\n\t\treturn;\n\t}\n\n\tlet trysCount = 0;\n\n\twhile (trysCount < maxRetrys) {\n\t\ttry {\n\t\t\tGriddoLog.info(`start ${name} life-cycle`);\n\t\t\tconst exeTime = await executeAndReturnExecutionTime(action);\n\t\t\tGriddoLog.success(`${name} - ${exeTime}s\\n`);\n\t\t\tbreak;\n\t\t} catch (error) {\n\t\t\tconst errorString = brush.red(` Error in ${name} LifeCycle `);\n\t\t\tconst attemptsString = brush.yellow(`Attempt (${trysCount + 1})`);\n\t\t\tGriddoLog.log(`\\n${errorString} ${attemptsString}\\n`);\n\t\t\tGriddoLog.log(error);\n\t\t\tGriddoLog.log();\n\n\t\t\ttrysCount++;\n\t\t}\n\t}\n\n\tif (trysCount === maxRetrys) {\n\t\tthrowError(LifecycleExecutionError(maxRetrys, name));\n\t}\n}\n\nexport { doLifeCycle, executeAndReturnExecutionTime };\n", "import type { RenderDB } from \"../shared/types/render\";\n\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { GRIDDO_BUILD_LOGS, GRIDDO_BUILD_LOGS_BUFFER_SIZE } from \"../shared/envs\";\nimport { readDB } from \"./db\";\nimport { GriddoLog } from \"./GriddoLog\";\n\nconst logBuffer: string[] = [];\nlet logFilePath: string | null = null;\nlet flushPromise: Promise<void> | null = null;\nconst LOG_BUFFER_FLUSH_THRESHOLD = GRIDDO_BUILD_LOGS_BUFFER_SIZE;\nconst LOG_FILENAME = \"render-detail-log.txt\";\nconst LOG_TO_FILE_IS_DISABLED = !GRIDDO_BUILD_LOGS;\n\nlet dbData: RenderDB | null = null;\n\n// Universal data cache for this module...\nasync function getDBData() {\n\tif (!dbData) {\n\t\tdbData = await readDB();\n\t}\n\treturn dbData;\n}\n\nasync function initializeLogFile() {\n\tif (LOG_TO_FILE_IS_DISABLED) {\n\t\treturn;\n\t}\n\n\tconst data = await getDBData();\n\tlogFilePath = path.join(data.paths.root, LOG_FILENAME);\n\n\tawait fsp.rm(logFilePath, { force: true });\n}\n\nfunction addLogToBuffer(lineContent: string) {\n\tif (LOG_TO_FILE_IS_DISABLED) {\n\t\treturn;\n\t}\n\n\tlogBuffer.push(lineContent.toString());\n\n\tif (logBuffer.length >= LOG_BUFFER_FLUSH_THRESHOLD) {\n\t\t// Fire-and-forget flush to avoid blocking the main thread.\n\t\tflushLogsToFile().catch((error) => {\n\t\t\tGriddoLog.error(\"Background log flush failed:\", error);\n\t\t});\n\t}\n}\n\n/**\n * Vuelca el contenido del buffer de logs al archivo de logs en disco.\n * Si el buffer est\u00E1 vac\u00EDo, ya se est\u00E1 volcando, o no hay ruta de archivo, no hace nada.\n * Si ocurre un error al escribir, los logs se reinsertan al buffer para reintentar en el siguiente flush.\n */\nasync function flushLogsToFile() {\n\t// Si ya hay un volcado en curso, espera a que termine.\n\tif (flushPromise) {\n\t\tawait flushPromise;\n\t}\n\n\tif (logBuffer.length === 0 || !logFilePath) {\n\t\treturn;\n\t}\n\n\tconst performFlush = async () => {\n\t\tconst logsToFlush = [...logBuffer];\n\t\tlogBuffer.length = 0;\n\n\t\ttry {\n\t\t\tawait fsp.appendFile(logFilePath!, `${logsToFlush.join(\"\\n\")}\\n`);\n\t\t} catch (error) {\n\t\t\tlogBuffer.unshift(...logsToFlush);\n\t\t\tGriddoLog.error(\"Error flushing logs:\", error);\n\t\t\t// No relanzamos el error para no detener el \"fire-and-forget\"\n\t\t}\n\t};\n\n\tflushPromise = performFlush();\n\n\ttry {\n\t\tawait flushPromise;\n\t} finally {\n\t\tflushPromise = null;\n\t}\n}\n\n/**\n * Copia el archivo de log detallado de renderizado (\"render-detail-log.txt\")\n * desde el directorio ra\u00EDz del proyecto al directorio de logs del dominio en exports,\n * usando una marca de tiempo en el nombre de destino.\n * Si el archivo no existe, ignora el error salvo que sea distinto de ENOENT.\n *\n * @param domain - Nombre del dominio para el que se guarda el log.\n */\nasync function saveDetailRenderLog(domain: string) {\n\tawait flushLogsToFile();\n\n\tconst data = await getDBData();\n\n\tconst dateString = getFormattedDateTime();\n\tconst debugDir = path.join(data.paths.exportsDir, domain, \"logs\");\n\n\tawait fsp.mkdir(debugDir, { recursive: true });\n\n\tconst src = path.join(data.paths.root, LOG_FILENAME);\n\tconst dst = path.join(debugDir, `${dateString}-${LOG_FILENAME}`);\n\n\t// Move log to exports\n\ttry {\n\t\tawait fsp.cp(src, dst);\n\t} catch (error) {\n\t\t// It's possible the file doesn't exist if GRIDDO_BUILD_LOGS is false\n\t\t// or if no logs were ever added.\n\t\tif (error instanceof Error && \"code\" in error && error.code !== \"ENOENT\") {\n\t\t\tthrow error;\n\t\t}\n\t}\n}\n\nfunction getFormattedDateTime() {\n\tconst now = new Date();\n\tconst year = now.getFullYear();\n\tconst month = String(now.getMonth() + 1).padStart(2, \"0\");\n\tconst day = String(now.getDate()).padStart(2, \"0\");\n\n\tconst hours = String(now.getHours()).padStart(2, \"0\");\n\tconst minutes = String(now.getMinutes()).padStart(2, \"0\");\n\tconst seconds = String(now.getSeconds()).padStart(2, \"0\");\n\n\t// Formato recomendado para ordenaci\u00F3n de archivos: YYYY-MM-DD_HH-mm-ss\n\treturn `${year}-${month}-${day}_${hours}-${minutes}-${seconds}`;\n}\n\nexport { addLogToBuffer, flushLogsToFile, initializeLogFile, saveDetailRenderLog };\n", "import type { RenderModeTuple } from \"../shared/types/render\";\n\nimport { execSync } from \"node:child_process\";\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { readDB, writeDB } from \"../core/db\";\nimport { throwError } from \"../core/errors\";\nimport { pathExists } from \"../core/fs\";\nimport { GriddoLog } from \"../core/GriddoLog\";\nimport { RenderUUIDError } from \"../shared/errors\";\nimport { brush } from \"../shared/npm-modules/brush\";\nimport { RENDER_MODE } from \"../shared/types/render\";\nimport { AuthService } from \"./auth\";\nimport { getBuildMetadata } from \"./manage-store\";\n\n/**\n * Creates a sentinel file with the current date and time.\n * This file is used to track later if node_modules/@griddo/cx was cleaned by a\n * npm install coming from a deploy.\n */\nasync function markRenderAsStarted(options: { domain: string; basePath: string }) {\n\tconst { domain } = options;\n\n\tconst db = await readDB();\n\tdb.domains[domain].isRendering = true;\n\tawait writeDB(db);\n\n\t// Creamos un archivo centinela, si al terminar el render este archivo no\n\t// existe es que ha habido un deploy por medio y hay que invalidar el render\n\tconst { __ssg } = await getRenderPathsHydratedWithDomainFromDB();\n\n\tconst renderSentinelFile = path.join(__ssg, `.render-sentinel-${domain}`);\n\tawait fsp.writeFile(renderSentinelFile, new Date().toISOString());\n}\n\nasync function markRenderAsCompleted(domain: string) {\n\tconst db = await readDB();\n\tdb.domains[domain].isRendering = false;\n\tdb.currentRenderingDomain = null;\n\tdb.domains[domain].renderMode = RENDER_MODE.COMPLETED;\n\t// db.domains[domain].shouldBeRendered = false;\n\tawait writeDB(db);\n\n\t// Borramos finalmente el archivo centinela\n\tconst { __ssg } = await getRenderPathsHydratedWithDomainFromDB();\n\tconst renderSentinelFile = path.join(__ssg, `.render-sentinel-${domain}`);\n\tawait fsp.unlink(renderSentinelFile);\n}\n\nasync function assertRenderIsValid(domain: string) {\n\t// Comprobamos que .render-sentinel exista, si no es que un deploy lo borro\n\t// y hay que invalidar el render.\n\tconst { __ssg } = await getRenderPathsHydratedWithDomainFromDB();\n\tconst renderSentinelFile = path.join(__ssg, `.render-sentinel-${domain}`);\n\tif (!(await pathExists(renderSentinelFile))) {\n\t\tthrowError(RenderUUIDError);\n\t}\n}\n\n/**\n * Determines the appropriate render mode for a given domain based on its current state,\n * previous render errors, deployment status, and whether rendering is required.\n *\n * @param options - An object containing:\n * - `domain`: The domain name to resolve the render mode for.\n * - `shouldBeRendered`: A boolean indicating if the domain should be rendered.\n * @returns An object with:\n * - `renderMode`: The resolved render mode (`FROM_SCRATCH`, `INCREMENTAL`, or `IDLE`).\n * - `reason`: A string describing the reason for the chosen render mode.\n *\n * @remarks\n * The function checks for missing exports, previous render errors, new deployments,\n * and whether rendering is necessary to decide the render mode.\n *\n * @todo\n * Improve ifs and reason concatenations...\n */\nasync function resolveDomainRenderMode(options: { domain: string; shouldBeRendered: boolean }) {\n\tconst { domain, shouldBeRendered } = options;\n\n\tconst db = await readDB();\n\n\tconst { __cache, __exports } = await getRenderPathsHydratedWithDomainFromDB({ domain });\n\tconst exportsAreMissing = !(await pathExists(path.join(__exports)));\n\tconst previousRenderFailed = db.domains[domain]?.isRendering;\n\tconst newDeployDetected = await hasNewCommit(__cache);\n\n\tif (exportsAreMissing) {\n\t\treturn {\n\t\t\trenderMode: RENDER_MODE.FROM_SCRATCH,\n\t\t\treason: \"missing exports directory\",\n\t\t};\n\t}\n\n\tif (previousRenderFailed) {\n\t\treturn {\n\t\t\trenderMode: RENDER_MODE.FROM_SCRATCH,\n\t\t\treason: \"error in previous render\",\n\t\t};\n\t}\n\n\tif (newDeployDetected) {\n\t\treturn {\n\t\t\trenderMode: RENDER_MODE.FROM_SCRATCH,\n\t\t\treason: \"new commit hash\",\n\t\t};\n\t}\n\n\tif (!shouldBeRendered) {\n\t\treturn {\n\t\t\trenderMode: RENDER_MODE.IDLE,\n\t\t\treason: \"no activity\",\n\t\t};\n\t}\n\n\treturn {\n\t\trenderMode: RENDER_MODE.INCREMENTAL,\n\t\treason: \"has changes\",\n\t};\n}\n\nasync function hasNewCommit(basePath: string): Promise<boolean> {\n\tconst commitFile = path.join(basePath, \"commit\");\n\tconst currentCommit = execSync(\"git rev-parse HEAD\").toString().trim();\n\n\tif (await pathExists(commitFile)) {\n\t\tconst savedCommit = (await fsp.readFile(commitFile, \"utf-8\")).trim();\n\t\tif (savedCommit === currentCommit) {\n\t\t\treturn false; // No hay nuevo commit\n\t\t}\n\n\t\treturn true;\n\t}\n\n\treturn true;\n}\n\nasync function updateCommitFile(options: { basePath: string }) {\n\tconst { basePath } = options;\n\tconst currentCommit = execSync(\"git rev-parse HEAD\").toString().trim();\n\tawait fsp.writeFile(path.join(basePath, \"commit\"), currentCommit);\n}\n\nasync function getRenderModeFromDB(domain: string): Promise<RenderModeTuple> {\n\tconst db = await readDB();\n\n\tif (!db.domains[domain]) {\n\t\tthrow new Error(brush.red(`[!] Error: Domain ${domain} not found in DB`));\n\t}\n\n\tif (!db.domains[domain].renderMode) {\n\t\tthrow new Error(brush.red(`[!] Error: Render mode not found for domain ${domain}`));\n\t}\n\n\treturn {\n\t\trenderMode: db.domains[domain].renderMode,\n\t\treason: db.domains[domain].renderModeReason,\n\t};\n}\n\nasync function getRenderPathsHydratedWithDomainFromDB(options?: {\n\tdomain?: string;\n\tdbFilePath?: string;\n}) {\n\tconst { domain, dbFilePath } = options || {};\n\n\tconst db = await readDB(dbFilePath);\n\tconst paths = db.paths;\n\n\treturn {\n\t\t__root: paths.root,\n\t\t__cache: path.join(paths.cxCache, domain || \"\"),\n\t\t__components: paths.components,\n\t\t__cx: paths.cx,\n\t\t__sites: paths.exportsDir,\n\t\t__exports: path.join(paths.exportsDir, domain || \"\"),\n\t\t__exports_backup: path.join(paths.exportsDirBackup, domain || \"\"),\n\t\t__ssg: paths.ssg,\n\t\t__exports_dist: path.join(paths.exportsDir, domain || \"\", \"dist\"),\n\t};\n}\n\nasync function getRenderMetadataFromDB() {\n\tconst db = await readDB();\n\treturn {\n\t\tgriddoVersion: db.griddoVersion,\n\t\tbuildReportFileName: db.buildReportFileName,\n\t};\n}\n\n/**\n * Save a file with the end of build process to use as `end-render` signal.\n */\nasync function generateBuildReport(domain: string) {\n\tconst authControl = await AuthService.login();\n\n\tconst { __root } = await getRenderPathsHydratedWithDomainFromDB();\n\tconst { buildReportFileName } = await getRenderMetadataFromDB();\n\tconst { buildProcessData } = await getBuildMetadata(domain);\n\n\tconst buildSitesInfo = Object.keys(buildProcessData).map((siteID) => ({\n\t\t...buildProcessData[siteID],\n\t\tsiteId: Number.parseInt(siteID),\n\t}));\n\n\tconst report = {\n\t\tauthControl,\n\t\tsites: buildSitesInfo,\n\t};\n\n\tconst reportFilePath = path.join(__root, \"current-dist\", buildReportFileName);\n\n\tawait fsp.writeFile(reportFilePath, JSON.stringify(report));\n\n\tGriddoLog.verbose(`build report saved in ${reportFilePath}`);\n}\n\nexport {\n\tassertRenderIsValid,\n\tgenerateBuildReport,\n\tgetRenderMetadataFromDB,\n\tgetRenderModeFromDB,\n\tgetRenderPathsHydratedWithDomainFromDB,\n\tmarkRenderAsCompleted,\n\tmarkRenderAsStarted,\n\tresolveDomainRenderMode,\n\tupdateCommitFile,\n};\n", "import type { BuildMetaData } from \"../shared/types/api\";\nimport type { RenderInfo } from \"../shared/types/global\";\nimport type { GriddoPageObject } from \"../shared/types/pages\";\nimport type { Site } from \"../shared/types/sites\";\n\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { readDB, writeDB } from \"../core/db\";\nimport { throwError } from \"../core/errors\";\nimport { pathExists } from \"../core/fs\";\nimport { GriddoLog } from \"../core/GriddoLog\";\nimport { WriteToStoreError } from \"../shared/errors\";\nimport { getRenderPathsHydratedWithDomainFromDB } from \"./render\";\n\n/**\n * Get the build metadata from the Store.\n */\nasync function getBuildMetadata(domain: string): Promise<BuildMetaData> {\n\tconst db = await readDB();\n\tconst { sitesToPublish, createdPages, buildProcessData } = db.domains[domain].renderInfo || {};\n\n\tif (!sitesToPublish || !createdPages || !buildProcessData) {\n\t\tthrow new Error(\"Build metadata not found\");\n\t}\n\n\treturn {\n\t\tbuildProcessData,\n\t\tcreatedPages,\n\t\tsitesToPublish,\n\t};\n}\n\n/**\n * Write render info into a file.\n * @param renderInfo - Data that will be saved related to the render process.\n */\nasync function saveRenderInfoInStore(renderInfo: RenderInfo, domain: string) {\n\tconst db = await readDB();\n\tdb.domains[domain] = db.domains[domain] || {};\n\tdb.domains[domain].renderInfo = renderInfo;\n\tawait writeDB(db);\n}\n\n/**\n * Return an array of paths only from `.json` files (no dirs) in the `basePath` dir based in the file name.\n * @param basePath - Absolute path of the dir from which files will be read.\n * @returns A number[] of pages ids in `basePath` dir.\n */\nasync function getPageInStoreDir(basePath: string) {\n\tconst filesInStore = await fsp.readdir(basePath);\n\n\treturn filesInStore\n\t\t.filter(async (file) => {\n\t\t\tconst fullPathFile = `${basePath}/${file}`;\n\t\t\tconst stat = await fsp.stat(fullPathFile);\n\t\t\t// Si es un directorio, no lo incluimos.\n\t\t\tif (stat?.isDirectory()) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Si es un archivo pero no tiene la extensi\u00F3n `.json`, no lo incluimos\n\t\t\tif (path.extname(file) !== \".json\") {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// no es dir, es json.\n\t\t\treturn true;\n\t\t})\n\t\t.map((page) => {\n\t\t\treturn path.join(basePath, page);\n\t\t});\n}\n\n/**\n * Save the pages into the file system.\n * @param pages - An array of Griddo page objects to be saved.\n */\nasync function saveSitePagesInStore(siteDirName: string, pages: GriddoPageObject[]) {\n\tconst { __root } = await getRenderPathsHydratedWithDomainFromDB();\n\n\ttry {\n\t\tconst propsToRemove = new Set([\"editorID\", \"parentEditorID\"]);\n\t\tfor (const page of pages) {\n\t\t\tremoveProperties(page, propsToRemove);\n\t\t\tconst filename = `${page.context.page.id}.json`;\n\t\t\tconst filePath = path.join(__root, \"store\", siteDirName, filename);\n\t\t\t// En los listados est\u00E1ticos y multipage los ids de las p\u00E1ginas son iguales\n\t\t\tawait writeUniqueFileSync(filePath, JSON.stringify(page));\n\t\t}\n\t} catch (error) {\n\t\tthrowError(WriteToStoreError, error);\n\t}\n}\n\n/**\n * Removes sites that exist in the store that should no longer be there because\n * the domain has been changed. This is necessary because those sites will not\n * be marked as `sitesToUnpublish` so they must be removed manually.\n */\nasync function removeOrphanSites(sitesToPublish: Site[], domain: string) {\n\tconst { __root } = await getRenderPathsHydratedWithDomainFromDB({ domain });\n\tconst storePath = path.join(__root, \"store\");\n\n\tif (!(await pathExists(storePath))) {\n\t\treturn;\n\t}\n\n\tconst currentSitesInStore = await fsp.readdir(storePath);\n\tconst sitesFromAPI = sitesToPublish.map(({ id }) => `${id}`);\n\tconst sitesToDelete = currentSitesInStore.filter((site) => !sitesFromAPI.includes(site));\n\n\tfor (const site of sitesToDelete) {\n\t\tawait fsp.rm(path.join(storePath, site), { recursive: true, force: true });\n\t\tGriddoLog.verbose(`Removed orphan site id: ${site}`);\n\t}\n}\n\nasync function writeUniqueFileSync(filePath: string, content: string) {\n\tconst dir = path.dirname(filePath);\n\tconst ext = path.extname(filePath);\n\tconst base = path.basename(filePath, ext);\n\n\tlet uniquePath = filePath;\n\tlet counter = 1;\n\n\twhile (await pathExists(uniquePath)) {\n\t\tconst newName = `${base}-${counter}${ext}`;\n\t\tuniquePath = path.join(dir, newName);\n\t\tcounter++;\n\t}\n\n\tawait fsp.writeFile(uniquePath, content);\n}\n\n/**\n * Remove props from an object\n *\n * @param obj The object\n * @param props An array of props to be removed\n */\nfunction removeProperties(obj: Record<string, unknown>, propsToRemove: Set<string>) {\n\tfunction remove(currentObj: Record<string, unknown>) {\n\t\tif (!currentObj || typeof currentObj !== \"object\" || Array.isArray(currentObj)) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor (const key in currentObj) {\n\t\t\tif (Object.hasOwn(currentObj, key)) {\n\t\t\t\tif (propsToRemove.has(key)) {\n\t\t\t\t\t// B\u00FAsqueda O(1) en lugar de O(n)\n\t\t\t\t\tdelete currentObj[key];\n\t\t\t\t} else {\n\t\t\t\t\tconst value = currentObj[key];\n\t\t\t\t\tif (typeof value === \"object\" && value !== null && !Array.isArray(value)) {\n\t\t\t\t\t\tremove(value as Record<string, unknown>);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tremove(obj);\n}\n\nexport {\n\tgetBuildMetadata,\n\tgetPageInStoreDir,\n\tremoveOrphanSites,\n\tsaveRenderInfoInStore,\n\tsaveSitePagesInStore,\n\twriteUniqueFileSync,\n};\n", "import type { RenderArtifacts } from \"../shared/types/global\";\n\nimport path from \"node:path\";\n\nimport { getRenderPathsHydratedWithDomainFromDB } from \"./render\";\n\n/**\n * Returns the artifacts of CX.\n */\nasync function getRenderArtifacts(domain: string): Promise<RenderArtifacts> {\n\tconst { __exports, __cache, __root, __ssg } = await getRenderPathsHydratedWithDomainFromDB({\n\t\tdomain,\n\t});\n\n\treturn {\n\t\tinitials: [\n\t\t\t__exports, // `<root>/exports/<domain>`\n\t\t\t__cache, // `<root>/.griddo/<domain>`\n\t\t\tpath.join(__exports, \"logs\"),\n\t\t\tpath.join(__root, \"store\"),\n\t\t\tpath.join(__root, \"apiCache\"),\n\t\t],\n\t\tdisposables: [\n\t\t\tpath.join(__root, \"store\"),\n\t\t\tpath.join(__root, \"apiCache\"),\n\t\t\tpath.join(__root, \"dist\"),\n\t\t\tpath.join(__root, \"dist-restored\"),\n\t\t\tpath.join(__root, \"assets\"),\n\t\t\tpath.join(__root, \"render-detail-log.txt\"),\n\t\t\tpath.join(__root, \"current-dist\"),\n\t\t\tpath.join(__ssg, \"domains.json\"),\n\t\t\tpath.join(__ssg, \"render-metadata.json\"),\n\t\t],\n\t\tcacheables: [],\n\t\tarchivables: [\n\t\t\t// dist ya se usa directamente en exports\n\t\t\t// \"dist\",\n\t\t\t\"assets\",\n\t\t],\n\t\trestaurable: [\"dist\"],\n\t};\n}\n\nexport { getRenderArtifacts };\n", "import type { PlaceholderPath, RenderArtifacts } from \"./types/global\";\nimport type { RenderMode } from \"./types/render\";\n\ninterface RenderContextProps<T> {\n\tdomain: string;\n\trenderMode: RenderMode;\n\tpathsHydratedWithDomain: Record<PlaceholderPath, string>;\n\tssg: T;\n\trenderMetadata: {\n\t\tgriddoVersion: string;\n\t\tbuildReportFileName: string;\n\t};\n\trenderArtifacts: RenderArtifacts;\n}\n\n/**\n * Encapsulates the state, configuration, and artifacts for a single SSG\n * render process.\n *\n * This class is instantiated at the beginning of a render and passed through\n * each lifecycle step, providing a centralized and consistent context for all\n * operations. It is agnostic to the specific SSG being used.\n */\nexport class RenderContext<T = unknown> {\n\treadonly domain: string;\n\treadonly renderMode: RenderMode;\n\treadonly pathsHydratedWithDomain: Record<PlaceholderPath, string>;\n\tpagesToCreate: number[] = [];\n\tpagesToDelete: number[] = [];\n\tssg: T;\n\trenderMetadata: { griddoVersion: string; buildReportFileName: string };\n\trenderArtifacts: RenderArtifacts;\n\n\tconstructor({\n\t\tdomain,\n\t\trenderMode,\n\t\tssg,\n\t\tpathsHydratedWithDomain,\n\t\trenderMetadata,\n\t\trenderArtifacts,\n\t}: RenderContextProps<T>) {\n\t\tthis.domain = domain;\n\t\tthis.renderMode = renderMode;\n\t\tthis.pathsHydratedWithDomain = pathsHydratedWithDomain;\n\t\tthis.renderMetadata = renderMetadata;\n\t\tthis.renderArtifacts = renderArtifacts;\n\t\tthis.ssg = ssg;\n\t}\n}\n", "import type { RenderContext } from \"../../../shared/context\";\nimport type { SSG } from \"../shared/types\";\n\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { rmDirs } from \"../../../core/fs\";\nimport { RENDER_MODE } from \"../../../shared/types/render\";\n\nexport async function cleanAction(context: RenderContext<SSG>) {\n\tconst {\n\t\trenderArtifacts,\n\t\tssg: { ssgArtifacts },\n\t\tpathsHydratedWithDomain: { __cache, __exports },\n\t\trenderMode,\n\t} = context;\n\n\tif (renderMode === RENDER_MODE.FROM_SCRATCH) {\n\t\tawait fsp.rm(path.join(__cache, \".cache\"), { recursive: true, force: true });\n\t\tawait fsp.rm(path.join(__exports, \"dist\"), { recursive: true, force: true });\n\t\tawait fsp.rm(path.join(__exports, \"assets\"), { recursive: true, force: true });\n\t}\n\n\tawait rmDirs(renderArtifacts.disposables);\n\tawait rmDirs(ssgArtifacts.disposables);\n}\n", "import type { RenderContext } from \"../../../shared/context\";\nimport type { SSG } from \"../shared/types\";\n\nimport { rmDirs } from \"../../../core/fs\";\nimport { updateCommitFile } from \"../../../services/render\";\n\nexport async function closeAction(context: RenderContext<SSG>) {\n\tconst {\n\t\trenderArtifacts,\n\t\tssg: { ssgArtifacts },\n\t\tpathsHydratedWithDomain: { __cache },\n\t} = context;\n\n\tawait rmDirs(renderArtifacts.disposables);\n\tawait rmDirs(ssgArtifacts.disposables);\n\tawait updateCommitFile({ basePath: __cache });\n}\n", "import type { BuildProcessData, Settings } from \"../shared/types/global\";\nimport type {\n\tGriddoListPage,\n\tGriddoMultiPage,\n\tGriddoPageObject,\n\tGriddoSinglePage,\n\tPageAdditionalInfo,\n} from \"../shared/types/pages\";\nimport type { HashSites, Site, SiteHash } from \"../shared/types/sites\";\n\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport pLimit from \"p-limit\";\n\nimport { GriddoLog } from \"../core/GriddoLog\";\nimport { SETTINGS } from \"../shared/endpoints\";\nimport {\n\tGRIDDO_API_CONCURRENCY_COUNT,\n\tGRIDDO_API_URL,\n\tGRIDDO_PUBLIC_API_URL,\n\tGRIDDO_REACT_APP_INSTANCE,\n} from \"../shared/envs\";\nimport { brush } from \"../shared/npm-modules/brush\";\nimport { RENDER_MODE, type RenderMode } from \"../shared/types/render\";\nimport { get } from \"./api\";\nimport { getSiteData, getSitesToRender, unpublishSites } from \"./manage-sites\";\nimport { removeOrphanSites, saveRenderInfoInStore, saveSitePagesInStore } from \"./manage-store\";\nimport { NavigationService } from \"./navigation\";\nimport {\n\tcreateGriddoListPages,\n\tcreateGriddoMultiPages,\n\tcreateGriddoSinglePage,\n\tgetMultiPageElements,\n\tgetPaginatedPages,\n} from \"./pages\";\nimport { getReferenceFieldData } from \"./reference-fields\";\nimport { getRenderPathsHydratedWithDomainFromDB } from \"./render\";\nimport { getPage } from \"./sites\";\n\nconst renderId = Date.now().toString();\n\nfunction guessSiteNeedsToBeRenderedFromScratch() {\n\treturn false;\n}\n\nfunction listSitesLog(title: string, sites: Site[]) {\n\tconst maxline = Math.max(\n\t\t...sites.map((s) => s.name.length + (s.shouldBeUpdated ? 1 : 0) + s.id.toString().length),\n\t);\n\n\tconst sitesStr = sites.map((s) => {\n\t\tconst shouldBeUpdated = s.shouldBeUpdated ? \"*\" : \"\";\n\t\tconst lineLen = s.name.length + shouldBeUpdated.length + s.id.toString().length;\n\t\tconst padding = \" \".repeat(maxline - lineLen);\n\t\treturn `${brush.bold(s.name)} ${brush.dim(`(${s.id})`)} ${shouldBeUpdated} ${padding}${brush.dim(\"-\")} ${brush.dim(s.slug)}`;\n\t});\n\n\tconst sitesOutput = sitesStr.length > 0 ? `\\n\\n${sitesStr.join(\"\\n\")}` : brush.dim(\"--none--\\n\");\n\n\tGriddoLog.log(`\n${title} ${sitesOutput}`);\n}\n\n/**\n * Fetch, process and save object pages and sites data into the file system to\n * be consumed by other services (Griddo itself, Adapters, etc.)\n */\nasync function createStore(options: {\n\tdomain: string;\n\trenderMode: RenderMode;\n\tgriddoVersion: string;\n\tbasePath: string;\n}) {\n\tconsole.info(`API calls with ${GRIDDO_API_CONCURRENCY_COUNT} threads`);\n\tconsole.info(`API URL ${GRIDDO_API_URL as string}`);\n\n\tconst { renderMode, domain, griddoVersion, basePath } = options;\n\tconst renderFromScratch = renderMode === RENDER_MODE.FROM_SCRATCH;\n\tconst storeDir = path.join(basePath, \"store\");\n\n\t// Vars to save later in the report file\n\tconst createdPages: number[] = [];\n\tconst buildProcessData: BuildProcessData = {};\n\n\t// Get sites objects to publish and unpublish from this domain\n\tconst { sitesToPublish, sitesToUnpublish } = await getSitesToRender(domain);\n\n\tlistSitesLog(\"Sites to publish:\", sitesToPublish);\n\tlistSitesLog(\"Sites to unpublish:\", sitesToUnpublish);\n\n\t// Send unpublished sites to API.\n\tawait unpublishSites(sitesToUnpublish);\n\n\t// Eliminamos posibles sites que est\u00E9n en el store pero que no deber\u00EDan\n\t// porque han sido cambiados de dominio. Si han sido despublicados ya se\n\t// despublican bien porque entran en `sitesToUnpublish`\n\tawait removeOrphanSites(sitesToPublish, domain);\n\n\tconst allPagesToRemoveFromBuild: number[] = [];\n\t// let numberOfFinalActivePages: number[] = [];\n\n\tfor (const site of sitesToUnpublish) {\n\t\tconst { pagesStatus } = site;\n\n\t\t// A\u00F1adimos a allPagesToRemoveFromBuild todas las p\u00E1ginas de un site\n\t\t// para despublicar.\n\t\tallPagesToRemoveFromBuild.push(\n\t\t\t...pagesStatus.active,\n\t\t\t...pagesStatus.offlinePending,\n\t\t\t...pagesStatus.uploadPending,\n\t\t\t...pagesStatus.deleted,\n\t\t\t...pagesStatus.offline,\n\t\t);\n\t}\n\n\tfor (const site of sitesToPublish) {\n\t\tconst { id: siteId, slug: siteSlug, theme, favicon, pagesStatus } = site;\n\t\tconst siteDirName = siteId.toString();\n\n\t\tallPagesToRemoveFromBuild.push(...pagesStatus.offlinePending, ...pagesStatus.deleted);\n\n\t\tconst {\n\t\t\tsiteInfo,\n\t\t\tsiteHash,\n\t\t\tunpublishHashes,\n\t\t\tsiteLangs,\n\t\t\tdefaultLang,\n\t\t\theaders,\n\t\t\tfooters,\n\t\t\tsocials,\n\t\t} = await getSiteData(siteId);\n\n\t\tconst {\n\t\t\tcloudinaryName,\n\t\t\tuseMetaTitle,\n\t\t\tuseMetaKeywords,\n\t\t\tshowBasicMetaRobots,\n\t\t\tavoidHrefLangsOnCanonicals,\n\t\t\tavoidSelfReferenceCanonicals,\n\t\t\tavoidHrefLangXDefault,\n\t\t\tavoidDebugMetas,\n\t\t} = await get<Settings>({ endpoint: SETTINGS });\n\n\t\tbuildProcessData[siteId] = {\n\t\t\tsiteHash,\n\t\t\tunpublishHashes,\n\t\t\tpublishHashes: [],\n\t\t\tpublishPagesIds: [],\n\t\t};\n\n\t\tconst NavService = new NavigationService();\n\t\tNavService.navigations = { headers, footers };\n\n\t\tsite.languages = siteLangs;\n\n\t\tconst shouldUpdateSite = await updatedSiteHash(siteId, siteHash);\n\n\t\tconst siteScript = siteInfo.siteScript;\n\n\t\tconst siteMetadata = {\n\t\t\tsiteUrl: siteInfo.slug,\n\t\t\ttitle: siteInfo.name,\n\t\t\tfavicon,\n\t\t};\n\n\t\tconst additionalInfo = {\n\t\t\tbaseUrl: GRIDDO_API_URL,\n\t\t\tpublicBaseUrl: GRIDDO_PUBLIC_API_URL,\n\t\t\tinstance: GRIDDO_REACT_APP_INSTANCE,\n\t\t\tsiteSlug,\n\t\t\ttheme,\n\t\t\tsiteMetadata,\n\t\t\tsocials,\n\t\t\tsiteLangs,\n\t\t\tcloudinaryName,\n\t\t\tgriddoVersion,\n\t\t\tsiteOptions: {\n\t\t\t\tuseMetaTitle,\n\t\t\t\tuseMetaKeywords,\n\t\t\t\tshowBasicMetaRobots,\n\t\t\t\tavoidHrefLangsOnCanonicals,\n\t\t\t\tavoidSelfReferenceCanonicals,\n\t\t\t\tavoidHrefLangXDefault,\n\t\t\t\tavoidDebugMetas,\n\t\t\t},\n\t\t\tsiteScript,\n\t\t};\n\n\t\tGriddoLog.info(`Getting pages from ${site.name} site`);\n\n\t\t/// Creates the store directory for each site using the id\n\t\tawait fsp.mkdir(path.join(storeDir, siteDirName), {\n\t\t\trecursive: true,\n\t\t});\n\n\t\t// -------------------------------------------------------------------------\n\t\t// Pages loop promise creation\n\t\t// -------------------------------------------------------------------------\n\t\t// Async function that process every page for one site to use later in the\n\t\t// `Promise.all` with pLimit.\n\t\tconst fetchSitePageAndSaveInStore = async (siteIdName: string, pageId: number) => {\n\t\t\t// Here will be store every page returned by the API and processed\n\t\t\tlet griddoPageObjects: GriddoPageObject[] = [];\n\n\t\t\t// Get page data\n\t\t\tconst page = await getPage(pageId, shouldUpdateSite);\n\n\t\t\t// Probably a 404\n\t\t\tif (!page) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Update Array of page ids\n\t\t\tcreatedPages.push(pageId);\n\n\t\t\t// TODO: Use structuredClone() when node 18 is available.\n\t\t\t// SHAME: This new pageAdditionalInfo needs to be a copy because\n\t\t\t// additionalInfo referenced from outside this function and\n\t\t\t// its used by other pages.\n\t\t\tconst pageAdditionalInfo = JSON.parse(JSON.stringify(additionalInfo)) as PageAdditionalInfo;\n\n\t\t\t// Updated with navigations (header & footer)\n\t\t\tpageAdditionalInfo.navigations = NavService.getPageNavigations(page);\n\n\t\t\t// Content Type Data Query.\n\t\t\t// Where the pair `hasDistributorData:true` /\n\t\t\t// `getStaticData:true` and `data` prop exists, this function\n\t\t\t// will attach a `queriedItems` prop with the result of the\n\t\t\t// fetch for the data.\n\t\t\tconst template = await getReferenceFieldData({\n\t\t\t\tpage,\n\t\t\t\tcacheKey: renderId,\n\t\t\t});\n\n\t\t\t// MultiPage Query\n\t\t\t// Where the pair `hasGriddoMultiPage:true` prop exists, this function\n\t\t\t// will process the schema and return a multiPageElemtens array to use\n\t\t\t// in `createGriddoMultiPages()`\n\t\t\tconst multiPageElements = await getMultiPageElements(template);\n\n\t\t\t// -----------------------------------------------------------------------\n\t\t\t// Build Griddo page objects.\n\t\t\t// -----------------------------------------------------------------------\n\t\t\t// A page from the API could be one of those:\n\t\t\t// - List with pagination (static list template): needs to be splitted in n pages\n\t\t\t// - Multi-page module: needs to be splitted in n pages\n\t\t\t// - Single: just one page\n\n\t\t\t// Griddo page types\n\t\t\tconst isStaticListPage = page?.mode === \"list\" || page?.mode === \"paginated-data\";\n\t\t\tconst isMultiPage = !isStaticListPage && multiPageElements;\n\t\t\tconst isSinglePage = !isMultiPage && !isStaticListPage;\n\n\t\t\t// >> List (static list template) <<\n\t\t\tif (isStaticListPage) {\n\t\t\t\tconst griddoListPage = {\n\t\t\t\t\tpage: page,\n\t\t\t\t\tpages: getPaginatedPages(template),\n\t\t\t\t\tisRoot: false,\n\t\t\t\t\tdefaultLang: defaultLang,\n\t\t\t\t\ttemplate: template,\n\t\t\t\t\ttotalQueriedItems: template.queriedItems,\n\t\t\t\t} as GriddoListPage;\n\n\t\t\t\t// pageObjects = await createGriddoListPages({ adapter: \"Gatsby\" })\n\t\t\t\tgriddoPageObjects = await createGriddoListPages(griddoListPage, pageAdditionalInfo);\n\n\t\t\t\t// \u00BFPor qu\u00E9 la a\u00F1adimos a las p\u00E1ginas para borrar?\n\t\t\t\t// Porque este tipo de p\u00E1ginas no est\u00E1 manejada por API y se crean varias p\u00E1ginas con el mismo ID.\n\t\t\t\t// Esto hace que no se pueda rastrear bien el render.\n\t\t\t\tallPagesToRemoveFromBuild.push(page.id);\n\t\t\t}\n\n\t\t\t// >> Multi-page <<\n\t\t\tif (isMultiPage) {\n\t\t\t\tconst griddoMultipage = page as GriddoMultiPage;\n\n\t\t\t\t// The `template` key with the (maybe) data (ReferenceField) items queried\n\t\t\t\tgriddoMultipage.template = template;\n\t\t\t\tgriddoMultipage.multiPageElements = multiPageElements;\n\t\t\t\tgriddoMultipage.defaultLang = defaultLang;\n\n\t\t\t\tgriddoPageObjects = await createGriddoMultiPages(griddoMultipage, pageAdditionalInfo);\n\n\t\t\t\t// \u00BFPor qu\u00E9 la a\u00F1adimos a las p\u00E1ginas para borrar?\n\t\t\t\t// Porque este tipo de p\u00E1ginas no est\u00E1 manejada por API y se crean varias p\u00E1ginas con el mismo ID.\n\t\t\t\t// Esto hace que no se pueda rastrear bien el render.\n\t\t\t\tallPagesToRemoveFromBuild.push(page.id);\n\t\t\t}\n\n\t\t\t// >> Single template <<\n\t\t\tif (isSinglePage) {\n\t\t\t\tconst griddoSinglePage = page as GriddoSinglePage;\n\n\t\t\t\t// The `template` key with the (maybe) data (ReferenceField) items queried\n\t\t\t\tgriddoSinglePage.template = template;\n\t\t\t\tgriddoSinglePage.defaultLang = defaultLang;\n\n\t\t\t\tgriddoPageObjects = [await createGriddoSinglePage(griddoSinglePage, pageAdditionalInfo)];\n\t\t\t}\n\n\t\t\t// Upload only the valid pages hashes or ids of pages that has\n\t\t\t// been changed or created.\n\t\t\tif (page.hash !== null) {\n\t\t\t\tbuildProcessData[siteId].publishHashes.push(page.hash);\n\t\t\t\tbuildProcessData[siteId].publishPagesIds.push(page.id);\n\t\t\t}\n\n\t\t\t// Save build data to store\n\t\t\tawait saveSitePagesInStore(siteIdName, griddoPageObjects);\n\t\t};\n\n\t\t// Pages that needs to be fetched from the API and written to the store.\n\t\tconst pagesToFetchFromAPI = pagesStatus.uploadPending;\n\n\t\t// Esto es necesario porque en la BBDD las p\u00E1ginas pueden estar\n\t\t// marcadas como activas (online) pero si es una m\u00E1quina nueva hace\n\t\t// falta hacerlas de nuevo...\n\t\t// const sitePendingOfPublishing = site.isPublished && site.shouldBeUpdated;\n\t\tconst sitePendingOfPublishing = guessSiteNeedsToBeRenderedFromScratch();\n\t\t// @todo: necesito tener un sistema par publicar todo de un site (cuando un site est\u00E9 pending to publish)\n\t\t// algo como site.status = pending | published | unpublished...\n\t\tif (renderFromScratch || sitePendingOfPublishing) {\n\t\t\tpagesToFetchFromAPI.push(...pagesStatus.active);\n\t\t}\n\n\t\t// Create pages to the store. First requesting from API,\n\t\t// transform, etc., and then writing them to disk.\n\t\tconst limit = pLimit(GRIDDO_API_CONCURRENCY_COUNT);\n\t\tconst pagesToStore = pagesToFetchFromAPI.map((id: number) =>\n\t\t\tlimit(() => fetchSitePageAndSaveInStore(siteDirName, id)),\n\t\t);\n\n\t\tawait Promise.all(pagesToStore);\n\t}\n\n\t// Despu\u00E9s de guardar en el store todos los sites y sus p\u00E1ginas (las que\n\t// sean que hayan cambiado etc.) guardamos un archivo con la informaci\u00F3n del\n\t// render para usos posteriores.\n\t// Render de dominios con sites para publicar o despublicar. Se guarda la\n\t// infor del render normalmente.\n\tawait saveRenderInfoInStore({ buildProcessData, createdPages, sitesToPublish }, domain);\n\n\treturn {\n\t\tpagesToCreate: createdPages,\n\t\tpagesToDelete: allPagesToRemoveFromBuild,\n\t};\n}\n\n/**\n * Get site hashes from the file as an object\n */\nasync function getHashSites(): Promise<HashSites> {\n\tconst { __root } = await getRenderPathsHydratedWithDomainFromDB();\n\tconst apiCacheDir = path.join(__root, \"apiCache\");\n\tconst siteHasFilename = `${apiCacheDir}/siteHash.json`;\n\n\ttry {\n\t\tconst fileContent = await fsp.readFile(siteHasFilename, \"utf8\");\n\t\tconst jsonData = JSON.parse(fileContent);\n\t\treturn jsonData || {};\n\t} catch {\n\t\treturn {};\n\t}\n}\n\n/**\n * Update (write) the site hash file.\n *\n * @param siteId The id of the site.\n * @param siteHash The has of the site.\n */\nasync function updatedSiteHash(siteId: number, siteHash: SiteHash) {\n\tconst allHash = await getHashSites();\n\tconst lastHash = allHash[siteId];\n\tconst currentHash = siteHash || lastHash || Date.now();\n\n\tconst { __root } = await getRenderPathsHydratedWithDomainFromDB();\n\tconst apiCacheDir = path.join(__root, \"apiCache\");\n\tconst siteHasFilename = `${apiCacheDir}/siteHash.json`;\n\n\tif (currentHash !== lastHash) {\n\t\tallHash[siteId] = currentHash;\n\t\tawait fsp.writeFile(siteHasFilename, JSON.stringify(allHash), {\n\t\t\tencoding: \"utf-8\",\n\t\t});\n\t}\n\n\treturn currentHash.toString();\n}\n\nexport { createStore };\n", "/*\nHow it works:\n`this.#head` is an instance of `Node` which keeps track of its current value and nests another instance of `Node` that keeps the value that comes after it. When a value is provided to `.enqueue()`, the code needs to iterate through `this.#head`, going deeper and deeper to find the last value. However, iterating through every single item is slow. This problem is solved by saving a reference to the last value as `this.#tail` so that it can reference it to add a new value.\n*/\n\nclass Node {\n\tvalue;\n\tnext;\n\n\tconstructor(value) {\n\t\tthis.value = value;\n\t}\n}\n\nexport default class Queue {\n\t#head;\n\t#tail;\n\t#size;\n\n\tconstructor() {\n\t\tthis.clear();\n\t}\n\n\tenqueue(value) {\n\t\tconst node = new Node(value);\n\n\t\tif (this.#head) {\n\t\t\tthis.#tail.next = node;\n\t\t\tthis.#tail = node;\n\t\t} else {\n\t\t\tthis.#head = node;\n\t\t\tthis.#tail = node;\n\t\t}\n\n\t\tthis.#size++;\n\t}\n\n\tdequeue() {\n\t\tconst current = this.#head;\n\t\tif (!current) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#head = this.#head.next;\n\t\tthis.#size--;\n\n\t\t// Clean up tail reference when queue becomes empty\n\t\tif (!this.#head) {\n\t\t\tthis.#tail = undefined;\n\t\t}\n\n\t\treturn current.value;\n\t}\n\n\tpeek() {\n\t\tif (!this.#head) {\n\t\t\treturn;\n\t\t}\n\n\t\treturn this.#head.value;\n\n\t\t// TODO: Node.js 18.\n\t\t// return this.#head?.value;\n\t}\n\n\tclear() {\n\t\tthis.#head = undefined;\n\t\tthis.#tail = undefined;\n\t\tthis.#size = 0;\n\t}\n\n\tget size() {\n\t\treturn this.#size;\n\t}\n\n\t* [Symbol.iterator]() {\n\t\tlet current = this.#head;\n\n\t\twhile (current) {\n\t\t\tyield current.value;\n\t\t\tcurrent = current.next;\n\t\t}\n\t}\n\n\t* drain() {\n\t\twhile (this.#head) {\n\t\t\tyield this.dequeue();\n\t\t}\n\t}\n}\n", "import Queue from 'yocto-queue';\n\nexport default function pLimit(concurrency) {\n\tvalidateConcurrency(concurrency);\n\n\tconst queue = new Queue();\n\tlet activeCount = 0;\n\n\tconst resumeNext = () => {\n\t\t// Process the next queued function if we're under the concurrency limit\n\t\tif (activeCount < concurrency && queue.size > 0) {\n\t\t\tactiveCount++;\n\t\t\tqueue.dequeue()();\n\t\t}\n\t};\n\n\tconst next = () => {\n\t\tactiveCount--;\n\t\tresumeNext();\n\t};\n\n\tconst run = async (function_, resolve, arguments_) => {\n\t\t// Execute the function and capture the result promise\n\t\tconst result = (async () => function_(...arguments_))();\n\n\t\t// Resolve immediately with the promise (don't wait for completion)\n\t\tresolve(result);\n\n\t\t// Wait for the function to complete (success or failure)\n\t\t// We catch errors here to prevent unhandled rejections,\n\t\t// but the original promise rejection is preserved for the caller\n\t\ttry {\n\t\t\tawait result;\n\t\t} catch {}\n\n\t\t// Decrement active count and process next queued function\n\t\tnext();\n\t};\n\n\tconst enqueue = (function_, resolve, arguments_) => {\n\t\t// Queue the internal resolve function instead of the run function\n\t\t// to preserve the asynchronous execution context.\n\t\tnew Promise(internalResolve => { // eslint-disable-line promise/param-names\n\t\t\tqueue.enqueue(internalResolve);\n\t\t}).then(run.bind(undefined, function_, resolve, arguments_)); // eslint-disable-line promise/prefer-await-to-then\n\n\t\t// Start processing immediately if we haven't reached the concurrency limit\n\t\tif (activeCount < concurrency) {\n\t\t\tresumeNext();\n\t\t}\n\t};\n\n\tconst generator = (function_, ...arguments_) => new Promise(resolve => {\n\t\tenqueue(function_, resolve, arguments_);\n\t});\n\n\tObject.defineProperties(generator, {\n\t\tactiveCount: {\n\t\t\tget: () => activeCount,\n\t\t},\n\t\tpendingCount: {\n\t\t\tget: () => queue.size,\n\t\t},\n\t\tclearQueue: {\n\t\t\tvalue() {\n\t\t\t\tqueue.clear();\n\t\t\t},\n\t\t},\n\t\tconcurrency: {\n\t\t\tget: () => concurrency,\n\n\t\t\tset(newConcurrency) {\n\t\t\t\tvalidateConcurrency(newConcurrency);\n\t\t\t\tconcurrency = newConcurrency;\n\n\t\t\t\tqueueMicrotask(() => {\n\t\t\t\t\t// eslint-disable-next-line no-unmodified-loop-condition\n\t\t\t\t\twhile (activeCount < concurrency && queue.size > 0) {\n\t\t\t\t\t\tresumeNext();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t},\n\t\t},\n\t\tmap: {\n\t\t\tasync value(iterable, function_) {\n\t\t\t\tconst promises = Array.from(iterable, (value, index) => this(function_, value, index));\n\t\t\t\treturn Promise.all(promises);\n\t\t\t},\n\t\t},\n\t});\n\n\treturn generator;\n}\n\nexport function limitFunction(function_, options) {\n\tconst {concurrency} = options;\n\tconst limit = pLimit(concurrency);\n\n\treturn (...arguments_) => limit(() => function_(...arguments_));\n}\n\nfunction validateConcurrency(concurrency) {\n\tif (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) {\n\t\tthrow new TypeError('Expected `concurrency` to be a number from 1 and up');\n\t}\n}\n", "import type {\n\tAPIRequest,\n\tAPIResponses,\n\tGetAPI,\n\tPostAPI,\n\tPutAPI,\n\tShowApiErrorOptions,\n} from \"../shared/types/api\";\nimport type { Petition } from \"../shared/types/global\";\n\nimport crypto from \"node:crypto\";\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { RenderError } from \"../core/errors\";\nimport { pathExists } from \"../core/fs\";\nimport { GriddoLog } from \"../core/GriddoLog\";\nimport { addLogToBuffer } from \"../core/logger\";\nimport { DEFAULT_HEADERS } from \"../shared/headers\";\nimport { brush } from \"../shared/npm-modules/brush\";\nimport { AuthService } from \"./auth\";\nimport { getRenderPathsHydratedWithDomainFromDB } from \"./render\";\n\n// Envs\nconst { env } = process;\nconst { RETRY_WAIT_SECONDS = \"4\", RETRY_ATTEMPTS = \"4\" } = env;\n\n/**\n * Make a GET/PUT/POST request to the Griddo API.\n *\n * @template T Response Type returned.\n * @returns {Promise<T>} A promise that is resolved with the data from the API response.\n *\n * @example\n *\tconst response = await requestAPI<Site>(\n *\t\t{ endpoint: \"...\", cacheKey: \"...\", ... },\n *\t\t\"get\",\n *\t\t\"...\"\n *\t);\n */\nasync function requestAPI<T extends APIResponses>(\n\tprops: APIRequest,\n\tmethod: string,\n\tappendToLog = \"\",\n): Promise<T> {\n\tconst {\n\t\tendpoint,\n\t\tbody,\n\t\tcacheKey = \"\",\n\t\tattempt = 1,\n\t\theaders,\n\t\tuseApiCacheDir = true,\n\t\tlogToFile = true,\n\t} = props;\n\tconst cacheOptions = { endpoint, body, headers, cacheKey };\n\n\t// Cache\n\tif (cacheKey && useApiCacheDir) {\n\t\tconst start = new Date();\n\t\tconst cacheData = await searchCacheData<T>(cacheOptions);\n\n\t\tif (cacheData) {\n\t\t\tif (logToFile) {\n\t\t\t\tconst siteId = getSafeSiteId(cacheData);\n\t\t\t\tconst siteIdMsg = siteId ? `site: ${siteId}` : \"\";\n\t\t\t\tconst duration = msToSec(Date.now() - start.getTime());\n\t\t\t\taddLogToBuffer(`${method} (cache) ${siteIdMsg} ${endpoint} - ${duration}s ${appendToLog}`);\n\t\t\t}\n\t\t\treturn cacheData;\n\t\t}\n\t}\n\n\t// Network\n\ttry {\n\t\tconst start = new Date();\n\n\t\t// Prepare fetch options\n\t\tconst fetchOptions: RequestInit = {\n\t\t\tmethod: method.toUpperCase(),\n\t\t\theaders: Object.assign({}, DEFAULT_HEADERS, headers, AuthService.headers) as Record<\n\t\t\t\tstring,\n\t\t\t\tstring\n\t\t\t>,\n\t\t};\n\n\t\t// Add body for non-GET requests\n\t\tif (method.toLowerCase() !== \"get\" && body) {\n\t\t\tfetchOptions.body = JSON.stringify(body);\n\t\t\tif (!fetchOptions.headers) fetchOptions.headers = {};\n\t\t\t(fetchOptions.headers as Record<string, string>)[\"Content-Type\"] = \"application/json\";\n\t\t}\n\n\t\tconst response = await fetch(endpoint, fetchOptions);\n\n\t\t// Handle non-2xx responses\n\t\tif (!response.ok) {\n\t\t\tif (response.status === 404) {\n\t\t\t\t// @ts-expect-error page maybe will be 404\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tthrow new Error(`HTTP ${response.status}: ${response.statusText}`);\n\t\t}\n\n\t\tconst data: T = await response.json();\n\n\t\tif (logToFile) {\n\t\t\tconst siteId = getSafeSiteId(data);\n\t\t\tconst siteIdMsg = siteId ? `site: ${siteId}` : \"\";\n\t\t\tconst duration = msToSec(Date.now() - start.getTime());\n\t\t\taddLogToBuffer(`${method} (fetch) ${siteIdMsg} ${endpoint} - ${duration}s ${appendToLog}`);\n\t\t}\n\n\t\tif (useApiCacheDir) {\n\t\t\tawait saveCache(cacheOptions, data);\n\t\t}\n\n\t\treturn data;\n\t} catch (e) {\n\t\tconst error = e as Error;\n\n\t\tif (attempt > parseInt(RETRY_ATTEMPTS)) {\n\t\t\tGriddoLog.log(`\nMax attempts ${RETRY_ATTEMPTS} reached\n--------------------------------------\n- ${method.toUpperCase()} ${endpoint}\n- BODY: ${JSON.stringify(body)}\n- HEADERS: ${JSON.stringify(headers)}\n- ERROR: ${error.message}\n--------------------------------------\n`);\n\t\t\tthrow new RenderError(error);\n\t\t}\n\n\t\tshowApiError(error, {\n\t\t\tcallInfo: { endpoint, body },\n\t\t});\n\n\t\tGriddoLog.warn(`Waiting for retry: ${method}`, endpoint);\n\n\t\tawait delay(parseInt(RETRY_WAIT_SECONDS) * 1000);\n\n\t\treturn requestAPI<T>(\n\t\t\t{\n\t\t\t\tendpoint,\n\t\t\t\tbody,\n\t\t\t\theaders,\n\t\t\t\tcacheKey,\n\t\t\t\tattempt: attempt + 1,\n\t\t\t},\n\t\t\tmethod,\n\t\t\tappendToLog,\n\t\t);\n\t}\n}\n\n/**\n * Make a GET request to the Griddo API.\n *\n * @template T Response Type returned.\n * @returns A promise that is resolved with the data from the API response.\n */\nasync function getApi<T extends APIResponses>(props: GetAPI) {\n\treturn requestAPI<T>(props, \"get\");\n}\n\n/**\n * Make a PUT request to the Griddo API.\n *\n * @template T Response Type returned.\n * @returns A promise that is resolved with the data from the API response.\n */\nasync function putApi<T extends APIResponses>(props: PutAPI) {\n\treturn requestAPI<T>(props, \"put\");\n}\n\n/**\n * Make a POST request to the Griddo API.\n *\n * @template T Response Type returned.\n * @returns A promise that is resolved with the data from the API response.\n */\nasync function postApi<T extends APIResponses>(props: PostAPI) {\n\tconst { endpoint, body, headers } = props;\n\tconst referenceFieldBodyParams =\n\t\tendpoint.endsWith(\"/distributor\") &&\n\t\t`# ReferenceField body: ${JSON.stringify(body)} lang: ${JSON.stringify(headers?.lang)}`;\n\n\treturn requestAPI<T>(props, \"post\", referenceFieldBodyParams || \"\");\n}\n\n/**\n * Shows an API error through the terminal.\n */\nfunction showApiError(error: Error, options: ShowApiErrorOptions) {\n\tconst { message, stack } = error;\n\tconst { callInfo } = options;\n\tconst callInfoArray = [];\n\n\tfor (const item of Object.keys(callInfo) as (keyof typeof callInfo)[]) {\n\t\tcallInfoArray.push(\n\t\t\t`${item}: ${\n\t\t\t\ttypeof callInfo[item] === \"object\" ? JSON.stringify(callInfo[item]) : callInfo[item]\n\t\t\t}`,\n\t\t);\n\t}\n\n\t// Compose the errors output\n\tconst callInfoStr = callInfoArray.join(\"\\n\");\n\tconst errorDetailsStr = `${message}\\n${stack}`;\n\n\t// Print the error\n\tGriddoLog.warn(\n\t\tbrush.red(`\n=============\n\n{ Call info }\n${callInfoStr}\n\n{ Error details }\n${errorDetailsStr}\n\n=============\n`),\n\t);\n}\n\n/**\n * Return a siteID from a response object if exist\n * @param response A response object\n */\nfunction getSafeSiteId(response: APIResponses) {\n\tif (typeof response !== \"object\" || response === null || Array.isArray(response)) {\n\t\treturn undefined;\n\t}\n\n\treturn \"site\" in response && response.site ? response.site : undefined;\n}\n\n/**\n * Custom delay using the \"promise hack\",\n *\n * @param ms Amount of miliseconds to be delayed\n */\nfunction delay(ms: number): Promise<void> {\n\treturn new Promise((res) => setTimeout(res, ms));\n}\n\n/**\n * Converts milliseconds to seconds with a fixed number of decimals.\n *\n * @param ms The number in milliseconds.\n * @param fixed The amount of fixed decimals.\n * @returns The converted number in seconds with the fixed number of decimals.\n */\nfunction msToSec(ms: number, decimals = 3): number {\n\treturn Number.parseFloat((ms / 1000).toFixed(decimals));\n}\n\n/**\n * Generate a filename with a hash using a Petition object\n * @param petition An object\n */\nasync function generateFilenameWithHash(petition: Petition) {\n\tconst { __root } = await getRenderPathsHydratedWithDomainFromDB();\n\tconst apiCacheDir = path.join(__root, \"apiCache\");\n\n\tconst hashSum = crypto.createHash(\"sha256\");\n\thashSum.update(JSON.stringify(petition));\n\n\treturn `${apiCacheDir}/${hashSum.digest(\"hex\")}`;\n}\n\n/**\n * Save a file using a hash name.\n *\n * @param petition An object.\n * @param content Content to be saved.\n */\nasync function saveCache<T>(petition: Petition, content: T) {\n\tconst stringContent = typeof content === \"string\" ? content : JSON.stringify(content);\n\tconst filename = await generateFilenameWithHash(petition);\n\tconst filepath = path.dirname(filename);\n\n\tif (!(await pathExists(filepath))) {\n\t\tawait fsp.mkdir(filepath, { recursive: true });\n\t}\n\n\tawait fsp.writeFile(filename, stringContent, \"utf8\");\n}\n\n/**\n * Search in the `apiCache` dir for a file using the petition as hash generator.\n * Return the file content if found or null if not.\n *\n * @param petition An object\n */\nasync function searchCacheData<T>(petition: Petition) {\n\ttry {\n\t\tconst file = await generateFilenameWithHash(petition);\n\t\tconst fileContent = await fsp.readFile(file, \"utf8\");\n\t\tconst jsonData = JSON.parse(fileContent) as T;\n\n\t\treturn jsonData;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport { getApi as get, postApi as post, putApi as put };\n", "import type { Site, SiteData } from \"../shared/types/sites\";\n\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { getRenderPathsHydratedWithDomainFromDB } from \"./render\";\nimport {\n\tendSiteRender,\n\tgetAllSites,\n\tgetSiteInfo,\n\tgetSiteLanguages,\n\tgetSiteSocials,\n\tstartSiteRender,\n} from \"./sites\";\n\n/**\n * Check the instance sites and returns site prepared to be published and unpublished.\n */\nasync function getSitesToRender(domain: string) {\n\t// Get all sites. An array of Site\n\tconst allSites = await getAllSites(domain);\n\n\t// If there are valid sites...\n\t// En este paso se a\u00F1ade al objeto `Site` la informaci\u00F3n de los dominios\n\t// utilizando los idiomas.\n\tif (allSites.length) {\n\t\tfor (const site of allSites) {\n\t\t\tconst { items } = await getSiteLanguages(site.id);\n\n\t\t\t// A\u00F1adimos la prop site.domains con el dominio \"cocinado\" con\n\t\t\t// los idiomas y teniendo en cuenta solo el dominio actual.\n\t\t\tsite.domains = items\n\t\t\t\t.filter(\n\t\t\t\t\t(item) =>\n\t\t\t\t\t\titem.domain && (item.domain.slug === domain || item.domain.slug === `/${domain}`),\n\t\t\t\t)\n\t\t\t\t.map((item) => ({ [item.id]: `${item.domain.slug}${item.path}` }));\n\t\t}\n\t}\n\n\t// Save sites object to publish\n\tconst sitesToPublish = allSites.filter((site) => !!site.isPublished);\n\n\t// Save sites object to unpublish\n\tconst sitesToUnpublish = allSites.filter((site) => !site.isPublished && site.shouldBeUpdated);\n\n\treturn {\n\t\tsitesToPublish,\n\t\tsitesToUnpublish,\n\t};\n}\n\n/**\n * Unpublish an array of sites sending the information to the API.\n *\n * @param sites An array of sites\n */\nasync function unpublishSites(sites: Site[]) {\n\tconst { __root } = await getRenderPathsHydratedWithDomainFromDB();\n\n\tfor (const site of sites) {\n\t\t// API\n\t\tconst buildInfo = await startSiteRender(site.id);\n\t\tconst { siteHash } = buildInfo;\n\t\tconst body = {\n\t\t\tsiteHash,\n\t\t\tpublishHashes: [],\n\t\t\tunpublishHashes: [],\n\t\t\tpublishPagesIds: [],\n\t\t};\n\n\t\tawait endSiteRender(site.id, body);\n\n\t\t// STORE\n\t\t// Remove site directory from the Store to prevent rendering\n\t\tawait fsp.rm(path.join(__root, \"store\", site.id.toString()), {\n\t\t\tforce: true,\n\t\t\trecursive: true,\n\t\t});\n\t}\n}\n\n/**\n * Return a single site generic data.\n *\n * @param siteID The site id.\n * @see SiteData\n */\nasync function getSiteData(siteID: number) {\n\tconst buildData = await startSiteRender(siteID);\n\tconst siteInfo = await getSiteInfo(siteID);\n\tconst siteLangs = await getSiteLanguages(siteID);\n\tconst socials = await getSiteSocials(siteID);\n\tconst siteLangsInfo = siteLangs.items;\n\tconst defaultLang = siteLangsInfo.find((lang) => lang.isDefault);\n\n\tconst { siteHash, unpublishHashes, publishIds } = buildData;\n\tconst { headers, footers } = siteInfo;\n\tconst validPagesIds = publishIds;\n\n\tconst siteData: SiteData = {\n\t\tsiteInfo,\n\t\tvalidPagesIds,\n\t\tsiteHash,\n\t\tunpublishHashes,\n\t\tsiteLangs: siteLangsInfo,\n\t\tdefaultLang,\n\t\theaders,\n\t\tfooters,\n\t\tsocials,\n\t};\n\n\treturn siteData;\n}\n\nexport { getSiteData, getSitesToRender, unpublishSites };\n", "import type { Core } from \"@griddo/core\";\nimport type {\n\tAllSitesReponse,\n\tEndPageInfoResponse,\n\tEndSiteRenderBody,\n\tLanguagesResponse,\n\tPageResponse,\n\tReferenceFieldBody,\n\tReferenceFieldResponse,\n\tSitemapAPIResponse,\n\tSocialsResponse,\n\tStartPageRenderResponse,\n} from \"../shared/types/api\";\nimport type { Site } from \"../shared/types/sites\";\n\nimport {\n\tBUILD_END,\n\tBUILD_START,\n\tGET_ALL,\n\tGET_PAGE,\n\tGET_REFERENCE_FIELD_DATA,\n\tGET_SITEMAP,\n\tINFO,\n\tLANGUAGES,\n\tSOCIALS,\n} from \"../shared/endpoints\";\nimport { get, post } from \"./api\";\n\n/**\n * Get a list of site objects.\n */\nasync function getAllSites(domain: string) {\n\treturn get<AllSitesReponse>({\n\t\tendpoint: `${GET_ALL}?domainSlug=${domain}`,\n\t});\n}\n\n/**\n * Get a list of site objects from a domain.\n */\nasync function getAllSitesFromDomain(domain: string) {\n\tconst allSites = await get<AllSitesReponse>({ endpoint: GET_ALL });\n\n\tif (allSites.length) {\n\t\tfor (const site of allSites) {\n\t\t\tconst { items } = await getSiteLanguages(site.id);\n\n\t\t\t// A\u00F1adimos la prop domains con el dominio \"cocinado\" con los\n\t\t\t// idiomas y teniendo en cuenta solo el dominio actual.\n\t\t\tsite.domains = items\n\t\t\t\t.filter(\n\t\t\t\t\t(item) =>\n\t\t\t\t\t\titem.domain && (item.domain.slug === domain || item.domain.slug === `/${domain}`),\n\t\t\t\t)\n\t\t\t\t.map((item) => ({ [item.id]: `${item.domain.slug}${item.path}` }));\n\t\t}\n\t}\n\n\treturn allSites.filter((site) => site.domains.length > 0);\n}\n\n/**\n * Fetch a page object from API.\n */\nasync function getPage(id: number, cacheKey: string) {\n\treturn get<PageResponse>({\n\t\tendpoint: `${GET_PAGE}/${id}`,\n\t\tcacheKey,\n\t});\n}\n\n/**\n * Get site info\n */\nasync function getSiteInfo(id: number, cacheKey = \"\") {\n\tconst [prefix, suffix] = INFO;\n\n\treturn get<Site>({\n\t\tendpoint: `${prefix}${id}${suffix}`,\n\t\tcacheKey,\n\t});\n}\n\nasync function getSiteLanguages(id: number, cacheKey = \"\") {\n\tconst [prefix, suffix] = LANGUAGES;\n\n\treturn get<LanguagesResponse>({\n\t\tendpoint: `${prefix}${id}${suffix}`,\n\t\tcacheKey,\n\t});\n}\n\nasync function startSiteRender(id: number) {\n\tconst [prefix, suffix] = BUILD_START;\n\n\treturn get<StartPageRenderResponse>({\n\t\tendpoint: `${prefix}${id}${suffix}`,\n\t});\n}\n\n/**\n * Send the end signal to API for a render site.\n */\nasync function endSiteRender(id: number, body: EndSiteRenderBody) {\n\tconst [prefix, suffix] = BUILD_END;\n\n\tawait post<EndPageInfoResponse>({\n\t\tendpoint: `${prefix}${id}${suffix}`,\n\t\tbody,\n\t\tuseApiCacheDir: false,\n\t\tlogToFile: false,\n\t});\n}\n\nasync function getReferenceFieldSiteData(\n\tpage: Core.Page,\n\tbody: ReferenceFieldBody,\n\tcacheKey: string,\n\tdataSiteId?: number,\n\tdataLangID?: number,\n) {\n\tconst [prefix, suffix] = GET_REFERENCE_FIELD_DATA;\n\tconst site = dataSiteId || page.site;\n\tconst lang = dataLangID || page.language;\n\n\treturn post<ReferenceFieldResponse>({\n\t\tendpoint: `${prefix}${site}${suffix}`,\n\t\tbody,\n\t\theaders: { lang },\n\t\tcacheKey,\n\t});\n}\n\nasync function getSitemap(options: { siteId: number; headers?: Record<string, string> }) {\n\tconst { siteId, headers } = options;\n\tconst [prefix, suffix] = GET_SITEMAP;\n\n\treturn get<SitemapAPIResponse>({\n\t\tendpoint: `${prefix}${siteId}${suffix}`,\n\t\theaders,\n\t});\n}\n\nasync function getSiteSocials(id: number, cacheKey = \"\") {\n\tconst [prefix, suffix] = SOCIALS;\n\n\treturn get<SocialsResponse>({\n\t\tendpoint: `${prefix}${id}${suffix}`,\n\t\tcacheKey,\n\t});\n}\n\nexport {\n\tendSiteRender,\n\tgetAllSites,\n\tgetAllSitesFromDomain,\n\tgetPage,\n\tgetReferenceFieldSiteData,\n\tgetSiteInfo,\n\tgetSiteLanguages,\n\tgetSitemap,\n\tgetSiteSocials,\n\tstartSiteRender,\n};\n", "import type { Footer, Header } from \"../shared/types/navigation\";\nimport type { APIPageObject } from \"../shared/types/pages\";\n\nclass NavigationService {\n\tprivate _defaultHeaders: Record<string, Header>;\n\tprivate _defaultFooters: Record<string, Footer>;\n\tprivate _navigations: {\n\t\theaders: Header[];\n\t\tfooters: Footer[];\n\t};\n\n\tconstructor() {\n\t\tthis._navigations = {\n\t\t\tfooters: [],\n\t\t\theaders: [],\n\t\t};\n\t\tthis._defaultHeaders = {};\n\t\tthis._defaultFooters = {};\n\t}\n\n\tset navigations(navigations) {\n\t\tthis._navigations = navigations;\n\t\tthis._defaultFooters = this.getDefaultFooters();\n\t\tthis._defaultHeaders = this.getDefaultHeaders();\n\t}\n\n\tget navigations() {\n\t\treturn this._navigations;\n\t}\n\n\tgetDefaultFooters() {\n\t\tconst footers = [...this.navigations.footers];\n\t\tconst defaultFooters = footers.filter((footer) => footer.setAsDefault);\n\t\tconst defaultFootersByLang = {} as Record<number, Footer>;\n\n\t\tfor (const item of defaultFooters) {\n\t\t\tdefaultFootersByLang[item.language] = item;\n\t\t}\n\n\t\treturn defaultFootersByLang;\n\t}\n\n\tgetDefaultHeaders() {\n\t\tconst headers = [...this.navigations.headers];\n\t\tconst defaultHeaders = headers.filter((header) => header.setAsDefault);\n\t\tconst defaultHeadersByLang = {} as Record<number, Header>;\n\n\t\tfor (const item of defaultHeaders) {\n\t\t\tdefaultHeadersByLang[item.language] = item;\n\t\t}\n\n\t\treturn defaultHeadersByLang;\n\t}\n\n\tgetRightLanguage(\n\t\tlist: {\n\t\t\tlanguage: number;\n\t\t\tnavigationLanguages: { navigationId: number }[];\n\t\t\tid: number;\n\t\t}[],\n\t\tid: number,\n\t\tlanguage: number,\n\t) {\n\t\tif (!list || !id) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst rightLanguageItem = list.find(\n\t\t\t(item) =>\n\t\t\t\titem.language === language &&\n\t\t\t\titem.navigationLanguages?.find((version) => version.navigationId === id),\n\t\t);\n\n\t\tconst result = rightLanguageItem || list.find((item) => item.id === id);\n\n\t\treturn result ? { ...result } : null;\n\t}\n\n\tgetPageHeader(id: number, language: number) {\n\t\treturn this.getRightLanguage(this.navigations.headers, id, language);\n\t}\n\n\tgetPageFooter(id: number, language: number) {\n\t\treturn this.getRightLanguage(this.navigations.footers, id, language);\n\t}\n\n\tgetPageNavigations(page: APIPageObject) {\n\t\tconst { header: pageHeader, footer: pageFooter, language, template, templateConfig } = page;\n\t\tconst { templateType } = template;\n\t\tconst { defaultHeader, defaultFooter, templates } = templateConfig;\n\n\t\t// The navigations would be:\n\t\t// - The one with the page or ...\n\t\t// - The one defined for that template or ...\n\t\t// - The one you have defined for that data package\n\t\tconst getValidNavigation = (values: (number | unknown)[]) => {\n\t\t\tconst fineNavigation = values.find((item) => typeof item === \"number\");\n\n\t\t\treturn typeof fineNavigation === \"number\" ? fineNavigation : null;\n\t\t};\n\n\t\tconst headerID = getValidNavigation([\n\t\t\tpageHeader,\n\t\t\ttemplates?.[templateType]?.defaultHeader,\n\t\t\tdefaultHeader,\n\t\t]);\n\n\t\tconst footerID = getValidNavigation([\n\t\t\tpageFooter,\n\t\t\ttemplates?.[templateType]?.defaultFooter,\n\t\t\tdefaultFooter,\n\t\t]);\n\n\t\tconst header = headerID\n\t\t\t? this.getPageHeader(headerID, language)\n\t\t\t: headerID === 0\n\t\t\t\t? null\n\t\t\t\t: this._defaultHeaders[language];\n\n\t\tconst footer = footerID\n\t\t\t? this.getPageFooter(footerID, language)\n\t\t\t: footerID === 0\n\t\t\t\t? null\n\t\t\t\t: this._defaultFooters[language];\n\n\t\treturn {\n\t\t\theader,\n\t\t\tfooter,\n\t\t} as { header: Header; footer: Footer };\n\t}\n}\n\nexport { NavigationService };\n", "import type { Fields } from \"@griddo/core\";\n\n/**\n * Format Cloudinary or DAM URL\n *\n * @param image The image url\n * @param width With of the image\n * @param height Height of the image\n * @param format Format of the image\n * @returns A composed URL for the Cloudinary or DAM service\n *\n * @example\n * formatImage(\"https://images.griddo.io/tree\", 300, 200, \"jpg\")\n * // https://images.griddo.io/tree/w/300/h/200/f/jpg\n */\nfunction formatImage(image: Fields.Image | string, width: number, height: number, format = \"jpg\") {\n\tconst url = typeof image === \"string\" ? image : image?.url;\n\n\tif (!url) {\n\t\treturn null;\n\t}\n\n\tconst isCloudinary = url.split(\"/\")[2].includes(\"cloudinary.com\");\n\n\treturn isCloudinary\n\t\t? addCloudinaryParams(url, `c_fill,w_${width},h_${height}`)\n\t\t: addGriddoDamParams(url, `f/${format}/w/${width}/h/${height}`);\n}\n\n/**\n * Format Griddo DAM image url.\n */\nfunction addGriddoDamParams(image: string, params: string) {\n\tconst urlParts = image.split(\"/\");\n\tconst imagePath = urlParts.slice(0, -1).join(\"/\");\n\tconst imageName = urlParts.slice(-1)[0];\n\n\treturn `${imagePath}/${params}/${imageName}`;\n}\n\n/**\n * Take a cloudinary url and add query params.\n */\nfunction addCloudinaryParams(image: string, params: string) {\n\tconst plainUrl = image.replace(\"https://\", \"\");\n\tconst head = plainUrl.split(\"/\").slice(0, 4).join(\"/\");\n\tconst fullId = plainUrl.replace(head, \"\");\n\n\treturn `https://${head}/${params}${fullId}`;\n}\n\nexport { formatImage };\n", "import type { Core, Fields } from \"@griddo/core\";\nimport type {\n\tAPIPageObject,\n\tGriddoListPage,\n\tGriddoMultiPage,\n\tGriddoPageObject,\n\tGriddoSinglePage,\n\tMultiPageElement,\n\tMultiPageElements,\n\tPageAdditionalInfo,\n} from \"../shared/types/pages\";\nimport type { TemplateWithReferenceField } from \"../shared/types/templates\";\n\nimport { formatImage } from \"../core/images\";\n\n// Consts\nconst DEFAULT_ITEMS_PER_PAGE_FOR_LIST_TEMPLATES = 25;\n\n/**\n * Return an OpenGraph object.\n *\n * @param props.socialTitle The social title.\n * @param props.socialDescription The social description.\n * @param props.socialImage The social image in Cloudinary or DAM url format.\n */\nfunction getOpenGraph({\n\tsocialTitle,\n\tsocialDescription,\n\tsocialImage,\n}: Pick<Core.Page, \"socialTitle\" | \"socialDescription\" | \"socialImage\">): Core.Page[\"openGraph\"] {\n\treturn {\n\t\ttype: \"website\",\n\t\ttitle: socialTitle,\n\t\tdescription: socialDescription,\n\t\timage: socialImage ? formatImage(socialImage, 1280, 768) : \"\",\n\t\ttwitterImage: socialImage ? formatImage(socialImage, 1280, 768) : \"\",\n\t};\n}\n\n/**\n * Get the Page metadata object from a page Object.\n *\n * @param params A Page object\n */\nfunction getPageMetadata(params: Core.Page): GriddoPageObject[\"context\"][\"pageMetadata\"] {\n\tconst {\n\t\ttitle,\n\t\tmetaTitle,\n\t\tmetaDescription,\n\t\tcanonicalURL,\n\t\tlocale,\n\t\turl,\n\t\tisIndexed,\n\t\tfollow,\n\t\tmetasAdvanced,\n\t\tpageLanguages,\n\t\tfullUrl,\n\t\tmetaKeywords,\n\t} = params;\n\n\tconst metasAdvancedList =\n\t\tmetasAdvanced\n\t\t\t?.split(\",\")\n\t\t\t.filter(Boolean)\n\t\t\t.map((item) => item.trim().toLowerCase()) || [];\n\n\treturn {\n\t\ttitle: (metaTitle || title || \"\").trim(),\n\t\tdescription: metaDescription,\n\t\tcanonical:\n\t\t\tcanonicalURL?.trim() && canonicalURL !== fullUrl\n\t\t\t\t? canonicalURL.trim()\n\t\t\t\t: isIndexed\n\t\t\t\t\t? fullUrl\n\t\t\t\t\t: undefined,\n\t\tlocale,\n\t\turl,\n\t\tindex: isIndexed ? \"index\" : \"noindex\",\n\t\tfollow: follow ? \"follow\" : \"nofollow\",\n\t\ttranslate: metasAdvancedList.includes(\"notranslate\") ? \"notranslate\" : \"\",\n\t\tmetasAdvanced: metasAdvancedList.filter((item) => item !== \"notranslate\").join(),\n\t\tpageLanguages,\n\t\tmetaKeywords: metaKeywords\n\t\t\t?.filter(Boolean)\n\t\t\t.map((keyword) => keyword.replace(/\"/g, \"'\"))\n\t\t\t.join(\", \"),\n\t};\n}\n\n/**\n * Create a Griddo page object\n *\n * @param page A page object ready to pass as content of the `context` to use in the React template.\n * @param additionalInfo Additional page info to pass as content of `context` to use in the React template.\n * @param excludeFromSearch Boolean to avoid this page to be indexed in internal search tool.\n */\nasync function createGriddoPageObject(\n\tpage: GriddoSinglePage | GriddoListPage | GriddoMultiPage,\n\tadditionalInfo: PageAdditionalInfo,\n): Promise<GriddoPageObject> {\n\t// Extract some props from page\n\tconst {\n\t\tid,\n\t\ttitle,\n\t\tfullPath,\n\t\tlanguage: languageId,\n\t\tbreadcrumb,\n\t\tsocialDescription,\n\t\tsocialImage,\n\t\tsocialTitle,\n\t} = page;\n\n\t// Extract some props from additionalInfo\n\tconst {\n\t\tbaseUrl,\n\t\tcloudinaryName,\n\t\tgriddoVersion,\n\t\tsiteLangs,\n\t\tsiteMetadata,\n\t\tsiteOptions,\n\t\tsiteScript,\n\t\tsiteSlug,\n\t\tsocials,\n\t\ttheme,\n\t\tnavigations,\n\t} = additionalInfo;\n\tconst { header, footer } = navigations;\n\n\t// Update page object\n\tpage.breadcrumb = breadcrumb;\n\tpage.siteSlug = siteSlug;\n\tpage.apiUrl = baseUrl;\n\tpage.publicApiUrl = additionalInfo.publicBaseUrl;\n\tpage.instance = additionalInfo.instance;\n\n\tconst foundLanguage = siteLangs.find(({ id }) => id === page?.language);\n\tconst locale = foundLanguage?.locale.replace(/_/g, \"-\");\n\n\t// Page Metadata\n\tconst pageMetadata = getPageMetadata(page);\n\n\t// Opengraph\n\tconst openGraph = getOpenGraph({\n\t\tsocialDescription,\n\t\tsocialImage,\n\t\tsocialTitle,\n\t});\n\n\tconst pagePath = fullPath.compose;\n\n\tconst renderDate = new Date().toString();\n\n\tconst griddoPageObject: GriddoPageObject = {\n\t\tpath: pagePath,\n\t\tsize: undefined,\n\t\tcontext: {\n\t\t\t// Page\n\t\t\tid,\n\t\t\ttitle,\n\t\t\tfullPath,\n\t\t\tlocale,\n\t\t\tlanguageId,\n\t\t\ttheme,\n\n\t\t\t// PARA <Helmet />\n\t\t\tsiteMetadata,\n\t\t\tpageMetadata,\n\t\t\topenGraph,\n\t\t\tsocials,\n\t\t\tsiteLangs,\n\t\t\tcloudinaryName,\n\t\t\tsiteOptions,\n\t\t\tgriddoVersion,\n\t\t\trenderDate,\n\t\t\tsiteScript,\n\n\t\t\t// Navigation sections\n\t\t\theader,\n\t\t\tfooter,\n\n\t\t\t// Page template\n\t\t\t// En este objeto se est\u00E1 pasando todos los metadatos que vienen en\n\t\t\t// el primer nivel pero el uso de los mismos en CX se hace con la\n\t\t\t// prop `pageMetadata` creada a partir de getPageMetadata. En\n\t\t\t// resumen, se est\u00E1 pasando por duplicado el contenido.\n\t\t\t// TODO: Eliminar las claves de metadata de este objeto page.\n\t\t\tpage,\n\t\t},\n\t};\n\n\treturn griddoPageObject;\n}\n\n/**\n * Create a single Griddo page object.\n *\n * @param page A Griddo single page object.\n * @param additionalInfo Additional page info.\n */\nasync function createGriddoSinglePage(page: GriddoSinglePage, additionalInfo: PageAdditionalInfo) {\n\treturn createGriddoPageObject(page, additionalInfo);\n}\n\n/**\n * Create multiples pages from one page as list paginated pages\n */\nasync function createGriddoListPages(\n\t{ page, pages, isRoot = false, defaultLang, template, totalQueriedItems }: GriddoListPage,\n\tadditionalInfo: PageAdditionalInfo,\n) {\n\tconst allPages = pages.map(async (dataInPage, idx) => {\n\t\tconst isFirstPage = idx === 0;\n\t\tconst pageNumber = idx + 1;\n\t\tconst { domainUrl, compose } = page.fullPath;\n\n\t\tconst paginatedPage = {\n\t\t\t...page,\n\t\t\tfullPath: {\n\t\t\t\t...page.fullPath,\n\t\t\t\t// Add a page number (tailPageNumber) from page 2 onwards\n\t\t\t\tcompose: addPageNumberToUrl(compose, pageNumber, {\n\t\t\t\t\taddEndingSlash: true,\n\t\t\t\t}),\n\t\t\t},\n\t\t\tfullUrl: addPageNumberToUrl(page.fullUrl, pageNumber, {\n\t\t\t\taddEndingSlash: true,\n\t\t\t}),\n\t\t\tslug: addPageNumberToUrl(page.slug, pageNumber),\n\t\t\ttitle: addPageNumberToTitle(page.title, pageNumber),\n\t\t\tmetaTitle: addPageNumberToTitle(page.metaTitle || \"\", pageNumber),\n\t\t\tdisableHrefLangs: pageNumber > 1,\n\t\t\ttemplate: {\n\t\t\t\t...template,\n\t\t\t\tisFirstPage,\n\t\t\t\tpageNumber,\n\t\t\t\ttotalPages: pages.length,\n\t\t\t\t// The base link, without page number to use in <Pagination />\n\t\t\t\t// component.\n\t\t\t\tbaseLink: `${domainUrl}${compose}`,\n\t\t\t\tqueriedItems: dataInPage,\n\t\t\t\ttotalQueriedItems: totalQueriedItems?.length,\n\t\t\t},\n\t\t\tisRoot,\n\t\t\tdefaultLang,\n\t\t};\n\n\t\treturn createGriddoPageObject(paginatedPage, additionalInfo);\n\t});\n\n\treturn Promise.all(allPages);\n}\n\n/**\n * Create multiples pages from a MultiPage module\n *\n * @param page A Griddo Multipage object.\n * @param additionalInfo Additional page info.\n */\nfunction createGriddoMultiPages(page: GriddoMultiPage, additionalInfo: PageAdditionalInfo) {\n\tconst { multiPageElements: multiPageElementsBulk, ...cleanPage } = page;\n\t// TODO: Use structuredClone() when node 18 is available.\n\t// WARN!! Se ha probado que parse(stringify()) est\u00E1 tan optimizado que puede ser m\u00E1s r\u00E1pido que structuredClone...\n\tconst multiPageElements: MultiPageElements = JSON.parse(JSON.stringify(multiPageElementsBulk));\n\n\t// Si no hay un elemento sin slug, como m\u00EDnimo hay que dibujar una p\u00E1gina\n\t// principal para el conjunto de p\u00E1ginas.\n\tif (!multiPageElements.find(({ sectionSlug }) => sectionSlug === \"/\")) {\n\t\tmultiPageElements.push({} as MultiPageElement);\n\t}\n\n\t// Creates each page based on `multiPageElements` from the schema.\n\tconst allPages = multiPageElements.map(async (pageElement) => {\n\t\t// TODO: Use structuredClone() when node 18 is available.\n\t\t// WARN!! Se ha probado que parse(stringify()) est\u00E1 tan optimizado que puede ser m\u00E1s r\u00E1pido que structuredClone...\n\t\tconst paginatedPage: APIPageObject = JSON.parse(JSON.stringify(cleanPage));\n\t\tconst {\n\t\t\tsectionSlug = \"/\",\n\t\t\ttitle: bulkTitle = \"\",\n\t\t\tmetaTitle = \"\",\n\t\t\tmetaDescription = \"\",\n\t\t} = pageElement;\n\t\tconst title = typeof bulkTitle === \"string\" ? bulkTitle : bulkTitle.content;\n\t\tconst compose = paginatedPage.fullPath.compose || \"\";\n\t\tconst fullUrl = paginatedPage.fullUrl.endsWith(\"/\")\n\t\t\t? paginatedPage.fullUrl.slice(0, -1)\n\t\t\t: paginatedPage.fullUrl;\n\n\t\tconst cleanSectionSlug = sectionSlug?.replace(/\\//g, \"\");\n\t\tconst isRootSlug = sectionSlug === \"/\";\n\t\tconst rightSectionSlug = isRootSlug ? cleanSectionSlug : `${cleanSectionSlug}/`;\n\n\t\tconst slash = compose.endsWith(\"/\") ? \"\" : \"/\";\n\t\tconst newCompose = `${compose}${slash}${rightSectionSlug}`;\n\n\t\tif (title.trim()) {\n\t\t\tpaginatedPage.title = title;\n\t\t}\n\n\t\tif (metaDescription.trim()) {\n\t\t\tpaginatedPage.metaDescription = metaDescription;\n\t\t}\n\n\t\tpaginatedPage.fullUrl = `${fullUrl}/${rightSectionSlug}`;\n\t\tpaginatedPage.fullPath.compose = newCompose;\n\t\tpaginatedPage.slug = newCompose;\n\t\tpaginatedPage.template.activeSectionSlug = sectionSlug;\n\t\tpaginatedPage.template.activeSectionBase = fullUrl;\n\t\tpaginatedPage.metaTitle = metaTitle.trim() || title.trim() || paginatedPage.metaTitle;\n\n\t\treturn createGriddoPageObject(paginatedPage, additionalInfo);\n\t});\n\n\treturn Promise.all(allPages);\n}\n\n/**\n * Get the multi pages elements.\n *\n * @param page The page to get the multipage parts.\n */\nfunction getMultiPageElements(page: TemplateWithReferenceField): Promise<MultiPageElements> | null {\n\tconst multiPageElements = new Promise((resolve) => {\n\t\t// Recursive\n\t\tconst getMultiPageComponent = (\n\t\t\t// No puede ser Core.Page['template'] porque a medida que va bajando en\n\t\t\t// el \u00E1rbol ya no es la estructura de un template.\n\t\t\ttemplate: Record<string, unknown>,\n\t\t\tlevel = 0,\n\t\t) => {\n\t\t\t// If it doesn't have a \"template strcuture\"\n\t\t\tif (!template || typeof template !== \"object\") {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// For each prop in the \"template\"\n\t\t\tfor (const key in template) {\n\t\t\t\tconst currentComponent = template[key] as {\n\t\t\t\t\tcomponent: string;\n\t\t\t\t\thasGriddoMultiPage: boolean;\n\t\t\t\t\telements: Record<string, unknown>[];\n\t\t\t\t};\n\t\t\t\tconst isValidComponent = currentComponent || typeof currentComponent === \"object\";\n\t\t\t\tconst hasGriddoMultiPageProp = JSON.stringify(currentComponent).includes(\n\t\t\t\t\t'\"hasGriddoMultiPage\":true',\n\t\t\t\t);\n\n\t\t\t\tif (!isValidComponent) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (!hasGriddoMultiPageProp) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst { component, hasGriddoMultiPage, elements } = currentComponent;\n\n\t\t\t\tif (component && hasGriddoMultiPage) {\n\t\t\t\t\tresolve(elements || []);\n\t\t\t\t}\n\n\t\t\t\t// Recursive call\n\t\t\t\tgetMultiPageComponent(currentComponent, level + 1);\n\t\t\t}\n\n\t\t\t// resolve promise when...\n\t\t\tif (!level) {\n\t\t\t\tresolve(null);\n\t\t\t}\n\t\t};\n\n\t\t// `page` en un array para que tambi\u00E9n revise la propia template como objeto.\n\t\t// @ts-expect-error remove the array\n\t\tgetMultiPageComponent([page]);\n\t});\n\n\treturn multiPageElements as Promise<MultiPageElements>;\n}\n\n// -----------------------------------------------------------------------------\n// Private functions\n// -----------------------------------------------------------------------------\n\n/**\n * Get `itemsPerPage` elements from the `items` using as offset `page` number.\n * It's a kind of paginator for an array.\n *\n * @param itemsPerPage The items per page.\n * @param items An array of items, the queriedData.\n * @param page The page to be returned.\n *\n * @example\n * getPage(3, [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\"], 2)\n * // -> [\"d\", \"e\", \"f\"]\n */\nfunction getPage(itemsPerPage: number, items: Fields.QueriedDataItem[], page: number) {\n\treturn items?.slice(itemsPerPage * (page - 1), itemsPerPage * page);\n}\n\n/**\n * Takes an array of items and split it grouping in arrays of pages based on `itemsPerPage`.\n *\n * @param itemsPerPage The items per page.\n * @param items An array of items, the queriedData.\n *\n * @example\n * getPageCluster(3, [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\"])\n * // -> [[\"a\", \"b\", \"c\"], [\"d\", \"e\", \"f\"], [\"g\", \"h\"]]\n */\nfunction getPageCluster(itemsPerPage: number, items: Fields.QueriedDataItem[]) {\n\tconst totalPagesCount = Math.ceil(items.length / itemsPerPage) || 1;\n\tconst pageNumbers = Array.from({ length: totalPagesCount }, (_, i) => i + 1);\n\n\treturn pageNumbers?.map((pageNumber) => getPage(itemsPerPage, items, pageNumber));\n}\n\n/**\n * Takes a template object and split the whole queriedItems into separated queriedItems to use in Griddo static list templates.\n *\n * @param listTemplate A template schema with the ReferenceField data included.\n */\nfunction getPaginatedPages(listTemplate: TemplateWithReferenceField) {\n\tconst items = listTemplate.queriedItems || [];\n\tconst itemsPerPage = listTemplate?.itemsPerPage || DEFAULT_ITEMS_PER_PAGE_FOR_LIST_TEMPLATES;\n\tconst pageClusters = getPageCluster(itemsPerPage, items);\n\n\treturn pageClusters;\n}\n\n/**\n * Remove duplicate ending trailing character from a string\n *\n * @param url the strin url\n * @example\n * removeDuplicateTrailingSlash('http://griddo.com/foo/bar//')\n * // -> http://griddo.com/foo/bar/\n */\nfunction removeDuplicateTrailing(url: string) {\n\treturn url.replace(/\\/+$/, \"/\");\n}\n\n/**\n * Adds a number to an URL adding optionally an ending slash.\n *\n * @param url The url.\n * @param pageNumber A number to be added to the url.\n * @param options.addEndingSlash Boolean that indicates if return the final url with an end slash or not.\n *\n * @example\n * addPageNumberToUrl(\"web.com\", 3) // \"web.com/3\"\n * addPageNumberToUrl(\"web.com\", 3, { addEndingSlash: true }) // \"web.com/3/\"\n */\nfunction addPageNumberToUrl(\n\turl: string,\n\tpageNumber: number,\n\toptions?: { addEndingSlash: boolean },\n) {\n\tconst trailingSlash = url.endsWith(\"/\") ? \"\" : \"/\";\n\tconst endingSlash = options?.addEndingSlash ? \"/\" : \"\";\n\n\tif (pageNumber <= 1) {\n\t\treturn removeDuplicateTrailing(`${url}${endingSlash}`);\n\t}\n\n\treturn removeDuplicateTrailing(`${url}${trailingSlash}${pageNumber}${endingSlash}`);\n}\n\n/**\n * Adds a number to an string with the format \"string - number\"\n *\n * @param title The title\n * @param pageNumber A number to be added to the title.\n *\n * @example\n * addPageNumberToTitle(\"The page\", 3) // \"The page - 3\"\n */\nfunction addPageNumberToTitle(title: string, pageNumber: number) {\n\tif (!title || pageNumber <= 1) {\n\t\treturn title;\n\t}\n\n\treturn `${title} - ${pageNumber}`;\n}\n\nexport {\n\tcreateGriddoListPages,\n\tcreateGriddoMultiPages,\n\tcreateGriddoSinglePage,\n\tgetMultiPageElements,\n\tgetPaginatedPages,\n};\n", "import type { Core, Fields } from \"@griddo/core\";\nimport type { FetchDataProps } from \"../shared/types/global\";\nimport type { APIPageObject } from \"../shared/types/pages\";\n\nimport { GriddoLog } from \"../core/GriddoLog\";\nimport { getReferenceFieldSiteData } from \"./sites\";\n\n/**\n * Get the body data from a ReferenceField.\n * `auto`, `manual` or `navigation` mode.\n *\n * @param data The ReferenceField props.\n * @returns The props for one of the ReferenceField mode.\n */\nfunction getBody(data: Fields.Reference<unknown>, page: Core.Page) {\n\tconst {\n\t\torder,\n\t\tsources,\n\t\tquantity,\n\t\tmode,\n\t\tfixed,\n\t\tfullRelations = false,\n\t\tallLanguages = false,\n\t\tpreferenceLanguage = false,\n\t\treferenceId,\n\t\tfields,\n\t} = data;\n\n\tif (mode === \"auto\") {\n\t\treturn {\n\t\t\tmode,\n\t\t\torder,\n\t\t\tsources,\n\t\t\tquantity,\n\t\t\tfullRelations,\n\t\t\tallLanguages,\n\t\t\tpreferenceLanguage,\n\t\t\tfields,\n\t\t};\n\t}\n\n\tif (mode === \"manual\") {\n\t\treturn { mode, fixed, fullRelations, fields };\n\t}\n\n\tif (mode === \"navigation\") {\n\t\treturn {\n\t\t\tmode,\n\t\t\torder,\n\t\t\tquantity,\n\t\t\tfullRelations,\n\t\t\treferenceId: referenceId || page?.structuredDataContent?.id,\n\t\t\tfields,\n\t\t};\n\t}\n\n\tGriddoLog.error(`ReferenceField mode: ${mode} is not recognized on page ${page?.id}.`);\n\n\treturn data;\n}\n\n/**\n * Gets ContentType data from API\n *\n * @param props\n * @param props.page The Page object\n * @param props.component.data The ReferenceField, always in the data prop.\n * @param props.cacheKey A cache key to manage cached files or using fetch\n * @returns The ContentType data.\n */\nasync function fetchContentTypeData(props: FetchDataProps) {\n\tconst { page, component, cacheKey } = props;\n\tconst { data } = component;\n\n\t// Distrubutor with `hasDistributorData: true` / `getStaticData: true` but without `data` prop\n\tif (!data) {\n\t\tGriddoLog.info(\n\t\t\t`Error: Page ${page.id} has \\`hasDistributorData: true\\` or \\`getStaticData: true\\` but it doesn't have a \\`data\\` property.`,\n\t\t);\n\n\t\treturn [];\n\t}\n\n\t// Avoid fetch ReferenceField with empty `data.sources`\n\tif (Array.isArray(data.sources) && data.sources.length < 1) {\n\t\tGriddoLog.info(\n\t\t\t`Warning: Page with id: ${page.id} has a ReferenceField with empty \\`data.sources\\``,\n\t\t);\n\n\t\treturn [];\n\t}\n\n\tconst { site, lang } = data;\n\n\t// Inform that the ReferenceField has not `data.sources`\n\tif (!data.sources && data.mode === \"auto\") {\n\t\tGriddoLog.info(\n\t\t\t`Warning: Page with id: ${page.id} has a ReferenceField with \\`undefined\\` \\`data.sources\\``,\n\t\t);\n\t}\n\n\tconst body = getBody(data, page);\n\n\tconst response = await getReferenceFieldSiteData(page, body, cacheKey, site, lang);\n\n\treturn response;\n}\n\n/**\n * Compose the queriedItems prop from a ReferenceField data of a page.\n *\n * @param props\n * @param props.page The APIPage object\n * @param props.cacheKey A cache key to manage cached files or using fetch\n */\nasync function getReferenceFieldData({\n\tpage,\n\tcacheKey = \"\",\n}: {\n\tpage: APIPageObject;\n\t/** Reference id to manage cache between renders. */\n\tcacheKey: string;\n}) {\n\ttry {\n\t\tconst { template } = page;\n\t\tconst checkReferenceFields = async (\n\t\t\ttemplateChunk: {\n\t\t\t\thasDistributorData?: boolean;\n\t\t\t\tgetStaticData?: boolean;\n\t\t\t\tqueriedItems: Fields.QueriedData<unknown>;\n\t\t\t},\n\t\t\tlevel = 1,\n\t\t) => {\n\t\t\t// If it doesn't a \"template strcuture\"\n\t\t\tif (!templateChunk || typeof templateChunk !== \"object\") {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst hasRequestForData =\n\t\t\t\tJSON.stringify(templateChunk).includes('\"hasDistributorData\":true') ||\n\t\t\t\tJSON.stringify(templateChunk).includes('\"getStaticData\":true');\n\n\t\t\tif (!hasRequestForData) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// For each prop in the \"template\"\n\t\t\tfor (const key in templateChunk) {\n\t\t\t\t// Si la key es `queriedItems` saltamos al siguiente `key`\n\t\t\t\tif (key === \"queriedItems\") {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst _key = key as \"hasDistributorData\" | \"queriedItems\" | \"getStaticData\";\n\t\t\t\tconst component = templateChunk[_key] as unknown as {\n\t\t\t\t\tdata: Fields.Reference<unknown>;\n\t\t\t\t\tqueriedItems: Fields.QueriedData<unknown>;\n\t\t\t\t\thasDistributorData: boolean;\n\t\t\t\t\tgetStaticData: boolean;\n\t\t\t\t};\n\n\t\t\t\t// Si el elemento no existe o no es un objeto saltamos al siguiente `key`\n\t\t\t\tif (!component || typeof component !== \"object\") {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst componentHasRequestForData = component.hasDistributorData || component.getStaticData;\n\n\t\t\t\tif (componentHasRequestForData) {\n\t\t\t\t\tcomponent.queriedItems = await fetchContentTypeData({\n\t\t\t\t\t\tpage,\n\t\t\t\t\t\tcacheKey,\n\t\t\t\t\t\tcomponent,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tawait checkReferenceFields(component, level + 1);\n\t\t\t}\n\t\t};\n\n\t\tconst getReferenceFields = async (template: Core.Page[\"template\"]) => {\n\t\t\t// `template` es un array para que tambi\u00E9n revise la propia template como objeto.\n\t\t\t// @ts-expect-error\tremove the array\n\t\t\tawait checkReferenceFields([template]);\n\n\t\t\treturn template;\n\t\t};\n\n\t\tconst response = await getReferenceFields(template);\n\n\t\treturn response;\n\t} catch (err) {\n\t\tGriddoLog.error(\"Error in getReferenceFieldData:\", err);\n\n\t\tthrow err;\n\t}\n}\n\nexport { getReferenceFieldData };\n", "import type { RenderContext } from \"../../../shared/context\";\n\nimport { createStore } from \"../../../services/store\";\n\nexport async function dataAction(context: RenderContext) {\n\tconst {\n\t\tdomain,\n\t\trenderMode,\n\t\trenderMetadata: { griddoVersion },\n\t\tpathsHydratedWithDomain: { __root },\n\t} = context;\n\n\tconst { pagesToCreate, pagesToDelete } = await createStore({\n\t\tdomain,\n\t\trenderMode,\n\t\tgriddoVersion,\n\t\tbasePath: __root,\n\t});\n\n\tcontext.pagesToCreate = pagesToCreate;\n\tcontext.pagesToDelete = pagesToDelete;\n}\n", "import type { RenderContext } from \"../../../shared/context\";\n\nimport { assertRenderIsValid, markRenderAsCompleted } from \"../../../services/render\";\n\nexport async function healthCheckAction(context: RenderContext) {\n\tconst { domain } = context;\n\n\tawait assertRenderIsValid(domain);\n\tawait markRenderAsCompleted(domain);\n}\n", "import type { RenderContext } from \"../../../shared/context\";\n\nimport { markRenderAsStarted } from \"../../../services/render\";\n\nexport async function initAction(context: RenderContext) {\n\tconst {\n\t\tdomain,\n\t\tpathsHydratedWithDomain: { __root },\n\t} = context;\n\n\tawait markRenderAsStarted({ basePath: __root, domain });\n}\n", "import type { RenderContext } from \"../../../shared/context\";\nimport type { SSG } from \"../shared/types\";\n\nimport { saveDetailRenderLog } from \"../../../core/logger\";\n\nexport async function logsAction(context: RenderContext<SSG>) {\n\tconst { domain } = context;\n\n\tawait saveDetailRenderLog(domain);\n}\n", "import type { Robots } from \"../shared/types/global\";\n\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { pathExists } from \"../core/fs\";\nimport { GriddoLog } from \"../core/GriddoLog\";\nimport { ROBOTS } from \"../shared/endpoints\";\nimport { get } from \"./api\";\nimport { getRenderPathsHydratedWithDomainFromDB } from \"./render\";\n\nasync function fetchRobots() {\n\tconst apiRobots = await get<Robots>({ endpoint: ROBOTS });\n\treturn (\n\t\tapiRobots\n\t\t\t?.filter((r) => !!r.path)\n\t\t\t.map(({ path, content }) => ({\n\t\t\t\tpath,\n\t\t\t\tcontent: content || \"User-agent: *\\n\\r\\n\\rAllow: /\",\n\t\t\t})) || []\n\t);\n}\n\nasync function generateRobots(domain: string) {\n\tconst { __root } = await getRenderPathsHydratedWithDomainFromDB({ domain });\n\tconst distDirectory = path.join(__root, \"current-dist\");\n\tconst robot = (await fetchRobots()).find(({ path }) => path === `/${domain}`);\n\n\tif (!robot) {\n\t\tGriddoLog.info(`Robots not found for ${domain}`);\n\t\treturn;\n\t}\n\n\tif (await pathExists(distDirectory)) {\n\t\tconst fileLocation = path.join(distDirectory, \"robots.txt\");\n\t\tawait fsp.writeFile(fileLocation, robot?.content);\n\t\tGriddoLog.verbose(`wrote robots.txt to ${fileLocation}`);\n\t} else {\n\t\tGriddoLog.info(`${distDirectory} not found`);\n\t}\n}\n\nexport { generateRobots };\n", "import fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { pathExists } from \"../core/fs\";\nimport { GriddoLog } from \"../core/GriddoLog\";\nimport { generateSitemapIndexXml, generateUrlsetXml } from \"../shared/npm-modules/xml-parser\";\nimport { AuthService } from \"./auth\";\nimport { getBuildMetadata } from \"./manage-store\";\nimport { getRenderPathsHydratedWithDomainFromDB } from \"./render\";\nimport { getSitemap } from \"./sites\";\n\n/**\n * Generate sitemaps and save them into file system.\n */\nasync function generateSitemaps(domain: string) {\n\tconst { __root } = await getRenderPathsHydratedWithDomainFromDB();\n\tconst { sitesToPublish } = await getBuildMetadata(domain);\n\tconst distDir = path.join(__root, \"current-dist\");\n\tconst templateSitemapPrefix = \"sitemap-\";\n\n\tconst isGriddoSitemapFile = (file: string) =>\n\t\tfile === \"sitemap.xml\" || (file.startsWith(templateSitemapPrefix) && file.endsWith(\".xml\"));\n\n\tfor (const site of sitesToPublish) {\n\t\tconst { id, languages } = site;\n\n\t\tfor (const lang of languages) {\n\t\t\t// Local copy of headers to avoid mutating the shared object\n\t\t\tconst localHeaders: Record<string, string> = AuthService.headers\n\t\t\t\t? { ...AuthService.headers }\n\t\t\t\t: {};\n\t\t\tlocalHeaders.lang = lang.id.toString();\n\n\t\t\tconst response = await getSitemap({ siteId: id, headers: localHeaders });\n\n\t\t\tif (!response) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst { items: sitemapPagesGroup, url } = response;\n\t\t\tconst { home, domain } = url;\n\n\t\t\tif (!home) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst domainLanguage = site.domains.find(\n\t\t\t\t(domain) => Object.keys(domain)[0] === lang.id.toString(),\n\t\t\t);\n\n\t\t\tif (!domainLanguage) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst slug = Object.values(domainLanguage)[0];\n\t\t\tconst sitemaps: string[] = [];\n\t\t\tconst sitemapPageGroupKeys = Object.keys(sitemapPagesGroup);\n\t\t\tconst sitemapBasePath = path.join(distDir, slug.replace(domain, \"\"));\n\n\t\t\t/** delete every griddo sitemap file before create the new ones */\n\t\t\tif (await pathExists(sitemapBasePath)) {\n\t\t\t\ttry {\n\t\t\t\t\tconst files = await fsp.readdir(sitemapBasePath);\n\t\t\t\t\tfor (const file of files) {\n\t\t\t\t\t\tif (isGriddoSitemapFile(file)) {\n\t\t\t\t\t\t\tconst filePath = path.join(sitemapBasePath, file);\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tawait fsp.rm(filePath);\n\t\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\tGriddoLog.error(`Error deleting file ${filePath}:`, err);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (err) {\n\t\t\t\t\tGriddoLog.error(`Error reading ${sitemapBasePath}:`, err);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const templateId of sitemapPageGroupKeys) {\n\t\t\t\tconst sitemapPages = sitemapPagesGroup[templateId];\n\n\t\t\t\tif (!sitemapPages.length) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst siteMap = generateUrlsetXml(sitemapPages);\n\n\t\t\t\tconst sitemapName = `/${templateSitemapPrefix}${templateId.toLowerCase()}.xml`;\n\t\t\t\tconst exactPath = path.join(sitemapBasePath, sitemapName);\n\n\t\t\t\tawait saveFile(exactPath, siteMap);\n\t\t\t\tGriddoLog.verbose(`sitemap generated in ${exactPath}`);\n\n\t\t\t\tsitemaps.push(`${home.endsWith(\"/\") ? home.slice(0, -1) : home}${sitemapName}`);\n\t\t\t}\n\n\t\t\tif (!sitemaps.length) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst siteMap = generateSitemapIndexXml(sitemaps);\n\n\t\t\tconst exactPath = path.join(sitemapBasePath, \"sitemap.xml\");\n\n\t\t\tawait saveFile(exactPath, siteMap);\n\t\t\tGriddoLog.verbose(`sitemap generated in ${exactPath}`);\n\t\t}\n\t}\n}\n\n/**\n * Saves the content to a file specified by its path. If the file exists, it will be overwritten.\n *\n * @param filePath The path of the file to save the content to.\n * @param content The content to save to the file.\n */\nasync function saveFile(filePath: string, content: string) {\n\ttry {\n\t\tconst pathName = path.dirname(filePath);\n\t\tif (!(await pathExists(pathName))) {\n\t\t\tawait fsp.mkdir(pathName, { recursive: true });\n\t\t}\n\t\tawait fsp.writeFile(filePath, content);\n\t} catch (_error) {\n\t\tthrow new Error(`Error saving a file`);\n\t}\n}\n\nexport { generateSitemaps };\n", "import type { SitemapItem } from \"../types/api\";\n\nfunction escapeXml(unsafe: string) {\n\treturn unsafe.replace(/[<>&'\"\u201D]/g, (c) => {\n\t\tswitch (c) {\n\t\t\tcase \"<\":\n\t\t\t\treturn \"<\";\n\t\t\tcase \">\":\n\t\t\t\treturn \">\";\n\t\t\tcase \"&\":\n\t\t\t\treturn \"&\";\n\t\t\tcase \"'\":\n\t\t\t\treturn \"'\";\n\t\t\tcase '\"':\n\t\t\t\treturn \""\";\n\t\t\tcase \"\u201D\":\n\t\t\t\treturn \""\";\n\t\t\tdefault:\n\t\t\t\treturn c;\n\t\t}\n\t});\n}\n\nfunction generateUrlsetXml(pages: SitemapItem[]) {\n\tconst urls = pages\n\t\t.map(\n\t\t\t(page) =>\n\t\t\t\t` <url>\n <loc>${escapeXml(page.loc)}</loc>\n <lastmod>${page.lastmod}</lastmod>\n <priority>${page.priority}</priority>\n </url>`,\n\t\t)\n\t\t.join(\"\\n\");\n\n\treturn `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd\">\n${urls}\n</urlset>`;\n}\n\nfunction generateSitemapIndexXml(sitemaps: string[]) {\n\tconst sitemapEntries = sitemaps\n\t\t.map(\n\t\t\t(loc) => ` <sitemap>\n <loc>${escapeXml(loc)}</loc>\n </sitemap>`,\n\t\t)\n\t\t.join(\"\\n\");\n\n\treturn `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<sitemapindex xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n${sitemapEntries}\n</sitemapindex>`;\n}\n\nexport { generateSitemapIndexXml, generateUrlsetXml };\n", "import type { RenderContext } from \"../../../shared/context\";\n\nimport { generateBuildReport } from \"../../../services/render\";\nimport { generateRobots } from \"../../../services/robots\";\nimport { generateSitemaps } from \"../../../services/sitemaps\";\n\nexport async function metaAction(context: RenderContext) {\n\tconst { domain } = context;\n\n\tawait generateBuildReport(domain);\n\tawait generateSitemaps(domain);\n\tawait generateRobots(domain);\n}\n", "import type { RenderContext } from \"../../../shared/context\";\n\nimport { mkDirs } from \"../../../core/fs\";\n\nexport async function prepareAction(context: RenderContext) {\n\tconst { renderArtifacts } = context;\n\n\tawait mkDirs(renderArtifacts.initials);\n}\n", "import type { RenderContext } from \"../../../shared/context\";\n\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nexport async function relocationAction(context: RenderContext) {\n\tconst {\n\t\tpathsHydratedWithDomain: { __root, __ssg },\n\t} = context;\n\n\tconst src = path.join(__ssg, \"public\");\n\tconst dst = path.join(__root, \"current-dist\");\n\n\tawait fsp.rename(src, dst);\n}\n", "import type { RenderContext } from \"../../../shared/context\";\nimport type { SSG } from \"../shared/types\";\n\nimport { cpDirs, mvDirs } from \"../../../core/fs\";\nimport { RENDER_MODE } from \"../../../shared/types/render\";\n\nexport async function restoreAction(context: RenderContext<SSG>) {\n\tconst {\n\t\trenderMode,\n\t\tssg: { ssgArtifacts },\n\t\trenderArtifacts,\n\t\tpathsHydratedWithDomain: { __components, __root, __cache, __ssg },\n\t} = context;\n\n\tawait cpDirs(__components, __ssg, [\"static\"]);\n\n\tif (renderMode === RENDER_MODE.INCREMENTAL) {\n\t\tawait mvDirs(__cache, __ssg, ssgArtifacts.cacheables);\n\t\tawait mvDirs(__cache, __root, renderArtifacts.cacheables);\n\t}\n}\n", "import { spawn } from \"node:child_process\";\nimport path from \"node:path\";\n\nimport { GriddoLog } from \"../../../core/GriddoLog\";\nimport { getRenderPathsHydratedWithDomainFromDB } from \"../../../services/render\";\nimport { GRIDDO_SSG_VERBOSE_LOGS } from \"../../../shared/envs\";\n\n/**\n * Spawn a new node process `gatsby build`\n * @note This proccess can not access to the custom Griddo `process.env` so it\n * needs variables passed to it via the `env` prop.\n */\nasync function gatsbyBuild(assetPrefixWithDomain: string): Promise<void> {\n\tGriddoLog.verbose(`read assetPrefixWithDomain, ${assetPrefixWithDomain}`);\n\tGriddoLog.verbose(`using this NODE_OPTIONS in gatsby command: ${process.env.NODE_OPTIONS}`);\n\n\tconst { __ssg } = await getRenderPathsHydratedWithDomainFromDB();\n\n\t// Remove `--openssl-legacy-provider` from NODE_OPTIONS because this value\n\t// break Gatsby render.\n\tconst nodeOptionsWithoutLegacyOpenSSL = process.env.NODE_OPTIONS\n\t\t? process.env.NODE_OPTIONS.replace(/--openssl-legacy-provider\\s*/g, \"\").trim()\n\t\t: \"\";\n\n\t// Ruta al ejecutable de Gatsby\n\tconst gatsbyExecutable = path.join(__ssg, \"node_modules\", \".bin\", \"gatsby\");\n\n\tconst args = [\"build\", \"--prefix-paths\"];\n\tif (GRIDDO_SSG_VERBOSE_LOGS) {\n\t\targs.push(\"--verbose\");\n\t}\n\n\treturn new Promise((resolve, reject) => {\n\t\tconst child = spawn(gatsbyExecutable, args, {\n\t\t\tcwd: __ssg,\n\t\t\tstdio: [\"ignore\", \"inherit\", \"inherit\"],\n\t\t\tenv: {\n\t\t\t\t...process.env,\n\t\t\t\tSPAWN_ASSET_PREFIX_WITH_DOMAIN: assetPrefixWithDomain,\n\t\t\t\tNODE_OPTIONS: nodeOptionsWithoutLegacyOpenSSL,\n\t\t\t},\n\t\t});\n\n\t\tchild.on(\"close\", (code) => {\n\t\t\tif (code === 0) {\n\t\t\t\tresolve();\n\t\t\t} else {\n\t\t\t\treject(new Error(`Gatsby build failed with exit code ${code}`));\n\t\t\t}\n\t\t});\n\n\t\tchild.on(\"error\", (error) => {\n\t\t\treject(new Error(`Failed to start Gatsby build process: ${error.message}`));\n\t\t});\n\t});\n}\n\nexport { gatsbyBuild };\n", "import type { RenderContext } from \"../../../shared/context\";\nimport type { SSG } from \"../shared/types\";\n\nimport { gatsbyBuild } from \"../shared/gatsby-build\";\n\nexport async function ssgAction(context: RenderContext<SSG>) {\n\tconst {\n\t\tssg: { assetPrefix },\n\t} = context;\n\n\tawait gatsbyBuild(assetPrefix);\n}\n", "import type { RenderContext } from \"../../../shared/context\";\nimport type { SSG } from \"../shared/types\";\n\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { deleteDisposableSiteDirs, deleteEmptyDirectories, mvDirs } from \"../../../core/fs\";\nimport { RENDER_MODE } from \"../../../shared/types/render\";\nimport { extractAssetsFromDist } from \"../shared/extract-assets\";\nimport { SyncRender } from \"../shared/sync-render\";\n\nexport async function syncAction(context: RenderContext<SSG>) {\n\tconst {\n\t\trenderMode,\n\t\trenderArtifacts,\n\t\tdomain,\n\t\tpagesToCreate,\n\t\tpagesToDelete,\n\t\tpathsHydratedWithDomain: { __root, __ssg, __cache, __exports },\n\t\tssg: { ssgArtifacts, assetPrefix },\n\t} = context;\n\n\tconst needsAssetPrefix = !!assetPrefix && assetPrefix !== \"\";\n\tconst currentDist = path.join(__root, \"current-dist\");\n\tconst previousDist = path.join(__exports, \"dist\");\n\n\t// caching...\n\tawait mvDirs(__root, __cache, renderArtifacts.cacheables, { override: true });\n\tawait mvDirs(__ssg, __cache, ssgArtifacts.cacheables, { override: true });\n\n\tif (renderMode === RENDER_MODE.FROM_SCRATCH) {\n\t\tawait deleteDisposableSiteDirs(currentDist);\n\t\t// Es render nuevo, as\u00ED que el current-dist generado por gatsby hay que renombrarlo a dist\n\t\t// porque muchas de las acciones posteriores asumen ese nombre en ese path...\n\t\t// TODO: Cambiar eso y atomizar m\u00E1s las acciones.\n\t\tawait fsp.rm(previousDist, { force: true, recursive: true });\n\t\tawait fsp.rename(currentDist, previousDist);\n\t}\n\n\tif (renderMode === RENDER_MODE.INCREMENTAL) {\n\t\tawait deleteDisposableSiteDirs(previousDist);\n\n\t\tconst syncRender = new SyncRender({\n\t\t\tsrc: currentDist,\n\t\t\tdst: previousDist,\n\t\t\tpagesToCreate,\n\t\t\tpagesToDelete,\n\t\t\tartifactsToCopyToExports: [\"build-report.json\"],\n\t\t});\n\n\t\tawait syncRender.execute();\n\t\t// despu\u00E9s syncRender.execute() currentDist (que lo hizo gatsby) ya no es necesario\n\t\t// esta todo en __exports/dist porque syncRender.execute() ya sincroniniz\u00F3.\n\t\tawait fsp.rm(currentDist, { force: true, recursive: true });\n\t\tawait deleteEmptyDirectories(path.join(__exports, \"dist\"));\n\t}\n\n\tif (needsAssetPrefix) {\n\t\t// TODO: Mejorar performance\n\t\tawait extractAssetsFromDist(domain);\n\t}\n\n\t// rsync assets\n\tawait mvDirs(__root, __exports, renderArtifacts.archivables, { override: true });\n}\n", "import fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { pathExists } from \"../../../core/fs\";\nimport { getRenderPathsHydratedWithDomainFromDB } from \"../../../services/render\";\n\n/**\n * Update the Griddo's `/dist` dir with the contents from `public` dir only\n * with files of type: js, json and css.\n * TODO: Explicar que el static se copia a assets porque el js va en el subdominio de assets.\n */\nasync function extractAssetsFromDist(domain: string) {\n\tconst { __root, __exports } = await getRenderPathsHydratedWithDomainFromDB({ domain });\n\n\t// Archivos (no carpetas) v\u00E1lidos de public\n\tconst filesFromDist = (await fsp.readdir(path.join(__exports, \"dist\"))).filter(\n\t\t(file) =>\n\t\t\tpath.extname(file) === \".js\" ||\n\t\t\tpath.extname(file) === \".json\" ||\n\t\t\tpath.extname(file) === \".css\",\n\t);\n\n\t// Creamos assets si es necesario (needsAssetPrefix)\n\tawait fsp.mkdir(path.join(__root, \"assets\"), { recursive: true });\n\t// page-data folder\n\tawait fsp.cp(\n\t\tpath.join(__exports, \"dist\", \"page-data\"),\n\t\tpath.join(__root, \"assets\", \"page-data\"),\n\t\t{\n\t\t\tpreserveTimestamps: true,\n\t\t\trecursive: true,\n\t\t},\n\t);\n\t// static folder si existe\n\tif (await pathExists(path.join(__root, \"static\"))) {\n\t\tawait fsp.cp(path.join(__root, \"static\"), path.join(__root, \"assets\"), {\n\t\t\tforce: false,\n\t\t\tpreserveTimestamps: true,\n\t\t\trecursive: true,\n\t\t});\n\t}\n\t// dist/static -> assets/static\n\tif (await pathExists(path.join(__exports, \"dist\", \"static\"))) {\n\t\tawait fsp.cp(path.join(__exports, \"dist\", \"static\"), path.join(__root, \"assets\", \"static\"), {\n\t\t\tforce: false,\n\t\t\tpreserveTimestamps: true,\n\t\t\trecursive: true,\n\t\t});\n\t}\n\t// otro static...\n\tif (await pathExists(path.join(__root, \"static\"))) {\n\t\tawait fsp.cp(path.join(__root, \"static\"), path.join(__exports, \"dist\", domain), {\n\t\t\tpreserveTimestamps: true,\n\t\t\trecursive: true,\n\t\t\tforce: false,\n\t\t});\n\t}\n\n\t// Copia el resto de archivos...\n\t// for (const file of filesFromDist) {\n\t// \tconst fileSrc = path.join(__exports, \"dist\", file);\n\t// \tconst fileDest = path.join(__root, \"assets\", file);\n\t// \tawait fsp.cp(fileSrc, fileDest, { preserveTimestamps: true, recursive: true });\n\t// }\n\n\tconst arraysOfPromises: Promise<void>[] = filesFromDist.map((file) => {\n\t\tconst fileSrc = path.join(__exports, \"dist\", file);\n\t\tconst fileDest = path.join(__root, \"assets\", file);\n\t\treturn fsp.cp(fileSrc, fileDest, { preserveTimestamps: true, recursive: true });\n\t});\n\n\tawait Promise.all(arraysOfPromises);\n}\n\nexport { extractAssetsFromDist };\n", "import fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport pLimit from \"p-limit\";\n\nimport { findFilesBySuffix } from \"../../../core/fs\";\nimport { GriddoLog } from \"../../../core/GriddoLog\";\nimport { GRIDDO_SSG_BUNDLE_ANALYZER } from \"../../../shared/envs\";\nimport { getAssetsDiffBetweenRenders, patchHtmlFile } from \"./diff-assets\";\n\ninterface SyncRenderConfig {\n\tsrc: string;\n\tdst: string;\n\tpagesToCreate: number[];\n\tpagesToDelete: number[];\n\tartifactsToCopyToExports: string[];\n}\ninterface CopyFilePath {\n\tfrom: string;\n\tto: string;\n}\ninterface SyncState {\n\thtmlToAdd: CopyFilePath[];\n\tjsonToAdd: CopyFilePath[];\n\thtmlToDelete: string[];\n\tjsonToDelete: string[];\n}\ninterface PageInfo {\n\tid: number;\n\tcomposePath: string; // p.ej. '/about-us' o '/'\n\thtmlPath: string; // p.ej. '/path/to/public/about-us/index.html'\n\tjsonPath: string; // p.ej. '/path/to/public/page-data/about-us/page-data.json'\n}\ninterface GatsbyPageData {\n\tresult: {\n\t\tpageContext: {\n\t\t\tid: number;\n\t\t\tfullPath: {\n\t\t\t\tsite: string;\n\t\t\t\tdomain: string;\n\t\t\t\tdomainUrl: string;\n\t\t\t\tlanguage: string;\n\t\t\t\tpage: string;\n\t\t\t\tcompose: string;\n\t\t\t};\n\t\t};\n\t};\n}\n\nclass SyncRender {\n\tprivate bundleDir: string;\n\tprivate currentRenderDir: string;\n\tprivate pagesToCreate: number[];\n\tprivate pagesToDelete: number[];\n\tprivate assetArtifacts: string[];\n\n\tprivate state: SyncState = {\n\t\thtmlToAdd: [],\n\t\tjsonToAdd: [],\n\t\thtmlToDelete: [],\n\t\tjsonToDelete: [],\n\t};\n\n\tconstructor(config: SyncRenderConfig) {\n\t\tthis.bundleDir = config.dst;\n\t\tthis.currentRenderDir = config.src;\n\t\tthis.pagesToCreate = config.pagesToCreate;\n\t\tthis.pagesToDelete = config.pagesToDelete;\n\t\tthis.assetArtifacts = config.artifactsToCopyToExports;\n\t}\n\n\tpublic async execute() {\n\t\tawait this.setPagesToDelete();\n\t\tawait this.setPagesToAdd();\n\t\tawait this.sync();\n\t\tif (GRIDDO_SSG_BUNDLE_ANALYZER) {\n\t\t\tawait this.assertAssetsAreValid();\n\t\t}\n\t}\n\n\tprivate async assertAssetsAreValid() {\n\t\tconst isDifferent = await getAssetsDiffBetweenRenders(this.currentRenderDir, this.bundleDir);\n\t\tif (isDifferent) {\n\t\t\tGriddoLog.info(\n\t\t\t\t\"Warning: JavaScript and CSS bundles must have the same files and content. You can ignore this warning if the rendering process only has pages to unpublish.\",\n\t\t\t);\n\t\t} else {\n\t\t\tGriddoLog.info(\"Previous and current JavaScript and CSS packages successfully matched\");\n\t\t}\n\t}\n\n\tprivate async setPagesToDelete() {\n\t\t// INCLUIMOS LAS P\u00C1GINAS A CREAR EN LAS CANDIDATAS A BORRAR\n\t\t// =======================================================\n\t\t// El set de ids incluye tanto las p\u00E1ginas a borrar como las que se van\n\t\t// a crear para manejar correctamente los cambios de slug.\n\t\t//\n\t\t// Ejemplo: Si la p\u00E1gina `id=3` tiene slug `about` y despu\u00E9s viene con\n\t\t// `slug=about-us`, necesitamos borrar la p\u00E1gina `id=3` del render previo\n\t\t// y volver a crearla con la nueva ruta.\n\t\t//\n\t\t// \u00BFPor qu\u00E9? Porque el slug determina d\u00F3nde se guarda la p\u00E1gina:\n\t\t// - /about/index.html -> /about-us/index.html\n\t\t//\n\t\t// Si no la borr\u00E1semos previamente, tendr\u00EDamos ambas p\u00E1ginas:\n\t\t// `/about/index.html` y `/about-us/index.html`\n\t\tconst candidateIdsToDelete = new Set<number>([...this.pagesToDelete, ...this.pagesToCreate]);\n\t\tconst existingPreviousPages = await this.scanPages(this.bundleDir);\n\n\t\tfor (const page of existingPreviousPages) {\n\t\t\tif (candidateIdsToDelete.has(page.id)) {\n\t\t\t\tthis.state.htmlToDelete.push(page.htmlPath);\n\t\t\t\tthis.state.jsonToDelete.push(page.jsonPath);\n\t\t\t}\n\t\t}\n\n\t\tGriddoLog.verbose(`${this.state.htmlToDelete.length} pages HTML to delete`);\n\t\tGriddoLog.verbose(`${this.state.jsonToDelete.length} pages JSON to delete`);\n\t}\n\n\tprivate async setPagesToAdd() {\n\t\tconst candidateIdsToCreate = new Set<number>(this.pagesToCreate);\n\t\tconst newPages = await this.scanPages(this.currentRenderDir);\n\n\t\tfor (const page of newPages) {\n\t\t\tif (candidateIdsToCreate.has(page.id)) {\n\t\t\t\tconst htmlTo = path.join(this.bundleDir, page.composePath, \"index.html\");\n\t\t\t\tconst normalizedCompose = page.composePath === \"/\" ? \"index\" : page.composePath;\n\t\t\t\tconst jsonTo = path.join(this.bundleDir, \"page-data\", normalizedCompose, \"page-data.json\");\n\n\t\t\t\tthis.state.htmlToAdd.push({ from: page.htmlPath, to: htmlTo });\n\t\t\t\tthis.state.jsonToAdd.push({ from: page.jsonPath, to: jsonTo });\n\t\t\t}\n\t\t}\n\n\t\tGriddoLog.verbose(`${this.state.htmlToAdd.length} pages HTML to create`);\n\t\tGriddoLog.verbose(`${this.state.jsonToAdd.length} pages JSON to create`);\n\t}\n\n\tprivate async sync() {\n\t\t// Delete...\n\t\tconst allFilesToDelete = [...this.state.htmlToDelete, ...this.state.jsonToDelete];\n\t\tfor (const file of allFilesToDelete) {\n\t\t\ttry {\n\t\t\t\t// Usar `force: true` para no fallar si el archivo ya no existe.\n\t\t\t\tawait fsp.rm(file, { force: true });\n\t\t\t\tGriddoLog.verbose(`Sync (remove) : ${file}`);\n\t\t\t} catch (e) {\n\t\t\t\t// El error solo se registrar\u00EDa si es un problema de permisos, etc.\n\t\t\t\tGriddoLog.error(`Failed to remove ${file}:`, e);\n\t\t\t}\n\t\t}\n\n\t\tawait this.restoreWebpackCompilationHash();\n\n\t\t// Copy...\n\t\tconst allFilesToAdd = [...this.state.htmlToAdd, ...this.state.jsonToAdd];\n\t\tfor (const file of allFilesToAdd) {\n\t\t\ttry {\n\t\t\t\tawait fsp.mkdir(path.dirname(file.to), { recursive: true });\n\t\t\t\tawait fsp.copyFile(file.from, file.to);\n\t\t\t\tGriddoLog.verbose(`Sync (copy) : ${file.from} -> ${file.to}`);\n\t\t\t} catch (e) {\n\t\t\t\tGriddoLog.error(`Failed to copy ${file.from} to ${file.to}:`, e);\n\t\t\t}\n\t\t}\n\n\t\t// AVOID TO RESTORE webpackCompilationHash\n\t\t// await this.copyAppDataJsonFile();\n\t\tawait this.copyAssetArtifacts();\n\t\tawait this.copySitemaps();\n\t}\n\n\t// TODO: Optimizar esto a lo bestia...\n\tprivate async restoreWebpackCompilationHash() {\n\t\tconst appDataJsonFile = path.join(this.bundleDir, \"page-data\", \"app-data.json\");\n\t\tconst webpackCompilationHash = JSON.parse(\n\t\t\tawait fsp.readFile(appDataJsonFile, \"utf8\"),\n\t\t).webpackCompilationHash;\n\t\tGriddoLog.build(\n\t\t\t`Reading webpackCompilationHash from ${appDataJsonFile} = ${webpackCompilationHash}`,\n\t\t);\n\n\t\tconst changedHtmlFilePaths = this.state.htmlToAdd.map(({ from }) => from);\n\n\t\tfor (const htmlFilePath of changedHtmlFilePaths) {\n\t\t\tGriddoLog.build(`Patching HTML file ${htmlFilePath} with the new webpackCompilationHash`);\n\t\t\tawait patchHtmlFile(htmlFilePath, webpackCompilationHash);\n\t\t}\n\t}\n\n\t// private async copyAppDataJsonFile() {\n\t// \ttry {\n\t// \t\tconst src = path.join(this.currentRenderDir, \"page-data\", \"app-data.json\");\n\t// \t\tconst dst = path.join(this.bundleDir, \"page-data\", \"app-data.json\");\n\t// \t\tawait fsp.copyFile(src, dst);\n\t// \t\tGriddoLog.verbose(\"Copied app-data.json\");\n\t// \t} catch (e) {\n\t// \t\tGriddoLog.error(\"Failed to copy app-data.json:\", e);\n\t// \t}\n\t// }\n\n\tprivate async copyAssetArtifacts() {\n\t\tfor (const assetArtifact of this.assetArtifacts) {\n\t\t\tconst src = path.join(this.currentRenderDir, assetArtifact);\n\t\t\tconst dst = path.join(this.bundleDir, assetArtifact);\n\t\t\ttry {\n\t\t\t\tawait fsp.mkdir(path.dirname(dst), { recursive: true });\n\t\t\t\tawait fsp.copyFile(src, dst);\n\t\t\t\tGriddoLog.verbose(`Copied artifact: ${assetArtifact}`);\n\t\t\t} catch (e) {\n\t\t\t\tGriddoLog.error(`Failed to copy artifact ${src} to ${dst}:`, e);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async copySitemaps() {\n\t\tconst renderSrc = path.resolve(this.currentRenderDir);\n\t\tconst renderDst = path.resolve(this.bundleDir);\n\n\t\t// Primero, elimina los sitemaps existentes en el destino\n\t\tconst xmlFilesInDst = findFilesBySuffix(renderDst, \".xml\");\n\t\tfor await (const xmlFile of xmlFilesInDst) {\n\t\t\tconst basename = path.basename(xmlFile);\n\t\t\tif (basename.startsWith(\"sitemap-\") || basename === \"sitemap.xml\") {\n\t\t\t\tawait fsp.rm(xmlFile, { force: true });\n\t\t\t}\n\t\t}\n\n\t\t// Segundo, copia los nuevos sitemaps desde el origen\n\t\tconst xmlFilesInSrc = findFilesBySuffix(renderSrc, \".xml\");\n\t\tfor await (const src of xmlFilesInSrc) {\n\t\t\t// Reconstruye la ruta de destino de forma m\u00E1s robusta\n\t\t\tconst relativePath = path.relative(renderSrc, src);\n\t\t\tconst dst = path.join(renderDst, relativePath);\n\n\t\t\ttry {\n\t\t\t\tawait fsp.mkdir(path.dirname(dst), { recursive: true });\n\t\t\t\tawait fsp.copyFile(src, dst);\n\t\t\t} catch (e) {\n\t\t\t\tGriddoLog.error(`Failed to copy sitemap ${src} to ${dst}:`, e);\n\t\t\t}\n\t\t}\n\n\t\tGriddoLog.verbose(`Copied sitemap files.`);\n\t}\n\n\t/**\n\t * Escanea un directorio de build de Gatsby y extrae la informaci\u00F3n esencial\n\t * (PageInfo[]) de cada p\u00E1gina.\n\t * @param dir Directorio a escanear (src o dst).\n\t * @returns Un array con la informaci\u00F3n de cada p\u00E1gina encontrada.\n\t */\n\tprivate async scanPages(dir: string): Promise<PageInfo[]> {\n\t\t// 1. Crea una instancia de p-limit con 128 lecturas a la vez...\n\t\t// Como ejemplo: macOS tiene un l\u00EDmite que suele empezar en 256.\n\t\t// De todas maneras libuv tiene un l\u00EDmite de 4 hilos en node\n\t\tconst limit = pLimit(32);\n\n\t\t// 2. Recolecta todos los paths de los archivos.\n\t\tconst gatsbyPageDataGenerator = findFilesBySuffix(\n\t\t\tpath.join(dir, \"page-data\"),\n\t\t\t\"page-data.json\",\n\t\t);\n\t\tconst processingPromises: Promise<PageInfo | null>[] = [];\n\t\tfor await (const file of gatsbyPageDataGenerator) {\n\t\t\tprocessingPromises.push(\n\t\t\t\tlimit(async (): Promise<PageInfo | null> => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst fileContent = await fsp.readFile(file, \"utf-8\");\n\t\t\t\t\t\tconst content = JSON.parse(fileContent) as GatsbyPageData;\n\n\t\t\t\t\t\tconst id = content.result.pageContext.id;\n\t\t\t\t\t\tconst composePath = content.result.pageContext.fullPath.compose;\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\tcomposePath,\n\t\t\t\t\t\t\thtmlPath: path.join(dir, composePath, \"index.html\"),\n\t\t\t\t\t\t\tjsonPath: file,\n\t\t\t\t\t\t};\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tGriddoLog.error(`Error reading or parsing page data from ${file}:`, e);\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\n\t\t// 4. Go :)\n\t\tconst pagesFoundOrNull = await Promise.all(processingPromises);\n\n\t\t// 5. Filtra los nulos y devuelve solo las p\u00E1ginas v\u00E1lidas.\n\t\treturn pagesFoundOrNull.filter((page): page is PageInfo => page !== null);\n\t}\n}\n\nexport { SyncRender };\n", "import { createHash } from \"node:crypto\";\nimport fsp from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { GriddoLog } from \"../../../core/GriddoLog\";\n\n/**\n * Patrones de archivos de assets cr\u00EDticos para la comparaci\u00F3n de builds.\n * Estos archivos son los que realmente afectan el webpackCompilationHash:\n * - app-*.js: C\u00F3digo principal de la aplicaci\u00F3n\n * - framework-*.js: Framework de Gatsby/React\n * - webpack-runtime-*.js: Runtime de webpack\n *\n * Si estos archivos no cambian entre renders, el hash deber\u00EDa ser el mismo.\n */\n// const _KEY_ASSET_PATTERNS = [/^app-.*\\.js$/, /^framework-.*\\.js$/, /^webpack-runtime-.*\\.js$/];\n\nconst KEY_ASSET_PATTERNS = [/\\.js$/];\n\n/**\n * Calcula los hashes SHA256 del contenido de los assets clave en un directorio.\n * Solo procesa archivos que coincidan con KEY_ASSET_PATTERNS.\n *\n * @param dir La ruta al directorio (ej. './public')\n * @returns Un Map donde la clave es el nombre del fichero y el valor es su hash.\n * Si el directorio no existe o hay errores, retorna un Map vac\u00EDo.\n */\nasync function getAssetHashes(dir: string): Promise<Map<string, string>> {\n\tconst assetHashes = new Map<string, string>();\n\n\ttry {\n\t\tconst allFiles = await fsp.readdir(dir);\n\t\tconst keyAssetFiles = allFiles.filter((fileName) =>\n\t\t\tKEY_ASSET_PATTERNS.some((pattern) => pattern.test(fileName)),\n\t\t);\n\n\t\tfor (const fileName of keyAssetFiles) {\n\t\t\tconst filePath = join(dir, fileName);\n\t\t\tconst fileContent = await fsp.readFile(filePath);\n\t\t\tconst hash = createHash(\"sha256\").update(fileContent).digest(\"hex\");\n\t\t\tassetHashes.set(fileName, hash);\n\t\t}\n\n\t\treturn assetHashes;\n\t} catch (error) {\n\t\tGriddoLog.build(`ERROR: Error processing directory ${dir}: ${error}`);\n\t\t// Si un directorio no existe (ej. el de producci\u00F3n la primera vez),\n\t\t// lo tratamos como si no tuviera assets.\n\t\treturn assetHashes;\n\t}\n}\n\n/**\n * Compara los assets clave entre dos directorios de build de Gatsby.\n * Solo compara los archivos definidos en KEY_ASSET_PATTERNS.\n *\n * @param dir1 Ruta al primer directorio (ej. el de producci\u00F3n)\n * @param dir2 Ruta al segundo directorio (ej. el del nuevo build)\n * @returns `true` si hay diferencias en los assets clave, `false` si son id\u00E9nticos.\n */\nexport async function getAssetsDiffBetweenRenders(dir1: string, dir2: string): Promise<boolean> {\n\tconst [hashes1, hashes2] = await Promise.all([getAssetHashes(dir1), getAssetHashes(dir2)]);\n\n\t// Si el n\u00FAmero de assets clave es diferente, hay cambios.\n\tif (hashes1.size !== hashes2.size) {\n\t\treturn true;\n\t}\n\n\t// Comparamos los hashes de cada fichero.\n\tfor (const [fileName, hash1] of hashes1.entries()) {\n\t\tconst hash2 = hashes2.get(fileName);\n\n\t\t// Si un fichero existe en el primero pero no en el segundo, hay cambios.\n\t\tif (!hash2) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Si el contenido (hash) de un fichero ha cambiado.\n\t\tif (hash1 !== hash2) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\n/**\n * Actualiza el webpackCompilationHash en un \u00FAnico fichero HTML.\n * @param filePath Ruta al fichero HTML.\n * @param newHash El nuevo hash a insertar.\n */\nexport async function patchHtmlFile(filePath: string, newHash: string): Promise<void> {\n\ttry {\n\t\tconst content = await fsp.readFile(filePath, \"utf-8\");\n\n\t\t// Esta expresi\u00F3n regular captura tres grupos:\n\t\t// 1. La parte ANTES del hash (window.___webpackCompilationHash=\")\n\t\t// 2. El hash ANTIGUO ([^\"]*)\n\t\t// 3. La parte DESPU\u00C9S del hash (\";</script>)\n\t\tconst regex = /(window\\.___webpackCompilationHash=\")([^\"]*)(\";<\\/script>)/;\n\n\t\t// Solo reemplazamos el segundo grupo (el hash)\n\t\tconst newContent = content.replace(regex, `$1${newHash}$3`);\n\n\t\tif (content === newContent) {\n\t\t\t// GriddoLog.warn(`WARN: No se encontr\u00F3 el hash en ${filePath}. El fichero no fue modificado.`);\n\t\t\treturn;\n\t\t}\n\n\t\tawait fsp.writeFile(filePath, newContent, \"utf-8\");\n\t} catch (error) {\n\t\tGriddoLog.error(`Failed to process file ${filePath}: ${error}`);\n\t}\n}\n\n// --- Ejemplo de uso ---\n// async function miScriptDeDeploy() {\n// const dirProduccion = '/ruta/a/produccion/public';\n// const dirNuevoBuild = './public';\n\n// const hayDiferencias = await getAssetsDiffBetweenRenders(dirProduccion, dirNuevoBuild);\n\n// if (hayDiferencias) {\n// // L\u00F3gica para el CAMINO A (cambio de c\u00F3digo)\n// } else {\n// // L\u00F3gica para el CAMINO B (solo contenido)\n// }\n// }\n", "import path from \"node:path\";\n\nimport { readDB } from \"../../../core/db\";\n\nexport async function getGatsbyArtifacts() {\n\tconst { ssg } = (await readDB()).paths;\n\n\treturn {\n\t\tdisposables: [\n\t\t\t//\n\t\t\tpath.join(ssg, \"public\"),\n\t\t\tpath.join(ssg, \"static\"),\n\t\t\tpath.join(ssg, \".cache\"),\n\t\t],\n\t\tcacheables: [\".cache\"],\n\t};\n}\n", "import { readDB, writeDB } from \"../../../core/db\";\nimport { GriddoLog } from \"../../../core/GriddoLog\";\n\n/**\n * Enables the rollback-on-error feature for subsequent render lifecycles.\n * When this feature is active, if an error occurs during a render process,\n * the application will automatically restore the 'exports' directory to its\n * state before the render began. This function updates the configuration\n * in the database to reflect this change.\n * @async\n */\nasync function enableRollbackOnError() {\n\tconst data = await readDB();\n\tdata.needsRollbackOnError = true;\n\tawait writeDB(data);\n\tGriddoLog.info(\"Render lifecycles that follow will restore the exports dir on error if needed\\n\");\n}\n\n/**\n * Disables the rollback-on-error feature for subsequent render lifecycles.\n * When this feature is inactive, the application will not restore the\n * 'exports' directory if a render process fails. This is the default behavior.\n * This function updates the configuration in the database.\n * @async\n */\nasync function disableRollbackOnError() {\n\tconst data = await readDB();\n\tdata.needsRollbackOnError = false;\n\tawait writeDB(data);\n\tGriddoLog.info(\"Render lifecycles that follow will not restore the exports dir on error\\n\");\n}\n\nexport { disableRollbackOnError, enableRollbackOnError };\n", "import { withErrorHandler } from \"../core/errors\";\nimport { showExporterVersion } from \"../core/print-logos\";\nimport { AuthService } from \"../services/auth\";\nimport { gatsbyRenderDomain } from \"../ssg-adapters/gatsby\";\n\nasync function render() {\n\tawait AuthService.login();\n\tconst [domain] = process.argv.slice(2);\n\tawait gatsbyRenderDomain(domain);\n}\n\nasync function main() {\n\tawait showExporterVersion();\n\tawait render();\n}\n\nwithErrorHandler(main);\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import type { ErrorsType } from \"../shared/errors\";\n\nimport path from \"node:path\";\n\nimport { brush } from \"../shared/npm-modules/brush\";\nimport { RENDER_MODE } from \"../shared/types/render\";\nimport { readDB, writeDB } from \"./db\";\nimport { distRollback } from \"./dist-rollback\";\nimport { GriddoLog } from \"./GriddoLog\";\n\nexport type ErrorData = {\n\terror: ErrorsType;\n\tmessage: string;\n\texpected?: string;\n\thint?: string;\n};\n\nexport class RenderError extends Error {\n\tconstructor(originalError?: unknown) {\n\t\tsuper(originalError instanceof Error ? originalError.message : String(originalError));\n\n\t\tthis.name = \"InternalCXError\";\n\t\tthis.stack = originalError instanceof Error ? originalError.stack : \"\";\n\t}\n}\n\n/**\n * Throws an error with the provided error message, expected value, and hint.\n */\nfunction throwError(options: ErrorData, stack?: unknown): never {\n\tconst { error, message, expected, hint } = options;\n\n\tconst errorColor = GriddoLog.log(brush.red(`[ ${error} ]`));\n\tconst extraText = [expected, hint].filter(Boolean).join(\"\\n\");\n\n\tGriddoLog.log(`\n${errorColor}\n${message}\n${extraText}\n\n${brush.red(\"stack\")}\n${JSON.stringify(stack, null, 2)}`);\n\n\tthrow new RenderError(stack);\n}\n\n/**\n * Executes the provided asynchronous function and handles errors that occur during execution.\n *\n * - If an error is thrown, attempts to log the error and, if necessary, rolls back the exports directory.\n * - Updates the render database to set the domain's rendering state to \"ERROR\" if an error occurs.\n *\n * @param fn - The asynchronous function to execute within the error handler.\n * @returns A promise that resolves when the function is executed successfully.\n * @throws RenderError | unknown - Rethrows the original error after handling and database state update.\n */\nasync function withErrorHandler(fn: () => Promise<void>) {\n\ttry {\n\t\tawait fn();\n\t} catch (error) {\n\t\tif (error instanceof RenderError) {\n\t\t\tGriddoLog.error(\"Internal Griddo RenderError\");\n\t\t} else if (error instanceof Error) {\n\t\t\tGriddoLog.error(error.message);\n\t\t} else {\n\t\t\tGriddoLog.error(`An unexpected error occurred ${error}`);\n\t\t}\n\n\t\t// Try to rollback the exports directory if needed\n\t\ttry {\n\t\t\tconst data = await readDB();\n\t\t\tconst { root } = data.paths;\n\t\t\tif (data.needsRollbackOnError) {\n\t\t\t\tGriddoLog.info(\"Cleaning exports dir...\");\n\t\t\t\tGriddoLog.verbose(`Deleting ${path.join(root, \"exports\")}...`);\n\n\t\t\t\tawait distRollback(data.currentRenderingDomain!);\n\t\t\t} else {\n\t\t\t\tGriddoLog.info(\"No rollback needed, skipping...\");\n\t\t\t}\n\t\t} catch (_e) {\n\t\t\tGriddoLog.info(\"Early render stage, no db.json created yet...\");\n\t\t}\n\n\t\tconst data = await readDB();\n\t\tdata.domains[data.currentRenderingDomain!].isRendering = false;\n\t\tdata.domains[data.currentRenderingDomain!].renderMode = RENDER_MODE.ERROR;\n\t\tawait writeDB(data);\n\t\tthrow error;\n\t}\n}\n\nexport { throwError, withErrorHandler };\n", "//\n// Brush adds color to a string|number, it does not print it!\n// Its simple, no log, no chains, just color in a string|number\n// usage:\n// console.log(brush.green(\"sucess!\"))\n//\n\nconst RESET = \"\\x1b[0m\";\nconst CODES = {\n\tblack: \"\\x1b[30m\",\n\tred: \"\\x1b[31m\",\n\tgreen: \"\\x1b[32m\",\n\tyellow: \"\\x1b[33m\",\n\tblue: \"\\x1b[34m\",\n\tmagenta: \"\\x1b[35m\",\n\tcyan: \"\\x1b[36m\",\n\twhite: \"\\x1b[37m\",\n\tgray: \"\\x1b[90m\",\n\tbold: \"\\x1b[1m\",\n\tdim: \"\\x1b[2m\",\n} as const;\n\ntype ColorFunction = (text: string | number) => string;\ntype ColorName = keyof typeof CODES;\ntype Brush = Record<ColorName, ColorFunction>;\n\nconst brush = {} as Brush;\n\nfor (const color in CODES) {\n\tconst key = color as ColorName;\n\tbrush[key] = (text: string | number) => `${CODES[key]}${text}${RESET}`;\n}\n\nexport { brush };\n", "import type { RenderInfo } from \"./global\";\n\nconst RENDER_MODE = {\n\tFROM_SCRATCH: \"FROM_SCRATCH\",\n\tINCREMENTAL: \"INCREMENTAL\",\n\tIDLE: \"IDLE\",\n\tERROR: \"ERROR\",\n\tCOMPLETED: \"COMPLETED\",\n} as const;\n\ntype RenderMode = (typeof RENDER_MODE)[keyof typeof RENDER_MODE];\n\nexport interface RenderModeTuple {\n\trenderMode: RenderMode;\n\treason?: string;\n}\n\ntype DomainLike = string;\n\ntype RenderDB = {\n\tgriddoVersion: string;\n\tbuildReportFileName: string;\n\tsortedDomains: DomainLike[];\n\tneedsRollbackOnError: boolean;\n\tcurrentRenderingDomain: string | null;\n\tcommitHash: string;\n\tcommitMessage: string;\n\tpaths: {\n\t\troot: string;\n\t\tcx: string;\n\t\tssg: string;\n\t\tcxCache: string;\n\t\tcomponents: string;\n\t\texportsDir: string;\n\t\texportsDirBackup: string;\n\t};\n\tdomains: {\n\t\t[key: DomainLike]: {\n\t\t\trenderMode?: RenderMode;\n\t\t\tshouldBeRendered?: boolean;\n\t\t\tisRendering?: boolean;\n\t\t\trenderInfo?: RenderInfo;\n\t\t\trenderModeReason?: string;\n\t\t};\n\t};\n};\n\ninterface Report {\n\tauthControl:\n\t\t| {\n\t\t\t\tAuthorization: string;\n\t\t\t\t\"Cache-Control\": string;\n\t\t\t\tlang?: string | undefined;\n\t\t }\n\t\t| undefined;\n\tsites: {\n\t\tsiteId: number;\n\t\tpublishHashes: string[];\n\t\tsiteHash: string | null;\n\t\tunpublishHashes: string[];\n\t\tpublishPagesIds: number[];\n\t}[];\n}\n\nexport { RENDER_MODE, type RenderDB, type RenderMode, type Report };\n", "import type { RenderDB } from \"../shared/types/render\";\n\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { pkgDirSync } from \"../shared/npm-modules/pkg-dir\";\nimport { GriddoLog } from \"./GriddoLog\";\n\nconst root = pkgDirSync({ cwd: path.resolve(__dirname, \"../../..\") }) || \"\";\nconst cache = path.join(root, \".griddo/cache\");\nconst dbFilePath = path.join(cache, \"db.json\");\n\nasync function readDB(customDBPath = \"\") {\n\tconst file = customDBPath || dbFilePath;\n\ttry {\n\t\treturn JSON.parse(await fsp.readFile(file, \"utf-8\")) as RenderDB;\n\t} catch (error) {\n\t\tGriddoLog.error(`Failed to read DB file at ${file}:`, error);\n\t\tthrow error;\n\t}\n}\n\nasync function writeDB(renderDB: RenderDB, customDBPath = \"\") {\n\tconst file = customDBPath || dbFilePath;\n\ttry {\n\t\tawait fsp.writeFile(file, JSON.stringify(renderDB, null, \"\\t\"));\n\t} catch (error) {\n\t\tGriddoLog.error(`Failed to write DB file at ${file}:`, error);\n\t\tthrow error;\n\t}\n}\n\nexport { readDB, writeDB };\n", "import path from \"node:path\";\n\nimport { findUp, findUpSync } from \"./find-up-simple\";\n\nasync function pkgDir(options?: { readonly cwd?: string }) {\n\tconst { cwd } = options || {};\n\tconst filePath = await findUp(\"package.json\", { cwd });\n\treturn filePath && path.dirname(filePath);\n}\n\nfunction pkgDirSync(options?: { readonly cwd?: string }) {\n\tconst { cwd } = options || {};\n\tconst filePath = findUpSync(\"package.json\", { cwd });\n\treturn filePath && path.dirname(filePath);\n}\n\nexport { pkgDir, pkgDirSync };\n", "import fs from \"node:fs\";\nimport fsPromises from \"node:fs/promises\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport { fileURLToPath } from \"node:url\";\n\n/**\n * Opciones para controlar el comportamiento de la b\u00FAsqueda.\n */\nexport type Options = {\n\t/**\n\tEl directorio desde donde empezar a buscar.\n\t@default process.cwd()\n\t*/\n\treadonly cwd?: URL | string;\n\n\t/**\n\tEl tipo de ruta a buscar.\n\t@default 'file'\n\t*/\n\treadonly type?: \"file\" | \"directory\";\n\n\t/**\n\tUn directorio en el que la b\u00FAsqueda se detiene si no se encuentran coincidencias.\n\t@default El directorio ra\u00EDz del sistema\n\t*/\n\treadonly stopAt?: URL | string;\n};\n\n// Funci\u00F3n auxiliar para convertir una URL en una ruta de archivo de tipo string.\nconst toPath = (urlOrPath: URL | string | undefined): string | undefined =>\n\turlOrPath instanceof URL ? fileURLToPath(urlOrPath) : urlOrPath;\n\n/**\n * Encuentra un archivo o directorio de forma as\u00EDncrona subiendo por los directorios padre.\n * @param name - El nombre del archivo o directorio a buscar.\n * @param options - Opciones de b\u00FAsqueda.\n * @returns La ruta encontrada o `undefined` si no se pudo encontrar.\n */\nexport async function findUp(name: string, options: Options = {}): Promise<string | undefined> {\n\tconst { cwd = process.cwd(), type = \"file\", stopAt: stopAtOption } = options;\n\n\tlet directory = path.resolve(toPath(cwd) ?? \"\");\n\tconst { root } = path.parse(directory);\n\tconst stopAt = stopAtOption ? path.resolve(directory, toPath(stopAtOption)!) : root;\n\tconst isAbsoluteName = path.isAbsolute(name);\n\n\twhile (true) {\n\t\tconst filePath = isAbsoluteName ? name : path.join(directory, name);\n\t\ttry {\n\t\t\t// eslint-disable-next-line no-await-in-loop\n\t\t\tconst stats = await fsPromises.stat(filePath);\n\t\t\tif ((type === \"file\" && stats.isFile()) || (type === \"directory\" && stats.isDirectory())) {\n\t\t\t\treturn filePath;\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignora errores (ej. el archivo no existe) y contin\u00FAa la b\u00FAsqueda.\n\t\t}\n\n\t\tif (directory === stopAt || directory === root) {\n\t\t\tbreak;\n\t\t}\n\n\t\tdirectory = path.dirname(directory);\n\t}\n}\n\n/**\n * Encuentra un archivo o directorio de forma s\u00EDncrona subiendo por los directorios padre.\n * @param name - El nombre del archivo o directorio a buscar.\n * @param options - Opciones de b\u00FAsqueda.\n * @returns La ruta encontrada o `undefined` si no se pudo encontrar.\n */\nexport function findUpSync(name: string, options: Options = {}): string | undefined {\n\tconst { cwd = process.cwd(), type = \"file\", stopAt: stopAtOption } = options;\n\n\tlet directory = path.resolve(toPath(cwd) ?? \"\");\n\tconst { root } = path.parse(directory);\n\tconst stopAt = stopAtOption ? path.resolve(directory, toPath(stopAtOption)!) : root;\n\tconst isAbsoluteName = path.isAbsolute(name);\n\n\twhile (true) {\n\t\tconst filePath = isAbsoluteName ? name : path.join(directory, name);\n\t\ttry {\n\t\t\tconst stats = fs.statSync(filePath, { throwIfNoEntry: false });\n\t\t\tif ((type === \"file\" && stats?.isFile()) || (type === \"directory\" && stats?.isDirectory())) {\n\t\t\t\treturn filePath;\n\t\t\t}\n\t\t} catch {\n\t\t\t// En teor\u00EDa, statSync con `throwIfNoEntry: false` no deber\u00EDa lanzar un error,\n\t\t\t// pero se mantiene por seguridad.\n\t\t}\n\n\t\tif (directory === stopAt || directory === root) {\n\t\t\tbreak;\n\t\t}\n\n\t\tdirectory = path.dirname(directory);\n\t}\n}\n", "const { env } = process;\n\n/**\n * Returns true/false from string\n */\nfunction envIsTruthy(value?: string): boolean {\n\tif (!value) return false;\n\n\tswitch (value.trim().toLowerCase()) {\n\t\tcase \"1\":\n\t\tcase \"true\":\n\t\tcase \"yes\":\n\t\tcase \"y\":\n\t\tcase \"on\":\n\t\t\treturn true;\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\n// Credentials\nconst GRIDDO_API_URL = env.GRIDDO_API_URL || env.API_URL;\nconst GRIDDO_PUBLIC_API_URL = env.GRIDDO_PUBLIC_API_URL || env.PUBLIC_API_URL;\nconst GRIDDO_BOT_USER = env.botEmail || env.GRIDDO_BOT_USER;\nconst GRIDDO_BOT_PASSWORD = env.botPassword || env.GRIDDO_BOT_PASSWORD;\n\n// Rendering\nconst GRIDDO_API_CONCURRENCY_COUNT = Number.parseInt(env.GRIDDO_API_CONCURRENCY_COUNT || \"10\");\nconst GRIDDO_SKIP_BUILD_CHECKS = envIsTruthy(env.GRIDDO_SKIP_BUILD_CHECKS);\nconst GRIDDO_BUILD_LOGS = envIsTruthy(env.GRIDDO_BUILD_LOGS);\nconst GRIDDO_BUILD_LOGS_BUFFER_SIZE = Number.parseInt(env.GRIDDO_BUILD_LOGS_BUFFER_SIZE || \"500\");\nconst GRIDDO_SSG_VERBOSE_LOGS = envIsTruthy(env.GRIDDO_SSG_VERBOSE_LOGS);\nconst GRIDDO_SEARCH_FEATURE = envIsTruthy(env.GRIDDO_SEARCH_FEATURE);\nconst GRIDDO_ASSET_PREFIX = env.GRIDDO_ASSET_PREFIX || env.ASSET_PREFIX;\nconst GRIDDO_REACT_APP_INSTANCE = env.GRIDDO_REACT_APP_INSTANCE || env.REACT_APP_INSTANCE;\nconst GRIDDO_AI_EMBEDDINGS = envIsTruthy(env.GRIDDO_AI_EMBEDDINGS);\nconst GRIDDO_VERBOSE_LOGS = envIsTruthy(env.GRIDDO_VERBOSE_LOGS);\nconst GRIDDO_USE_DIST_BACKUP = envIsTruthy(env.GRIDDO_USE_DIST_BACKUP);\nconst GRIDDO_SSG_BUNDLE_ANALYZER = envIsTruthy(env.GRIDDO_SSG_BUNDLE_ANALYZER);\n\nexport {\n\tGRIDDO_AI_EMBEDDINGS,\n\tGRIDDO_API_CONCURRENCY_COUNT,\n\tGRIDDO_API_URL,\n\tGRIDDO_ASSET_PREFIX,\n\tGRIDDO_BOT_PASSWORD,\n\tGRIDDO_BOT_USER,\n\tGRIDDO_BUILD_LOGS,\n\tGRIDDO_BUILD_LOGS_BUFFER_SIZE,\n\tGRIDDO_PUBLIC_API_URL,\n\tGRIDDO_REACT_APP_INSTANCE,\n\tGRIDDO_SEARCH_FEATURE,\n\tGRIDDO_SKIP_BUILD_CHECKS,\n\tGRIDDO_SSG_BUNDLE_ANALYZER,\n\tGRIDDO_SSG_VERBOSE_LOGS,\n\tGRIDDO_USE_DIST_BACKUP,\n\tGRIDDO_VERBOSE_LOGS,\n};\n", "import { GRIDDO_BUILD_LOGS, GRIDDO_VERBOSE_LOGS } from \"../shared/envs\";\nimport { brush } from \"../shared/npm-modules/brush\";\n\n/**\n * Clase est\u00E1tica para gestionar los logs de la aplicaci\u00F3n.\n * No se puede instanciar, se usa directamente: GriddoLogs.info(\"mensaje\").\n */\nclass GriddoLog {\n\t/** El constructor es privado para prevenir la instanciaci\u00F3n de la clase. */\n\tprivate constructor() {}\n\n\tpublic static verbose(...str: unknown[]): void {\n\t\tif (GRIDDO_VERBOSE_LOGS) {\n\t\t\tconsole.log(brush.yellow(\"verbose\"), brush.dim(str.join(\" \")));\n\t\t}\n\t}\n\n\tpublic static build(...str: unknown[]): void {\n\t\tif (GRIDDO_BUILD_LOGS) {\n\t\t\tGriddoLog.log(...str);\n\t\t}\n\t}\n\n\tpublic static info(...str: unknown[]): void {\n\t\tconsole.log(`${brush.blue(\"info\")} ${str.join(\" \")}`);\n\t}\n\n\tpublic static success(...str: unknown[]): void {\n\t\tconsole.log(`${brush.green(\"success\")} ${str.join(\" \")}`);\n\t}\n\n\tpublic static error(...str: unknown[]): void {\n\t\tconsole.error(`${brush.red(\"error\")} ${str.join(\" \")}`);\n\t}\n\n\tpublic static warn(...str: unknown[]): void {\n\t\tconsole.warn(`${brush.yellow(\"warn\")} ${str.join(\" \")}`);\n\t}\n\n\tpublic static log(...args: Parameters<typeof console.log>): void {\n\t\tconsole.log(...args);\n\t}\n}\n\nexport { GriddoLog };\n", "import fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { readDB } from \"./db\";\nimport { pathExists } from \"./fs\";\nimport { GriddoLog } from \"./GriddoLog\";\n\n/**\n * Rolls back the exports directory for the given domain.\n *\n * - Deletes the potentially corrupt exports directory for the domain.\n * - If a backup exists, it restores the directory from the backup location.\n * - If no backup is found, it informs that a fresh exports directory will be created on the next render.\n *\n * @param domain The domain for which to rollback the exports directory.\n */\nasync function distRollback(domain: string): Promise<void> {\n\tconst data = await readDB();\n\tconst { exportsDir, exportsDirBackup } = data.paths;\n\n\tGriddoLog.info(`Cleaning exports dir for the domain ${domain}`);\n\tGriddoLog.verbose(`Deleting ${path.join(exportsDir, domain)}...`);\n\n\t// TODO: Probar rsync en lugar de borrar y copiar\n\n\t// 1 - Borrar dist corrupto\n\tawait fsp.rm(path.join(exportsDir, domain), {\n\t\trecursive: true,\n\t\tforce: true,\n\t});\n\n\t// 2 - Si hay backup, restaurar\n\tif (await pathExists(path.join(exportsDirBackup, domain))) {\n\t\tawait fsp.cp(path.join(exportsDirBackup, domain), path.join(exportsDir, domain), {\n\t\t\trecursive: true,\n\t\t});\n\n\t\tGriddoLog.info(`export-backup dir for the domain ${domain} found. Restoring before exit...`);\n\t\tGriddoLog.verbose(\n\t\t\t`Copying ${path.join(exportsDirBackup, domain)} -> ${path.join(exportsDir, domain)}...`,\n\t\t);\n\t} else {\n\t\tGriddoLog.info(\n\t\t\t\"No export-backup found, skipping rollback. Next render will create a new exports dir from scratch...\",\n\t\t);\n\t}\n}\n\nexport { distRollback };\n", "import type { MakeDirectoryOptions } from \"node:fs\";\n\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { ArtifactError } from \"../shared/errors\";\nimport { throwError } from \"./errors\";\nimport { GriddoLog } from \"./GriddoLog\";\n\n/**\n * Remove an empty directory from the basePath recursively.\n * If the directory has only .xml files it will handle as empty too (empty site)\n *\n * @param baseDir - The base directory.\n */\nasync function deleteDisposableSiteDirs(baseDir: string) {\n\tif (!(await pathExists(baseDir))) {\n\t\treturn;\n\t}\n\n\tconst sitesDirs = (await fsp.readdir(baseDir, { withFileTypes: true })).filter((file) =>\n\t\tfile.isDirectory(),\n\t);\n\n\tfor (const siteDir of sitesDirs) {\n\t\tconst sitePath = path.join(baseDir, siteDir.name);\n\t\tif (await siteIsEmpty(sitePath)) {\n\t\t\tawait fsp.rm(sitePath, { recursive: true });\n\t\t}\n\t}\n}\n\n/**\n * Creates multiple artifact directories.\n *\n * @param dirs - An array of directory paths.\n * @param options - Same option as `fs.mkdirSync()`\n */\nasync function mkDirs(dirs: string[], options?: MakeDirectoryOptions) {\n\tfor (const dir of dirs) {\n\t\ttry {\n\t\t\tif (!(await pathExists(dir))) {\n\t\t\t\tawait fsp.mkdir(dir, { recursive: true, ...options });\n\t\t\t\tGriddoLog.verbose(`create directory: ${dir}`);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthrowError(ArtifactError, error);\n\t\t}\n\t}\n}\n\nasync function renamePath(src: string, dst: string) {\n\ttry {\n\t\tif (await pathExists(src)) {\n\t\t\tawait fsp.rename(src, dst);\n\t\t\tGriddoLog.verbose(`rename ${src} to ${dst}`);\n\t\t}\n\t} catch (error) {\n\t\tthrowError(ArtifactError, error);\n\t}\n}\n\n/**\n * Copy multiple directories with backup option.\n *\n * @param src - Source directory.\n * @param dst - Destination directory.\n * @param dirs - Directories to copy.\n * @param options.withBackup - Create a previous backup before copy.\n */\nasync function cpDirs(\n\tsrc: string,\n\tdst: string,\n\tdirs: string[],\n\toptions = {\n\t\twithBackup: false,\n\t},\n) {\n\tconst { withBackup } = options;\n\tfor (const dir of dirs) {\n\t\tconst srcCompose = path.join(src, dir);\n\t\tconst dstCompose = path.join(dst, dir);\n\n\t\t// The dir we want to copy, doesn't exist.\n\t\tif (!(await pathExists(srcCompose))) {\n\t\t\tGriddoLog.info(`(Maybe first render) Source directory does not exist: ${srcCompose}`);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Create the backup\n\t\tif (withBackup) {\n\t\t\tawait createBackup(dstCompose);\n\t\t\tGriddoLog.verbose(`create backup: ${dstCompose}`);\n\t\t}\n\n\t\t// Copy directory\n\t\ttry {\n\t\t\t// First clean destination\n\t\t\tif (await pathExists(dstCompose)) {\n\t\t\t\tawait fsp.rm(dstCompose, { recursive: true, force: true });\n\t\t\t\tGriddoLog.verbose(`clean destination: ${dstCompose}`);\n\t\t\t}\n\n\t\t\t// Then copy src to dst\n\t\t\tawait fsp.cp(srcCompose, dstCompose, {\n\t\t\t\trecursive: true,\n\t\t\t\tpreserveTimestamps: true,\n\t\t\t});\n\t\t\tGriddoLog.verbose(`copy: ${srcCompose} to ${dstCompose}`);\n\n\t\t\tif (withBackup) {\n\t\t\t\tawait deleteBackup(dstCompose);\n\t\t\t\tGriddoLog.verbose(`delete backup: ${dstCompose}`);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (withBackup) {\n\t\t\t\tawait restoreBackup(dstCompose);\n\t\t\t\tGriddoLog.verbose(\"Backup has been restored.\");\n\t\t\t}\n\n\t\t\tthrowError(ArtifactError, error);\n\t\t}\n\t}\n}\n\n/**\n * Move artifacts between cx-paths\n *\n * @param src - Source directory.\n * @param dst - Destination directory.\n * @param dirs - Directories to move.\n * @param options - Options.\n */\nasync function mvDirs(\n\tsrc: string,\n\tdst: string,\n\tdirs: string[],\n\toptions?: { withBackup?: boolean; override?: boolean },\n) {\n\tconst { override, withBackup } = options || {};\n\n\tfor (const dir of dirs) {\n\t\tconst srcCompose = path.join(src, dir);\n\t\tconst dstCompose = path.join(dst, dir);\n\n\t\tif (!(await pathExists(srcCompose))) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (withBackup) {\n\t\t\tawait createBackup(dstCompose);\n\t\t}\n\n\t\ttry {\n\t\t\t// Clean destination\n\t\t\tif (override && (await pathExists(dstCompose))) {\n\t\t\t\tawait fsp.rm(dstCompose, { recursive: true, force: true });\n\t\t\t}\n\n\t\t\tawait fsp.rename(srcCompose, dstCompose);\n\t\t\tGriddoLog.verbose(`moved: ${srcCompose} to ${dstCompose}`);\n\n\t\t\tif (withBackup) {\n\t\t\t\tawait deleteBackup(dstCompose);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (withBackup) {\n\t\t\t\tawait restoreBackup(dstCompose);\n\t\t\t\tGriddoLog.info(\"Backup has been restored.\");\n\t\t\t}\n\n\t\t\tthrowError(ArtifactError, error);\n\t\t}\n\t}\n}\n\n/**\n * Removes multiple artifact directories.\n *\n * @param dirs - An array of directory paths.\n */\nasync function rmDirs(dirs: string[]) {\n\tfor (const dir of dirs) {\n\t\ttry {\n\t\t\tawait fsp.rm(dir, { recursive: true, force: true });\n\t\t\tGriddoLog.verbose(`artifact removed: ${dir}`);\n\t\t} catch (error) {\n\t\t\tthrowError(ArtifactError, error);\n\t\t}\n\t}\n}\n\nasync function restoreBackup(src: string, suffix = \"-BACKUP\") {\n\tconst dst = src + suffix;\n\ttry {\n\t\tawait fsp.rename(dst, src);\n\t\tGriddoLog.info(`Backup ${dst} has been restored`);\n\t} catch (_error) {\n\t\tthrow new Error(`Error while delete ${dst} backup`);\n\t}\n}\n\nasync function deleteBackup(src: string, suffix = \"-BACKUP\") {\n\tconst dst = src + suffix;\n\n\tif (!(await pathExists(dst))) {\n\t\treturn;\n\t}\n\n\ttry {\n\t\tawait fsp.rm(dst, { recursive: true, force: true });\n\t\tGriddoLog.verbose(`Backup ${dst} has been deleted`);\n\t} catch (_error) {\n\t\tthrow new Error(`Error while delete ${dst} backup`);\n\t}\n}\n\nasync function createBackup(src: string, suffix = \"-BACKUP\") {\n\tconst dst = src + suffix;\n\n\tif (!(await pathExists(src))) {\n\t\treturn;\n\t}\n\n\tif (await pathExists(dst)) {\n\t\tGriddoLog.warn(`Destination ${dst} already exists`);\n\t\treturn;\n\t}\n\n\ttry {\n\t\tawait fsp.rename(src, dst);\n\t\tGriddoLog.verbose(`Backup of ${src} has been created in ${dst}`);\n\t} catch (error) {\n\t\tGriddoLog.error(`Error while coping ${src} to ${dst} backup`);\n\t\tthrowError(ArtifactError, error);\n\t}\n}\n\n/**\n * Return true if the site folder is empty or only has xml files. (Recursively)\n */\nasync function siteIsEmpty(sitePath: string) {\n\tconst siteFiles = (\n\t\tawait fsp.readdir(sitePath, {\n\t\t\twithFileTypes: true,\n\t\t\trecursive: true,\n\t\t})\n\t).filter((file) => file.isFile() && !path.basename(file.name).startsWith(\".\"));\n\n\tconst xmlFiles = siteFiles.filter((file) => file.name.endsWith(\".xml\"));\n\n\tif (siteFiles.length === xmlFiles.length) {\n\t\treturn true;\n\t}\n}\n\n/**\n * Delete empty directories from the given directory in a recursive way.\n */\nasync function deleteEmptyDirectories(dirPath: string) {\n\ttry {\n\t\tconst stats = await fsp.stat(dirPath);\n\n\t\t// Si no es un directorio, no hacemos nada\n\t\tif (!stats.isDirectory()) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet filesInDirectory: string[];\n\t\ttry {\n\t\t\tfilesInDirectory = await fsp.readdir(dirPath);\n\t\t} catch (err: any) {\n\t\t\t// Si el directorio no existe o no se puede leer (ej. permisos), lo saltamos.\n\t\t\tif (err.code === \"ENOENT\") {\n\t\t\t\tGriddoLog.warn(`The directory \"${dirPath}\" does not exist, skipping it.`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tGriddoLog.error(`Error al leer el directorio \"${dirPath}\":`, err);\n\t\t\tthrow err; // Re-lanza el error para que sea manejado por el llamador\n\t\t}\n\n\t\t// Recorrer los contenidos del directorio\n\t\tfor (const file of filesInDirectory) {\n\t\t\tconst fullPath = path.join(dirPath, file);\n\t\t\tawait deleteEmptyDirectories(fullPath); // Llamada recursiva s\u00EDncrona\n\t\t}\n\n\t\t// Despu\u00E9s de procesar todos los subdirectorios, verifica si el directorio actual est\u00E1 vac\u00EDo\n\t\tconst remainingFiles = await fsp.readdir(dirPath);\n\n\t\tif (remainingFiles.length === 0) {\n\t\t\ttry {\n\t\t\t\tawait fsp.rmdir(dirPath);\n\t\t\t\tGriddoLog.verbose(`Remove empty directory: ${dirPath}`);\n\t\t\t} catch (err: any) {\n\t\t\t\t// Puede que haya habido un problema de concurrencia o permisos\n\t\t\t\tif (err.code === \"ENOENT\") {\n\t\t\t\t\tGriddoLog.warn(\n\t\t\t\t\t\t`El directorio \"${dirPath}\" ya no existe. Posiblemente fue borrado por otra operaci\u00F3n.`,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tGriddoLog.error(`Error al borrar el directorio \"${dirPath}\":`, err);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch (err: any) {\n\t\tif (err.code === \"ENOENT\") {\n\t\t\t// El directorio ya no existe, no es un error para nosotros en este contexto\n\t\t\tGriddoLog.warn(`The directory \"${dirPath}\" does not exist or has already been processed.`);\n\t\t} else {\n\t\t\tGriddoLog.error(`General error general while processing \"${dirPath}\":`, err);\n\t\t\tthrow err;\n\t\t}\n\t}\n}\n\nasync function pathExists(dir: string) {\n\ttry {\n\t\tawait fsp.access(dir);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Busca recursivamente archivos que terminen con un sufijo espec\u00EDfico dentro de un directorio.\n * Esta funci\u00F3n es un generador as\u00EDncrono, lo que la hace muy eficiente en uso de memoria.\n *\n * @param dir El directorio base para comenzar la b\u00FAsqueda.\n * @param suffix El sufijo con el que deben terminar los nombres de archivo (ej: 'page-data.json').\n * @returns Un generador as\u00EDncrono que produce la ruta completa de cada archivo encontrado.\n * @throws Si el directorio inicial `dir` no existe o no se puede leer.\n */\nasync function* findFilesBySuffix(dir: string, suffix: string): AsyncGenerator<string> {\n\tconst dirHandle = await fsp.opendir(dir);\n\tfor await (const item of dirHandle) {\n\t\tconst fullPath = path.join(dir, item.name);\n\t\tif (item.isDirectory()) {\n\t\t\t// yield* para encadenar otro generator.\n\t\t\tyield* findFilesBySuffix(fullPath, suffix);\n\t\t} else if (item.isFile() && item.name.endsWith(suffix)) {\n\t\t\tyield fullPath;\n\t\t}\n\t}\n}\n\n/**\n * Walk a directory and returns the JSON file absolute paths with one level of depth.\n * /abs/.../sotre/331/158.json\n * /abs/.../sotre/114/443.json\n * /abs/.../sotre/131/217.json\n * /abs/.../sotre/191/281.json\n */\nasync function* walkStore(storeDir: string): AsyncGenerator<string> {\n\tconst storeDirHandle = await fsp.opendir(storeDir);\n\n\tfor await (const siteDirent of storeDirHandle) {\n\t\tif (siteDirent.isDirectory()) {\n\t\t\tconst siteDirPath = path.join(storeDir, siteDirent.name);\n\t\t\tconst siteDirHandle = await fsp.opendir(siteDirPath);\n\n\t\t\tfor await (const fileDirent of siteDirHandle) {\n\t\t\t\tconst filePath = path.join(siteDirPath, fileDirent.name);\n\n\t\t\t\tif (fileDirent.isFile() && path.extname(filePath) === \".json\") {\n\t\t\t\t\tyield filePath;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport {\n\tcpDirs,\n\tdeleteDisposableSiteDirs,\n\tdeleteEmptyDirectories,\n\tfindFilesBySuffix,\n\tmkDirs,\n\tmvDirs,\n\tpathExists,\n\trenamePath,\n\trmDirs,\n\twalkStore,\n};\n", "/**\n * Do you want to add a new error to the list?\n *\n * 1 - Add the new error type name to the `ErrorsType` union type.\n * 2 - Export a new ErrorData object (or a function that returns one) in this\n * file by completing the `error` (ErrosType) and `message` (string) properties\n * obligatorily.\n */\n\nimport type { SpawnSyncReturns } from \"node:child_process\";\nimport type { ErrorData } from \"../core/errors\";\n\ntype ErrorsType =\n\t| \"ArtifactError\"\n\t| \"BundlesInconsistencyError\"\n\t| \"CheckHealthError\"\n\t| \"ErrorInSSGBuildProcess\"\n\t| \"LifecycleExecutionError\"\n\t| \"LoginError\"\n\t| \"NoDomainsFoundError\"\n\t| \"NoJSConfigFileFound\"\n\t| \"ReadFromStoreError\"\n\t| \"ReferenceFieldSourcesNotFoundError\"\n\t| \"RenderUUIDError\"\n\t| \"UploadSearchError\"\n\t| \"WriteToStoreError\";\n\nconst ArtifactError: ErrorData = {\n\terror: \"ArtifactError\",\n\tmessage: \"There was a problem with an artifact\",\n\texpected:\n\t\t\"An external process may have has modified or deleted one of the artifacts (files and directories).\",\n\thint: \"Have there been any recent deployments? These can delete directories from the current render.\",\n};\n\nconst ErrorInSSGBuildProcess = (command: SpawnSyncReturns<string>): ErrorData => ({\n\terror: \"ErrorInSSGBuildProcess\",\n\tmessage: `Error in SSG build process: ${JSON.stringify(command)}`,\n\texpected: \"This can happen if there was a problem with the SSG build process.\",\n});\n\nconst LifecycleExecutionError = (attempts: number, name: string): ErrorData => ({\n\terror: \"LifecycleExecutionError\",\n\tmessage: `Exceeded maximum retry attempts (${attempts}) for ${name} LifeCycle`,\n});\n\nconst LoginError: ErrorData = {\n\terror: \"LoginError\",\n\tmessage: \"There was a problem logging in to the API\",\n\texpected: \"This happens if the API is currently not working or the credentials are incorrect.\",\n};\n\nconst NoDomainsFoundError: ErrorData = {\n\terror: \"NoDomainsFoundError\",\n\tmessage: \"No domains were found in this instance. The process cannot continue.\",\n\texpected:\n\t\t\"This may happen if the API is not functioning, or the site is not properly configured, or the domains are not registered.\",\n\thint: \"You can contact the instance administrator.\",\n};\n\nconst NoJSConfigFileFound: ErrorData = {\n\terror: \"NoJSConfigFileFound\",\n\tmessage: \"Could not find jsconfig.json or tsconfig.json\",\n\texpected:\n\t\t\"This can happen if the instance is not properly configured with a jsconfig.json or tsconfig.json file.\",\n};\n\nconst ReadFromStoreError: ErrorData = {\n\terror: \"ReadFromStoreError\",\n\tmessage: \"There was an error reading a file to the Store directory\",\n\thint: \"There may be an issue such as permissions preventing the file from being read.\",\n};\n\nconst ReferenceFieldSourcesNotFoundError: ErrorData = {\n\terror: \"ReferenceFieldSourcesNotFoundError\",\n\tmessage: \"The distributor has no sources defined.\",\n\texpected:\n\t\t\"It is expected to have at least one data source in the `sources` property, even if it is empty.\",\n};\n\nconst RenderUUIDError: ErrorData = {\n\terror: \"RenderUUIDError\",\n\tmessage: `Render sentinel file does not exist.\nThe rendering UUID cannot be read safely.\nThere was probably an instance deployment during the render, and files were deleted.\n\nThe files generated in this render will not be published.`,\n};\n\nconst WriteToStoreError: ErrorData = {\n\terror: \"WriteToStoreError\",\n\tmessage: \"There was an error writing a file to the Store directory\",\n\thint: \"There may be an issue such as lack of space or permissions preventing the file from being written.\",\n};\n\nconst UploadSearchError: ErrorData = {\n\terror: \"UploadSearchError\",\n\tmessage: \"There was an error uploading content to API for search\",\n\thint: \"This happens if the API is currently not working or the credentials are incorrect.\",\n};\n\nconst CheckHealthError: ErrorData = {\n\terror: \"CheckHealthError\",\n\tmessage: \"There was a problem with environment vars configuration.\",\n\texpected: \"Some of the required environment variables are not set correctly or are missing\",\n\thint: \"Are the environment variables correctly set?\",\n};\n\nexport {\n\tArtifactError,\n\tCheckHealthError,\n\tErrorInSSGBuildProcess,\n\tLifecycleExecutionError,\n\tLoginError,\n\tNoDomainsFoundError,\n\tNoJSConfigFileFound,\n\tReadFromStoreError,\n\tReferenceFieldSourcesNotFoundError,\n\tRenderUUIDError,\n\tUploadSearchError,\n\tWriteToStoreError,\n\ttype ErrorsType,\n};\n", "import fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { brush } from \"../shared/npm-modules/brush\";\nimport { GriddoLog } from \"./GriddoLog\";\n\n/**\n * Console log the Griddo exporter version.\n */\nasync function showExporterVersion() {\n\t// console.clear();\n\tconst { version } = JSON.parse(\n\t\tawait fsp.readFile(path.resolve(__dirname, \"../..\", \"package.json\"), \"utf-8\"),\n\t) as { version: string };\n\tconst logo = `\\n${brush.yellow(`Griddo Exporter ${version}`)}\n${brush.dim(`Node ${process.version.slice(1)}`)}\\n`;\n\n\tGriddoLog.log(logo);\n}\n\nexport { showExporterVersion };\n", "const GRIDDO_API_URL = process.env.GRIDDO_API_URL;\nconst GRIDDO_PUBLIC_API_URL = process.env.GRIDDO_PUBLIC_API_URL;\n\nconst AI_EMBEDDINGS = `${GRIDDO_API_URL}/ai/embeddings`;\nconst ALERT = `${GRIDDO_PUBLIC_API_URL}/alert`;\nconst DOMAINS = `${GRIDDO_API_URL}/domains`;\nconst GET_ALL = `${GRIDDO_API_URL}/sites/all`;\nconst GET_PAGE = `${GRIDDO_API_URL}/page`;\nconst LOGIN = `${GRIDDO_API_URL}/login_check`;\nconst RESET_RENDER = `${GRIDDO_API_URL}/debug/reset-render`;\nconst ROBOTS = `${GRIDDO_API_URL}/domains/robots`;\nconst SEARCH = `${GRIDDO_API_URL}/search`;\nconst SETTINGS = `${GRIDDO_API_URL}/settings`;\n\n// Site\nconst SITE_URI = `${GRIDDO_API_URL}/site/`;\nconst BUILD_END = [SITE_URI, \"/build/end\"];\nconst BUILD_START = [SITE_URI, \"/build/start\"];\nconst GET_REFERENCE_FIELD_DATA = [SITE_URI, \"/distributor\"];\nconst GET_SITEMAP = [SITE_URI, \"/sitemap\"];\nconst INFO = [SITE_URI, \"/all\"];\nconst LANGUAGES = [SITE_URI, \"/languages\"];\nconst SOCIALS = [SITE_URI, \"/socials\"];\n\nexport {\n\tAI_EMBEDDINGS,\n\tALERT,\n\tBUILD_END,\n\tBUILD_START,\n\tDOMAINS,\n\tGET_ALL,\n\tGET_PAGE,\n\tGET_REFERENCE_FIELD_DATA,\n\tGET_SITEMAP,\n\tINFO,\n\tLANGUAGES,\n\tLOGIN,\n\tRESET_RENDER,\n\tROBOTS,\n\tSEARCH,\n\tSETTINGS,\n\tSOCIALS,\n};\n", "{\n\t\"name\": \"@griddo/cx\",\n\t\"description\": \"Griddo SSG based on Gatsby\",\n\t\"version\": \"11.10.12-rc.0\",\n\t\"authors\": [\n\t\t\"Hisco <francis.vega@griddo.io>\"\n\t],\n\t\"license\": \"UNLICENSED\",\n\t\"homepage\": \"https://griddo.io\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/griddo/griddo\"\n\t},\n\t\"bin\": {\n\t\t\"griddo-render\": \"cli.mjs\"\n\t},\n\t\"exports\": {\n\t\t\".\": {\n\t\t\t\"import\": \"./build/index.js\",\n\t\t\t\"require\": \"./build/index.js\",\n\t\t\t\"types\": \"./build/index.d.ts\"\n\t\t},\n\t\t\"./react\": {\n\t\t\t\"import\": \"./build/react/index.js\",\n\t\t\t\"require\": \"./build/react/index.js\",\n\t\t\t\"types\": \"./build/react/index.d.ts\"\n\t\t}\n\t},\n\t\"scripts\": {\n\t\t\"// NPM\": \"\",\n\t\t\"prepare\": \"yarn run build\",\n\t\t\"// BUILD\": \"\",\n\t\t\"build\": \"rm -rf build && sh ./exporter/build.sh\",\n\t\t\"build:debug\": \"rm -rf build && sh ./exporter/build.sh --debug\",\n\t\t\"// TESTS\": \"\",\n\t\t\"test\": \"npm run test:compile && npm run test:create-render-fixtures && node --env-file=.env --test ./build/__tests__/* && npm run test:remove-render-fixtures\",\n\t\t\"test-exporter\": \"npm run test:compile && node --env-file=.env --test ./build/__tests__exporter__/\",\n\t\t\"test:create-render-fixtures\": \"node --env-file=.env ./build/__tests__/utils/create-fixtures\",\n\t\t\"test:remove-render-fixtures\": \"node --env-file=.env ./build/__tests__/utils/remove-fixtures\",\n\t\t\"test:compile\": \"tsgo --project tsconfig.tests.json\",\n\t\t\"// INFRA SCRIPTS\": \"\",\n\t\t\"prepare-domains-render\": \"node ./build/commands/prepare-domains-render\",\n\t\t\"start-render\": \"node ./build/commands/start-render\",\n\t\t\"end-render\": \"node ./build/commands/end-render\",\n\t\t\"upload-search-content\": \"node ./build/commands/upload-search-content\",\n\t\t\"reset-render\": \"node ./build/commands/reset-render\",\n\t\t\"// ONLY LOCAL SCRIPTS\": \"\",\n\t\t\"prepare-assets-directory\": \"node ./build/commands/prepare-assets-directory\",\n\t\t\"create-rollback-copy\": \"rm -rf ../../exports-backup && cp -r ../../exports ../../exports-backup\",\n\t\t\"render\": \"npm run build && node --env-file=.env cli.mjs render --root=../..\",\n\t\t\"// LINTER & FORMATTER\": \"\",\n\t\t\"lint\": \"biome check --write\",\n\t\t\"format\": \"biome format --write\",\n\t\t\"flint\": \"npm run lint && npm run format\",\n\t\t\"ts-lint\": \"tsgo --noEmit\",\n\t\t\"watch:ts-lint\": \"tsc --noEmit --watch\"\n\t},\n\t\"dependencies\": {\n\t\t\"gatsby\": \"5.15.0\",\n\t\t\"html-react-parser\": \"^5.2.10\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@biomejs/biome\": \"2.3.4\",\n\t\t\"@types/node\": \"20.19.4\",\n\t\t\"@typescript/native-preview\": \"latest\",\n\t\t\"cheerio\": \"1.1.2\",\n\t\t\"esbuild\": \"0.25.12\",\n\t\t\"p-limit\": \"7.2.0\",\n\t\t\"typescript\": \"5.9.3\"\n\t},\n\t\"peerDependencies\": {\n\t\t\"@griddo/core\": \"11.9.16\",\n\t\t\"react\": \">=18 <19\",\n\t\t\"react-dom\": \">=18 <19\"\n\t},\n\t\"engines\": {\n\t\t\"node\": \">=20.19\"\n\t},\n\t\"files\": [\n\t\t\"build\",\n\t\t\"exporter\",\n\t\t\"src\",\n\t\t\"gatsby-browser.tsx\",\n\t\t\"gatsby-config.ts\",\n\t\t\"gatsby-node.ts\",\n\t\t\"gatsby-ssr.tsx\",\n\t\t\"global.d.ts\",\n\t\t\"tsconfig.commands.json\",\n\t\t\"tsconfig.exporter.json\",\n\t\t\"tsconfig.json\",\n\t\t\"plugins\",\n\t\t\"cli.mjs\"\n\t],\n\t\"publishConfig\": {\n\t\t\"access\": \"public\"\n\t},\n\t\"gitHead\": \"114a2b713bcf8b762705c3d492269600d4c95509\"\n}\n", "import packageJson from \"../../package.json\";\n\nexport const DEFAULT_HEADERS = {\n\t\"x-application-id\": \"griddo-cx\",\n\t\"x-client-version\": packageJson.version,\n\t\"x-client-name\": \"CX\",\n} as const;\n", "import type { AuthHeaders } from \"../shared/types/api\";\n\nimport { throwError } from \"../core/errors\";\nimport { LOGIN } from \"../shared/endpoints\";\nimport { GRIDDO_BOT_PASSWORD, GRIDDO_BOT_USER } from \"../shared/envs\";\nimport { LoginError } from \"../shared/errors\";\nimport { DEFAULT_HEADERS } from \"../shared/headers\";\n\nclass AuthService {\n\theaders: AuthHeaders | undefined;\n\n\tasync login() {\n\t\ttry {\n\t\t\tconst response = await fetch(LOGIN, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: Object.assign({}, DEFAULT_HEADERS, {\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\tConnection: \"close\",\n\t\t\t\t}),\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tusername: GRIDDO_BOT_USER,\n\t\t\t\t\tpassword: GRIDDO_BOT_PASSWORD,\n\t\t\t\t}),\n\t\t\t});\n\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow new Error(\"Error while login in the API\");\n\t\t\t}\n\n\t\t\tconst { token } = await response.json();\n\t\t\tthis.headers = {\n\t\t\t\tAuthorization: `bearer ${token}`,\n\t\t\t\t\"Cache-Control\": \"no-store\",\n\t\t\t};\n\n\t\t\treturn this.headers;\n\t\t} catch (e) {\n\t\t\tthrowError(LoginError, e);\n\t\t}\n\t}\n}\n\nconst authService = new AuthService();\n\nexport { authService as AuthService };\n", "import type { SSG } from \"./shared/types\";\n\nimport path from \"node:path\";\n\nimport { readDB, writeDB } from \"../../core/db\";\nimport { pathExists } from \"../../core/fs\";\nimport { GriddoLog } from \"../../core/GriddoLog\";\nimport { doLifeCycle } from \"../../core/life-cycle\";\nimport { initializeLogFile } from \"../../core/logger\";\nimport {\n\tgetRenderMetadataFromDB,\n\tgetRenderModeFromDB,\n\tgetRenderPathsHydratedWithDomainFromDB,\n} from \"../../services/render\";\nimport { getRenderArtifacts } from \"../../services/render-artifacts\";\nimport { RenderContext } from \"../../shared/context\";\nimport { GRIDDO_ASSET_PREFIX, GRIDDO_BUILD_LOGS } from \"../../shared/envs\";\nimport { RENDER_MODE } from \"../../shared/types/render\";\nimport { cleanAction } from \"./actions/clean\";\nimport { closeAction } from \"./actions/close\";\nimport { dataAction } from \"./actions/data\";\nimport { healthCheckAction } from \"./actions/healthCheck\";\nimport { initAction } from \"./actions/init\";\nimport { logsAction } from \"./actions/logs\";\nimport { metaAction } from \"./actions/meta\";\nimport { prepareAction } from \"./actions/prepare\";\nimport { relocationAction } from \"./actions/relocation\";\nimport { restoreAction } from \"./actions/restore\";\nimport { ssgAction } from \"./actions/ssg\";\nimport { syncAction } from \"./actions/sync\";\nimport { getGatsbyArtifacts } from \"./shared/artifacts\";\nimport { disableRollbackOnError, enableRollbackOnError } from \"./shared/render-rollback\";\n\n/**\n * Executes a complete Gatsby render process for a given domain.\n *\n * The render process consists of multiple lifecycle steps that handle cleaning,\n * preparing, building and syncing the site. It can run in two modes:\n * - FROM_SCRATCH: Performs a complete rebuild of the domains sites.\n * - INCREMENTAL: Only rebuilds changed pages while preserving the rest.\n */\nexport async function gatsbyRenderDomain(domain: string) {\n\t// Init render log\n\tawait initializeLogFile();\n\n\t// Render data\n\tconst { renderMode, reason } = await getRenderModeFromDB(domain);\n\tconst renderMetadata = await getRenderMetadataFromDB();\n\tconst pathsHydratedWithDomain = await getRenderPathsHydratedWithDomainFromDB({ domain });\n\tconst { __ssg } = pathsHydratedWithDomain;\n\n\t// Artifacts\n\tconst renderArtifacts = await getRenderArtifacts(domain);\n\tconst ssgArtifacts = await getGatsbyArtifacts();\n\n\t// SSG Gatsby assetPrefix\n\tconst assetPrefix = GRIDDO_ASSET_PREFIX ? `${GRIDDO_ASSET_PREFIX}/${domain}` : \"\";\n\n\t// Previous render error management\n\tconst domainSentinelFile = await pathExists(path.join(__ssg, `.render-sentinel-${domain}`));\n\tconst derivedRenderMode = domainSentinelFile ? RENDER_MODE.FROM_SCRATCH : renderMode;\n\tconst derivedRenderModeReason = domainSentinelFile ? \"previous render error\" : reason;\n\n\tconst data = await readDB();\n\tdata.domains[domain].renderMode = derivedRenderMode;\n\tdata.domains[domain].renderModeReason = derivedRenderModeReason;\n\tdata.domains[domain].isRendering = false;\n\n\tif (renderMode === RENDER_MODE.IDLE && derivedRenderMode === RENDER_MODE.IDLE) {\n\t\tGriddoLog.info(\n\t\t\t`(From Current Render) [${domain}]: Skipping start-render as it is marked as IDLE with the reason ${reason}.`,\n\t\t);\n\t\treturn;\n\t}\n\n\tdata.domains[domain].isRendering = true;\n\tdata.currentRenderingDomain = domain;\n\tawait writeDB(data);\n\n\t// Render mode reason to log information to the terminal\n\tconst renderModeReason = derivedRenderModeReason ? ` <${derivedRenderModeReason}>` : \"\";\n\tGriddoLog.info(`Init render (${derivedRenderMode})${renderModeReason} for domain ${domain}\\n`);\n\n\t// Render context\n\tconst context = new RenderContext<SSG>({\n\t\tdomain,\n\t\tpathsHydratedWithDomain,\n\t\trenderArtifacts,\n\t\trenderMetadata,\n\t\trenderMode: derivedRenderMode,\n\t\tssg: { assetPrefix, ssgArtifacts },\n\t});\n\n\t// A las actions se les pasa siempre `context` y cada action ya utiliza lo que necesita.\n\t// Si una action necesita devolver algo para otra, se guarda en el context.\n\t// Ejemplo: el dataAction obtiene los ids de p\u00E1ginas para renderizar y\n\t// borrar y los guarda en context.pathsToRender y context.pathsToDelete.\n\tawait doLifeCycle(\"Init\", async () => initAction(context));\n\tawait doLifeCycle(\"Clean\", async () => cleanAction(context));\n\tawait doLifeCycle(\"Prepare\", async () => prepareAction(context));\n\tawait doLifeCycle(\"Restore\", async () => restoreAction(context));\n\n\tawait enableRollbackOnError();\n\n\tawait doLifeCycle(\"Data\", async () => dataAction(context));\n\tawait doLifeCycle(\"SSG\", async () => ssgAction(context));\n\tawait doLifeCycle(\"Relocation\", async () => relocationAction(context));\n\tawait doLifeCycle(\"Meta\", async () => metaAction(context));\n\tawait doLifeCycle(\"Sync\", async () => syncAction(context));\n\tawait doLifeCycle(\"HealthCheck\", async () => healthCheckAction(context));\n\tawait doLifeCycle(\"Logs\", async () => logsAction(context), {\n\t\tskip: !GRIDDO_BUILD_LOGS ? \"Build logs to file are disabled\" : false,\n\t});\n\tawait doLifeCycle(\"Close\", async () => closeAction(context));\n\n\tawait disableRollbackOnError();\n}\n", "import type { LifeCycleAction } from \"../shared/types/global\";\n\nimport { LifecycleExecutionError } from \"../shared/errors\";\nimport { brush } from \"../shared/npm-modules/brush\";\nimport { throwError } from \"./errors\";\nimport { GriddoLog } from \"./GriddoLog\";\n\n/**\n * Measures the execution time of a series of sync or async functions.\n *\n * @async\n * @param functions - Functions to be executed to measure their execution time.\n * @returns A promise that resolves with the total execution time in seconds.\n */\nasync function executeAndReturnExecutionTime<T>(func: () => T | Promise<T>): Promise<number> {\n\tconst start = process.hrtime.bigint();\n\tawait Promise.resolve(func());\n\tconst end = process.hrtime.bigint();\n\treturn Number((Number(end - start) / 1e9).toFixed(3));\n}\n\n/**\n * Executes a life cycle process, which involves executing a callback\n * function, printing to the console, and handling errors with optional retries.\n *\n * @async\n * @param name - The name of the life cycle.\n * @param action - A callback function to execute.\n * @param options - Optional configuration for the life cycle process.\n * @param options.maxRetrys - The maximum number of retries for the life cycle.\n * @param options.enabled - Whether the life cycle process should be executed.\n * @returns - A promise that resolves when the life cycle process is completed.\n */\nasync function doLifeCycle(\n\tname: string,\n\taction: LifeCycleAction,\n\toptions?: {\n\t\tmaxRetrys?: number;\n\t\tskip?: undefined | false | string;\n\t},\n) {\n\tconst { maxRetrys = 3, skip } = options || {};\n\n\tif (skip) {\n\t\tGriddoLog.info(`Skiping life-cycle ${name}. Reason: ${skip}\\n`);\n\t\treturn;\n\t}\n\n\tlet trysCount = 0;\n\n\twhile (trysCount < maxRetrys) {\n\t\ttry {\n\t\t\tGriddoLog.info(`start ${name} life-cycle`);\n\t\t\tconst exeTime = await executeAndReturnExecutionTime(action);\n\t\t\tGriddoLog.success(`${name} - ${exeTime}s\\n`);\n\t\t\tbreak;\n\t\t} catch (error) {\n\t\t\tconst errorString = brush.red(` Error in ${name} LifeCycle `);\n\t\t\tconst attemptsString = brush.yellow(`Attempt (${trysCount + 1})`);\n\t\t\tGriddoLog.log(`\\n${errorString} ${attemptsString}\\n`);\n\t\t\tGriddoLog.log(error);\n\t\t\tGriddoLog.log();\n\n\t\t\ttrysCount++;\n\t\t}\n\t}\n\n\tif (trysCount === maxRetrys) {\n\t\tthrowError(LifecycleExecutionError(maxRetrys, name));\n\t}\n}\n\nexport { doLifeCycle, executeAndReturnExecutionTime };\n", "import type { RenderDB } from \"../shared/types/render\";\n\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { GRIDDO_BUILD_LOGS, GRIDDO_BUILD_LOGS_BUFFER_SIZE } from \"../shared/envs\";\nimport { readDB } from \"./db\";\nimport { GriddoLog } from \"./GriddoLog\";\n\nconst logBuffer: string[] = [];\nlet logFilePath: string | null = null;\nlet flushPromise: Promise<void> | null = null;\nconst LOG_BUFFER_FLUSH_THRESHOLD = GRIDDO_BUILD_LOGS_BUFFER_SIZE;\nconst LOG_FILENAME = \"render-detail-log.txt\";\nconst LOG_TO_FILE_IS_DISABLED = !GRIDDO_BUILD_LOGS;\n\nlet dbData: RenderDB | null = null;\n\n// Universal data cache for this module...\nasync function getDBData() {\n\tif (!dbData) {\n\t\tdbData = await readDB();\n\t}\n\treturn dbData;\n}\n\nasync function initializeLogFile() {\n\tif (LOG_TO_FILE_IS_DISABLED) {\n\t\treturn;\n\t}\n\n\tconst data = await getDBData();\n\tlogFilePath = path.join(data.paths.root, LOG_FILENAME);\n\n\tawait fsp.rm(logFilePath, { force: true });\n}\n\nfunction addLogToBuffer(lineContent: string) {\n\tif (LOG_TO_FILE_IS_DISABLED) {\n\t\treturn;\n\t}\n\n\tlogBuffer.push(lineContent.toString());\n\n\tif (logBuffer.length >= LOG_BUFFER_FLUSH_THRESHOLD) {\n\t\t// Fire-and-forget flush to avoid blocking the main thread.\n\t\tflushLogsToFile().catch((error) => {\n\t\t\tGriddoLog.error(\"Background log flush failed:\", error);\n\t\t});\n\t}\n}\n\n/**\n * Vuelca el contenido del buffer de logs al archivo de logs en disco.\n * Si el buffer est\u00E1 vac\u00EDo, ya se est\u00E1 volcando, o no hay ruta de archivo, no hace nada.\n * Si ocurre un error al escribir, los logs se reinsertan al buffer para reintentar en el siguiente flush.\n */\nasync function flushLogsToFile() {\n\t// Si ya hay un volcado en curso, espera a que termine.\n\tif (flushPromise) {\n\t\tawait flushPromise;\n\t}\n\n\tif (logBuffer.length === 0 || !logFilePath) {\n\t\treturn;\n\t}\n\n\tconst performFlush = async () => {\n\t\tconst logsToFlush = [...logBuffer];\n\t\tlogBuffer.length = 0;\n\n\t\ttry {\n\t\t\tawait fsp.appendFile(logFilePath!, `${logsToFlush.join(\"\\n\")}\\n`);\n\t\t} catch (error) {\n\t\t\tlogBuffer.unshift(...logsToFlush);\n\t\t\tGriddoLog.error(\"Error flushing logs:\", error);\n\t\t\t// No relanzamos el error para no detener el \"fire-and-forget\"\n\t\t}\n\t};\n\n\tflushPromise = performFlush();\n\n\ttry {\n\t\tawait flushPromise;\n\t} finally {\n\t\tflushPromise = null;\n\t}\n}\n\n/**\n * Copia el archivo de log detallado de renderizado (\"render-detail-log.txt\")\n * desde el directorio ra\u00EDz del proyecto al directorio de logs del dominio en exports,\n * usando una marca de tiempo en el nombre de destino.\n * Si el archivo no existe, ignora el error salvo que sea distinto de ENOENT.\n *\n * @param domain - Nombre del dominio para el que se guarda el log.\n */\nasync function saveDetailRenderLog(domain: string) {\n\tawait flushLogsToFile();\n\n\tconst data = await getDBData();\n\n\tconst dateString = getFormattedDateTime();\n\tconst debugDir = path.join(data.paths.exportsDir, domain, \"logs\");\n\n\tawait fsp.mkdir(debugDir, { recursive: true });\n\n\tconst src = path.join(data.paths.root, LOG_FILENAME);\n\tconst dst = path.join(debugDir, `${dateString}-${LOG_FILENAME}`);\n\n\t// Move log to exports\n\ttry {\n\t\tawait fsp.cp(src, dst);\n\t} catch (error) {\n\t\t// It's possible the file doesn't exist if GRIDDO_BUILD_LOGS is false\n\t\t// or if no logs were ever added.\n\t\tif (error instanceof Error && \"code\" in error && error.code !== \"ENOENT\") {\n\t\t\tthrow error;\n\t\t}\n\t}\n}\n\nfunction getFormattedDateTime() {\n\tconst now = new Date();\n\tconst year = now.getFullYear();\n\tconst month = String(now.getMonth() + 1).padStart(2, \"0\");\n\tconst day = String(now.getDate()).padStart(2, \"0\");\n\n\tconst hours = String(now.getHours()).padStart(2, \"0\");\n\tconst minutes = String(now.getMinutes()).padStart(2, \"0\");\n\tconst seconds = String(now.getSeconds()).padStart(2, \"0\");\n\n\t// Formato recomendado para ordenaci\u00F3n de archivos: YYYY-MM-DD_HH-mm-ss\n\treturn `${year}-${month}-${day}_${hours}-${minutes}-${seconds}`;\n}\n\nexport { addLogToBuffer, flushLogsToFile, initializeLogFile, saveDetailRenderLog };\n", "import type { RenderModeTuple } from \"../shared/types/render\";\n\nimport { execSync } from \"node:child_process\";\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { readDB, writeDB } from \"../core/db\";\nimport { throwError } from \"../core/errors\";\nimport { pathExists } from \"../core/fs\";\nimport { GriddoLog } from \"../core/GriddoLog\";\nimport { RenderUUIDError } from \"../shared/errors\";\nimport { brush } from \"../shared/npm-modules/brush\";\nimport { RENDER_MODE } from \"../shared/types/render\";\nimport { AuthService } from \"./auth\";\nimport { getBuildMetadata } from \"./manage-store\";\n\n/**\n * Creates a sentinel file with the current date and time.\n * This file is used to track later if node_modules/@griddo/cx was cleaned by a\n * npm install coming from a deploy.\n */\nasync function markRenderAsStarted(options: { domain: string; basePath: string }) {\n\tconst { domain } = options;\n\n\tconst db = await readDB();\n\tdb.domains[domain].isRendering = true;\n\tawait writeDB(db);\n\n\t// Creamos un archivo centinela, si al terminar el render este archivo no\n\t// existe es que ha habido un deploy por medio y hay que invalidar el render\n\tconst { __ssg } = await getRenderPathsHydratedWithDomainFromDB();\n\n\tconst renderSentinelFile = path.join(__ssg, `.render-sentinel-${domain}`);\n\tawait fsp.writeFile(renderSentinelFile, new Date().toISOString());\n}\n\nasync function markRenderAsCompleted(domain: string) {\n\tconst db = await readDB();\n\tdb.domains[domain].isRendering = false;\n\tdb.currentRenderingDomain = null;\n\tdb.domains[domain].renderMode = RENDER_MODE.COMPLETED;\n\t// db.domains[domain].shouldBeRendered = false;\n\tawait writeDB(db);\n\n\t// Borramos finalmente el archivo centinela\n\tconst { __ssg } = await getRenderPathsHydratedWithDomainFromDB();\n\tconst renderSentinelFile = path.join(__ssg, `.render-sentinel-${domain}`);\n\tawait fsp.unlink(renderSentinelFile);\n}\n\nasync function assertRenderIsValid(domain: string) {\n\t// Comprobamos que .render-sentinel exista, si no es que un deploy lo borro\n\t// y hay que invalidar el render.\n\tconst { __ssg } = await getRenderPathsHydratedWithDomainFromDB();\n\tconst renderSentinelFile = path.join(__ssg, `.render-sentinel-${domain}`);\n\tif (!(await pathExists(renderSentinelFile))) {\n\t\tthrowError(RenderUUIDError);\n\t}\n}\n\n/**\n * Determines the appropriate render mode for a given domain based on its current state,\n * previous render errors, deployment status, and whether rendering is required.\n *\n * @param options - An object containing:\n * - `domain`: The domain name to resolve the render mode for.\n * - `shouldBeRendered`: A boolean indicating if the domain should be rendered.\n * @returns An object with:\n * - `renderMode`: The resolved render mode (`FROM_SCRATCH`, `INCREMENTAL`, or `IDLE`).\n * - `reason`: A string describing the reason for the chosen render mode.\n *\n * @remarks\n * The function checks for missing exports, previous render errors, new deployments,\n * and whether rendering is necessary to decide the render mode.\n *\n * @todo\n * Improve ifs and reason concatenations...\n */\nasync function resolveDomainRenderMode(options: { domain: string; shouldBeRendered: boolean }) {\n\tconst { domain, shouldBeRendered } = options;\n\n\tconst db = await readDB();\n\n\tconst { __cache, __exports } = await getRenderPathsHydratedWithDomainFromDB({ domain });\n\tconst exportsAreMissing = !(await pathExists(path.join(__exports)));\n\tconst previousRenderFailed = db.domains[domain]?.isRendering;\n\tconst newDeployDetected = await hasNewCommit(__cache);\n\n\tif (exportsAreMissing) {\n\t\treturn {\n\t\t\trenderMode: RENDER_MODE.FROM_SCRATCH,\n\t\t\treason: \"missing exports directory\",\n\t\t};\n\t}\n\n\tif (previousRenderFailed) {\n\t\treturn {\n\t\t\trenderMode: RENDER_MODE.FROM_SCRATCH,\n\t\t\treason: \"error in previous render\",\n\t\t};\n\t}\n\n\tif (newDeployDetected) {\n\t\treturn {\n\t\t\trenderMode: RENDER_MODE.FROM_SCRATCH,\n\t\t\treason: \"new commit hash\",\n\t\t};\n\t}\n\n\tif (!shouldBeRendered) {\n\t\treturn {\n\t\t\trenderMode: RENDER_MODE.IDLE,\n\t\t\treason: \"no activity\",\n\t\t};\n\t}\n\n\treturn {\n\t\trenderMode: RENDER_MODE.INCREMENTAL,\n\t\treason: \"has changes\",\n\t};\n}\n\nasync function hasNewCommit(basePath: string): Promise<boolean> {\n\tconst commitFile = path.join(basePath, \"commit\");\n\tconst currentCommit = execSync(\"git rev-parse HEAD\").toString().trim();\n\n\tif (await pathExists(commitFile)) {\n\t\tconst savedCommit = (await fsp.readFile(commitFile, \"utf-8\")).trim();\n\t\tif (savedCommit === currentCommit) {\n\t\t\treturn false; // No hay nuevo commit\n\t\t}\n\n\t\treturn true;\n\t}\n\n\treturn true;\n}\n\nasync function updateCommitFile(options: { basePath: string }) {\n\tconst { basePath } = options;\n\tconst currentCommit = execSync(\"git rev-parse HEAD\").toString().trim();\n\tawait fsp.writeFile(path.join(basePath, \"commit\"), currentCommit);\n}\n\nasync function getRenderModeFromDB(domain: string): Promise<RenderModeTuple> {\n\tconst db = await readDB();\n\n\tif (!db.domains[domain]) {\n\t\tthrow new Error(brush.red(`[!] Error: Domain ${domain} not found in DB`));\n\t}\n\n\tif (!db.domains[domain].renderMode) {\n\t\tthrow new Error(brush.red(`[!] Error: Render mode not found for domain ${domain}`));\n\t}\n\n\treturn {\n\t\trenderMode: db.domains[domain].renderMode,\n\t\treason: db.domains[domain].renderModeReason,\n\t};\n}\n\nasync function getRenderPathsHydratedWithDomainFromDB(options?: {\n\tdomain?: string;\n\tdbFilePath?: string;\n}) {\n\tconst { domain, dbFilePath } = options || {};\n\n\tconst db = await readDB(dbFilePath);\n\tconst paths = db.paths;\n\n\treturn {\n\t\t__root: paths.root,\n\t\t__cache: path.join(paths.cxCache, domain || \"\"),\n\t\t__components: paths.components,\n\t\t__cx: paths.cx,\n\t\t__sites: paths.exportsDir,\n\t\t__exports: path.join(paths.exportsDir, domain || \"\"),\n\t\t__exports_backup: path.join(paths.exportsDirBackup, domain || \"\"),\n\t\t__ssg: paths.ssg,\n\t\t__exports_dist: path.join(paths.exportsDir, domain || \"\", \"dist\"),\n\t};\n}\n\nasync function getRenderMetadataFromDB() {\n\tconst db = await readDB();\n\treturn {\n\t\tgriddoVersion: db.griddoVersion,\n\t\tbuildReportFileName: db.buildReportFileName,\n\t};\n}\n\n/**\n * Save a file with the end of build process to use as `end-render` signal.\n */\nasync function generateBuildReport(domain: string) {\n\tconst authControl = await AuthService.login();\n\n\tconst { __root } = await getRenderPathsHydratedWithDomainFromDB();\n\tconst { buildReportFileName } = await getRenderMetadataFromDB();\n\tconst { buildProcessData } = await getBuildMetadata(domain);\n\n\tconst buildSitesInfo = Object.keys(buildProcessData).map((siteID) => ({\n\t\t...buildProcessData[siteID],\n\t\tsiteId: Number.parseInt(siteID),\n\t}));\n\n\tconst report = {\n\t\tauthControl,\n\t\tsites: buildSitesInfo,\n\t};\n\n\tconst reportFilePath = path.join(__root, \"current-dist\", buildReportFileName);\n\n\tawait fsp.writeFile(reportFilePath, JSON.stringify(report));\n\n\tGriddoLog.verbose(`build report saved in ${reportFilePath}`);\n}\n\nexport {\n\tassertRenderIsValid,\n\tgenerateBuildReport,\n\tgetRenderMetadataFromDB,\n\tgetRenderModeFromDB,\n\tgetRenderPathsHydratedWithDomainFromDB,\n\tmarkRenderAsCompleted,\n\tmarkRenderAsStarted,\n\tresolveDomainRenderMode,\n\tupdateCommitFile,\n};\n", "import type { BuildMetaData } from \"../shared/types/api\";\nimport type { RenderInfo } from \"../shared/types/global\";\nimport type { GriddoPageObject } from \"../shared/types/pages\";\nimport type { Site } from \"../shared/types/sites\";\n\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { readDB, writeDB } from \"../core/db\";\nimport { throwError } from \"../core/errors\";\nimport { pathExists } from \"../core/fs\";\nimport { GriddoLog } from \"../core/GriddoLog\";\nimport { WriteToStoreError } from \"../shared/errors\";\nimport { getRenderPathsHydratedWithDomainFromDB } from \"./render\";\n\n/**\n * Get the build metadata from the Store.\n */\nasync function getBuildMetadata(domain: string): Promise<BuildMetaData> {\n\tconst db = await readDB();\n\tconst { sitesToPublish, createdPages, buildProcessData } = db.domains[domain].renderInfo || {};\n\n\tif (!sitesToPublish || !createdPages || !buildProcessData) {\n\t\tthrow new Error(\"Build metadata not found\");\n\t}\n\n\treturn {\n\t\tbuildProcessData,\n\t\tcreatedPages,\n\t\tsitesToPublish,\n\t};\n}\n\n/**\n * Write render info into a file.\n * @param renderInfo - Data that will be saved related to the render process.\n */\nasync function saveRenderInfoInStore(renderInfo: RenderInfo, domain: string) {\n\tconst db = await readDB();\n\tdb.domains[domain] = db.domains[domain] || {};\n\tdb.domains[domain].renderInfo = renderInfo;\n\tawait writeDB(db);\n}\n\n/**\n * Return an array of paths only from `.json` files (no dirs) in the `basePath` dir based in the file name.\n * @param basePath - Absolute path of the dir from which files will be read.\n * @returns A number[] of pages ids in `basePath` dir.\n */\nasync function getPageInStoreDir(basePath: string) {\n\tconst filesInStore = await fsp.readdir(basePath);\n\n\treturn filesInStore\n\t\t.filter(async (file) => {\n\t\t\tconst fullPathFile = `${basePath}/${file}`;\n\t\t\tconst stat = await fsp.stat(fullPathFile);\n\t\t\t// Si es un directorio, no lo incluimos.\n\t\t\tif (stat?.isDirectory()) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Si es un archivo pero no tiene la extensi\u00F3n `.json`, no lo incluimos\n\t\t\tif (path.extname(file) !== \".json\") {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// no es dir, es json.\n\t\t\treturn true;\n\t\t})\n\t\t.map((page) => {\n\t\t\treturn path.join(basePath, page);\n\t\t});\n}\n\n/**\n * Save the pages into the file system.\n * @param pages - An array of Griddo page objects to be saved.\n */\nasync function saveSitePagesInStore(siteDirName: string, pages: GriddoPageObject[]) {\n\tconst { __root } = await getRenderPathsHydratedWithDomainFromDB();\n\n\ttry {\n\t\tconst propsToRemove = new Set([\"editorID\", \"parentEditorID\"]);\n\t\tfor (const page of pages) {\n\t\t\tremoveProperties(page, propsToRemove);\n\t\t\tconst filename = `${page.context.page.id}.json`;\n\t\t\tconst filePath = path.join(__root, \"store\", siteDirName, filename);\n\t\t\t// En los listados est\u00E1ticos y multipage los ids de las p\u00E1ginas son iguales\n\t\t\tawait writeUniqueFileSync(filePath, JSON.stringify(page));\n\t\t}\n\t} catch (error) {\n\t\tthrowError(WriteToStoreError, error);\n\t}\n}\n\n/**\n * Removes sites that exist in the store that should no longer be there because\n * the domain has been changed. This is necessary because those sites will not\n * be marked as `sitesToUnpublish` so they must be removed manually.\n */\nasync function removeOrphanSites(sitesToPublish: Site[], domain: string) {\n\tconst { __root } = await getRenderPathsHydratedWithDomainFromDB({ domain });\n\tconst storePath = path.join(__root, \"store\");\n\n\tif (!(await pathExists(storePath))) {\n\t\treturn;\n\t}\n\n\tconst currentSitesInStore = await fsp.readdir(storePath);\n\tconst sitesFromAPI = sitesToPublish.map(({ id }) => `${id}`);\n\tconst sitesToDelete = currentSitesInStore.filter((site) => !sitesFromAPI.includes(site));\n\n\tfor (const site of sitesToDelete) {\n\t\tawait fsp.rm(path.join(storePath, site), { recursive: true, force: true });\n\t\tGriddoLog.verbose(`Removed orphan site id: ${site}`);\n\t}\n}\n\nasync function writeUniqueFileSync(filePath: string, content: string) {\n\tconst dir = path.dirname(filePath);\n\tconst ext = path.extname(filePath);\n\tconst base = path.basename(filePath, ext);\n\n\tlet uniquePath = filePath;\n\tlet counter = 1;\n\n\twhile (await pathExists(uniquePath)) {\n\t\tconst newName = `${base}-${counter}${ext}`;\n\t\tuniquePath = path.join(dir, newName);\n\t\tcounter++;\n\t}\n\n\tawait fsp.writeFile(uniquePath, content);\n}\n\n/**\n * Remove props from an object\n *\n * @param obj The object\n * @param props An array of props to be removed\n */\nfunction removeProperties(obj: Record<string, unknown>, propsToRemove: Set<string>) {\n\tfunction remove(currentObj: Record<string, unknown>) {\n\t\tif (!currentObj || typeof currentObj !== \"object\" || Array.isArray(currentObj)) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor (const key in currentObj) {\n\t\t\tif (Object.hasOwn(currentObj, key)) {\n\t\t\t\tif (propsToRemove.has(key)) {\n\t\t\t\t\t// B\u00FAsqueda O(1) en lugar de O(n)\n\t\t\t\t\tdelete currentObj[key];\n\t\t\t\t} else {\n\t\t\t\t\tconst value = currentObj[key];\n\t\t\t\t\tif (typeof value === \"object\" && value !== null && !Array.isArray(value)) {\n\t\t\t\t\t\tremove(value as Record<string, unknown>);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tremove(obj);\n}\n\nexport {\n\tgetBuildMetadata,\n\tgetPageInStoreDir,\n\tremoveOrphanSites,\n\tsaveRenderInfoInStore,\n\tsaveSitePagesInStore,\n\twriteUniqueFileSync,\n};\n", "import type { RenderArtifacts } from \"../shared/types/global\";\n\nimport path from \"node:path\";\n\nimport { getRenderPathsHydratedWithDomainFromDB } from \"./render\";\n\n/**\n * Returns the artifacts of CX.\n */\nasync function getRenderArtifacts(domain: string): Promise<RenderArtifacts> {\n\tconst { __exports, __cache, __root, __ssg } = await getRenderPathsHydratedWithDomainFromDB({\n\t\tdomain,\n\t});\n\n\treturn {\n\t\tinitials: [\n\t\t\t__exports, // `<root>/exports/<domain>`\n\t\t\t__cache, // `<root>/.griddo/<domain>`\n\t\t\tpath.join(__exports, \"logs\"),\n\t\t\tpath.join(__root, \"store\"),\n\t\t\tpath.join(__root, \"apiCache\"),\n\t\t],\n\t\tdisposables: [\n\t\t\tpath.join(__root, \"store\"),\n\t\t\tpath.join(__root, \"apiCache\"),\n\t\t\tpath.join(__root, \"dist\"),\n\t\t\tpath.join(__root, \"dist-restored\"),\n\t\t\tpath.join(__root, \"assets\"),\n\t\t\tpath.join(__root, \"render-detail-log.txt\"),\n\t\t\tpath.join(__root, \"current-dist\"),\n\t\t\tpath.join(__ssg, \"domains.json\"),\n\t\t\tpath.join(__ssg, \"render-metadata.json\"),\n\t\t],\n\t\tcacheables: [],\n\t\tarchivables: [\n\t\t\t// dist ya se usa directamente en exports\n\t\t\t// \"dist\",\n\t\t\t\"assets\",\n\t\t],\n\t\trestaurable: [\"dist\"],\n\t};\n}\n\nexport { getRenderArtifacts };\n", "import type { PlaceholderPath, RenderArtifacts } from \"./types/global\";\nimport type { RenderMode } from \"./types/render\";\n\ninterface RenderContextProps<T> {\n\tdomain: string;\n\trenderMode: RenderMode;\n\tpathsHydratedWithDomain: Record<PlaceholderPath, string>;\n\tssg: T;\n\trenderMetadata: {\n\t\tgriddoVersion: string;\n\t\tbuildReportFileName: string;\n\t};\n\trenderArtifacts: RenderArtifacts;\n}\n\n/**\n * Encapsulates the state, configuration, and artifacts for a single SSG\n * render process.\n *\n * This class is instantiated at the beginning of a render and passed through\n * each lifecycle step, providing a centralized and consistent context for all\n * operations. It is agnostic to the specific SSG being used.\n */\nexport class RenderContext<T = unknown> {\n\treadonly domain: string;\n\treadonly renderMode: RenderMode;\n\treadonly pathsHydratedWithDomain: Record<PlaceholderPath, string>;\n\tpagesToCreate: number[] = [];\n\tpagesToDelete: number[] = [];\n\tssg: T;\n\trenderMetadata: { griddoVersion: string; buildReportFileName: string };\n\trenderArtifacts: RenderArtifacts;\n\n\tconstructor({\n\t\tdomain,\n\t\trenderMode,\n\t\tssg,\n\t\tpathsHydratedWithDomain,\n\t\trenderMetadata,\n\t\trenderArtifacts,\n\t}: RenderContextProps<T>) {\n\t\tthis.domain = domain;\n\t\tthis.renderMode = renderMode;\n\t\tthis.pathsHydratedWithDomain = pathsHydratedWithDomain;\n\t\tthis.renderMetadata = renderMetadata;\n\t\tthis.renderArtifacts = renderArtifacts;\n\t\tthis.ssg = ssg;\n\t}\n}\n", "import type { RenderContext } from \"../../../shared/context\";\nimport type { SSG } from \"../shared/types\";\n\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { rmDirs } from \"../../../core/fs\";\nimport { RENDER_MODE } from \"../../../shared/types/render\";\n\nexport async function cleanAction(context: RenderContext<SSG>) {\n\tconst {\n\t\trenderArtifacts,\n\t\tssg: { ssgArtifacts },\n\t\tpathsHydratedWithDomain: { __cache, __exports },\n\t\trenderMode,\n\t} = context;\n\n\tif (renderMode === RENDER_MODE.FROM_SCRATCH) {\n\t\tawait fsp.rm(path.join(__cache, \".cache\"), { recursive: true, force: true });\n\t\tawait fsp.rm(path.join(__exports, \"dist\"), { recursive: true, force: true });\n\t\tawait fsp.rm(path.join(__exports, \"assets\"), { recursive: true, force: true });\n\t}\n\n\tawait rmDirs(renderArtifacts.disposables);\n\tawait rmDirs(ssgArtifacts.disposables);\n}\n", "import type { RenderContext } from \"../../../shared/context\";\nimport type { SSG } from \"../shared/types\";\n\nimport { rmDirs } from \"../../../core/fs\";\nimport { updateCommitFile } from \"../../../services/render\";\n\nexport async function closeAction(context: RenderContext<SSG>) {\n\tconst {\n\t\trenderArtifacts,\n\t\tssg: { ssgArtifacts },\n\t\tpathsHydratedWithDomain: { __cache },\n\t} = context;\n\n\tawait rmDirs(renderArtifacts.disposables);\n\tawait rmDirs(ssgArtifacts.disposables);\n\tawait updateCommitFile({ basePath: __cache });\n}\n", "import type { BuildProcessData, Settings } from \"../shared/types/global\";\nimport type {\n\tGriddoListPage,\n\tGriddoMultiPage,\n\tGriddoPageObject,\n\tGriddoSinglePage,\n\tPageAdditionalInfo,\n} from \"../shared/types/pages\";\nimport type { HashSites, Site, SiteHash } from \"../shared/types/sites\";\n\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport pLimit from \"p-limit\";\n\nimport { GriddoLog } from \"../core/GriddoLog\";\nimport { SETTINGS } from \"../shared/endpoints\";\nimport {\n\tGRIDDO_API_CONCURRENCY_COUNT,\n\tGRIDDO_API_URL,\n\tGRIDDO_PUBLIC_API_URL,\n\tGRIDDO_REACT_APP_INSTANCE,\n} from \"../shared/envs\";\nimport { brush } from \"../shared/npm-modules/brush\";\nimport { RENDER_MODE, type RenderMode } from \"../shared/types/render\";\nimport { get } from \"./api\";\nimport { getSiteData, getSitesToRender, unpublishSites } from \"./manage-sites\";\nimport { removeOrphanSites, saveRenderInfoInStore, saveSitePagesInStore } from \"./manage-store\";\nimport { NavigationService } from \"./navigation\";\nimport {\n\tcreateGriddoListPages,\n\tcreateGriddoMultiPages,\n\tcreateGriddoSinglePage,\n\tgetMultiPageElements,\n\tgetPaginatedPages,\n} from \"./pages\";\nimport { getReferenceFieldData } from \"./reference-fields\";\nimport { getRenderPathsHydratedWithDomainFromDB } from \"./render\";\nimport { getPage } from \"./sites\";\n\nconst renderId = Date.now().toString();\n\nfunction guessSiteNeedsToBeRenderedFromScratch() {\n\treturn false;\n}\n\nfunction listSitesLog(title: string, sites: Site[]) {\n\tconst maxline = Math.max(\n\t\t...sites.map((s) => s.name.length + (s.shouldBeUpdated ? 1 : 0) + s.id.toString().length),\n\t);\n\n\tconst sitesStr = sites.map((s) => {\n\t\tconst shouldBeUpdated = s.shouldBeUpdated ? \"*\" : \"\";\n\t\tconst lineLen = s.name.length + shouldBeUpdated.length + s.id.toString().length;\n\t\tconst padding = \" \".repeat(maxline - lineLen);\n\t\treturn `${brush.bold(s.name)} ${brush.dim(`(${s.id})`)} ${shouldBeUpdated} ${padding}${brush.dim(\"-\")} ${brush.dim(s.slug)}`;\n\t});\n\n\tconst sitesOutput = sitesStr.length > 0 ? `\\n\\n${sitesStr.join(\"\\n\")}` : brush.dim(\"--none--\\n\");\n\n\tGriddoLog.log(`\n${title} ${sitesOutput}`);\n}\n\n/**\n * Fetch, process and save object pages and sites data into the file system to\n * be consumed by other services (Griddo itself, Adapters, etc.)\n */\nasync function createStore(options: {\n\tdomain: string;\n\trenderMode: RenderMode;\n\tgriddoVersion: string;\n\tbasePath: string;\n}) {\n\tconsole.info(`API calls with ${GRIDDO_API_CONCURRENCY_COUNT} threads`);\n\tconsole.info(`API URL ${GRIDDO_API_URL as string}`);\n\n\tconst { renderMode, domain, griddoVersion, basePath } = options;\n\tconst renderFromScratch = renderMode === RENDER_MODE.FROM_SCRATCH;\n\tconst storeDir = path.join(basePath, \"store\");\n\n\t// Vars to save later in the report file\n\tconst createdPages: number[] = [];\n\tconst buildProcessData: BuildProcessData = {};\n\n\t// Get sites objects to publish and unpublish from this domain\n\tconst { sitesToPublish, sitesToUnpublish } = await getSitesToRender(domain);\n\n\tlistSitesLog(\"Sites to publish:\", sitesToPublish);\n\tlistSitesLog(\"Sites to unpublish:\", sitesToUnpublish);\n\n\t// Send unpublished sites to API.\n\tawait unpublishSites(sitesToUnpublish);\n\n\t// Eliminamos posibles sites que est\u00E9n en el store pero que no deber\u00EDan\n\t// porque han sido cambiados de dominio. Si han sido despublicados ya se\n\t// despublican bien porque entran en `sitesToUnpublish`\n\tawait removeOrphanSites(sitesToPublish, domain);\n\n\tconst allPagesToRemoveFromBuild: number[] = [];\n\t// let numberOfFinalActivePages: number[] = [];\n\n\tfor (const site of sitesToUnpublish) {\n\t\tconst { pagesStatus } = site;\n\n\t\t// A\u00F1adimos a allPagesToRemoveFromBuild todas las p\u00E1ginas de un site\n\t\t// para despublicar.\n\t\tallPagesToRemoveFromBuild.push(\n\t\t\t...pagesStatus.active,\n\t\t\t...pagesStatus.offlinePending,\n\t\t\t...pagesStatus.uploadPending,\n\t\t\t...pagesStatus.deleted,\n\t\t\t...pagesStatus.offline,\n\t\t);\n\t}\n\n\tfor (const site of sitesToPublish) {\n\t\tconst { id: siteId, slug: siteSlug, theme, favicon, pagesStatus } = site;\n\t\tconst siteDirName = siteId.toString();\n\n\t\tallPagesToRemoveFromBuild.push(...pagesStatus.offlinePending, ...pagesStatus.deleted);\n\n\t\tconst {\n\t\t\tsiteInfo,\n\t\t\tsiteHash,\n\t\t\tunpublishHashes,\n\t\t\tsiteLangs,\n\t\t\tdefaultLang,\n\t\t\theaders,\n\t\t\tfooters,\n\t\t\tsocials,\n\t\t} = await getSiteData(siteId);\n\n\t\tconst {\n\t\t\tcloudinaryName,\n\t\t\tuseMetaTitle,\n\t\t\tuseMetaKeywords,\n\t\t\tshowBasicMetaRobots,\n\t\t\tavoidHrefLangsOnCanonicals,\n\t\t\tavoidSelfReferenceCanonicals,\n\t\t\tavoidHrefLangXDefault,\n\t\t\tavoidDebugMetas,\n\t\t} = await get<Settings>({ endpoint: SETTINGS });\n\n\t\tbuildProcessData[siteId] = {\n\t\t\tsiteHash,\n\t\t\tunpublishHashes,\n\t\t\tpublishHashes: [],\n\t\t\tpublishPagesIds: [],\n\t\t};\n\n\t\tconst NavService = new NavigationService();\n\t\tNavService.navigations = { headers, footers };\n\n\t\tsite.languages = siteLangs;\n\n\t\tconst shouldUpdateSite = await updatedSiteHash(siteId, siteHash);\n\n\t\tconst siteScript = siteInfo.siteScript;\n\n\t\tconst siteMetadata = {\n\t\t\tsiteUrl: siteInfo.slug,\n\t\t\ttitle: siteInfo.name,\n\t\t\tfavicon,\n\t\t};\n\n\t\tconst additionalInfo = {\n\t\t\tbaseUrl: GRIDDO_API_URL,\n\t\t\tpublicBaseUrl: GRIDDO_PUBLIC_API_URL,\n\t\t\tinstance: GRIDDO_REACT_APP_INSTANCE,\n\t\t\tsiteSlug,\n\t\t\ttheme,\n\t\t\tsiteMetadata,\n\t\t\tsocials,\n\t\t\tsiteLangs,\n\t\t\tcloudinaryName,\n\t\t\tgriddoVersion,\n\t\t\tsiteOptions: {\n\t\t\t\tuseMetaTitle,\n\t\t\t\tuseMetaKeywords,\n\t\t\t\tshowBasicMetaRobots,\n\t\t\t\tavoidHrefLangsOnCanonicals,\n\t\t\t\tavoidSelfReferenceCanonicals,\n\t\t\t\tavoidHrefLangXDefault,\n\t\t\t\tavoidDebugMetas,\n\t\t\t},\n\t\t\tsiteScript,\n\t\t};\n\n\t\tGriddoLog.info(`Getting pages from ${site.name} site`);\n\n\t\t/// Creates the store directory for each site using the id\n\t\tawait fsp.mkdir(path.join(storeDir, siteDirName), {\n\t\t\trecursive: true,\n\t\t});\n\n\t\t// -------------------------------------------------------------------------\n\t\t// Pages loop promise creation\n\t\t// -------------------------------------------------------------------------\n\t\t// Async function that process every page for one site to use later in the\n\t\t// `Promise.all` with pLimit.\n\t\tconst fetchSitePageAndSaveInStore = async (siteIdName: string, pageId: number) => {\n\t\t\t// Here will be store every page returned by the API and processed\n\t\t\tlet griddoPageObjects: GriddoPageObject[] = [];\n\n\t\t\t// Get page data\n\t\t\tconst page = await getPage(pageId, shouldUpdateSite);\n\n\t\t\t// Probably a 404\n\t\t\tif (!page) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Update Array of page ids\n\t\t\tcreatedPages.push(pageId);\n\n\t\t\t// TODO: Use structuredClone() when node 18 is available.\n\t\t\t// SHAME: This new pageAdditionalInfo needs to be a copy because\n\t\t\t// additionalInfo referenced from outside this function and\n\t\t\t// its used by other pages.\n\t\t\tconst pageAdditionalInfo = JSON.parse(JSON.stringify(additionalInfo)) as PageAdditionalInfo;\n\n\t\t\t// Updated with navigations (header & footer)\n\t\t\tpageAdditionalInfo.navigations = NavService.getPageNavigations(page);\n\n\t\t\t// Content Type Data Query.\n\t\t\t// Where the pair `hasDistributorData:true` /\n\t\t\t// `getStaticData:true` and `data` prop exists, this function\n\t\t\t// will attach a `queriedItems` prop with the result of the\n\t\t\t// fetch for the data.\n\t\t\tconst template = await getReferenceFieldData({\n\t\t\t\tpage,\n\t\t\t\tcacheKey: renderId,\n\t\t\t});\n\n\t\t\t// MultiPage Query\n\t\t\t// Where the pair `hasGriddoMultiPage:true` prop exists, this function\n\t\t\t// will process the schema and return a multiPageElemtens array to use\n\t\t\t// in `createGriddoMultiPages()`\n\t\t\tconst multiPageElements = await getMultiPageElements(template);\n\n\t\t\t// -----------------------------------------------------------------------\n\t\t\t// Build Griddo page objects.\n\t\t\t// -----------------------------------------------------------------------\n\t\t\t// A page from the API could be one of those:\n\t\t\t// - List with pagination (static list template): needs to be splitted in n pages\n\t\t\t// - Multi-page module: needs to be splitted in n pages\n\t\t\t// - Single: just one page\n\n\t\t\t// Griddo page types\n\t\t\tconst isStaticListPage = page?.mode === \"list\" || page?.mode === \"paginated-data\";\n\t\t\tconst isMultiPage = !isStaticListPage && multiPageElements;\n\t\t\tconst isSinglePage = !isMultiPage && !isStaticListPage;\n\n\t\t\t// >> List (static list template) <<\n\t\t\tif (isStaticListPage) {\n\t\t\t\tconst griddoListPage = {\n\t\t\t\t\tpage: page,\n\t\t\t\t\tpages: getPaginatedPages(template),\n\t\t\t\t\tisRoot: false,\n\t\t\t\t\tdefaultLang: defaultLang,\n\t\t\t\t\ttemplate: template,\n\t\t\t\t\ttotalQueriedItems: template.queriedItems,\n\t\t\t\t} as GriddoListPage;\n\n\t\t\t\t// pageObjects = await createGriddoListPages({ adapter: \"Gatsby\" })\n\t\t\t\tgriddoPageObjects = await createGriddoListPages(griddoListPage, pageAdditionalInfo);\n\n\t\t\t\t// \u00BFPor qu\u00E9 la a\u00F1adimos a las p\u00E1ginas para borrar?\n\t\t\t\t// Porque este tipo de p\u00E1ginas no est\u00E1 manejada por API y se crean varias p\u00E1ginas con el mismo ID.\n\t\t\t\t// Esto hace que no se pueda rastrear bien el render.\n\t\t\t\tallPagesToRemoveFromBuild.push(page.id);\n\t\t\t}\n\n\t\t\t// >> Multi-page <<\n\t\t\tif (isMultiPage) {\n\t\t\t\tconst griddoMultipage = page as GriddoMultiPage;\n\n\t\t\t\t// The `template` key with the (maybe) data (ReferenceField) items queried\n\t\t\t\tgriddoMultipage.template = template;\n\t\t\t\tgriddoMultipage.multiPageElements = multiPageElements;\n\t\t\t\tgriddoMultipage.defaultLang = defaultLang;\n\n\t\t\t\tgriddoPageObjects = await createGriddoMultiPages(griddoMultipage, pageAdditionalInfo);\n\n\t\t\t\t// \u00BFPor qu\u00E9 la a\u00F1adimos a las p\u00E1ginas para borrar?\n\t\t\t\t// Porque este tipo de p\u00E1ginas no est\u00E1 manejada por API y se crean varias p\u00E1ginas con el mismo ID.\n\t\t\t\t// Esto hace que no se pueda rastrear bien el render.\n\t\t\t\tallPagesToRemoveFromBuild.push(page.id);\n\t\t\t}\n\n\t\t\t// >> Single template <<\n\t\t\tif (isSinglePage) {\n\t\t\t\tconst griddoSinglePage = page as GriddoSinglePage;\n\n\t\t\t\t// The `template` key with the (maybe) data (ReferenceField) items queried\n\t\t\t\tgriddoSinglePage.template = template;\n\t\t\t\tgriddoSinglePage.defaultLang = defaultLang;\n\n\t\t\t\tgriddoPageObjects = [await createGriddoSinglePage(griddoSinglePage, pageAdditionalInfo)];\n\t\t\t}\n\n\t\t\t// Upload only the valid pages hashes or ids of pages that has\n\t\t\t// been changed or created.\n\t\t\tif (page.hash !== null) {\n\t\t\t\tbuildProcessData[siteId].publishHashes.push(page.hash);\n\t\t\t\tbuildProcessData[siteId].publishPagesIds.push(page.id);\n\t\t\t}\n\n\t\t\t// Save build data to store\n\t\t\tawait saveSitePagesInStore(siteIdName, griddoPageObjects);\n\t\t};\n\n\t\t// Pages that needs to be fetched from the API and written to the store.\n\t\tconst pagesToFetchFromAPI = pagesStatus.uploadPending;\n\n\t\t// Esto es necesario porque en la BBDD las p\u00E1ginas pueden estar\n\t\t// marcadas como activas (online) pero si es una m\u00E1quina nueva hace\n\t\t// falta hacerlas de nuevo...\n\t\t// const sitePendingOfPublishing = site.isPublished && site.shouldBeUpdated;\n\t\tconst sitePendingOfPublishing = guessSiteNeedsToBeRenderedFromScratch();\n\t\t// @todo: necesito tener un sistema par publicar todo de un site (cuando un site est\u00E9 pending to publish)\n\t\t// algo como site.status = pending | published | unpublished...\n\t\tif (renderFromScratch || sitePendingOfPublishing) {\n\t\t\tpagesToFetchFromAPI.push(...pagesStatus.active);\n\t\t}\n\n\t\t// Create pages to the store. First requesting from API,\n\t\t// transform, etc., and then writing them to disk.\n\t\tconst limit = pLimit(GRIDDO_API_CONCURRENCY_COUNT);\n\t\tconst pagesToStore = pagesToFetchFromAPI.map((id: number) =>\n\t\t\tlimit(() => fetchSitePageAndSaveInStore(siteDirName, id)),\n\t\t);\n\n\t\tawait Promise.all(pagesToStore);\n\t}\n\n\t// Despu\u00E9s de guardar en el store todos los sites y sus p\u00E1ginas (las que\n\t// sean que hayan cambiado etc.) guardamos un archivo con la informaci\u00F3n del\n\t// render para usos posteriores.\n\t// Render de dominios con sites para publicar o despublicar. Se guarda la\n\t// infor del render normalmente.\n\tawait saveRenderInfoInStore({ buildProcessData, createdPages, sitesToPublish }, domain);\n\n\treturn {\n\t\tpagesToCreate: createdPages,\n\t\tpagesToDelete: allPagesToRemoveFromBuild,\n\t};\n}\n\n/**\n * Get site hashes from the file as an object\n */\nasync function getHashSites(): Promise<HashSites> {\n\tconst { __root } = await getRenderPathsHydratedWithDomainFromDB();\n\tconst apiCacheDir = path.join(__root, \"apiCache\");\n\tconst siteHasFilename = `${apiCacheDir}/siteHash.json`;\n\n\ttry {\n\t\tconst fileContent = await fsp.readFile(siteHasFilename, \"utf8\");\n\t\tconst jsonData = JSON.parse(fileContent);\n\t\treturn jsonData || {};\n\t} catch {\n\t\treturn {};\n\t}\n}\n\n/**\n * Update (write) the site hash file.\n *\n * @param siteId The id of the site.\n * @param siteHash The has of the site.\n */\nasync function updatedSiteHash(siteId: number, siteHash: SiteHash) {\n\tconst allHash = await getHashSites();\n\tconst lastHash = allHash[siteId];\n\tconst currentHash = siteHash || lastHash || Date.now();\n\n\tconst { __root } = await getRenderPathsHydratedWithDomainFromDB();\n\tconst apiCacheDir = path.join(__root, \"apiCache\");\n\tconst siteHasFilename = `${apiCacheDir}/siteHash.json`;\n\n\tif (currentHash !== lastHash) {\n\t\tallHash[siteId] = currentHash;\n\t\tawait fsp.writeFile(siteHasFilename, JSON.stringify(allHash), {\n\t\t\tencoding: \"utf-8\",\n\t\t});\n\t}\n\n\treturn currentHash.toString();\n}\n\nexport { createStore };\n", "/*\nHow it works:\n`this.#head` is an instance of `Node` which keeps track of its current value and nests another instance of `Node` that keeps the value that comes after it. When a value is provided to `.enqueue()`, the code needs to iterate through `this.#head`, going deeper and deeper to find the last value. However, iterating through every single item is slow. This problem is solved by saving a reference to the last value as `this.#tail` so that it can reference it to add a new value.\n*/\n\nclass Node {\n\tvalue;\n\tnext;\n\n\tconstructor(value) {\n\t\tthis.value = value;\n\t}\n}\n\nexport default class Queue {\n\t#head;\n\t#tail;\n\t#size;\n\n\tconstructor() {\n\t\tthis.clear();\n\t}\n\n\tenqueue(value) {\n\t\tconst node = new Node(value);\n\n\t\tif (this.#head) {\n\t\t\tthis.#tail.next = node;\n\t\t\tthis.#tail = node;\n\t\t} else {\n\t\t\tthis.#head = node;\n\t\t\tthis.#tail = node;\n\t\t}\n\n\t\tthis.#size++;\n\t}\n\n\tdequeue() {\n\t\tconst current = this.#head;\n\t\tif (!current) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#head = this.#head.next;\n\t\tthis.#size--;\n\n\t\t// Clean up tail reference when queue becomes empty\n\t\tif (!this.#head) {\n\t\t\tthis.#tail = undefined;\n\t\t}\n\n\t\treturn current.value;\n\t}\n\n\tpeek() {\n\t\tif (!this.#head) {\n\t\t\treturn;\n\t\t}\n\n\t\treturn this.#head.value;\n\n\t\t// TODO: Node.js 18.\n\t\t// return this.#head?.value;\n\t}\n\n\tclear() {\n\t\tthis.#head = undefined;\n\t\tthis.#tail = undefined;\n\t\tthis.#size = 0;\n\t}\n\n\tget size() {\n\t\treturn this.#size;\n\t}\n\n\t* [Symbol.iterator]() {\n\t\tlet current = this.#head;\n\n\t\twhile (current) {\n\t\t\tyield current.value;\n\t\t\tcurrent = current.next;\n\t\t}\n\t}\n\n\t* drain() {\n\t\twhile (this.#head) {\n\t\t\tyield this.dequeue();\n\t\t}\n\t}\n}\n", "import Queue from 'yocto-queue';\n\nexport default function pLimit(concurrency) {\n\tvalidateConcurrency(concurrency);\n\n\tconst queue = new Queue();\n\tlet activeCount = 0;\n\n\tconst resumeNext = () => {\n\t\t// Process the next queued function if we're under the concurrency limit\n\t\tif (activeCount < concurrency && queue.size > 0) {\n\t\t\tactiveCount++;\n\t\t\tqueue.dequeue()();\n\t\t}\n\t};\n\n\tconst next = () => {\n\t\tactiveCount--;\n\t\tresumeNext();\n\t};\n\n\tconst run = async (function_, resolve, arguments_) => {\n\t\t// Execute the function and capture the result promise\n\t\tconst result = (async () => function_(...arguments_))();\n\n\t\t// Resolve immediately with the promise (don't wait for completion)\n\t\tresolve(result);\n\n\t\t// Wait for the function to complete (success or failure)\n\t\t// We catch errors here to prevent unhandled rejections,\n\t\t// but the original promise rejection is preserved for the caller\n\t\ttry {\n\t\t\tawait result;\n\t\t} catch {}\n\n\t\t// Decrement active count and process next queued function\n\t\tnext();\n\t};\n\n\tconst enqueue = (function_, resolve, arguments_) => {\n\t\t// Queue the internal resolve function instead of the run function\n\t\t// to preserve the asynchronous execution context.\n\t\tnew Promise(internalResolve => { // eslint-disable-line promise/param-names\n\t\t\tqueue.enqueue(internalResolve);\n\t\t}).then(run.bind(undefined, function_, resolve, arguments_)); // eslint-disable-line promise/prefer-await-to-then\n\n\t\t// Start processing immediately if we haven't reached the concurrency limit\n\t\tif (activeCount < concurrency) {\n\t\t\tresumeNext();\n\t\t}\n\t};\n\n\tconst generator = (function_, ...arguments_) => new Promise(resolve => {\n\t\tenqueue(function_, resolve, arguments_);\n\t});\n\n\tObject.defineProperties(generator, {\n\t\tactiveCount: {\n\t\t\tget: () => activeCount,\n\t\t},\n\t\tpendingCount: {\n\t\t\tget: () => queue.size,\n\t\t},\n\t\tclearQueue: {\n\t\t\tvalue() {\n\t\t\t\tqueue.clear();\n\t\t\t},\n\t\t},\n\t\tconcurrency: {\n\t\t\tget: () => concurrency,\n\n\t\t\tset(newConcurrency) {\n\t\t\t\tvalidateConcurrency(newConcurrency);\n\t\t\t\tconcurrency = newConcurrency;\n\n\t\t\t\tqueueMicrotask(() => {\n\t\t\t\t\t// eslint-disable-next-line no-unmodified-loop-condition\n\t\t\t\t\twhile (activeCount < concurrency && queue.size > 0) {\n\t\t\t\t\t\tresumeNext();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t},\n\t\t},\n\t\tmap: {\n\t\t\tasync value(iterable, function_) {\n\t\t\t\tconst promises = Array.from(iterable, (value, index) => this(function_, value, index));\n\t\t\t\treturn Promise.all(promises);\n\t\t\t},\n\t\t},\n\t});\n\n\treturn generator;\n}\n\nexport function limitFunction(function_, options) {\n\tconst {concurrency} = options;\n\tconst limit = pLimit(concurrency);\n\n\treturn (...arguments_) => limit(() => function_(...arguments_));\n}\n\nfunction validateConcurrency(concurrency) {\n\tif (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) {\n\t\tthrow new TypeError('Expected `concurrency` to be a number from 1 and up');\n\t}\n}\n", "import type {\n\tAPIRequest,\n\tAPIResponses,\n\tGetAPI,\n\tPostAPI,\n\tPutAPI,\n\tShowApiErrorOptions,\n} from \"../shared/types/api\";\nimport type { Petition } from \"../shared/types/global\";\n\nimport crypto from \"node:crypto\";\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { RenderError } from \"../core/errors\";\nimport { pathExists } from \"../core/fs\";\nimport { GriddoLog } from \"../core/GriddoLog\";\nimport { addLogToBuffer } from \"../core/logger\";\nimport { DEFAULT_HEADERS } from \"../shared/headers\";\nimport { brush } from \"../shared/npm-modules/brush\";\nimport { AuthService } from \"./auth\";\nimport { getRenderPathsHydratedWithDomainFromDB } from \"./render\";\n\n// Envs\nconst { env } = process;\nconst { RETRY_WAIT_SECONDS = \"4\", RETRY_ATTEMPTS = \"4\" } = env;\n\n/**\n * Make a GET/PUT/POST request to the Griddo API.\n *\n * @template T Response Type returned.\n * @returns {Promise<T>} A promise that is resolved with the data from the API response.\n *\n * @example\n *\tconst response = await requestAPI<Site>(\n *\t\t{ endpoint: \"...\", cacheKey: \"...\", ... },\n *\t\t\"get\",\n *\t\t\"...\"\n *\t);\n */\nasync function requestAPI<T extends APIResponses>(\n\tprops: APIRequest,\n\tmethod: string,\n\tappendToLog = \"\",\n): Promise<T> {\n\tconst {\n\t\tendpoint,\n\t\tbody,\n\t\tcacheKey = \"\",\n\t\tattempt = 1,\n\t\theaders,\n\t\tuseApiCacheDir = true,\n\t\tlogToFile = true,\n\t} = props;\n\tconst cacheOptions = { endpoint, body, headers, cacheKey };\n\n\t// Cache\n\tif (cacheKey && useApiCacheDir) {\n\t\tconst start = new Date();\n\t\tconst cacheData = await searchCacheData<T>(cacheOptions);\n\n\t\tif (cacheData) {\n\t\t\tif (logToFile) {\n\t\t\t\tconst siteId = getSafeSiteId(cacheData);\n\t\t\t\tconst siteIdMsg = siteId ? `site: ${siteId}` : \"\";\n\t\t\t\tconst duration = msToSec(Date.now() - start.getTime());\n\t\t\t\taddLogToBuffer(`${method} (cache) ${siteIdMsg} ${endpoint} - ${duration}s ${appendToLog}`);\n\t\t\t}\n\t\t\treturn cacheData;\n\t\t}\n\t}\n\n\t// Network\n\ttry {\n\t\tconst start = new Date();\n\n\t\t// Prepare fetch options\n\t\tconst fetchOptions: RequestInit = {\n\t\t\tmethod: method.toUpperCase(),\n\t\t\theaders: Object.assign({}, DEFAULT_HEADERS, headers, AuthService.headers) as Record<\n\t\t\t\tstring,\n\t\t\t\tstring\n\t\t\t>,\n\t\t};\n\n\t\t// Add body for non-GET requests\n\t\tif (method.toLowerCase() !== \"get\" && body) {\n\t\t\tfetchOptions.body = JSON.stringify(body);\n\t\t\tif (!fetchOptions.headers) fetchOptions.headers = {};\n\t\t\t(fetchOptions.headers as Record<string, string>)[\"Content-Type\"] = \"application/json\";\n\t\t}\n\n\t\tconst response = await fetch(endpoint, fetchOptions);\n\n\t\t// Handle non-2xx responses\n\t\tif (!response.ok) {\n\t\t\tif (response.status === 404) {\n\t\t\t\t// @ts-expect-error page maybe will be 404\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tthrow new Error(`HTTP ${response.status}: ${response.statusText}`);\n\t\t}\n\n\t\tconst data: T = await response.json();\n\n\t\tif (logToFile) {\n\t\t\tconst siteId = getSafeSiteId(data);\n\t\t\tconst siteIdMsg = siteId ? `site: ${siteId}` : \"\";\n\t\t\tconst duration = msToSec(Date.now() - start.getTime());\n\t\t\taddLogToBuffer(`${method} (fetch) ${siteIdMsg} ${endpoint} - ${duration}s ${appendToLog}`);\n\t\t}\n\n\t\tif (useApiCacheDir) {\n\t\t\tawait saveCache(cacheOptions, data);\n\t\t}\n\n\t\treturn data;\n\t} catch (e) {\n\t\tconst error = e as Error;\n\n\t\tif (attempt > parseInt(RETRY_ATTEMPTS)) {\n\t\t\tGriddoLog.log(`\nMax attempts ${RETRY_ATTEMPTS} reached\n--------------------------------------\n- ${method.toUpperCase()} ${endpoint}\n- BODY: ${JSON.stringify(body)}\n- HEADERS: ${JSON.stringify(headers)}\n- ERROR: ${error.message}\n--------------------------------------\n`);\n\t\t\tthrow new RenderError(error);\n\t\t}\n\n\t\tshowApiError(error, {\n\t\t\tcallInfo: { endpoint, body },\n\t\t});\n\n\t\tGriddoLog.warn(`Waiting for retry: ${method}`, endpoint);\n\n\t\tawait delay(parseInt(RETRY_WAIT_SECONDS) * 1000);\n\n\t\treturn requestAPI<T>(\n\t\t\t{\n\t\t\t\tendpoint,\n\t\t\t\tbody,\n\t\t\t\theaders,\n\t\t\t\tcacheKey,\n\t\t\t\tattempt: attempt + 1,\n\t\t\t},\n\t\t\tmethod,\n\t\t\tappendToLog,\n\t\t);\n\t}\n}\n\n/**\n * Make a GET request to the Griddo API.\n *\n * @template T Response Type returned.\n * @returns A promise that is resolved with the data from the API response.\n */\nasync function getApi<T extends APIResponses>(props: GetAPI) {\n\treturn requestAPI<T>(props, \"get\");\n}\n\n/**\n * Make a PUT request to the Griddo API.\n *\n * @template T Response Type returned.\n * @returns A promise that is resolved with the data from the API response.\n */\nasync function putApi<T extends APIResponses>(props: PutAPI) {\n\treturn requestAPI<T>(props, \"put\");\n}\n\n/**\n * Make a POST request to the Griddo API.\n *\n * @template T Response Type returned.\n * @returns A promise that is resolved with the data from the API response.\n */\nasync function postApi<T extends APIResponses>(props: PostAPI) {\n\tconst { endpoint, body, headers } = props;\n\tconst referenceFieldBodyParams =\n\t\tendpoint.endsWith(\"/distributor\") &&\n\t\t`# ReferenceField body: ${JSON.stringify(body)} lang: ${JSON.stringify(headers?.lang)}`;\n\n\treturn requestAPI<T>(props, \"post\", referenceFieldBodyParams || \"\");\n}\n\n/**\n * Shows an API error through the terminal.\n */\nfunction showApiError(error: Error, options: ShowApiErrorOptions) {\n\tconst { message, stack } = error;\n\tconst { callInfo } = options;\n\tconst callInfoArray = [];\n\n\tfor (const item of Object.keys(callInfo) as (keyof typeof callInfo)[]) {\n\t\tcallInfoArray.push(\n\t\t\t`${item}: ${\n\t\t\t\ttypeof callInfo[item] === \"object\" ? JSON.stringify(callInfo[item]) : callInfo[item]\n\t\t\t}`,\n\t\t);\n\t}\n\n\t// Compose the errors output\n\tconst callInfoStr = callInfoArray.join(\"\\n\");\n\tconst errorDetailsStr = `${message}\\n${stack}`;\n\n\t// Print the error\n\tGriddoLog.warn(\n\t\tbrush.red(`\n=============\n\n{ Call info }\n${callInfoStr}\n\n{ Error details }\n${errorDetailsStr}\n\n=============\n`),\n\t);\n}\n\n/**\n * Return a siteID from a response object if exist\n * @param response A response object\n */\nfunction getSafeSiteId(response: APIResponses) {\n\tif (typeof response !== \"object\" || response === null || Array.isArray(response)) {\n\t\treturn undefined;\n\t}\n\n\treturn \"site\" in response && response.site ? response.site : undefined;\n}\n\n/**\n * Custom delay using the \"promise hack\",\n *\n * @param ms Amount of miliseconds to be delayed\n */\nfunction delay(ms: number): Promise<void> {\n\treturn new Promise((res) => setTimeout(res, ms));\n}\n\n/**\n * Converts milliseconds to seconds with a fixed number of decimals.\n *\n * @param ms The number in milliseconds.\n * @param fixed The amount of fixed decimals.\n * @returns The converted number in seconds with the fixed number of decimals.\n */\nfunction msToSec(ms: number, decimals = 3): number {\n\treturn Number.parseFloat((ms / 1000).toFixed(decimals));\n}\n\n/**\n * Generate a filename with a hash using a Petition object\n * @param petition An object\n */\nasync function generateFilenameWithHash(petition: Petition) {\n\tconst { __root } = await getRenderPathsHydratedWithDomainFromDB();\n\tconst apiCacheDir = path.join(__root, \"apiCache\");\n\n\tconst hashSum = crypto.createHash(\"sha256\");\n\thashSum.update(JSON.stringify(petition));\n\n\treturn `${apiCacheDir}/${hashSum.digest(\"hex\")}`;\n}\n\n/**\n * Save a file using a hash name.\n *\n * @param petition An object.\n * @param content Content to be saved.\n */\nasync function saveCache<T>(petition: Petition, content: T) {\n\tconst stringContent = typeof content === \"string\" ? content : JSON.stringify(content);\n\tconst filename = await generateFilenameWithHash(petition);\n\tconst filepath = path.dirname(filename);\n\n\tif (!(await pathExists(filepath))) {\n\t\tawait fsp.mkdir(filepath, { recursive: true });\n\t}\n\n\tawait fsp.writeFile(filename, stringContent, \"utf8\");\n}\n\n/**\n * Search in the `apiCache` dir for a file using the petition as hash generator.\n * Return the file content if found or null if not.\n *\n * @param petition An object\n */\nasync function searchCacheData<T>(petition: Petition) {\n\ttry {\n\t\tconst file = await generateFilenameWithHash(petition);\n\t\tconst fileContent = await fsp.readFile(file, \"utf8\");\n\t\tconst jsonData = JSON.parse(fileContent) as T;\n\n\t\treturn jsonData;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport { getApi as get, postApi as post, putApi as put };\n", "import type { Site, SiteData } from \"../shared/types/sites\";\n\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { getRenderPathsHydratedWithDomainFromDB } from \"./render\";\nimport {\n\tendSiteRender,\n\tgetAllSites,\n\tgetSiteInfo,\n\tgetSiteLanguages,\n\tgetSiteSocials,\n\tstartSiteRender,\n} from \"./sites\";\n\n/**\n * Check the instance sites and returns site prepared to be published and unpublished.\n */\nasync function getSitesToRender(domain: string) {\n\t// Get all sites. An array of Site\n\tconst allSites = await getAllSites(domain);\n\n\t// If there are valid sites...\n\t// En este paso se a\u00F1ade al objeto `Site` la informaci\u00F3n de los dominios\n\t// utilizando los idiomas.\n\tif (allSites.length) {\n\t\tfor (const site of allSites) {\n\t\t\tconst { items } = await getSiteLanguages(site.id);\n\n\t\t\t// A\u00F1adimos la prop site.domains con el dominio \"cocinado\" con\n\t\t\t// los idiomas y teniendo en cuenta solo el dominio actual.\n\t\t\tsite.domains = items\n\t\t\t\t.filter(\n\t\t\t\t\t(item) =>\n\t\t\t\t\t\titem.domain && (item.domain.slug === domain || item.domain.slug === `/${domain}`),\n\t\t\t\t)\n\t\t\t\t.map((item) => ({ [item.id]: `${item.domain.slug}${item.path}` }));\n\t\t}\n\t}\n\n\t// Save sites object to publish\n\tconst sitesToPublish = allSites.filter((site) => !!site.isPublished);\n\n\t// Save sites object to unpublish\n\tconst sitesToUnpublish = allSites.filter((site) => !site.isPublished && site.shouldBeUpdated);\n\n\treturn {\n\t\tsitesToPublish,\n\t\tsitesToUnpublish,\n\t};\n}\n\n/**\n * Unpublish an array of sites sending the information to the API.\n *\n * @param sites An array of sites\n */\nasync function unpublishSites(sites: Site[]) {\n\tconst { __root } = await getRenderPathsHydratedWithDomainFromDB();\n\n\tfor (const site of sites) {\n\t\t// API\n\t\tconst buildInfo = await startSiteRender(site.id);\n\t\tconst { siteHash } = buildInfo;\n\t\tconst body = {\n\t\t\tsiteHash,\n\t\t\tpublishHashes: [],\n\t\t\tunpublishHashes: [],\n\t\t\tpublishPagesIds: [],\n\t\t};\n\n\t\tawait endSiteRender(site.id, body);\n\n\t\t// STORE\n\t\t// Remove site directory from the Store to prevent rendering\n\t\tawait fsp.rm(path.join(__root, \"store\", site.id.toString()), {\n\t\t\tforce: true,\n\t\t\trecursive: true,\n\t\t});\n\t}\n}\n\n/**\n * Return a single site generic data.\n *\n * @param siteID The site id.\n * @see SiteData\n */\nasync function getSiteData(siteID: number) {\n\tconst buildData = await startSiteRender(siteID);\n\tconst siteInfo = await getSiteInfo(siteID);\n\tconst siteLangs = await getSiteLanguages(siteID);\n\tconst socials = await getSiteSocials(siteID);\n\tconst siteLangsInfo = siteLangs.items;\n\tconst defaultLang = siteLangsInfo.find((lang) => lang.isDefault);\n\n\tconst { siteHash, unpublishHashes, publishIds } = buildData;\n\tconst { headers, footers } = siteInfo;\n\tconst validPagesIds = publishIds;\n\n\tconst siteData: SiteData = {\n\t\tsiteInfo,\n\t\tvalidPagesIds,\n\t\tsiteHash,\n\t\tunpublishHashes,\n\t\tsiteLangs: siteLangsInfo,\n\t\tdefaultLang,\n\t\theaders,\n\t\tfooters,\n\t\tsocials,\n\t};\n\n\treturn siteData;\n}\n\nexport { getSiteData, getSitesToRender, unpublishSites };\n", "import type { Core } from \"@griddo/core\";\nimport type {\n\tAllSitesReponse,\n\tEndPageInfoResponse,\n\tEndSiteRenderBody,\n\tLanguagesResponse,\n\tPageResponse,\n\tReferenceFieldBody,\n\tReferenceFieldResponse,\n\tSitemapAPIResponse,\n\tSocialsResponse,\n\tStartPageRenderResponse,\n} from \"../shared/types/api\";\nimport type { Site } from \"../shared/types/sites\";\n\nimport {\n\tBUILD_END,\n\tBUILD_START,\n\tGET_ALL,\n\tGET_PAGE,\n\tGET_REFERENCE_FIELD_DATA,\n\tGET_SITEMAP,\n\tINFO,\n\tLANGUAGES,\n\tSOCIALS,\n} from \"../shared/endpoints\";\nimport { get, post } from \"./api\";\n\n/**\n * Get a list of site objects.\n */\nasync function getAllSites(domain: string) {\n\treturn get<AllSitesReponse>({\n\t\tendpoint: `${GET_ALL}?domainSlug=${domain}`,\n\t});\n}\n\n/**\n * Get a list of site objects from a domain.\n */\nasync function getAllSitesFromDomain(domain: string) {\n\tconst allSites = await get<AllSitesReponse>({ endpoint: GET_ALL });\n\n\tif (allSites.length) {\n\t\tfor (const site of allSites) {\n\t\t\tconst { items } = await getSiteLanguages(site.id);\n\n\t\t\t// A\u00F1adimos la prop domains con el dominio \"cocinado\" con los\n\t\t\t// idiomas y teniendo en cuenta solo el dominio actual.\n\t\t\tsite.domains = items\n\t\t\t\t.filter(\n\t\t\t\t\t(item) =>\n\t\t\t\t\t\titem.domain && (item.domain.slug === domain || item.domain.slug === `/${domain}`),\n\t\t\t\t)\n\t\t\t\t.map((item) => ({ [item.id]: `${item.domain.slug}${item.path}` }));\n\t\t}\n\t}\n\n\treturn allSites.filter((site) => site.domains.length > 0);\n}\n\n/**\n * Fetch a page object from API.\n */\nasync function getPage(id: number, cacheKey: string) {\n\treturn get<PageResponse>({\n\t\tendpoint: `${GET_PAGE}/${id}`,\n\t\tcacheKey,\n\t});\n}\n\n/**\n * Get site info\n */\nasync function getSiteInfo(id: number, cacheKey = \"\") {\n\tconst [prefix, suffix] = INFO;\n\n\treturn get<Site>({\n\t\tendpoint: `${prefix}${id}${suffix}`,\n\t\tcacheKey,\n\t});\n}\n\nasync function getSiteLanguages(id: number, cacheKey = \"\") {\n\tconst [prefix, suffix] = LANGUAGES;\n\n\treturn get<LanguagesResponse>({\n\t\tendpoint: `${prefix}${id}${suffix}`,\n\t\tcacheKey,\n\t});\n}\n\nasync function startSiteRender(id: number) {\n\tconst [prefix, suffix] = BUILD_START;\n\n\treturn get<StartPageRenderResponse>({\n\t\tendpoint: `${prefix}${id}${suffix}`,\n\t});\n}\n\n/**\n * Send the end signal to API for a render site.\n */\nasync function endSiteRender(id: number, body: EndSiteRenderBody) {\n\tconst [prefix, suffix] = BUILD_END;\n\n\tawait post<EndPageInfoResponse>({\n\t\tendpoint: `${prefix}${id}${suffix}`,\n\t\tbody,\n\t\tuseApiCacheDir: false,\n\t\tlogToFile: false,\n\t});\n}\n\nasync function getReferenceFieldSiteData(\n\tpage: Core.Page,\n\tbody: ReferenceFieldBody,\n\tcacheKey: string,\n\tdataSiteId?: number,\n\tdataLangID?: number,\n) {\n\tconst [prefix, suffix] = GET_REFERENCE_FIELD_DATA;\n\tconst site = dataSiteId || page.site;\n\tconst lang = dataLangID || page.language;\n\n\treturn post<ReferenceFieldResponse>({\n\t\tendpoint: `${prefix}${site}${suffix}`,\n\t\tbody,\n\t\theaders: { lang },\n\t\tcacheKey,\n\t});\n}\n\nasync function getSitemap(options: { siteId: number; headers?: Record<string, string> }) {\n\tconst { siteId, headers } = options;\n\tconst [prefix, suffix] = GET_SITEMAP;\n\n\treturn get<SitemapAPIResponse>({\n\t\tendpoint: `${prefix}${siteId}${suffix}`,\n\t\theaders,\n\t});\n}\n\nasync function getSiteSocials(id: number, cacheKey = \"\") {\n\tconst [prefix, suffix] = SOCIALS;\n\n\treturn get<SocialsResponse>({\n\t\tendpoint: `${prefix}${id}${suffix}`,\n\t\tcacheKey,\n\t});\n}\n\nexport {\n\tendSiteRender,\n\tgetAllSites,\n\tgetAllSitesFromDomain,\n\tgetPage,\n\tgetReferenceFieldSiteData,\n\tgetSiteInfo,\n\tgetSiteLanguages,\n\tgetSitemap,\n\tgetSiteSocials,\n\tstartSiteRender,\n};\n", "import type { Footer, Header } from \"../shared/types/navigation\";\nimport type { APIPageObject } from \"../shared/types/pages\";\n\nclass NavigationService {\n\tprivate _defaultHeaders: Record<string, Header>;\n\tprivate _defaultFooters: Record<string, Footer>;\n\tprivate _navigations: {\n\t\theaders: Header[];\n\t\tfooters: Footer[];\n\t};\n\n\tconstructor() {\n\t\tthis._navigations = {\n\t\t\tfooters: [],\n\t\t\theaders: [],\n\t\t};\n\t\tthis._defaultHeaders = {};\n\t\tthis._defaultFooters = {};\n\t}\n\n\tset navigations(navigations) {\n\t\tthis._navigations = navigations;\n\t\tthis._defaultFooters = this.getDefaultFooters();\n\t\tthis._defaultHeaders = this.getDefaultHeaders();\n\t}\n\n\tget navigations() {\n\t\treturn this._navigations;\n\t}\n\n\tgetDefaultFooters() {\n\t\tconst footers = [...this.navigations.footers];\n\t\tconst defaultFooters = footers.filter((footer) => footer.setAsDefault);\n\t\tconst defaultFootersByLang = {} as Record<number, Footer>;\n\n\t\tfor (const item of defaultFooters) {\n\t\t\tdefaultFootersByLang[item.language] = item;\n\t\t}\n\n\t\treturn defaultFootersByLang;\n\t}\n\n\tgetDefaultHeaders() {\n\t\tconst headers = [...this.navigations.headers];\n\t\tconst defaultHeaders = headers.filter((header) => header.setAsDefault);\n\t\tconst defaultHeadersByLang = {} as Record<number, Header>;\n\n\t\tfor (const item of defaultHeaders) {\n\t\t\tdefaultHeadersByLang[item.language] = item;\n\t\t}\n\n\t\treturn defaultHeadersByLang;\n\t}\n\n\tgetRightLanguage(\n\t\tlist: {\n\t\t\tlanguage: number;\n\t\t\tnavigationLanguages: { navigationId: number }[];\n\t\t\tid: number;\n\t\t}[],\n\t\tid: number,\n\t\tlanguage: number,\n\t) {\n\t\tif (!list || !id) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst rightLanguageItem = list.find(\n\t\t\t(item) =>\n\t\t\t\titem.language === language &&\n\t\t\t\titem.navigationLanguages?.find((version) => version.navigationId === id),\n\t\t);\n\n\t\tconst result = rightLanguageItem || list.find((item) => item.id === id);\n\n\t\treturn result ? { ...result } : null;\n\t}\n\n\tgetPageHeader(id: number, language: number) {\n\t\treturn this.getRightLanguage(this.navigations.headers, id, language);\n\t}\n\n\tgetPageFooter(id: number, language: number) {\n\t\treturn this.getRightLanguage(this.navigations.footers, id, language);\n\t}\n\n\tgetPageNavigations(page: APIPageObject) {\n\t\tconst { header: pageHeader, footer: pageFooter, language, template, templateConfig } = page;\n\t\tconst { templateType } = template;\n\t\tconst { defaultHeader, defaultFooter, templates } = templateConfig;\n\n\t\t// The navigations would be:\n\t\t// - The one with the page or ...\n\t\t// - The one defined for that template or ...\n\t\t// - The one you have defined for that data package\n\t\tconst getValidNavigation = (values: (number | unknown)[]) => {\n\t\t\tconst fineNavigation = values.find((item) => typeof item === \"number\");\n\n\t\t\treturn typeof fineNavigation === \"number\" ? fineNavigation : null;\n\t\t};\n\n\t\tconst headerID = getValidNavigation([\n\t\t\tpageHeader,\n\t\t\ttemplates?.[templateType]?.defaultHeader,\n\t\t\tdefaultHeader,\n\t\t]);\n\n\t\tconst footerID = getValidNavigation([\n\t\t\tpageFooter,\n\t\t\ttemplates?.[templateType]?.defaultFooter,\n\t\t\tdefaultFooter,\n\t\t]);\n\n\t\tconst header = headerID\n\t\t\t? this.getPageHeader(headerID, language)\n\t\t\t: headerID === 0\n\t\t\t\t? null\n\t\t\t\t: this._defaultHeaders[language];\n\n\t\tconst footer = footerID\n\t\t\t? this.getPageFooter(footerID, language)\n\t\t\t: footerID === 0\n\t\t\t\t? null\n\t\t\t\t: this._defaultFooters[language];\n\n\t\treturn {\n\t\t\theader,\n\t\t\tfooter,\n\t\t} as { header: Header; footer: Footer };\n\t}\n}\n\nexport { NavigationService };\n", "import type { Fields } from \"@griddo/core\";\n\n/**\n * Format Cloudinary or DAM URL\n *\n * @param image The image url\n * @param width With of the image\n * @param height Height of the image\n * @param format Format of the image\n * @returns A composed URL for the Cloudinary or DAM service\n *\n * @example\n * formatImage(\"https://images.griddo.io/tree\", 300, 200, \"jpg\")\n * // https://images.griddo.io/tree/w/300/h/200/f/jpg\n */\nfunction formatImage(image: Fields.Image | string, width: number, height: number, format = \"jpg\") {\n\tconst url = typeof image === \"string\" ? image : image?.url;\n\n\tif (!url) {\n\t\treturn null;\n\t}\n\n\tconst isCloudinary = url.split(\"/\")[2].includes(\"cloudinary.com\");\n\n\treturn isCloudinary\n\t\t? addCloudinaryParams(url, `c_fill,w_${width},h_${height}`)\n\t\t: addGriddoDamParams(url, `f/${format}/w/${width}/h/${height}`);\n}\n\n/**\n * Format Griddo DAM image url.\n */\nfunction addGriddoDamParams(image: string, params: string) {\n\tconst urlParts = image.split(\"/\");\n\tconst imagePath = urlParts.slice(0, -1).join(\"/\");\n\tconst imageName = urlParts.slice(-1)[0];\n\n\treturn `${imagePath}/${params}/${imageName}`;\n}\n\n/**\n * Take a cloudinary url and add query params.\n */\nfunction addCloudinaryParams(image: string, params: string) {\n\tconst plainUrl = image.replace(\"https://\", \"\");\n\tconst head = plainUrl.split(\"/\").slice(0, 4).join(\"/\");\n\tconst fullId = plainUrl.replace(head, \"\");\n\n\treturn `https://${head}/${params}${fullId}`;\n}\n\nexport { formatImage };\n", "import type { Core, Fields } from \"@griddo/core\";\nimport type {\n\tAPIPageObject,\n\tGriddoListPage,\n\tGriddoMultiPage,\n\tGriddoPageObject,\n\tGriddoSinglePage,\n\tMultiPageElement,\n\tMultiPageElements,\n\tPageAdditionalInfo,\n} from \"../shared/types/pages\";\nimport type { TemplateWithReferenceField } from \"../shared/types/templates\";\n\nimport { formatImage } from \"../core/images\";\n\n// Consts\nconst DEFAULT_ITEMS_PER_PAGE_FOR_LIST_TEMPLATES = 25;\n\n/**\n * Return an OpenGraph object.\n *\n * @param props.socialTitle The social title.\n * @param props.socialDescription The social description.\n * @param props.socialImage The social image in Cloudinary or DAM url format.\n */\nfunction getOpenGraph({\n\tsocialTitle,\n\tsocialDescription,\n\tsocialImage,\n}: Pick<Core.Page, \"socialTitle\" | \"socialDescription\" | \"socialImage\">): Core.Page[\"openGraph\"] {\n\treturn {\n\t\ttype: \"website\",\n\t\ttitle: socialTitle,\n\t\tdescription: socialDescription,\n\t\timage: socialImage ? formatImage(socialImage, 1280, 768) : \"\",\n\t\ttwitterImage: socialImage ? formatImage(socialImage, 1280, 768) : \"\",\n\t};\n}\n\n/**\n * Get the Page metadata object from a page Object.\n *\n * @param params A Page object\n */\nfunction getPageMetadata(params: Core.Page): GriddoPageObject[\"context\"][\"pageMetadata\"] {\n\tconst {\n\t\ttitle,\n\t\tmetaTitle,\n\t\tmetaDescription,\n\t\tcanonicalURL,\n\t\tlocale,\n\t\turl,\n\t\tisIndexed,\n\t\tfollow,\n\t\tmetasAdvanced,\n\t\tpageLanguages,\n\t\tfullUrl,\n\t\tmetaKeywords,\n\t} = params;\n\n\tconst metasAdvancedList =\n\t\tmetasAdvanced\n\t\t\t?.split(\",\")\n\t\t\t.filter(Boolean)\n\t\t\t.map((item) => item.trim().toLowerCase()) || [];\n\n\treturn {\n\t\ttitle: (metaTitle || title || \"\").trim(),\n\t\tdescription: metaDescription,\n\t\tcanonical:\n\t\t\tcanonicalURL?.trim() && canonicalURL !== fullUrl\n\t\t\t\t? canonicalURL.trim()\n\t\t\t\t: isIndexed\n\t\t\t\t\t? fullUrl\n\t\t\t\t\t: undefined,\n\t\tlocale,\n\t\turl,\n\t\tindex: isIndexed ? \"index\" : \"noindex\",\n\t\tfollow: follow ? \"follow\" : \"nofollow\",\n\t\ttranslate: metasAdvancedList.includes(\"notranslate\") ? \"notranslate\" : \"\",\n\t\tmetasAdvanced: metasAdvancedList.filter((item) => item !== \"notranslate\").join(),\n\t\tpageLanguages,\n\t\tmetaKeywords: metaKeywords\n\t\t\t?.filter(Boolean)\n\t\t\t.map((keyword) => keyword.replace(/\"/g, \"'\"))\n\t\t\t.join(\", \"),\n\t};\n}\n\n/**\n * Create a Griddo page object\n *\n * @param page A page object ready to pass as content of the `context` to use in the React template.\n * @param additionalInfo Additional page info to pass as content of `context` to use in the React template.\n * @param excludeFromSearch Boolean to avoid this page to be indexed in internal search tool.\n */\nasync function createGriddoPageObject(\n\tpage: GriddoSinglePage | GriddoListPage | GriddoMultiPage,\n\tadditionalInfo: PageAdditionalInfo,\n): Promise<GriddoPageObject> {\n\t// Extract some props from page\n\tconst {\n\t\tid,\n\t\ttitle,\n\t\tfullPath,\n\t\tlanguage: languageId,\n\t\tbreadcrumb,\n\t\tsocialDescription,\n\t\tsocialImage,\n\t\tsocialTitle,\n\t} = page;\n\n\t// Extract some props from additionalInfo\n\tconst {\n\t\tbaseUrl,\n\t\tcloudinaryName,\n\t\tgriddoVersion,\n\t\tsiteLangs,\n\t\tsiteMetadata,\n\t\tsiteOptions,\n\t\tsiteScript,\n\t\tsiteSlug,\n\t\tsocials,\n\t\ttheme,\n\t\tnavigations,\n\t} = additionalInfo;\n\tconst { header, footer } = navigations;\n\n\t// Update page object\n\tpage.breadcrumb = breadcrumb;\n\tpage.siteSlug = siteSlug;\n\tpage.apiUrl = baseUrl;\n\tpage.publicApiUrl = additionalInfo.publicBaseUrl;\n\tpage.instance = additionalInfo.instance;\n\n\tconst foundLanguage = siteLangs.find(({ id }) => id === page?.language);\n\tconst locale = foundLanguage?.locale.replace(/_/g, \"-\");\n\n\t// Page Metadata\n\tconst pageMetadata = getPageMetadata(page);\n\n\t// Opengraph\n\tconst openGraph = getOpenGraph({\n\t\tsocialDescription,\n\t\tsocialImage,\n\t\tsocialTitle,\n\t});\n\n\tconst pagePath = fullPath.compose;\n\n\tconst renderDate = new Date().toString();\n\n\tconst griddoPageObject: GriddoPageObject = {\n\t\tpath: pagePath,\n\t\tsize: undefined,\n\t\tcontext: {\n\t\t\t// Page\n\t\t\tid,\n\t\t\ttitle,\n\t\t\tfullPath,\n\t\t\tlocale,\n\t\t\tlanguageId,\n\t\t\ttheme,\n\n\t\t\t// PARA <Helmet />\n\t\t\tsiteMetadata,\n\t\t\tpageMetadata,\n\t\t\topenGraph,\n\t\t\tsocials,\n\t\t\tsiteLangs,\n\t\t\tcloudinaryName,\n\t\t\tsiteOptions,\n\t\t\tgriddoVersion,\n\t\t\trenderDate,\n\t\t\tsiteScript,\n\n\t\t\t// Navigation sections\n\t\t\theader,\n\t\t\tfooter,\n\n\t\t\t// Page template\n\t\t\t// En este objeto se est\u00E1 pasando todos los metadatos que vienen en\n\t\t\t// el primer nivel pero el uso de los mismos en CX se hace con la\n\t\t\t// prop `pageMetadata` creada a partir de getPageMetadata. En\n\t\t\t// resumen, se est\u00E1 pasando por duplicado el contenido.\n\t\t\t// TODO: Eliminar las claves de metadata de este objeto page.\n\t\t\tpage,\n\t\t},\n\t};\n\n\treturn griddoPageObject;\n}\n\n/**\n * Create a single Griddo page object.\n *\n * @param page A Griddo single page object.\n * @param additionalInfo Additional page info.\n */\nasync function createGriddoSinglePage(page: GriddoSinglePage, additionalInfo: PageAdditionalInfo) {\n\treturn createGriddoPageObject(page, additionalInfo);\n}\n\n/**\n * Create multiples pages from one page as list paginated pages\n */\nasync function createGriddoListPages(\n\t{ page, pages, isRoot = false, defaultLang, template, totalQueriedItems }: GriddoListPage,\n\tadditionalInfo: PageAdditionalInfo,\n) {\n\tconst allPages = pages.map(async (dataInPage, idx) => {\n\t\tconst isFirstPage = idx === 0;\n\t\tconst pageNumber = idx + 1;\n\t\tconst { domainUrl, compose } = page.fullPath;\n\n\t\tconst paginatedPage = {\n\t\t\t...page,\n\t\t\tfullPath: {\n\t\t\t\t...page.fullPath,\n\t\t\t\t// Add a page number (tailPageNumber) from page 2 onwards\n\t\t\t\tcompose: addPageNumberToUrl(compose, pageNumber, {\n\t\t\t\t\taddEndingSlash: true,\n\t\t\t\t}),\n\t\t\t},\n\t\t\tfullUrl: addPageNumberToUrl(page.fullUrl, pageNumber, {\n\t\t\t\taddEndingSlash: true,\n\t\t\t}),\n\t\t\tslug: addPageNumberToUrl(page.slug, pageNumber),\n\t\t\ttitle: addPageNumberToTitle(page.title, pageNumber),\n\t\t\tmetaTitle: addPageNumberToTitle(page.metaTitle || \"\", pageNumber),\n\t\t\tdisableHrefLangs: pageNumber > 1,\n\t\t\ttemplate: {\n\t\t\t\t...template,\n\t\t\t\tisFirstPage,\n\t\t\t\tpageNumber,\n\t\t\t\ttotalPages: pages.length,\n\t\t\t\t// The base link, without page number to use in <Pagination />\n\t\t\t\t// component.\n\t\t\t\tbaseLink: `${domainUrl}${compose}`,\n\t\t\t\tqueriedItems: dataInPage,\n\t\t\t\ttotalQueriedItems: totalQueriedItems?.length,\n\t\t\t},\n\t\t\tisRoot,\n\t\t\tdefaultLang,\n\t\t};\n\n\t\treturn createGriddoPageObject(paginatedPage, additionalInfo);\n\t});\n\n\treturn Promise.all(allPages);\n}\n\n/**\n * Create multiples pages from a MultiPage module\n *\n * @param page A Griddo Multipage object.\n * @param additionalInfo Additional page info.\n */\nfunction createGriddoMultiPages(page: GriddoMultiPage, additionalInfo: PageAdditionalInfo) {\n\tconst { multiPageElements: multiPageElementsBulk, ...cleanPage } = page;\n\t// TODO: Use structuredClone() when node 18 is available.\n\t// WARN!! Se ha probado que parse(stringify()) est\u00E1 tan optimizado que puede ser m\u00E1s r\u00E1pido que structuredClone...\n\tconst multiPageElements: MultiPageElements = JSON.parse(JSON.stringify(multiPageElementsBulk));\n\n\t// Si no hay un elemento sin slug, como m\u00EDnimo hay que dibujar una p\u00E1gina\n\t// principal para el conjunto de p\u00E1ginas.\n\tif (!multiPageElements.find(({ sectionSlug }) => sectionSlug === \"/\")) {\n\t\tmultiPageElements.push({} as MultiPageElement);\n\t}\n\n\t// Creates each page based on `multiPageElements` from the schema.\n\tconst allPages = multiPageElements.map(async (pageElement) => {\n\t\t// TODO: Use structuredClone() when node 18 is available.\n\t\t// WARN!! Se ha probado que parse(stringify()) est\u00E1 tan optimizado que puede ser m\u00E1s r\u00E1pido que structuredClone...\n\t\tconst paginatedPage: APIPageObject = JSON.parse(JSON.stringify(cleanPage));\n\t\tconst {\n\t\t\tsectionSlug = \"/\",\n\t\t\ttitle: bulkTitle = \"\",\n\t\t\tmetaTitle = \"\",\n\t\t\tmetaDescription = \"\",\n\t\t} = pageElement;\n\t\tconst title = typeof bulkTitle === \"string\" ? bulkTitle : bulkTitle.content;\n\t\tconst compose = paginatedPage.fullPath.compose || \"\";\n\t\tconst fullUrl = paginatedPage.fullUrl.endsWith(\"/\")\n\t\t\t? paginatedPage.fullUrl.slice(0, -1)\n\t\t\t: paginatedPage.fullUrl;\n\n\t\tconst cleanSectionSlug = sectionSlug?.replace(/\\//g, \"\");\n\t\tconst isRootSlug = sectionSlug === \"/\";\n\t\tconst rightSectionSlug = isRootSlug ? cleanSectionSlug : `${cleanSectionSlug}/`;\n\n\t\tconst slash = compose.endsWith(\"/\") ? \"\" : \"/\";\n\t\tconst newCompose = `${compose}${slash}${rightSectionSlug}`;\n\n\t\tif (title.trim()) {\n\t\t\tpaginatedPage.title = title;\n\t\t}\n\n\t\tif (metaDescription.trim()) {\n\t\t\tpaginatedPage.metaDescription = metaDescription;\n\t\t}\n\n\t\tpaginatedPage.fullUrl = `${fullUrl}/${rightSectionSlug}`;\n\t\tpaginatedPage.fullPath.compose = newCompose;\n\t\tpaginatedPage.slug = newCompose;\n\t\tpaginatedPage.template.activeSectionSlug = sectionSlug;\n\t\tpaginatedPage.template.activeSectionBase = fullUrl;\n\t\tpaginatedPage.metaTitle = metaTitle.trim() || title.trim() || paginatedPage.metaTitle;\n\n\t\treturn createGriddoPageObject(paginatedPage, additionalInfo);\n\t});\n\n\treturn Promise.all(allPages);\n}\n\n/**\n * Get the multi pages elements.\n *\n * @param page The page to get the multipage parts.\n */\nfunction getMultiPageElements(page: TemplateWithReferenceField): Promise<MultiPageElements> | null {\n\tconst multiPageElements = new Promise((resolve) => {\n\t\t// Recursive\n\t\tconst getMultiPageComponent = (\n\t\t\t// No puede ser Core.Page['template'] porque a medida que va bajando en\n\t\t\t// el \u00E1rbol ya no es la estructura de un template.\n\t\t\ttemplate: Record<string, unknown>,\n\t\t\tlevel = 0,\n\t\t) => {\n\t\t\t// If it doesn't have a \"template strcuture\"\n\t\t\tif (!template || typeof template !== \"object\") {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// For each prop in the \"template\"\n\t\t\tfor (const key in template) {\n\t\t\t\tconst currentComponent = template[key] as {\n\t\t\t\t\tcomponent: string;\n\t\t\t\t\thasGriddoMultiPage: boolean;\n\t\t\t\t\telements: Record<string, unknown>[];\n\t\t\t\t};\n\t\t\t\tconst isValidComponent = currentComponent || typeof currentComponent === \"object\";\n\t\t\t\tconst hasGriddoMultiPageProp = JSON.stringify(currentComponent).includes(\n\t\t\t\t\t'\"hasGriddoMultiPage\":true',\n\t\t\t\t);\n\n\t\t\t\tif (!isValidComponent) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (!hasGriddoMultiPageProp) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst { component, hasGriddoMultiPage, elements } = currentComponent;\n\n\t\t\t\tif (component && hasGriddoMultiPage) {\n\t\t\t\t\tresolve(elements || []);\n\t\t\t\t}\n\n\t\t\t\t// Recursive call\n\t\t\t\tgetMultiPageComponent(currentComponent, level + 1);\n\t\t\t}\n\n\t\t\t// resolve promise when...\n\t\t\tif (!level) {\n\t\t\t\tresolve(null);\n\t\t\t}\n\t\t};\n\n\t\t// `page` en un array para que tambi\u00E9n revise la propia template como objeto.\n\t\t// @ts-expect-error remove the array\n\t\tgetMultiPageComponent([page]);\n\t});\n\n\treturn multiPageElements as Promise<MultiPageElements>;\n}\n\n// -----------------------------------------------------------------------------\n// Private functions\n// -----------------------------------------------------------------------------\n\n/**\n * Get `itemsPerPage` elements from the `items` using as offset `page` number.\n * It's a kind of paginator for an array.\n *\n * @param itemsPerPage The items per page.\n * @param items An array of items, the queriedData.\n * @param page The page to be returned.\n *\n * @example\n * getPage(3, [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\"], 2)\n * // -> [\"d\", \"e\", \"f\"]\n */\nfunction getPage(itemsPerPage: number, items: Fields.QueriedDataItem[], page: number) {\n\treturn items?.slice(itemsPerPage * (page - 1), itemsPerPage * page);\n}\n\n/**\n * Takes an array of items and split it grouping in arrays of pages based on `itemsPerPage`.\n *\n * @param itemsPerPage The items per page.\n * @param items An array of items, the queriedData.\n *\n * @example\n * getPageCluster(3, [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\"])\n * // -> [[\"a\", \"b\", \"c\"], [\"d\", \"e\", \"f\"], [\"g\", \"h\"]]\n */\nfunction getPageCluster(itemsPerPage: number, items: Fields.QueriedDataItem[]) {\n\tconst totalPagesCount = Math.ceil(items.length / itemsPerPage) || 1;\n\tconst pageNumbers = Array.from({ length: totalPagesCount }, (_, i) => i + 1);\n\n\treturn pageNumbers?.map((pageNumber) => getPage(itemsPerPage, items, pageNumber));\n}\n\n/**\n * Takes a template object and split the whole queriedItems into separated queriedItems to use in Griddo static list templates.\n *\n * @param listTemplate A template schema with the ReferenceField data included.\n */\nfunction getPaginatedPages(listTemplate: TemplateWithReferenceField) {\n\tconst items = listTemplate.queriedItems || [];\n\tconst itemsPerPage = listTemplate?.itemsPerPage || DEFAULT_ITEMS_PER_PAGE_FOR_LIST_TEMPLATES;\n\tconst pageClusters = getPageCluster(itemsPerPage, items);\n\n\treturn pageClusters;\n}\n\n/**\n * Remove duplicate ending trailing character from a string\n *\n * @param url the strin url\n * @example\n * removeDuplicateTrailingSlash('http://griddo.com/foo/bar//')\n * // -> http://griddo.com/foo/bar/\n */\nfunction removeDuplicateTrailing(url: string) {\n\treturn url.replace(/\\/+$/, \"/\");\n}\n\n/**\n * Adds a number to an URL adding optionally an ending slash.\n *\n * @param url The url.\n * @param pageNumber A number to be added to the url.\n * @param options.addEndingSlash Boolean that indicates if return the final url with an end slash or not.\n *\n * @example\n * addPageNumberToUrl(\"web.com\", 3) // \"web.com/3\"\n * addPageNumberToUrl(\"web.com\", 3, { addEndingSlash: true }) // \"web.com/3/\"\n */\nfunction addPageNumberToUrl(\n\turl: string,\n\tpageNumber: number,\n\toptions?: { addEndingSlash: boolean },\n) {\n\tconst trailingSlash = url.endsWith(\"/\") ? \"\" : \"/\";\n\tconst endingSlash = options?.addEndingSlash ? \"/\" : \"\";\n\n\tif (pageNumber <= 1) {\n\t\treturn removeDuplicateTrailing(`${url}${endingSlash}`);\n\t}\n\n\treturn removeDuplicateTrailing(`${url}${trailingSlash}${pageNumber}${endingSlash}`);\n}\n\n/**\n * Adds a number to an string with the format \"string - number\"\n *\n * @param title The title\n * @param pageNumber A number to be added to the title.\n *\n * @example\n * addPageNumberToTitle(\"The page\", 3) // \"The page - 3\"\n */\nfunction addPageNumberToTitle(title: string, pageNumber: number) {\n\tif (!title || pageNumber <= 1) {\n\t\treturn title;\n\t}\n\n\treturn `${title} - ${pageNumber}`;\n}\n\nexport {\n\tcreateGriddoListPages,\n\tcreateGriddoMultiPages,\n\tcreateGriddoSinglePage,\n\tgetMultiPageElements,\n\tgetPaginatedPages,\n};\n", "import type { Core, Fields } from \"@griddo/core\";\nimport type { FetchDataProps } from \"../shared/types/global\";\nimport type { APIPageObject } from \"../shared/types/pages\";\n\nimport { GriddoLog } from \"../core/GriddoLog\";\nimport { getReferenceFieldSiteData } from \"./sites\";\n\n/**\n * Get the body data from a ReferenceField.\n * `auto`, `manual` or `navigation` mode.\n *\n * @param data The ReferenceField props.\n * @returns The props for one of the ReferenceField mode.\n */\nfunction getBody(data: Fields.Reference<unknown>, page: Core.Page) {\n\tconst {\n\t\torder,\n\t\tsources,\n\t\tquantity,\n\t\tmode,\n\t\tfixed,\n\t\tfullRelations = false,\n\t\tallLanguages = false,\n\t\tpreferenceLanguage = false,\n\t\treferenceId,\n\t\tfields,\n\t} = data;\n\n\tif (mode === \"auto\") {\n\t\treturn {\n\t\t\tmode,\n\t\t\torder,\n\t\t\tsources,\n\t\t\tquantity,\n\t\t\tfullRelations,\n\t\t\tallLanguages,\n\t\t\tpreferenceLanguage,\n\t\t\tfields,\n\t\t};\n\t}\n\n\tif (mode === \"manual\") {\n\t\treturn { mode, fixed, fullRelations, fields };\n\t}\n\n\tif (mode === \"navigation\") {\n\t\treturn {\n\t\t\tmode,\n\t\t\torder,\n\t\t\tquantity,\n\t\t\tfullRelations,\n\t\t\treferenceId: referenceId || page?.structuredDataContent?.id,\n\t\t\tfields,\n\t\t};\n\t}\n\n\tGriddoLog.error(`ReferenceField mode: ${mode} is not recognized on page ${page?.id}.`);\n\n\treturn data;\n}\n\n/**\n * Gets ContentType data from API\n *\n * @param props\n * @param props.page The Page object\n * @param props.component.data The ReferenceField, always in the data prop.\n * @param props.cacheKey A cache key to manage cached files or using fetch\n * @returns The ContentType data.\n */\nasync function fetchContentTypeData(props: FetchDataProps) {\n\tconst { page, component, cacheKey } = props;\n\tconst { data } = component;\n\n\t// Distrubutor with `hasDistributorData: true` / `getStaticData: true` but without `data` prop\n\tif (!data) {\n\t\tGriddoLog.info(\n\t\t\t`Error: Page ${page.id} has \\`hasDistributorData: true\\` or \\`getStaticData: true\\` but it doesn't have a \\`data\\` property.`,\n\t\t);\n\n\t\treturn [];\n\t}\n\n\t// Avoid fetch ReferenceField with empty `data.sources`\n\tif (Array.isArray(data.sources) && data.sources.length < 1) {\n\t\tGriddoLog.info(\n\t\t\t`Warning: Page with id: ${page.id} has a ReferenceField with empty \\`data.sources\\``,\n\t\t);\n\n\t\treturn [];\n\t}\n\n\tconst { site, lang } = data;\n\n\t// Inform that the ReferenceField has not `data.sources`\n\tif (!data.sources && data.mode === \"auto\") {\n\t\tGriddoLog.info(\n\t\t\t`Warning: Page with id: ${page.id} has a ReferenceField with \\`undefined\\` \\`data.sources\\``,\n\t\t);\n\t}\n\n\tconst body = getBody(data, page);\n\n\tconst response = await getReferenceFieldSiteData(page, body, cacheKey, site, lang);\n\n\treturn response;\n}\n\n/**\n * Compose the queriedItems prop from a ReferenceField data of a page.\n *\n * @param props\n * @param props.page The APIPage object\n * @param props.cacheKey A cache key to manage cached files or using fetch\n */\nasync function getReferenceFieldData({\n\tpage,\n\tcacheKey = \"\",\n}: {\n\tpage: APIPageObject;\n\t/** Reference id to manage cache between renders. */\n\tcacheKey: string;\n}) {\n\ttry {\n\t\tconst { template } = page;\n\t\tconst checkReferenceFields = async (\n\t\t\ttemplateChunk: {\n\t\t\t\thasDistributorData?: boolean;\n\t\t\t\tgetStaticData?: boolean;\n\t\t\t\tqueriedItems: Fields.QueriedData<unknown>;\n\t\t\t},\n\t\t\tlevel = 1,\n\t\t) => {\n\t\t\t// If it doesn't a \"template strcuture\"\n\t\t\tif (!templateChunk || typeof templateChunk !== \"object\") {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst hasRequestForData =\n\t\t\t\tJSON.stringify(templateChunk).includes('\"hasDistributorData\":true') ||\n\t\t\t\tJSON.stringify(templateChunk).includes('\"getStaticData\":true');\n\n\t\t\tif (!hasRequestForData) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// For each prop in the \"template\"\n\t\t\tfor (const key in templateChunk) {\n\t\t\t\t// Si la key es `queriedItems` saltamos al siguiente `key`\n\t\t\t\tif (key === \"queriedItems\") {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst _key = key as \"hasDistributorData\" | \"queriedItems\" | \"getStaticData\";\n\t\t\t\tconst component = templateChunk[_key] as unknown as {\n\t\t\t\t\tdata: Fields.Reference<unknown>;\n\t\t\t\t\tqueriedItems: Fields.QueriedData<unknown>;\n\t\t\t\t\thasDistributorData: boolean;\n\t\t\t\t\tgetStaticData: boolean;\n\t\t\t\t};\n\n\t\t\t\t// Si el elemento no existe o no es un objeto saltamos al siguiente `key`\n\t\t\t\tif (!component || typeof component !== \"object\") {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst componentHasRequestForData = component.hasDistributorData || component.getStaticData;\n\n\t\t\t\tif (componentHasRequestForData) {\n\t\t\t\t\tcomponent.queriedItems = await fetchContentTypeData({\n\t\t\t\t\t\tpage,\n\t\t\t\t\t\tcacheKey,\n\t\t\t\t\t\tcomponent,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tawait checkReferenceFields(component, level + 1);\n\t\t\t}\n\t\t};\n\n\t\tconst getReferenceFields = async (template: Core.Page[\"template\"]) => {\n\t\t\t// `template` es un array para que tambi\u00E9n revise la propia template como objeto.\n\t\t\t// @ts-expect-error\tremove the array\n\t\t\tawait checkReferenceFields([template]);\n\n\t\t\treturn template;\n\t\t};\n\n\t\tconst response = await getReferenceFields(template);\n\n\t\treturn response;\n\t} catch (err) {\n\t\tGriddoLog.error(\"Error in getReferenceFieldData:\", err);\n\n\t\tthrow err;\n\t}\n}\n\nexport { getReferenceFieldData };\n", "import type { RenderContext } from \"../../../shared/context\";\n\nimport { createStore } from \"../../../services/store\";\n\nexport async function dataAction(context: RenderContext) {\n\tconst {\n\t\tdomain,\n\t\trenderMode,\n\t\trenderMetadata: { griddoVersion },\n\t\tpathsHydratedWithDomain: { __root },\n\t} = context;\n\n\tconst { pagesToCreate, pagesToDelete } = await createStore({\n\t\tdomain,\n\t\trenderMode,\n\t\tgriddoVersion,\n\t\tbasePath: __root,\n\t});\n\n\tcontext.pagesToCreate = pagesToCreate;\n\tcontext.pagesToDelete = pagesToDelete;\n}\n", "import type { RenderContext } from \"../../../shared/context\";\n\nimport { assertRenderIsValid, markRenderAsCompleted } from \"../../../services/render\";\n\nexport async function healthCheckAction(context: RenderContext) {\n\tconst { domain } = context;\n\n\tawait assertRenderIsValid(domain);\n\tawait markRenderAsCompleted(domain);\n}\n", "import type { RenderContext } from \"../../../shared/context\";\n\nimport { markRenderAsStarted } from \"../../../services/render\";\n\nexport async function initAction(context: RenderContext) {\n\tconst {\n\t\tdomain,\n\t\tpathsHydratedWithDomain: { __root },\n\t} = context;\n\n\tawait markRenderAsStarted({ basePath: __root, domain });\n}\n", "import type { RenderContext } from \"../../../shared/context\";\nimport type { SSG } from \"../shared/types\";\n\nimport { saveDetailRenderLog } from \"../../../core/logger\";\n\nexport async function logsAction(context: RenderContext<SSG>) {\n\tconst { domain } = context;\n\n\tawait saveDetailRenderLog(domain);\n}\n", "import type { Robots } from \"../shared/types/global\";\n\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { pathExists } from \"../core/fs\";\nimport { GriddoLog } from \"../core/GriddoLog\";\nimport { ROBOTS } from \"../shared/endpoints\";\nimport { get } from \"./api\";\nimport { getRenderPathsHydratedWithDomainFromDB } from \"./render\";\n\nasync function fetchRobots() {\n\tconst apiRobots = await get<Robots>({ endpoint: ROBOTS });\n\treturn (\n\t\tapiRobots\n\t\t\t?.filter((r) => !!r.path)\n\t\t\t.map(({ path, content }) => ({\n\t\t\t\tpath,\n\t\t\t\tcontent: content || \"User-agent: *\\n\\r\\n\\rAllow: /\",\n\t\t\t})) || []\n\t);\n}\n\nasync function generateRobots(domain: string) {\n\tconst { __root } = await getRenderPathsHydratedWithDomainFromDB({ domain });\n\tconst distDirectory = path.join(__root, \"current-dist\");\n\tconst robot = (await fetchRobots()).find(({ path }) => path === `/${domain}`);\n\n\tif (!robot) {\n\t\tGriddoLog.info(`Robots not found for ${domain}`);\n\t\treturn;\n\t}\n\n\tif (await pathExists(distDirectory)) {\n\t\tconst fileLocation = path.join(distDirectory, \"robots.txt\");\n\t\tawait fsp.writeFile(fileLocation, robot?.content);\n\t\tGriddoLog.verbose(`wrote robots.txt to ${fileLocation}`);\n\t} else {\n\t\tGriddoLog.info(`${distDirectory} not found`);\n\t}\n}\n\nexport { generateRobots };\n", "import fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { pathExists } from \"../core/fs\";\nimport { GriddoLog } from \"../core/GriddoLog\";\nimport { generateSitemapIndexXml, generateUrlsetXml } from \"../shared/npm-modules/xml-parser\";\nimport { AuthService } from \"./auth\";\nimport { getBuildMetadata } from \"./manage-store\";\nimport { getRenderPathsHydratedWithDomainFromDB } from \"./render\";\nimport { getSitemap } from \"./sites\";\n\n/**\n * Generate sitemaps and save them into file system.\n */\nasync function generateSitemaps(domain: string) {\n\tconst { __root } = await getRenderPathsHydratedWithDomainFromDB();\n\tconst { sitesToPublish } = await getBuildMetadata(domain);\n\tconst distDir = path.join(__root, \"current-dist\");\n\tconst templateSitemapPrefix = \"sitemap-\";\n\n\tconst isGriddoSitemapFile = (file: string) =>\n\t\tfile === \"sitemap.xml\" || (file.startsWith(templateSitemapPrefix) && file.endsWith(\".xml\"));\n\n\tfor (const site of sitesToPublish) {\n\t\tconst { id, languages } = site;\n\n\t\tfor (const lang of languages) {\n\t\t\t// Local copy of headers to avoid mutating the shared object\n\t\t\tconst localHeaders: Record<string, string> = AuthService.headers\n\t\t\t\t? { ...AuthService.headers }\n\t\t\t\t: {};\n\t\t\tlocalHeaders.lang = lang.id.toString();\n\n\t\t\tconst response = await getSitemap({ siteId: id, headers: localHeaders });\n\n\t\t\tif (!response) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst { items: sitemapPagesGroup, url } = response;\n\t\t\tconst { home, domain } = url;\n\n\t\t\tif (!home) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst domainLanguage = site.domains.find(\n\t\t\t\t(domain) => Object.keys(domain)[0] === lang.id.toString(),\n\t\t\t);\n\n\t\t\tif (!domainLanguage) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst slug = Object.values(domainLanguage)[0];\n\t\t\tconst sitemaps: string[] = [];\n\t\t\tconst sitemapPageGroupKeys = Object.keys(sitemapPagesGroup);\n\t\t\tconst sitemapBasePath = path.join(distDir, slug.replace(domain, \"\"));\n\n\t\t\t/** delete every griddo sitemap file before create the new ones */\n\t\t\tif (await pathExists(sitemapBasePath)) {\n\t\t\t\ttry {\n\t\t\t\t\tconst files = await fsp.readdir(sitemapBasePath);\n\t\t\t\t\tfor (const file of files) {\n\t\t\t\t\t\tif (isGriddoSitemapFile(file)) {\n\t\t\t\t\t\t\tconst filePath = path.join(sitemapBasePath, file);\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tawait fsp.rm(filePath);\n\t\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\tGriddoLog.error(`Error deleting file ${filePath}:`, err);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (err) {\n\t\t\t\t\tGriddoLog.error(`Error reading ${sitemapBasePath}:`, err);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const templateId of sitemapPageGroupKeys) {\n\t\t\t\tconst sitemapPages = sitemapPagesGroup[templateId];\n\n\t\t\t\tif (!sitemapPages.length) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst siteMap = generateUrlsetXml(sitemapPages);\n\n\t\t\t\tconst sitemapName = `/${templateSitemapPrefix}${templateId.toLowerCase()}.xml`;\n\t\t\t\tconst exactPath = path.join(sitemapBasePath, sitemapName);\n\n\t\t\t\tawait saveFile(exactPath, siteMap);\n\t\t\t\tGriddoLog.verbose(`sitemap generated in ${exactPath}`);\n\n\t\t\t\tsitemaps.push(`${home.endsWith(\"/\") ? home.slice(0, -1) : home}${sitemapName}`);\n\t\t\t}\n\n\t\t\tif (!sitemaps.length) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst siteMap = generateSitemapIndexXml(sitemaps);\n\n\t\t\tconst exactPath = path.join(sitemapBasePath, \"sitemap.xml\");\n\n\t\t\tawait saveFile(exactPath, siteMap);\n\t\t\tGriddoLog.verbose(`sitemap generated in ${exactPath}`);\n\t\t}\n\t}\n}\n\n/**\n * Saves the content to a file specified by its path. If the file exists, it will be overwritten.\n *\n * @param filePath The path of the file to save the content to.\n * @param content The content to save to the file.\n */\nasync function saveFile(filePath: string, content: string) {\n\ttry {\n\t\tconst pathName = path.dirname(filePath);\n\t\tif (!(await pathExists(pathName))) {\n\t\t\tawait fsp.mkdir(pathName, { recursive: true });\n\t\t}\n\t\tawait fsp.writeFile(filePath, content);\n\t} catch (_error) {\n\t\tthrow new Error(`Error saving a file`);\n\t}\n}\n\nexport { generateSitemaps };\n", "import type { SitemapItem } from \"../types/api\";\n\nfunction escapeXml(unsafe: string) {\n\treturn unsafe.replace(/[<>&'\"\u201D]/g, (c) => {\n\t\tswitch (c) {\n\t\t\tcase \"<\":\n\t\t\t\treturn \"<\";\n\t\t\tcase \">\":\n\t\t\t\treturn \">\";\n\t\t\tcase \"&\":\n\t\t\t\treturn \"&\";\n\t\t\tcase \"'\":\n\t\t\t\treturn \"'\";\n\t\t\tcase '\"':\n\t\t\t\treturn \""\";\n\t\t\tcase \"\u201D\":\n\t\t\t\treturn \""\";\n\t\t\tdefault:\n\t\t\t\treturn c;\n\t\t}\n\t});\n}\n\nfunction generateUrlsetXml(pages: SitemapItem[]) {\n\tconst urls = pages\n\t\t.map(\n\t\t\t(page) =>\n\t\t\t\t` <url>\n <loc>${escapeXml(page.loc)}</loc>\n <lastmod>${page.lastmod}</lastmod>\n <priority>${page.priority}</priority>\n </url>`,\n\t\t)\n\t\t.join(\"\\n\");\n\n\treturn `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd\">\n${urls}\n</urlset>`;\n}\n\nfunction generateSitemapIndexXml(sitemaps: string[]) {\n\tconst sitemapEntries = sitemaps\n\t\t.map(\n\t\t\t(loc) => ` <sitemap>\n <loc>${escapeXml(loc)}</loc>\n </sitemap>`,\n\t\t)\n\t\t.join(\"\\n\");\n\n\treturn `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<sitemapindex xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n${sitemapEntries}\n</sitemapindex>`;\n}\n\nexport { generateSitemapIndexXml, generateUrlsetXml };\n", "import type { RenderContext } from \"../../../shared/context\";\n\nimport { generateBuildReport } from \"../../../services/render\";\nimport { generateRobots } from \"../../../services/robots\";\nimport { generateSitemaps } from \"../../../services/sitemaps\";\n\nexport async function metaAction(context: RenderContext) {\n\tconst { domain } = context;\n\n\tawait generateBuildReport(domain);\n\tawait generateSitemaps(domain);\n\tawait generateRobots(domain);\n}\n", "import type { RenderContext } from \"../../../shared/context\";\n\nimport { mkDirs } from \"../../../core/fs\";\n\nexport async function prepareAction(context: RenderContext) {\n\tconst { renderArtifacts } = context;\n\n\tawait mkDirs(renderArtifacts.initials);\n}\n", "import type { RenderContext } from \"../../../shared/context\";\n\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nexport async function relocationAction(context: RenderContext) {\n\tconst {\n\t\tpathsHydratedWithDomain: { __root, __ssg },\n\t} = context;\n\n\tconst src = path.join(__ssg, \"public\");\n\tconst dst = path.join(__root, \"current-dist\");\n\n\tawait fsp.rename(src, dst);\n}\n", "import type { RenderContext } from \"../../../shared/context\";\nimport type { SSG } from \"../shared/types\";\n\nimport { cpDirs, mvDirs } from \"../../../core/fs\";\nimport { RENDER_MODE } from \"../../../shared/types/render\";\n\nexport async function restoreAction(context: RenderContext<SSG>) {\n\tconst {\n\t\trenderMode,\n\t\tssg: { ssgArtifacts },\n\t\trenderArtifacts,\n\t\tpathsHydratedWithDomain: { __components, __root, __cache, __ssg },\n\t} = context;\n\n\tawait cpDirs(__components, __ssg, [\"static\"]);\n\n\tif (renderMode === RENDER_MODE.INCREMENTAL) {\n\t\tawait mvDirs(__cache, __ssg, ssgArtifacts.cacheables);\n\t\tawait mvDirs(__cache, __root, renderArtifacts.cacheables);\n\t}\n}\n", "import { spawn } from \"node:child_process\";\nimport path from \"node:path\";\n\nimport { GriddoLog } from \"../../../core/GriddoLog\";\nimport { getRenderPathsHydratedWithDomainFromDB } from \"../../../services/render\";\nimport { GRIDDO_SSG_VERBOSE_LOGS } from \"../../../shared/envs\";\n\n/**\n * Spawn a new node process `gatsby build`\n * @note This proccess can not access to the custom Griddo `process.env` so it\n * needs variables passed to it via the `env` prop.\n */\nasync function gatsbyBuild(assetPrefixWithDomain: string): Promise<void> {\n\tGriddoLog.verbose(`read assetPrefixWithDomain, ${assetPrefixWithDomain}`);\n\tGriddoLog.verbose(`using this NODE_OPTIONS in gatsby command: ${process.env.NODE_OPTIONS}`);\n\n\tconst { __ssg } = await getRenderPathsHydratedWithDomainFromDB();\n\n\t// Remove `--openssl-legacy-provider` from NODE_OPTIONS because this value\n\t// break Gatsby render.\n\tconst nodeOptionsWithoutLegacyOpenSSL = process.env.NODE_OPTIONS\n\t\t? process.env.NODE_OPTIONS.replace(/--openssl-legacy-provider\\s*/g, \"\").trim()\n\t\t: \"\";\n\n\t// Ruta al ejecutable de Gatsby\n\tconst gatsbyExecutable = path.join(__ssg, \"node_modules\", \".bin\", \"gatsby\");\n\n\tconst args = [\"build\", \"--prefix-paths\"];\n\tif (GRIDDO_SSG_VERBOSE_LOGS) {\n\t\targs.push(\"--verbose\");\n\t}\n\n\treturn new Promise((resolve, reject) => {\n\t\tconst child = spawn(gatsbyExecutable, args, {\n\t\t\tcwd: __ssg,\n\t\t\tstdio: [\"ignore\", \"inherit\", \"inherit\"],\n\t\t\tenv: {\n\t\t\t\t...process.env,\n\t\t\t\tSPAWN_ASSET_PREFIX_WITH_DOMAIN: assetPrefixWithDomain,\n\t\t\t\tNODE_OPTIONS: nodeOptionsWithoutLegacyOpenSSL,\n\t\t\t},\n\t\t});\n\n\t\tchild.on(\"close\", (code) => {\n\t\t\tif (code === 0) {\n\t\t\t\tresolve();\n\t\t\t} else {\n\t\t\t\treject(new Error(`Gatsby build failed with exit code ${code}`));\n\t\t\t}\n\t\t});\n\n\t\tchild.on(\"error\", (error) => {\n\t\t\treject(new Error(`Failed to start Gatsby build process: ${error.message}`));\n\t\t});\n\t});\n}\n\nexport { gatsbyBuild };\n", "import type { RenderContext } from \"../../../shared/context\";\nimport type { SSG } from \"../shared/types\";\n\nimport { gatsbyBuild } from \"../shared/gatsby-build\";\n\nexport async function ssgAction(context: RenderContext<SSG>) {\n\tconst {\n\t\tssg: { assetPrefix },\n\t} = context;\n\n\tawait gatsbyBuild(assetPrefix);\n}\n", "import type { RenderContext } from \"../../../shared/context\";\nimport type { SSG } from \"../shared/types\";\n\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { deleteDisposableSiteDirs, deleteEmptyDirectories, mvDirs } from \"../../../core/fs\";\nimport { RENDER_MODE } from \"../../../shared/types/render\";\nimport { extractAssetsFromDist } from \"../shared/extract-assets\";\nimport { SyncRender } from \"../shared/sync-render\";\n\nexport async function syncAction(context: RenderContext<SSG>) {\n\tconst {\n\t\trenderMode,\n\t\trenderArtifacts,\n\t\tdomain,\n\t\tpagesToCreate,\n\t\tpagesToDelete,\n\t\tpathsHydratedWithDomain: { __root, __ssg, __cache, __exports },\n\t\tssg: { ssgArtifacts, assetPrefix },\n\t} = context;\n\n\tconst needsAssetPrefix = !!assetPrefix && assetPrefix !== \"\";\n\tconst currentDist = path.join(__root, \"current-dist\");\n\tconst previousDist = path.join(__exports, \"dist\");\n\n\t// caching...\n\tawait mvDirs(__root, __cache, renderArtifacts.cacheables, { override: true });\n\tawait mvDirs(__ssg, __cache, ssgArtifacts.cacheables, { override: true });\n\n\tif (renderMode === RENDER_MODE.FROM_SCRATCH) {\n\t\tawait deleteDisposableSiteDirs(currentDist);\n\t\t// Es render nuevo, as\u00ED que el current-dist generado por gatsby hay que renombrarlo a dist\n\t\t// porque muchas de las acciones posteriores asumen ese nombre en ese path...\n\t\t// TODO: Cambiar eso y atomizar m\u00E1s las acciones.\n\t\tawait fsp.rm(previousDist, { force: true, recursive: true });\n\t\tawait fsp.rename(currentDist, previousDist);\n\t}\n\n\tif (renderMode === RENDER_MODE.INCREMENTAL) {\n\t\tawait deleteDisposableSiteDirs(previousDist);\n\n\t\tconst syncRender = new SyncRender({\n\t\t\tsrc: currentDist,\n\t\t\tdst: previousDist,\n\t\t\tpagesToCreate,\n\t\t\tpagesToDelete,\n\t\t\tartifactsToCopyToExports: [\"build-report.json\"],\n\t\t});\n\n\t\tawait syncRender.execute();\n\t\t// despu\u00E9s syncRender.execute() currentDist (que lo hizo gatsby) ya no es necesario\n\t\t// esta todo en __exports/dist porque syncRender.execute() ya sincroniniz\u00F3.\n\t\tawait fsp.rm(currentDist, { force: true, recursive: true });\n\t\tawait deleteEmptyDirectories(path.join(__exports, \"dist\"));\n\t}\n\n\tif (needsAssetPrefix) {\n\t\t// TODO: Mejorar performance\n\t\tawait extractAssetsFromDist(domain);\n\t}\n\n\t// rsync assets\n\tawait mvDirs(__root, __exports, renderArtifacts.archivables, { override: true });\n}\n", "import fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { pathExists } from \"../../../core/fs\";\nimport { getRenderPathsHydratedWithDomainFromDB } from \"../../../services/render\";\n\n/**\n * Update the Griddo's `/dist` dir with the contents from `public` dir only\n * with files of type: js, json and css.\n * TODO: Explicar que el static se copia a assets porque el js va en el subdominio de assets.\n */\nasync function extractAssetsFromDist(domain: string) {\n\tconst { __root, __exports } = await getRenderPathsHydratedWithDomainFromDB({ domain });\n\n\t// Archivos (no carpetas) v\u00E1lidos de public\n\tconst filesFromDist = (await fsp.readdir(path.join(__exports, \"dist\"))).filter(\n\t\t(file) =>\n\t\t\tpath.extname(file) === \".js\" ||\n\t\t\tpath.extname(file) === \".json\" ||\n\t\t\tpath.extname(file) === \".css\",\n\t);\n\n\t// Creamos assets si es necesario (needsAssetPrefix)\n\tawait fsp.mkdir(path.join(__root, \"assets\"), { recursive: true });\n\t// page-data folder\n\tawait fsp.cp(\n\t\tpath.join(__exports, \"dist\", \"page-data\"),\n\t\tpath.join(__root, \"assets\", \"page-data\"),\n\t\t{\n\t\t\tpreserveTimestamps: true,\n\t\t\trecursive: true,\n\t\t},\n\t);\n\t// static folder si existe\n\tif (await pathExists(path.join(__root, \"static\"))) {\n\t\tawait fsp.cp(path.join(__root, \"static\"), path.join(__root, \"assets\"), {\n\t\t\tforce: false,\n\t\t\tpreserveTimestamps: true,\n\t\t\trecursive: true,\n\t\t});\n\t}\n\t// dist/static -> assets/static\n\tif (await pathExists(path.join(__exports, \"dist\", \"static\"))) {\n\t\tawait fsp.cp(path.join(__exports, \"dist\", \"static\"), path.join(__root, \"assets\", \"static\"), {\n\t\t\tforce: false,\n\t\t\tpreserveTimestamps: true,\n\t\t\trecursive: true,\n\t\t});\n\t}\n\t// otro static...\n\tif (await pathExists(path.join(__root, \"static\"))) {\n\t\tawait fsp.cp(path.join(__root, \"static\"), path.join(__exports, \"dist\", domain), {\n\t\t\tpreserveTimestamps: true,\n\t\t\trecursive: true,\n\t\t\tforce: false,\n\t\t});\n\t}\n\n\t// Copia el resto de archivos...\n\t// for (const file of filesFromDist) {\n\t// \tconst fileSrc = path.join(__exports, \"dist\", file);\n\t// \tconst fileDest = path.join(__root, \"assets\", file);\n\t// \tawait fsp.cp(fileSrc, fileDest, { preserveTimestamps: true, recursive: true });\n\t// }\n\n\tconst arraysOfPromises: Promise<void>[] = filesFromDist.map((file) => {\n\t\tconst fileSrc = path.join(__exports, \"dist\", file);\n\t\tconst fileDest = path.join(__root, \"assets\", file);\n\t\treturn fsp.cp(fileSrc, fileDest, { preserveTimestamps: true, recursive: true });\n\t});\n\n\tawait Promise.all(arraysOfPromises);\n}\n\nexport { extractAssetsFromDist };\n", "import fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport pLimit from \"p-limit\";\n\nimport { findFilesBySuffix } from \"../../../core/fs\";\nimport { GriddoLog } from \"../../../core/GriddoLog\";\nimport { GRIDDO_SSG_BUNDLE_ANALYZER } from \"../../../shared/envs\";\nimport { getAssetsDiffBetweenRenders, patchHtmlFile } from \"./diff-assets\";\n\ninterface SyncRenderConfig {\n\tsrc: string;\n\tdst: string;\n\tpagesToCreate: number[];\n\tpagesToDelete: number[];\n\tartifactsToCopyToExports: string[];\n}\ninterface CopyFilePath {\n\tfrom: string;\n\tto: string;\n}\ninterface SyncState {\n\thtmlToAdd: CopyFilePath[];\n\tjsonToAdd: CopyFilePath[];\n\thtmlToDelete: string[];\n\tjsonToDelete: string[];\n}\ninterface PageInfo {\n\tid: number;\n\tcomposePath: string; // p.ej. '/about-us' o '/'\n\thtmlPath: string; // p.ej. '/path/to/public/about-us/index.html'\n\tjsonPath: string; // p.ej. '/path/to/public/page-data/about-us/page-data.json'\n}\ninterface GatsbyPageData {\n\tresult: {\n\t\tpageContext: {\n\t\t\tid: number;\n\t\t\tfullPath: {\n\t\t\t\tsite: string;\n\t\t\t\tdomain: string;\n\t\t\t\tdomainUrl: string;\n\t\t\t\tlanguage: string;\n\t\t\t\tpage: string;\n\t\t\t\tcompose: string;\n\t\t\t};\n\t\t};\n\t};\n}\n\nclass SyncRender {\n\tprivate bundleDir: string;\n\tprivate currentRenderDir: string;\n\tprivate pagesToCreate: number[];\n\tprivate pagesToDelete: number[];\n\tprivate assetArtifacts: string[];\n\n\tprivate state: SyncState = {\n\t\thtmlToAdd: [],\n\t\tjsonToAdd: [],\n\t\thtmlToDelete: [],\n\t\tjsonToDelete: [],\n\t};\n\n\tconstructor(config: SyncRenderConfig) {\n\t\tthis.bundleDir = config.dst;\n\t\tthis.currentRenderDir = config.src;\n\t\tthis.pagesToCreate = config.pagesToCreate;\n\t\tthis.pagesToDelete = config.pagesToDelete;\n\t\tthis.assetArtifacts = config.artifactsToCopyToExports;\n\t}\n\n\tpublic async execute() {\n\t\tawait this.setPagesToDelete();\n\t\tawait this.setPagesToAdd();\n\t\tawait this.sync();\n\t\tif (GRIDDO_SSG_BUNDLE_ANALYZER) {\n\t\t\tawait this.assertAssetsAreValid();\n\t\t}\n\t}\n\n\tprivate async assertAssetsAreValid() {\n\t\tconst isDifferent = await getAssetsDiffBetweenRenders(this.currentRenderDir, this.bundleDir);\n\t\tif (isDifferent) {\n\t\t\tGriddoLog.info(\n\t\t\t\t\"Warning: JavaScript and CSS bundles must have the same files and content. You can ignore this warning if the rendering process only has pages to unpublish.\",\n\t\t\t);\n\t\t} else {\n\t\t\tGriddoLog.info(\"Previous and current JavaScript and CSS packages successfully matched\");\n\t\t}\n\t}\n\n\tprivate async setPagesToDelete() {\n\t\t// INCLUIMOS LAS P\u00C1GINAS A CREAR EN LAS CANDIDATAS A BORRAR\n\t\t// =======================================================\n\t\t// El set de ids incluye tanto las p\u00E1ginas a borrar como las que se van\n\t\t// a crear para manejar correctamente los cambios de slug.\n\t\t//\n\t\t// Ejemplo: Si la p\u00E1gina `id=3` tiene slug `about` y despu\u00E9s viene con\n\t\t// `slug=about-us`, necesitamos borrar la p\u00E1gina `id=3` del render previo\n\t\t// y volver a crearla con la nueva ruta.\n\t\t//\n\t\t// \u00BFPor qu\u00E9? Porque el slug determina d\u00F3nde se guarda la p\u00E1gina:\n\t\t// - /about/index.html -> /about-us/index.html\n\t\t//\n\t\t// Si no la borr\u00E1semos previamente, tendr\u00EDamos ambas p\u00E1ginas:\n\t\t// `/about/index.html` y `/about-us/index.html`\n\t\tconst candidateIdsToDelete = new Set<number>([...this.pagesToDelete, ...this.pagesToCreate]);\n\t\tconst existingPreviousPages = await this.scanPages(this.bundleDir);\n\n\t\tfor (const page of existingPreviousPages) {\n\t\t\tif (candidateIdsToDelete.has(page.id)) {\n\t\t\t\tthis.state.htmlToDelete.push(page.htmlPath);\n\t\t\t\tthis.state.jsonToDelete.push(page.jsonPath);\n\t\t\t}\n\t\t}\n\n\t\tGriddoLog.verbose(`${this.state.htmlToDelete.length} pages HTML to delete`);\n\t\tGriddoLog.verbose(`${this.state.jsonToDelete.length} pages JSON to delete`);\n\t}\n\n\tprivate async setPagesToAdd() {\n\t\tconst candidateIdsToCreate = new Set<number>(this.pagesToCreate);\n\t\tconst newPages = await this.scanPages(this.currentRenderDir);\n\n\t\tfor (const page of newPages) {\n\t\t\tif (candidateIdsToCreate.has(page.id)) {\n\t\t\t\tconst htmlTo = path.join(this.bundleDir, page.composePath, \"index.html\");\n\t\t\t\tconst normalizedCompose = page.composePath === \"/\" ? \"index\" : page.composePath;\n\t\t\t\tconst jsonTo = path.join(this.bundleDir, \"page-data\", normalizedCompose, \"page-data.json\");\n\n\t\t\t\tthis.state.htmlToAdd.push({ from: page.htmlPath, to: htmlTo });\n\t\t\t\tthis.state.jsonToAdd.push({ from: page.jsonPath, to: jsonTo });\n\t\t\t}\n\t\t}\n\n\t\tGriddoLog.verbose(`${this.state.htmlToAdd.length} pages HTML to create`);\n\t\tGriddoLog.verbose(`${this.state.jsonToAdd.length} pages JSON to create`);\n\t}\n\n\tprivate async sync() {\n\t\t// Delete...\n\t\tconst allFilesToDelete = [...this.state.htmlToDelete, ...this.state.jsonToDelete];\n\t\tfor (const file of allFilesToDelete) {\n\t\t\ttry {\n\t\t\t\t// Usar `force: true` para no fallar si el archivo ya no existe.\n\t\t\t\tawait fsp.rm(file, { force: true });\n\t\t\t\tGriddoLog.verbose(`Sync (remove) : ${file}`);\n\t\t\t} catch (e) {\n\t\t\t\t// El error solo se registrar\u00EDa si es un problema de permisos, etc.\n\t\t\t\tGriddoLog.error(`Failed to remove ${file}:`, e);\n\t\t\t}\n\t\t}\n\n\t\tawait this.restoreWebpackCompilationHash();\n\n\t\t// Copy...\n\t\tconst allFilesToAdd = [...this.state.htmlToAdd, ...this.state.jsonToAdd];\n\t\tfor (const file of allFilesToAdd) {\n\t\t\ttry {\n\t\t\t\tawait fsp.mkdir(path.dirname(file.to), { recursive: true });\n\t\t\t\tawait fsp.copyFile(file.from, file.to);\n\t\t\t\tGriddoLog.verbose(`Sync (copy) : ${file.from} -> ${file.to}`);\n\t\t\t} catch (e) {\n\t\t\t\tGriddoLog.error(`Failed to copy ${file.from} to ${file.to}:`, e);\n\t\t\t}\n\t\t}\n\n\t\t// AVOID TO RESTORE webpackCompilationHash\n\t\t// await this.copyAppDataJsonFile();\n\t\tawait this.copyAssetArtifacts();\n\t\tawait this.copySitemaps();\n\t}\n\n\t// TODO: Optimizar esto a lo bestia...\n\tprivate async restoreWebpackCompilationHash() {\n\t\tconst appDataJsonFile = path.join(this.bundleDir, \"page-data\", \"app-data.json\");\n\t\tconst webpackCompilationHash = JSON.parse(\n\t\t\tawait fsp.readFile(appDataJsonFile, \"utf8\"),\n\t\t).webpackCompilationHash;\n\t\tGriddoLog.build(\n\t\t\t`Reading webpackCompilationHash from ${appDataJsonFile} = ${webpackCompilationHash}`,\n\t\t);\n\n\t\tconst changedHtmlFilePaths = this.state.htmlToAdd.map(({ from }) => from);\n\n\t\tfor (const htmlFilePath of changedHtmlFilePaths) {\n\t\t\tGriddoLog.build(`Patching HTML file ${htmlFilePath} with the new webpackCompilationHash`);\n\t\t\tawait patchHtmlFile(htmlFilePath, webpackCompilationHash);\n\t\t}\n\t}\n\n\t// private async copyAppDataJsonFile() {\n\t// \ttry {\n\t// \t\tconst src = path.join(this.currentRenderDir, \"page-data\", \"app-data.json\");\n\t// \t\tconst dst = path.join(this.bundleDir, \"page-data\", \"app-data.json\");\n\t// \t\tawait fsp.copyFile(src, dst);\n\t// \t\tGriddoLog.verbose(\"Copied app-data.json\");\n\t// \t} catch (e) {\n\t// \t\tGriddoLog.error(\"Failed to copy app-data.json:\", e);\n\t// \t}\n\t// }\n\n\tprivate async copyAssetArtifacts() {\n\t\tfor (const assetArtifact of this.assetArtifacts) {\n\t\t\tconst src = path.join(this.currentRenderDir, assetArtifact);\n\t\t\tconst dst = path.join(this.bundleDir, assetArtifact);\n\t\t\ttry {\n\t\t\t\tawait fsp.mkdir(path.dirname(dst), { recursive: true });\n\t\t\t\tawait fsp.copyFile(src, dst);\n\t\t\t\tGriddoLog.verbose(`Copied artifact: ${assetArtifact}`);\n\t\t\t} catch (e) {\n\t\t\t\tGriddoLog.error(`Failed to copy artifact ${src} to ${dst}:`, e);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async copySitemaps() {\n\t\tconst renderSrc = path.resolve(this.currentRenderDir);\n\t\tconst renderDst = path.resolve(this.bundleDir);\n\n\t\t// Primero, elimina los sitemaps existentes en el destino\n\t\tconst xmlFilesInDst = findFilesBySuffix(renderDst, \".xml\");\n\t\tfor await (const xmlFile of xmlFilesInDst) {\n\t\t\tconst basename = path.basename(xmlFile);\n\t\t\tif (basename.startsWith(\"sitemap-\") || basename === \"sitemap.xml\") {\n\t\t\t\tawait fsp.rm(xmlFile, { force: true });\n\t\t\t}\n\t\t}\n\n\t\t// Segundo, copia los nuevos sitemaps desde el origen\n\t\tconst xmlFilesInSrc = findFilesBySuffix(renderSrc, \".xml\");\n\t\tfor await (const src of xmlFilesInSrc) {\n\t\t\t// Reconstruye la ruta de destino de forma m\u00E1s robusta\n\t\t\tconst relativePath = path.relative(renderSrc, src);\n\t\t\tconst dst = path.join(renderDst, relativePath);\n\n\t\t\ttry {\n\t\t\t\tawait fsp.mkdir(path.dirname(dst), { recursive: true });\n\t\t\t\tawait fsp.copyFile(src, dst);\n\t\t\t} catch (e) {\n\t\t\t\tGriddoLog.error(`Failed to copy sitemap ${src} to ${dst}:`, e);\n\t\t\t}\n\t\t}\n\n\t\tGriddoLog.verbose(`Copied sitemap files.`);\n\t}\n\n\t/**\n\t * Escanea un directorio de build de Gatsby y extrae la informaci\u00F3n esencial\n\t * (PageInfo[]) de cada p\u00E1gina.\n\t * @param dir Directorio a escanear (src o dst).\n\t * @returns Un array con la informaci\u00F3n de cada p\u00E1gina encontrada.\n\t */\n\tprivate async scanPages(dir: string): Promise<PageInfo[]> {\n\t\t// 1. Crea una instancia de p-limit con 128 lecturas a la vez...\n\t\t// Como ejemplo: macOS tiene un l\u00EDmite que suele empezar en 256.\n\t\t// De todas maneras libuv tiene un l\u00EDmite de 4 hilos en node\n\t\tconst limit = pLimit(32);\n\n\t\t// 2. Recolecta todos los paths de los archivos.\n\t\tconst gatsbyPageDataGenerator = findFilesBySuffix(\n\t\t\tpath.join(dir, \"page-data\"),\n\t\t\t\"page-data.json\",\n\t\t);\n\t\tconst processingPromises: Promise<PageInfo | null>[] = [];\n\t\tfor await (const file of gatsbyPageDataGenerator) {\n\t\t\tprocessingPromises.push(\n\t\t\t\tlimit(async (): Promise<PageInfo | null> => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst fileContent = await fsp.readFile(file, \"utf-8\");\n\t\t\t\t\t\tconst content = JSON.parse(fileContent) as GatsbyPageData;\n\n\t\t\t\t\t\tconst id = content.result.pageContext.id;\n\t\t\t\t\t\tconst composePath = content.result.pageContext.fullPath.compose;\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\tcomposePath,\n\t\t\t\t\t\t\thtmlPath: path.join(dir, composePath, \"index.html\"),\n\t\t\t\t\t\t\tjsonPath: file,\n\t\t\t\t\t\t};\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tGriddoLog.error(`Error reading or parsing page data from ${file}:`, e);\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\n\t\t// 4. Go :)\n\t\tconst pagesFoundOrNull = await Promise.all(processingPromises);\n\n\t\t// 5. Filtra los nulos y devuelve solo las p\u00E1ginas v\u00E1lidas.\n\t\treturn pagesFoundOrNull.filter((page): page is PageInfo => page !== null);\n\t}\n}\n\nexport { SyncRender };\n", "import { createHash } from \"node:crypto\";\nimport fsp from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { GriddoLog } from \"../../../core/GriddoLog\";\n\n/**\n * Patrones de archivos de assets cr\u00EDticos para la comparaci\u00F3n de builds.\n * Estos archivos son los que realmente afectan el webpackCompilationHash:\n * - app-*.js: C\u00F3digo principal de la aplicaci\u00F3n\n * - framework-*.js: Framework de Gatsby/React\n * - webpack-runtime-*.js: Runtime de webpack\n *\n * Si estos archivos no cambian entre renders, el hash deber\u00EDa ser el mismo.\n */\n// const _KEY_ASSET_PATTERNS = [/^app-.*\\.js$/, /^framework-.*\\.js$/, /^webpack-runtime-.*\\.js$/];\n\nconst KEY_ASSET_PATTERNS = [/\\.js$/];\n\n/**\n * Calcula los hashes SHA256 del contenido de los assets clave en un directorio.\n * Solo procesa archivos que coincidan con KEY_ASSET_PATTERNS.\n *\n * @param dir La ruta al directorio (ej. './public')\n * @returns Un Map donde la clave es el nombre del fichero y el valor es su hash.\n * Si el directorio no existe o hay errores, retorna un Map vac\u00EDo.\n */\nasync function getAssetHashes(dir: string): Promise<Map<string, string>> {\n\tconst assetHashes = new Map<string, string>();\n\n\ttry {\n\t\tconst allFiles = await fsp.readdir(dir);\n\t\tconst keyAssetFiles = allFiles.filter((fileName) =>\n\t\t\tKEY_ASSET_PATTERNS.some((pattern) => pattern.test(fileName)),\n\t\t);\n\n\t\tfor (const fileName of keyAssetFiles) {\n\t\t\tconst filePath = join(dir, fileName);\n\t\t\tconst fileContent = await fsp.readFile(filePath);\n\t\t\tconst hash = createHash(\"sha256\").update(fileContent).digest(\"hex\");\n\t\t\tassetHashes.set(fileName, hash);\n\t\t}\n\n\t\treturn assetHashes;\n\t} catch (error) {\n\t\tGriddoLog.build(`ERROR: Error processing directory ${dir}: ${error}`);\n\t\t// Si un directorio no existe (ej. el de producci\u00F3n la primera vez),\n\t\t// lo tratamos como si no tuviera assets.\n\t\treturn assetHashes;\n\t}\n}\n\n/**\n * Compara los assets clave entre dos directorios de build de Gatsby.\n * Solo compara los archivos definidos en KEY_ASSET_PATTERNS.\n *\n * @param dir1 Ruta al primer directorio (ej. el de producci\u00F3n)\n * @param dir2 Ruta al segundo directorio (ej. el del nuevo build)\n * @returns `true` si hay diferencias en los assets clave, `false` si son id\u00E9nticos.\n */\nexport async function getAssetsDiffBetweenRenders(dir1: string, dir2: string): Promise<boolean> {\n\tconst [hashes1, hashes2] = await Promise.all([getAssetHashes(dir1), getAssetHashes(dir2)]);\n\n\t// Si el n\u00FAmero de assets clave es diferente, hay cambios.\n\tif (hashes1.size !== hashes2.size) {\n\t\treturn true;\n\t}\n\n\t// Comparamos los hashes de cada fichero.\n\tfor (const [fileName, hash1] of hashes1.entries()) {\n\t\tconst hash2 = hashes2.get(fileName);\n\n\t\t// Si un fichero existe en el primero pero no en el segundo, hay cambios.\n\t\tif (!hash2) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Si el contenido (hash) de un fichero ha cambiado.\n\t\tif (hash1 !== hash2) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\n/**\n * Actualiza el webpackCompilationHash en un \u00FAnico fichero HTML.\n * @param filePath Ruta al fichero HTML.\n * @param newHash El nuevo hash a insertar.\n */\nexport async function patchHtmlFile(filePath: string, newHash: string): Promise<void> {\n\ttry {\n\t\tconst content = await fsp.readFile(filePath, \"utf-8\");\n\n\t\t// Esta expresi\u00F3n regular captura tres grupos:\n\t\t// 1. La parte ANTES del hash (window.___webpackCompilationHash=\")\n\t\t// 2. El hash ANTIGUO ([^\"]*)\n\t\t// 3. La parte DESPU\u00C9S del hash (\";</script>)\n\t\tconst regex = /(window\\.___webpackCompilationHash=\")([^\"]*)(\";<\\/script>)/;\n\n\t\t// Solo reemplazamos el segundo grupo (el hash)\n\t\tconst newContent = content.replace(regex, `$1${newHash}$3`);\n\n\t\tif (content === newContent) {\n\t\t\t// GriddoLog.warn(`WARN: No se encontr\u00F3 el hash en ${filePath}. El fichero no fue modificado.`);\n\t\t\treturn;\n\t\t}\n\n\t\tawait fsp.writeFile(filePath, newContent, \"utf-8\");\n\t} catch (error) {\n\t\tGriddoLog.error(`Failed to process file ${filePath}: ${error}`);\n\t}\n}\n\n// --- Ejemplo de uso ---\n// async function miScriptDeDeploy() {\n// const dirProduccion = '/ruta/a/produccion/public';\n// const dirNuevoBuild = './public';\n\n// const hayDiferencias = await getAssetsDiffBetweenRenders(dirProduccion, dirNuevoBuild);\n\n// if (hayDiferencias) {\n// // L\u00F3gica para el CAMINO A (cambio de c\u00F3digo)\n// } else {\n// // L\u00F3gica para el CAMINO B (solo contenido)\n// }\n// }\n", "import path from \"node:path\";\n\nimport { readDB } from \"../../../core/db\";\n\nexport async function getGatsbyArtifacts() {\n\tconst { ssg } = (await readDB()).paths;\n\n\treturn {\n\t\tdisposables: [\n\t\t\t//\n\t\t\tpath.join(ssg, \"public\"),\n\t\t\tpath.join(ssg, \"static\"),\n\t\t\tpath.join(ssg, \".cache\"),\n\t\t],\n\t\tcacheables: [\".cache\"],\n\t};\n}\n", "import { readDB, writeDB } from \"../../../core/db\";\nimport { GriddoLog } from \"../../../core/GriddoLog\";\n\n/**\n * Enables the rollback-on-error feature for subsequent render lifecycles.\n * When this feature is active, if an error occurs during a render process,\n * the application will automatically restore the 'exports' directory to its\n * state before the render began. This function updates the configuration\n * in the database to reflect this change.\n * @async\n */\nasync function enableRollbackOnError() {\n\tconst data = await readDB();\n\tdata.needsRollbackOnError = true;\n\tawait writeDB(data);\n\tGriddoLog.info(\"Render lifecycles that follow will restore the exports dir on error if needed\\n\");\n}\n\n/**\n * Disables the rollback-on-error feature for subsequent render lifecycles.\n * When this feature is inactive, the application will not restore the\n * 'exports' directory if a render process fails. This is the default behavior.\n * This function updates the configuration in the database.\n * @async\n */\nasync function disableRollbackOnError() {\n\tconst data = await readDB();\n\tdata.needsRollbackOnError = false;\n\tawait writeDB(data);\n\tGriddoLog.info(\"Render lifecycles that follow will not restore the exports dir on error\\n\");\n}\n\nexport { disableRollbackOnError, enableRollbackOnError };\n", "import { withErrorHandler } from \"../core/errors\";\nimport { showExporterVersion } from \"../core/print-logos\";\nimport { AuthService } from \"../services/auth\";\nimport { gatsbyRenderDomain } from \"../ssg-adapters/gatsby\";\n\nasync function render() {\n\tawait AuthService.login();\n\tconst [domain] = process.argv.slice(2);\n\tawait gatsbyRenderDomain(domain);\n}\n\nasync function main() {\n\tawait showExporterVersion();\n\tawait render();\n}\n\nwithErrorHandler(main);\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["import_node_path", "RESET", "CODES", "brush", "color", "key", "text", "RENDER_MODE", "import_promises", "import_node_path", "import_node_path", "import_node_fs", "import_node_path", "import_node_process", "import_node_url", "toPath", "urlOrPath", "findUpSync", "name", "options", "cwd", "process", "type", "stopAtOption", "directory", "path", "toPath", "root", "stopAt", "isAbsoluteName", "filePath", "stats", "fs", "pkgDirSync", "options", "cwd", "filePath", "findUpSync", "path", "env", "envIsTruthy", "value", "GRIDDO_API_URL", "GRIDDO_PUBLIC_API_URL", "GRIDDO_BOT_USER", "GRIDDO_BOT_PASSWORD", "GRIDDO_API_CONCURRENCY_COUNT", "GRIDDO_SKIP_BUILD_CHECKS", "GRIDDO_BUILD_LOGS", "GRIDDO_BUILD_LOGS_BUFFER_SIZE", "GRIDDO_SSG_VERBOSE_LOGS", "GRIDDO_SEARCH_FEATURE", "GRIDDO_ASSET_PREFIX", "GRIDDO_REACT_APP_INSTANCE", "GRIDDO_AI_EMBEDDINGS", "GRIDDO_VERBOSE_LOGS", "GRIDDO_USE_DIST_BACKUP", "GRIDDO_SSG_BUNDLE_ANALYZER", "GriddoLog", "_GriddoLog", "str", "GRIDDO_VERBOSE_LOGS", "brush", "GRIDDO_BUILD_LOGS", "args", "root", "pkgDirSync", "path", "cache", "dbFilePath", "readDB", "customDBPath", "file", "fsp", "error", "GriddoLog", "writeDB", "renderDB", "import_promises", "import_node_path", "import_promises", "import_node_path", "ArtifactError", "LifecycleExecutionError", "attempts", "name", "LoginError", "RenderUUIDError", "WriteToStoreError", "deleteDisposableSiteDirs", "baseDir", "pathExists", "sitesDirs", "fsp", "file", "siteDir", "sitePath", "path", "siteIsEmpty", "mkDirs", "dirs", "options", "dir", "GriddoLog", "error", "throwError", "ArtifactError", "cpDirs", "src", "dst", "dirs", "options", "withBackup", "dir", "srcCompose", "path", "dstCompose", "pathExists", "GriddoLog", "createBackup", "fsp", "deleteBackup", "error", "restoreBackup", "throwError", "ArtifactError", "mvDirs", "override", "rmDirs", "suffix", "siteIsEmpty", "sitePath", "siteFiles", "file", "xmlFiles", "deleteEmptyDirectories", "dirPath", "filesInDirectory", "err", "fullPath", "findFilesBySuffix", "dirHandle", "item", "distRollback", "domain", "data", "readDB", "exportsDir", "exportsDirBackup", "GriddoLog", "path", "fsp", "pathExists", "RenderError", "originalError", "throwError", "options", "stack", "error", "message", "expected", "hint", "errorColor", "GriddoLog", "brush", "extraText", "withErrorHandler", "fn", "data", "readDB", "root", "path", "distRollback", "RENDER_MODE", "writeDB", "import_promises", "import_node_path", "showExporterVersion", "version", "fsp", "path", "logo", "brush", "GriddoLog", "GRIDDO_API_URL", "GRIDDO_PUBLIC_API_URL", "AI_EMBEDDINGS", "ALERT", "DOMAINS", "GET_ALL", "GET_PAGE", "LOGIN", "RESET_RENDER", "ROBOTS", "SEARCH", "SETTINGS", "SITE_URI", "BUILD_END", "BUILD_START", "GET_REFERENCE_FIELD_DATA", "GET_SITEMAP", "INFO", "LANGUAGES", "SOCIALS", "package_default", "DEFAULT_HEADERS", "package_default", "AuthService", "response", "LOGIN", "DEFAULT_HEADERS", "GRIDDO_BOT_USER", "GRIDDO_BOT_PASSWORD", "token", "e", "throwError", "LoginError", "authService", "import_node_path", "executeAndReturnExecutionTime", "func", "start", "end", "doLifeCycle", "name", "action", "options", "maxRetrys", "skip", "GriddoLog", "trysCount", "exeTime", "error", "errorString", "brush", "attemptsString", "throwError", "LifecycleExecutionError", "import_promises", "import_node_path", "logBuffer", "logFilePath", "flushPromise", "LOG_BUFFER_FLUSH_THRESHOLD", "GRIDDO_BUILD_LOGS_BUFFER_SIZE", "LOG_FILENAME", "LOG_TO_FILE_IS_DISABLED", "GRIDDO_BUILD_LOGS", "dbData", "getDBData", "readDB", "initializeLogFile", "data", "path", "fsp", "addLogToBuffer", "lineContent", "flushLogsToFile", "error", "GriddoLog", "logsToFlush", "saveDetailRenderLog", "domain", "dateString", "getFormattedDateTime", "debugDir", "src", "dst", "now", "year", "month", "day", "hours", "minutes", "seconds", "import_node_child_process", "import_promises", "import_node_path", "import_promises", "import_node_path", "getBuildMetadata", "domain", "db", "readDB", "sitesToPublish", "createdPages", "buildProcessData", "saveRenderInfoInStore", "renderInfo", "writeDB", "saveSitePagesInStore", "siteDirName", "pages", "__root", "getRenderPathsHydratedWithDomainFromDB", "propsToRemove", "page", "removeProperties", "filename", "filePath", "path", "writeUniqueFileSync", "error", "throwError", "WriteToStoreError", "removeOrphanSites", "sitesToPublish", "domain", "storePath", "pathExists", "currentSitesInStore", "fsp", "sitesFromAPI", "id", "sitesToDelete", "site", "GriddoLog", "content", "dir", "ext", "base", "uniquePath", "counter", "newName", "obj", "remove", "currentObj", "key", "value", "markRenderAsStarted", "options", "domain", "db", "readDB", "writeDB", "__ssg", "getRenderPathsHydratedWithDomainFromDB", "renderSentinelFile", "path", "fsp", "markRenderAsCompleted", "RENDER_MODE", "assertRenderIsValid", "pathExists", "throwError", "RenderUUIDError", "updateCommitFile", "options", "basePath", "currentCommit", "fsp", "path", "getRenderModeFromDB", "domain", "db", "readDB", "brush", "getRenderPathsHydratedWithDomainFromDB", "dbFilePath", "paths", "getRenderMetadataFromDB", "generateBuildReport", "authControl", "authService", "__root", "buildReportFileName", "buildProcessData", "getBuildMetadata", "buildSitesInfo", "siteID", "report", "reportFilePath", "GriddoLog", "import_node_path", "getRenderArtifacts", "domain", "__exports", "__cache", "__root", "__ssg", "getRenderPathsHydratedWithDomainFromDB", "path", "RenderContext", "domain", "renderMode", "ssg", "pathsHydratedWithDomain", "renderMetadata", "renderArtifacts", "import_promises", "import_node_path", "cleanAction", "context", "renderArtifacts", "ssgArtifacts", "__cache", "__exports", "renderMode", "RENDER_MODE", "fsp", "path", "rmDirs", "closeAction", "context", "renderArtifacts", "ssgArtifacts", "__cache", "rmDirs", "updateCommitFile", "import_promises", "import_node_path", "Node", "value", "Queue", "#head", "#tail", "#size", "node", "current", "pLimit", "concurrency", "validateConcurrency", "queue", "Queue", "activeCount", "resumeNext", "next", "run", "function_", "resolve", "arguments_", "result", "enqueue", "internalResolve", "generator", "newConcurrency", "iterable", "promises", "value", "index", "validateConcurrency", "concurrency", "import_node_crypto", "import_promises", "import_node_path", "env", "RETRY_WAIT_SECONDS", "RETRY_ATTEMPTS", "requestAPI", "props", "method", "appendToLog", "endpoint", "body", "cacheKey", "attempt", "headers", "useApiCacheDir", "logToFile", "cacheOptions", "start", "cacheData", "searchCacheData", "siteId", "getSafeSiteId", "siteIdMsg", "duration", "msToSec", "addLogToBuffer", "fetchOptions", "DEFAULT_HEADERS", "authService", "response", "data", "saveCache", "e", "error", "GriddoLog", "RenderError", "showApiError", "delay", "getApi", "postApi", "props", "endpoint", "body", "headers", "referenceFieldBodyParams", "requestAPI", "showApiError", "error", "options", "message", "stack", "callInfo", "callInfoArray", "item", "callInfoStr", "errorDetailsStr", "GriddoLog", "brush", "getSafeSiteId", "response", "delay", "ms", "res", "msToSec", "decimals", "generateFilenameWithHash", "petition", "__root", "getRenderPathsHydratedWithDomainFromDB", "apiCacheDir", "path", "hashSum", "crypto", "saveCache", "content", "stringContent", "filename", "filepath", "pathExists", "fsp", "searchCacheData", "file", "fileContent", "import_promises", "import_node_path", "getAllSites", "domain", "getApi", "GET_ALL", "getPage", "id", "cacheKey", "getApi", "GET_PAGE", "getSiteInfo", "prefix", "suffix", "INFO", "getSiteLanguages", "LANGUAGES", "startSiteRender", "BUILD_START", "endSiteRender", "body", "BUILD_END", "postApi", "getReferenceFieldSiteData", "page", "dataSiteId", "dataLangID", "GET_REFERENCE_FIELD_DATA", "site", "lang", "getSitemap", "options", "siteId", "headers", "GET_SITEMAP", "getSiteSocials", "SOCIALS", "getSitesToRender", "domain", "allSites", "getAllSites", "site", "items", "getSiteLanguages", "item", "sitesToPublish", "sitesToUnpublish", "unpublishSites", "sites", "__root", "getRenderPathsHydratedWithDomainFromDB", "buildInfo", "startSiteRender", "siteHash", "body", "endSiteRender", "fsp", "path", "getSiteData", "siteID", "buildData", "siteInfo", "getSiteInfo", "siteLangs", "socials", "getSiteSocials", "siteLangsInfo", "defaultLang", "lang", "unpublishHashes", "publishIds", "headers", "footers", "NavigationService", "navigations", "defaultFooters", "footer", "defaultFootersByLang", "item", "defaultHeaders", "header", "defaultHeadersByLang", "list", "id", "language", "result", "version", "page", "pageHeader", "pageFooter", "template", "templateConfig", "templateType", "defaultHeader", "defaultFooter", "templates", "getValidNavigation", "values", "fineNavigation", "headerID", "footerID", "formatImage", "image", "width", "height", "format", "url", "addCloudinaryParams", "addGriddoDamParams", "params", "urlParts", "imagePath", "imageName", "plainUrl", "head", "fullId", "DEFAULT_ITEMS_PER_PAGE_FOR_LIST_TEMPLATES", "getOpenGraph", "socialTitle", "socialDescription", "socialImage", "formatImage", "getPageMetadata", "params", "title", "metaTitle", "metaDescription", "canonicalURL", "locale", "url", "isIndexed", "follow", "metasAdvanced", "pageLanguages", "fullUrl", "metaKeywords", "metasAdvancedList", "item", "keyword", "createGriddoPageObject", "page", "additionalInfo", "id", "fullPath", "languageId", "breadcrumb", "baseUrl", "cloudinaryName", "griddoVersion", "siteLangs", "siteMetadata", "siteOptions", "siteScript", "siteSlug", "socials", "theme", "navigations", "header", "footer", "pageMetadata", "openGraph", "pagePath", "renderDate", "createGriddoSinglePage", "createGriddoListPages", "pages", "isRoot", "defaultLang", "template", "totalQueriedItems", "allPages", "dataInPage", "idx", "isFirstPage", "pageNumber", "domainUrl", "compose", "paginatedPage", "addPageNumberToUrl", "addPageNumberToTitle", "createGriddoMultiPages", "multiPageElementsBulk", "cleanPage", "multiPageElements", "sectionSlug", "pageElement", "bulkTitle", "cleanSectionSlug", "rightSectionSlug", "slash", "newCompose", "getMultiPageElements", "resolve", "getMultiPageComponent", "level", "key", "currentComponent", "isValidComponent", "hasGriddoMultiPageProp", "component", "hasGriddoMultiPage", "elements", "getPage", "itemsPerPage", "items", "getPageCluster", "totalPagesCount", "_", "i", "getPaginatedPages", "listTemplate", "removeDuplicateTrailing", "options", "trailingSlash", "endingSlash", "getBody", "data", "page", "order", "sources", "quantity", "mode", "fixed", "fullRelations", "allLanguages", "preferenceLanguage", "referenceId", "fields", "GriddoLog", "fetchContentTypeData", "props", "component", "cacheKey", "site", "lang", "body", "getReferenceFieldSiteData", "getReferenceFieldData", "template", "checkReferenceFields", "templateChunk", "level", "key", "err", "renderId", "guessSiteNeedsToBeRenderedFromScratch", "listSitesLog", "title", "sites", "maxline", "s", "sitesStr", "shouldBeUpdated", "lineLen", "padding", "brush", "sitesOutput", "GriddoLog", "createStore", "options", "GRIDDO_API_CONCURRENCY_COUNT", "GRIDDO_API_URL", "renderMode", "domain", "griddoVersion", "basePath", "renderFromScratch", "RENDER_MODE", "storeDir", "path", "createdPages", "buildProcessData", "sitesToPublish", "sitesToUnpublish", "getSitesToRender", "unpublishSites", "removeOrphanSites", "allPagesToRemoveFromBuild", "site", "pagesStatus", "siteId", "siteSlug", "theme", "favicon", "siteDirName", "siteInfo", "siteHash", "unpublishHashes", "siteLangs", "defaultLang", "headers", "footers", "socials", "getSiteData", "cloudinaryName", "useMetaTitle", "useMetaKeywords", "showBasicMetaRobots", "avoidHrefLangsOnCanonicals", "avoidSelfReferenceCanonicals", "avoidHrefLangXDefault", "avoidDebugMetas", "getApi", "SETTINGS", "NavService", "NavigationService", "shouldUpdateSite", "updatedSiteHash", "siteScript", "siteMetadata", "additionalInfo", "GRIDDO_PUBLIC_API_URL", "GRIDDO_REACT_APP_INSTANCE", "fsp", "fetchSitePageAndSaveInStore", "siteIdName", "pageId", "griddoPageObjects", "page", "getPage", "pageAdditionalInfo", "template", "getReferenceFieldData", "multiPageElements", "getMultiPageElements", "isStaticListPage", "isMultiPage", "isSinglePage", "griddoListPage", "getPaginatedPages", "createGriddoListPages", "griddoMultipage", "createGriddoMultiPages", "griddoSinglePage", "createGriddoSinglePage", "saveSitePagesInStore", "pagesToFetchFromAPI", "sitePendingOfPublishing", "limit", "pLimit", "pagesToStore", "id", "saveRenderInfoInStore", "getHashSites", "__root", "getRenderPathsHydratedWithDomainFromDB", "siteHasFilename", "fileContent", "allHash", "lastHash", "currentHash", "dataAction", "context", "domain", "renderMode", "griddoVersion", "__root", "pagesToCreate", "pagesToDelete", "createStore", "healthCheckAction", "context", "domain", "assertRenderIsValid", "markRenderAsCompleted", "initAction", "context", "domain", "__root", "markRenderAsStarted", "logsAction", "context", "domain", "saveDetailRenderLog", "import_promises", "import_node_path", "fetchRobots", "getApi", "ROBOTS", "r", "path", "content", "generateRobots", "domain", "__root", "getRenderPathsHydratedWithDomainFromDB", "distDirectory", "robot", "GriddoLog", "pathExists", "fileLocation", "fsp", "import_promises", "import_node_path", "escapeXml", "unsafe", "c", "generateUrlsetXml", "pages", "page", "generateSitemapIndexXml", "sitemaps", "loc", "generateSitemaps", "domain", "__root", "getRenderPathsHydratedWithDomainFromDB", "sitesToPublish", "getBuildMetadata", "distDir", "path", "templateSitemapPrefix", "isGriddoSitemapFile", "file", "site", "id", "languages", "lang", "localHeaders", "authService", "response", "getSitemap", "sitemapPagesGroup", "url", "home", "domainLanguage", "slug", "sitemaps", "sitemapPageGroupKeys", "sitemapBasePath", "pathExists", "files", "fsp", "filePath", "err", "GriddoLog", "templateId", "sitemapPages", "siteMap", "generateUrlsetXml", "sitemapName", "exactPath", "saveFile", "generateSitemapIndexXml", "content", "pathName", "metaAction", "context", "domain", "generateBuildReport", "generateSitemaps", "generateRobots", "prepareAction", "context", "renderArtifacts", "mkDirs", "import_promises", "import_node_path", "relocationAction", "context", "__root", "__ssg", "src", "path", "dst", "fsp", "restoreAction", "context", "renderMode", "ssgArtifacts", "renderArtifacts", "__components", "__root", "__cache", "__ssg", "cpDirs", "RENDER_MODE", "mvDirs", "import_node_child_process", "import_node_path", "gatsbyBuild", "assetPrefixWithDomain", "GriddoLog", "__ssg", "getRenderPathsHydratedWithDomainFromDB", "nodeOptionsWithoutLegacyOpenSSL", "gatsbyExecutable", "path", "args", "GRIDDO_SSG_VERBOSE_LOGS", "resolve", "reject", "child", "code", "error", "ssgAction", "context", "assetPrefix", "gatsbyBuild", "import_promises", "import_node_path", "import_promises", "import_node_path", "extractAssetsFromDist", "domain", "__root", "__exports", "getRenderPathsHydratedWithDomainFromDB", "filesFromDist", "fsp", "path", "file", "pathExists", "arraysOfPromises", "fileSrc", "fileDest", "import_promises", "import_node_path", "import_node_crypto", "import_promises", "import_node_path", "KEY_ASSET_PATTERNS", "getAssetHashes", "dir", "assetHashes", "keyAssetFiles", "fsp", "fileName", "pattern", "filePath", "fileContent", "hash", "error", "GriddoLog", "getAssetsDiffBetweenRenders", "dir1", "dir2", "hashes1", "hashes2", "hash1", "hash2", "patchHtmlFile", "newHash", "content", "regex", "newContent", "SyncRender", "config", "GRIDDO_SSG_BUNDLE_ANALYZER", "getAssetsDiffBetweenRenders", "GriddoLog", "candidateIdsToDelete", "existingPreviousPages", "page", "candidateIdsToCreate", "newPages", "htmlTo", "path", "normalizedCompose", "jsonTo", "allFilesToDelete", "file", "fsp", "e", "allFilesToAdd", "appDataJsonFile", "webpackCompilationHash", "changedHtmlFilePaths", "from", "htmlFilePath", "patchHtmlFile", "assetArtifact", "src", "dst", "renderSrc", "renderDst", "xmlFilesInDst", "findFilesBySuffix", "xmlFile", "basename", "xmlFilesInSrc", "relativePath", "dir", "limit", "pLimit", "gatsbyPageDataGenerator", "processingPromises", "fileContent", "content", "id", "composePath", "syncAction", "context", "renderMode", "renderArtifacts", "domain", "pagesToCreate", "pagesToDelete", "__root", "__ssg", "__cache", "__exports", "ssgArtifacts", "assetPrefix", "needsAssetPrefix", "currentDist", "path", "previousDist", "mvDirs", "RENDER_MODE", "deleteDisposableSiteDirs", "fsp", "SyncRender", "deleteEmptyDirectories", "extractAssetsFromDist", "import_node_path", "getGatsbyArtifacts", "ssg", "readDB", "path", "enableRollbackOnError", "data", "readDB", "writeDB", "GriddoLog", "disableRollbackOnError", "gatsbyRenderDomain", "domain", "initializeLogFile", "renderMode", "reason", "getRenderModeFromDB", "renderMetadata", "getRenderMetadataFromDB", "pathsHydratedWithDomain", "getRenderPathsHydratedWithDomainFromDB", "__ssg", "renderArtifacts", "getRenderArtifacts", "ssgArtifacts", "getGatsbyArtifacts", "assetPrefix", "GRIDDO_ASSET_PREFIX", "domainSentinelFile", "pathExists", "path", "derivedRenderMode", "RENDER_MODE", "derivedRenderModeReason", "data", "readDB", "GriddoLog", "writeDB", "renderModeReason", "context", "RenderContext", "doLifeCycle", "initAction", "cleanAction", "prepareAction", "restoreAction", "enableRollbackOnError", "dataAction", "ssgAction", "relocationAction", "metaAction", "syncAction", "healthCheckAction", "logsAction", "GRIDDO_BUILD_LOGS", "closeAction", "disableRollbackOnError", "render", "authService", "domain", "gatsbyRenderDomain", "main", "showExporterVersion", "withErrorHandler"]
|
|
7
7
|
}
|