@griddo/cx 11.10.17-rc.0 → 11.10.17-rc.1

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.
Files changed (37) hide show
  1. package/build/commands/end-render.js +4 -4
  2. package/build/commands/end-render.js.map +3 -3
  3. package/build/commands/prepare-assets-directory.js +2 -2
  4. package/build/commands/prepare-assets-directory.js.map +3 -3
  5. package/build/commands/prepare-domains-render.js +5 -5
  6. package/build/commands/prepare-domains-render.js.map +3 -3
  7. package/build/commands/reset-render.js +9 -9
  8. package/build/commands/reset-render.js.map +3 -3
  9. package/build/commands/start-render.js +24 -20
  10. package/build/commands/start-render.js.map +4 -4
  11. package/build/commands/upload-search-content.js +13 -13
  12. package/build/commands/upload-search-content.js.map +3 -3
  13. package/build/index.js +4 -2
  14. package/build/services/domains.d.ts +5 -1
  15. package/build/services/llms.d.ts +2 -0
  16. package/build/services/sites.d.ts +1 -1
  17. package/build/shared/endpoints.d.ts +2 -1
  18. package/build/shared/envs.d.ts +2 -1
  19. package/build/shared/types/global.d.ts +7 -1
  20. package/build/shared/types/render.d.ts +1 -0
  21. package/build/ssg-adapters/gatsby/actions/meta.d.ts +1 -1
  22. package/exporter/build.sh +1 -0
  23. package/exporter/commands/generate-md.noop +109 -0
  24. package/exporter/commands/prepare-domains-render.ts +19 -13
  25. package/exporter/commands/upload-search-content.ts +1 -1
  26. package/exporter/services/domains.ts +3 -1
  27. package/exporter/services/llms.ts +51 -0
  28. package/exporter/shared/endpoints.ts +5 -0
  29. package/exporter/shared/envs.ts +2 -0
  30. package/exporter/shared/types/global.ts +10 -2
  31. package/exporter/shared/types/render.ts +1 -0
  32. package/exporter/ssg-adapters/gatsby/actions/meta.ts +6 -4
  33. package/exporter/ssg-adapters/gatsby/actions/sync.ts +1 -1
  34. package/package.json +2 -2
  35. package/tsconfig.commands.json +2 -1
  36. package/tsconfig.exporter.json +2 -1
  37. package/tsconfig.json +2 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../exporter/commands/prepare-domains-render.ts", "../../package.json", "../../exporter/shared/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/fs.ts", "../../exporter/core/errors.ts", "../../exporter/core/check-env-health.ts", "../../exporter/core/instance.ts", "../../exporter/shared/endpoints.ts", "../../exporter/shared/headers.ts", "../../exporter/services/auth.ts", "../../exporter/services/api.ts", "../../exporter/core/logger.ts", "../../exporter/services/render.ts", "../../exporter/services/domains.ts", "../../exporter/services/sites.ts", "../../exporter/services/manage-sites.ts"],
4
- "sourcesContent": ["import type { RenderDB } from \"../shared/types/render\";\n\nimport { execSync } from \"node:child_process\";\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { version as griddoVersion } from \"../../package.json\";\nimport { checkEnvironmentHealth } from \"../core/check-env-health\";\nimport { readDB, writeDB } from \"../core/db\";\nimport { pathExists, rmDirs } from \"../core/fs\";\nimport { GriddoLog } from \"../core/GriddoLog\";\nimport { resolveComponentsPath } from \"../core/instance\";\nimport { AuthService } from \"../services/auth\";\nimport { getInstanceDomains } from \"../services/domains\";\nimport { getSitesToRender } from \"../services/manage-sites\";\nimport { resolveDomainRenderMode } from \"../services/render\";\nimport { GRIDDO_SKIP_BUILD_CHECKS } from \"../shared/envs\";\nimport { pkgDir } from \"../shared/npm-modules/pkg-dir\";\n\nasync function getDomainsWithNumberOfPagesWithActivity(domains: string[]) {\n\tconst results = await Promise.all(\n\t\tdomains.map(async (domain) => {\n\t\t\tconst { sitesToPublish, sitesToUnpublish } = await getSitesToRender(domain);\n\t\t\tconst allSites = [...sitesToPublish, ...sitesToUnpublish];\n\n\t\t\tif (allSites.length < 1) {\n\t\t\t\tGriddoLog.warn(`No sites to publish or unpublish for domain: ${domain}`);\n\t\t\t\treturn { domain, totalPendingPages: 0 };\n\t\t\t}\n\n\t\t\tconst pages: number[] = [];\n\t\t\tfor (const site of allSites) {\n\t\t\t\tconst { offlinePending, uploadPending, active } = site.pagesStatus;\n\n\t\t\t\t// HACK/SHAME\n\t\t\t\t// Si un site no tiene p\u00E1ginas (est\u00E1 totalmente vac\u00EDo) pero est\u00E1\n\t\t\t\t// pendiente de ser publicado/despublicado\n\t\t\t\t// `shouldBeUpdated=true`, marcamos como que tiene 1 p\u00E1gina.\n\t\t\t\t// Esto es solo para indicarle a CX que tenga en cuenta el site\n\t\t\t\t// para el incremental render.\n\t\t\t\t// HACK/SHAME\n\t\t\t\tconst siteHasNoPagesToRender =\n\t\t\t\t\tofflinePending.length === 0 && uploadPending.length === 0 && active.length === 0;\n\t\t\t\tconst ghostPage = site.shouldBeUpdated && siteHasNoPagesToRender ? 1 : 0;\n\t\t\t\tconst pagesWithPendingActivity = offlinePending.length + uploadPending.length + ghostPage;\n\t\t\t\tpages.push(pagesWithPendingActivity);\n\t\t\t}\n\n\t\t\tconst totalPendingPages = pages.reduce((a, b) => a + b, 0);\n\n\t\t\treturn { domain, totalPendingPages };\n\t\t}),\n\t);\n\n\treturn results;\n}\n\nfunction getDomainsSortedByNumberOfPages(\n\tdomainsInfo: { domain: string; totalPendingPages: number }[],\n) {\n\tdomainsInfo.sort((a, b) => a.totalPendingPages - b.totalPendingPages);\n\n\treturn domainsInfo.map(({ domain }) => domain);\n}\n\nasync function initRender() {\n\tconst root = (await pkgDir({ cwd: path.resolve(__dirname, \"../../..\") })) || \"\";\n\tconst cx = root;\n\tconst ssg = path.resolve((await pkgDir({ cwd: __dirname })) || \"\");\n\tconst cxCache = path.resolve(root, \".griddo/cache\");\n\tconst components = resolveComponentsPath();\n\tconst exportsDir = path.join(root, \"exports/sites\");\n\tconst exportsDirBackup = path.join(root, \"exports-backup/sites\");\n\n\tconst data: RenderDB = {\n\t\tgriddoVersion,\n\t\tbuildReportFileName: \"build-report.json\",\n\t\tsortedDomains: [],\n\t\tneedsRollbackOnError: false,\n\t\tdomains: {},\n\t\tcurrentRenderingDomain: null,\n\t\tcommitHash: execSync(\"git rev-parse HEAD\").toString().trim(),\n\t\tcommitMessage: execSync(\"git log -1 --pretty=%B\").toString().trim(),\n\t\tpaths: {\n\t\t\tcomponents,\n\t\t\tcx,\n\t\t\tcxCache,\n\t\t\texportsDir,\n\t\t\troot,\n\t\t\tssg,\n\t\t\texportsDirBackup,\n\t\t},\n\t};\n\n\t// create the main cache folder for cx if it doesn't exist.\n\tif (!(await pathExists(cxCache))) {\n\t\tawait fsp.mkdir(cxCache, { recursive: true });\n\t}\n\n\tawait writeDB(data);\n}\n\nasync function prepareDomains() {\n\tawait AuthService.login();\n\n\tconst db = await readDB();\n\n\tconst __ssg = db.paths.ssg;\n\tconst domains = await getInstanceDomains();\n\tconst domainsWithNumberOfPendingPages = await getDomainsWithNumberOfPagesWithActivity(domains);\n\tconst domainSorted = getDomainsSortedByNumberOfPages(domainsWithNumberOfPendingPages);\n\n\t// @deprecated use db.json (only for infra)\n\tawait fsp.writeFile(path.join(__ssg, \"domains.json\"), JSON.stringify(domainSorted));\n\n\tdb.sortedDomains = domainSorted;\n\tdb.domains = {};\n\n\tfor (const { domain, totalPendingPages } of domainsWithNumberOfPendingPages) {\n\t\tconst shouldBeRendered = totalPendingPages > 0;\n\t\tconst { renderMode, reason } = await resolveDomainRenderMode({\n\t\t\tdomain,\n\t\t\tshouldBeRendered,\n\t\t});\n\n\t\t// Log RenderModes/Reason\n\t\tGriddoLog.info(\n\t\t\t`(From Initial Render) [${domain}]: Marked as ${renderMode} with the reason: ${reason}`,\n\t\t);\n\n\t\tdb.domains[domain] = db.domains[domain] || {};\n\t\tdb.domains[domain].renderMode = renderMode;\n\t\tdb.domains[domain].shouldBeRendered = shouldBeRendered;\n\t\tdb.domains[domain].renderModeReason = reason;\n\t}\n\n\tawait writeDB(db);\n}\n\nasync function clean() {\n\tconst db = await readDB();\n\tconst { root } = db.paths;\n\tawait rmDirs([path.join(root, \"apiCache\")]);\n}\n\nasync function main() {\n\tGRIDDO_SKIP_BUILD_CHECKS\n\t\t? GriddoLog.info(\"Build health check bypassed\")\n\t\t: checkEnvironmentHealth();\n\n\tawait initRender();\n\tawait prepareDomains();\n\tawait clean();\n}\n\nmain().catch((error) => {\n\tif (error instanceof Error) {\n\t\tGriddoLog.error(error.message);\n\t} else {\n\t\tGriddoLog.error(`An unexpected error occurred ${error}`);\n\t}\n\tprocess.exit(1);\n});\n", "{\n\t\"name\": \"@griddo/cx\",\n\t\"description\": \"Griddo SSG based on Gatsby\",\n\t\"version\": \"11.10.17-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\": \"42fac4ed9d10fcdf197830446f5de48d54828610\"\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", "//\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 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", "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", "import { CheckHealthError } from \"../shared/errors\";\nimport { brush } from \"../shared/npm-modules/brush\";\nimport { throwError } from \"./errors\";\nimport { GriddoLog } from \"./GriddoLog\";\n\n// Environment variables that must be present (but value doesn't matter)\nconst REQUIRED_ENV_VARS: readonly string[] = [];\n\n// Environment variables that must have specific values\nconst REQUIRED_ENV_VALUES: readonly {\n\tkey: string;\n\texpected: string;\n\tdescription?: string;\n}[] = [];\n\n// Environment variables that are recommended but not required\n// These will show warnings if missing but won't fail the health check\nconst RECOMMENDED_ENV_VARS: readonly { key: string; description?: string }[] = [\n\t{\n\t\tkey: \"GRIDDO_BUILD_LOGS\",\n\t\tdescription: \"Recommended for detailed render logs\",\n\t},\n\t{\n\t\tkey: \"GRIDDO_API_CONCURRENCY_COUNT\",\n\t\tdescription: \"Recommended for better performance and memory management\",\n\t},\n];\n\n// Environment variables that must be present (but value doesn't matter)\nconst DEPRECATED_ENV_VARS: readonly { key: string; description?: string }[] = [\n\t{\n\t\tkey: \"GRIDDO_RENDER_SITE\",\n\t\tdescription:\n\t\t\t\"This environment variable no longer has any effect because it is incompatible with incremental rendering.\",\n\t},\n\t{\n\t\tkey: \"GRIDDO_RENDER_PAGES\",\n\t\tdescription:\n\t\t\t\"This environment variable no longer has any effect because it is incompatible with incremental rendering.\",\n\t},\n\t{\n\t\tkey: \"REACT_APP_API_ENDPOINT\",\n\t\tdescription: \"Use GRIDDO_API_URL\",\n\t},\n\t{\n\t\tkey: \"REACT_APP_PUBLIC_API_ENDPOINT\",\n\t\tdescription: \"Use GRIDDO_PUBLIC_API_URL\",\n\t},\n\t{\n\t\tkey: \"GRIDDO_RENDER_ALL_SITES\",\n\t\tdescription: \"This environment variable is deprecated, it has not effect anymore, remove it\",\n\t},\n\t{\n\t\tkey: \"GRIDDO_RENDER_BY_DOMAINS\",\n\t\tdescription: \"This environment variable is deprecated, it has not effect anymore, remove it\",\n\t},\n\t{\n\t\tkey: \"GRIDDO_EXPERIMENTAL_DO_NOT_USE_MATCH_PATH\",\n\t\tdescription: \"This environment variable is deprecated, it has not effect anymore, remove it\",\n\t},\n];\n\n/**\n * Check if required environment variables exist with any value.\n *\n * @returns An object containing:\n * - isValid: boolean indicating if all required environment variables are present.\n * - missing: an array of missing environment variable names.\n */\nfunction checkRequiredEnvVars(): { isValid: boolean; missing: string[] } {\n\tconst missing = REQUIRED_ENV_VARS.filter((envName) => !process.env[envName]);\n\n\tif (missing.length > 0) {\n\t\tGriddoLog.error(`Missing required environment variables: ${missing.join(\", \")}`);\n\t\treturn { isValid: false, missing };\n\t}\n\n\treturn { isValid: true, missing: [] };\n}\n\n/**\n * Check if environment variables have the expected values.\n *\n * @returns An object containing:\n * - isValid: boolean indicating if all required environment variables have the expected values.\n * - mismatches: an array of mismatched environment variable names and their expected and actual values.\n */\nfunction checkEnvVarValues(): {\n\tisValid: boolean;\n\tmismatches: { key: string; expected: string; actual: string }[];\n} {\n\tconst mismatches: { key: string; expected: string; actual: string }[] = [];\n\n\tfor (const { key, expected } of REQUIRED_ENV_VALUES) {\n\t\tconst actual = process.env[key];\n\n\t\tif (actual !== expected) {\n\t\t\tmismatches.push({ key, expected, actual: actual || \"(undefined)\" });\n\t\t}\n\t}\n\n\tif (mismatches.length > 0) {\n\t\treturn { isValid: false, mismatches };\n\t}\n\n\treturn { isValid: true, mismatches: [] };\n}\n\n/**\n * Check recommended environment variables and show warnings for missing ones.\n *\n * @returns An object containing:\n * - isValid: boolean indicating if all recommended environment variables are set.\n * - missing: an array of missing recommended environment variable names.\n */\nfunction checkRecommendedEnvVars() {\n\tconst missing = RECOMMENDED_ENV_VARS.filter(({ key }) => !process.env[key]);\n\n\tif (missing.length > 0) {\n\t\tGriddoLog.warn(\"Recommended environment variables not set:\");\n\n\t\tfor (const { key, description } of missing) {\n\t\t\tconst desc = description ? ` # ${description}` : \"\";\n\t\t\tGriddoLog.log(`\\t${brush.green(key)}${brush.dim(desc)}`);\n\t\t}\n\t}\n}\n\n/**\n * Check if set enviroment variables have been deprecated\n *\n * @returns An object containing:\n * - deprecated: an array of deprecated environment variable names.\n */\nfunction checkDeprecatedEnvVars() {\n\tconst deprecated = DEPRECATED_ENV_VARS.filter(({ key }) => process.env[key]);\n\n\tif (deprecated.length > 0) {\n\t\tconst deprecatedMessages = deprecated.map(({ key, description }) => {\n\t\t\tconst desc = description ? ` # ${description}` : \"\";\n\t\t\treturn `${brush.red(key)}${brush.dim(desc)}`;\n\t\t});\n\n\t\tGriddoLog.warn(\"Deprecated environment variables set:\");\n\t\tGriddoLog.log(`${deprecatedMessages.map((str) => `\\t${str}`).join(\"\\n\")}\\n`);\n\t}\n\n\treturn { deprecated: deprecated.map((key) => key) };\n}\n\n/**\n * Check if the environment is secure to launch a render.\n * If something fails then log an error message and exit from the process.\n * Otherwise just return true.\n *\n * @returns A boolean indicating if the environment is secure to launch a render.\n */\nfunction checkEnvironmentHealth() {\n\t// Check required environment variables\n\tconst envVarsCheck = checkRequiredEnvVars();\n\tconst envValuesCheck = checkEnvVarValues();\n\n\t// (warnings only)\n\tcheckRecommendedEnvVars();\n\tcheckDeprecatedEnvVars();\n\n\t// Render is safe if all required checks pass\n\tconst isSafeToRender = envVarsCheck.isValid && envValuesCheck.isValid;\n\n\tif (isSafeToRender) {\n\t\tGriddoLog.info(\"Build health check passed\");\n\t\treturn true;\n\t}\n\n\t// Generate consolidated error message\n\tconst allIssues: string[] = [];\n\n\tif (!envVarsCheck.isValid) {\n\t\tallIssues.push(`Missing:\\n${envVarsCheck.missing.map((str) => `\\t${str}`).join(\"\\n\")}`);\n\t}\n\n\tif (!envValuesCheck.isValid) {\n\t\tconst mismatchMessages = envValuesCheck.mismatches.map(\n\t\t\t({ key, expected, actual }) => `${key}=\"${actual || \"undefined\"}\" (expected \"${expected}\")`,\n\t\t);\n\t\tallIssues.push(`Incorrect values:\\n${mismatchMessages.map((str) => `\\t${str}`).join(\"\\n\")}`);\n\t}\n\n\t// Show what needs to be set\n\tconst requiredVarsMessage = REQUIRED_ENV_VALUES.map(({ key, expected, description }) => {\n\t\tconst desc = description ? ` # ${description}` : \"\";\n\t\treturn ` ${key}=\"${expected}\"${desc}`;\n\t}).join(\"\\n\");\n\n\tGriddoLog.error(`Environment health check failed:`);\n\tGriddoLog.log(`${allIssues.join(\"\\n\")}`);\n\tGriddoLog.warn(\"\\nRequired environment variables:\");\n\tGriddoLog.error(requiredVarsMessage);\n\n\tthrowError(CheckHealthError);\n}\n\nexport { checkEnvironmentHealth };\n", "import path from \"node:path\";\n\nimport { NoJSConfigFileFound } from \"../shared/errors\";\nimport { findUpSync } from \"../shared/npm-modules/find-up-simple\";\nimport { pkgDirSync } from \"../shared/npm-modules/pkg-dir\";\nimport { throwError } from \"./errors\";\n\n// Consts\nconst isComponentLibrary = __dirname.includes(\"node_modules\");\nconst componentLibraryPathAlias = getComponentsLibAliases();\n\n/**\n * Returns the instance or monorepo paths.\n *\n * @param customPath The path for the instance components\n */\nfunction resolveComponentsPath(customPath = \"\") {\n\treturn isComponentLibrary\n\t\t? path.resolve(pkgDirSync({ cwd: __dirname }) as string, \"../../../\", customPath)\n\t\t: path.resolve(pkgDirSync({ cwd: __dirname }) as string, \"../griddo-components\", customPath);\n}\n\n/**\n * Return the instance or monorepo components {t|j}sconfig.json file.\n */\nfunction getComponentsJSConfig() {\n\tconst jsConfigPath = findUpSync(\"jsconfig.json\", {\n\t\tcwd: resolveComponentsPath(),\n\t});\n\tconst tsConfigPath = findUpSync(\"tsconfig.json\", {\n\t\tcwd: resolveComponentsPath(),\n\t});\n\n\treturn tsConfigPath || jsConfigPath;\n}\n\n/**\n * Get the instance webpack aliases\n */\nfunction getComponentsLibAliases() {\n\tconst xsConfig = require(getComponentsJSConfig() as string);\n\n\tif (!xsConfig) {\n\t\tthrowError(NoJSConfigFileFound);\n\t}\n\n\treturn Object.keys(xsConfig.compilerOptions?.paths).reduce(\n\t\t(currentAlias, pathKey) => {\n\t\t\tconst [aliasKey] = pathKey.split(\"/\");\n\t\t\tconst [pathAtJsConfig] = xsConfig.compilerOptions.paths[pathKey];\n\t\t\tconst [relativePathToDir] = pathAtJsConfig.split(\"/*\");\n\t\t\tconst absolutePath = resolveComponentsPath(relativePathToDir);\n\n\t\t\treturn {\n\t\t\t\t// biome-ignore lint/performance/noAccumulatingSpread: to be fixed\n\t\t\t\t...currentAlias,\n\t\t\t\t[aliasKey]: absolutePath,\n\t\t\t};\n\t\t},\n\t\t{\n\t\t\t// Por este motivo se puede hacer `... import from \"@griddo-instance\" en\n\t\t\t// los packages del monorepo.\n\t\t\t\"@griddo-instance\": `${resolveComponentsPath()}/src/index.js`,\n\t\t},\n\t);\n}\n\nexport {\n\tcomponentLibraryPathAlias,\n\tgetComponentsJSConfig,\n\tgetComponentsLibAliases,\n\tisComponentLibrary,\n\tresolveComponentsPath,\n};\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", "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 {\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 { 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\t// We use the commit saved at the beginning of the render, not the current\n\t// machine commit, thus avoiding problems if there is a deployment during\n\t// the render\n\tconst db = await readDB();\n\tconst currentCommit = db.commitHash;\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 { Domains } from \"../shared/types/global\";\n\nimport { throwError } from \"../core/errors\";\nimport { GriddoLog } from \"../core/GriddoLog\";\nimport { DOMAINS } from \"../shared/endpoints\";\nimport { NoDomainsFoundError } from \"../shared/errors\";\nimport { get } from \"./api\";\n\n/**\n * Return an array of domains name (string) of the current instance.\n */\nasync function getInstanceDomains() {\n\tconst domains = await get<Domains>({\n\t\tendpoint: DOMAINS,\n\t\tuseApiCacheDir: false,\n\t});\n\n\tif (!domains.length) {\n\t\tthrowError(NoDomainsFoundError);\n\t}\n\n\tGriddoLog.verbose(`getting domains names (${domains.length})`);\n\n\tconst filteredDomains = domains\n\t\t.filter(({ slug }) => !!slug)\n\t\t.map(({ slug }) => slug.replace(\"/\", \"\"));\n\n\treturn [...new Set(filteredDomains)];\n}\n\nexport { getInstanceDomains };\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 { 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"],
5
- "mappings": "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",
6
- "names": ["import_node_child_process", "import_promises", "import_node_path", "version", "package_default", "version", "ArtifactError", "LoginError", "NoDomainsFoundError", "NoJSConfigFileFound", "CheckHealthError", "RESET", "CODES", "brush", "color", "key", "text", "RENDER_MODE", "import_promises", "import_node_path", "import_node_path", "import_node_fs", "import_promises", "import_node_path", "import_node_process", "import_node_url", "toPath", "urlOrPath", "findUp", "name", "options", "cwd", "process", "type", "stopAtOption", "directory", "path", "root", "stopAt", "isAbsoluteName", "filePath", "stats", "fsPromises", "findUpSync", "fs", "pkgDir", "options", "cwd", "filePath", "findUp", "path", "pkgDirSync", "findUpSync", "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", "rmDirs", "dirs", "dir", "fsp", "GriddoLog", "error", "throwError", "ArtifactError", "pathExists", "dir", "fsp", "RenderError", "originalError", "throwError", "options", "stack", "error", "message", "expected", "hint", "errorColor", "GriddoLog", "brush", "extraText", "REQUIRED_ENV_VARS", "REQUIRED_ENV_VALUES", "RECOMMENDED_ENV_VARS", "DEPRECATED_ENV_VARS", "checkRequiredEnvVars", "missing", "envName", "GriddoLog", "checkEnvVarValues", "mismatches", "key", "expected", "actual", "checkRecommendedEnvVars", "description", "desc", "brush", "checkDeprecatedEnvVars", "deprecated", "deprecatedMessages", "str", "checkEnvironmentHealth", "envVarsCheck", "envValuesCheck", "allIssues", "mismatchMessages", "requiredVarsMessage", "throwError", "CheckHealthError", "import_node_path", "isComponentLibrary", "componentLibraryPathAlias", "getComponentsLibAliases", "resolveComponentsPath", "customPath", "path", "pkgDirSync", "getComponentsJSConfig", "jsConfigPath", "findUpSync", "xsConfig", "throwError", "NoJSConfigFileFound", "currentAlias", "pathKey", "aliasKey", "pathAtJsConfig", "relativePathToDir", "absolutePath", "GRIDDO_API_URL", "GRIDDO_PUBLIC_API_URL", "AI_EMBEDDINGS", "ALERT", "DOMAINS", "GET_ALL", "GET_PAGE", "LOGIN", "RESET_RENDER", "ROBOTS", "SEARCH", "SETTINGS", "SITE_URI", "LANGUAGES", "SITE_URI", "DEFAULT_HEADERS", "package_default", "AuthService", "response", "LOGIN", "DEFAULT_HEADERS", "GRIDDO_BOT_USER", "GRIDDO_BOT_PASSWORD", "token", "e", "throwError", "LoginError", "authService", "import_node_crypto", "import_promises", "import_node_path", "import_promises", "logBuffer", "logFilePath", "flushPromise", "LOG_BUFFER_FLUSH_THRESHOLD", "GRIDDO_BUILD_LOGS_BUFFER_SIZE", "LOG_TO_FILE_IS_DISABLED", "GRIDDO_BUILD_LOGS", "addLogToBuffer", "lineContent", "LOG_TO_FILE_IS_DISABLED", "logBuffer", "LOG_BUFFER_FLUSH_THRESHOLD", "flushLogsToFile", "error", "GriddoLog", "flushPromise", "logFilePath", "logsToFlush", "fsp", "import_node_child_process", "import_promises", "import_node_path", "resolveDomainRenderMode", "options", "domain", "shouldBeRendered", "db", "readDB", "__cache", "__exports", "getRenderPathsHydratedWithDomainFromDB", "exportsAreMissing", "pathExists", "path", "previousRenderFailed", "newDeployDetected", "hasNewCommit", "RENDER_MODE", "basePath", "commitFile", "currentCommit", "fsp", "getRenderPathsHydratedWithDomainFromDB", "options", "domain", "dbFilePath", "paths", "readDB", "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", "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", "getInstanceDomains", "domains", "getApi", "DOMAINS", "throwError", "NoDomainsFoundError", "GriddoLog", "filteredDomains", "slug", "getAllSites", "domain", "getApi", "GET_ALL", "getSiteLanguages", "id", "cacheKey", "prefix", "suffix", "LANGUAGES", "getApi", "getSitesToRender", "domain", "allSites", "getAllSites", "site", "items", "getSiteLanguages", "item", "sitesToPublish", "sitesToUnpublish", "getDomainsWithNumberOfPagesWithActivity", "domains", "domain", "sitesToPublish", "sitesToUnpublish", "getSitesToRender", "allSites", "GriddoLog", "pages", "site", "offlinePending", "uploadPending", "active", "siteHasNoPagesToRender", "ghostPage", "pagesWithPendingActivity", "totalPendingPages", "a", "b", "getDomainsSortedByNumberOfPages", "domainsInfo", "initRender", "root", "pkgDir", "path", "cx", "ssg", "cxCache", "components", "resolveComponentsPath", "exportsDir", "exportsDirBackup", "data", "version", "pathExists", "fsp", "writeDB", "prepareDomains", "authService", "db", "readDB", "__ssg", "getInstanceDomains", "domainsWithNumberOfPendingPages", "domainSorted", "shouldBeRendered", "renderMode", "reason", "resolveDomainRenderMode", "clean", "rmDirs", "main", "GRIDDO_SKIP_BUILD_CHECKS", "checkEnvironmentHealth", "error"]
4
+ "sourcesContent": ["import type { Domain } from \"@shared/types/global\";\nimport type { RenderDB } from \"../shared/types/render\";\n\nimport { execSync } from \"node:child_process\";\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { version as griddoVersion } from \"../../package.json\";\nimport { checkEnvironmentHealth } from \"../core/check-env-health\";\nimport { readDB, writeDB } from \"../core/db\";\nimport { pathExists, rmDirs } from \"../core/fs\";\nimport { GriddoLog } from \"../core/GriddoLog\";\nimport { resolveComponentsPath } from \"../core/instance\";\nimport { AuthService } from \"../services/auth\";\nimport { getInstanceDomains } from \"../services/domains\";\nimport { getSitesToRender } from \"../services/manage-sites\";\nimport { resolveDomainRenderMode } from \"../services/render\";\nimport { GRIDDO_SKIP_BUILD_CHECKS } from \"../shared/envs\";\nimport { pkgDir } from \"../shared/npm-modules/pkg-dir\";\n\nasync function getDomainsWithNumberOfPagesWithActivity(domains: Domain[]) {\n\tconst results = await Promise.all(\n\t\tdomains.map(async (domain) => {\n\t\t\tconst { sitesToPublish, sitesToUnpublish } = await getSitesToRender(domain.slug);\n\t\t\tconst allSites = [...sitesToPublish, ...sitesToUnpublish];\n\n\t\t\tif (allSites.length < 1) {\n\t\t\t\tGriddoLog.warn(`No sites to publish or unpublish for domain: ${domain}`);\n\t\t\t\treturn { domain, totalPendingPages: 0 };\n\t\t\t}\n\n\t\t\tconst pages: number[] = [];\n\t\t\tfor (const site of allSites) {\n\t\t\t\tconst { offlinePending, uploadPending, active } = site.pagesStatus;\n\n\t\t\t\t// HACK/SHAME\n\t\t\t\t// Si un site no tiene p\u00E1ginas (est\u00E1 totalmente vac\u00EDo) pero est\u00E1\n\t\t\t\t// pendiente de ser publicado/despublicado\n\t\t\t\t// `shouldBeUpdated=true`, marcamos como que tiene 1 p\u00E1gina.\n\t\t\t\t// Esto es solo para indicarle a CX que tenga en cuenta el site\n\t\t\t\t// para el incremental render.\n\t\t\t\t// HACK/SHAME\n\t\t\t\tconst siteHasNoPagesToRender =\n\t\t\t\t\tofflinePending.length === 0 && uploadPending.length === 0 && active.length === 0;\n\t\t\t\tconst ghostPage = site.shouldBeUpdated && siteHasNoPagesToRender ? 1 : 0;\n\t\t\t\tconst pagesWithPendingActivity = offlinePending.length + uploadPending.length + ghostPage;\n\t\t\t\tpages.push(pagesWithPendingActivity);\n\t\t\t}\n\n\t\t\tconst totalPendingPages = pages.reduce((a, b) => a + b, 0);\n\n\t\t\treturn { domain, totalPendingPages };\n\t\t}),\n\t);\n\n\treturn results;\n}\n\nfunction getDomainsSortedByNumberOfPages(\n\tdomainsInfo: { domain: Domain; totalPendingPages: number }[],\n) {\n\tdomainsInfo.sort((a, b) => a.totalPendingPages - b.totalPendingPages);\n\n\treturn domainsInfo.map(({ domain }) => domain);\n}\n\nasync function initRender() {\n\tconst root = (await pkgDir({ cwd: path.resolve(__dirname, \"../../..\") })) || \"\";\n\tconst cx = root;\n\tconst ssg = path.resolve((await pkgDir({ cwd: __dirname })) || \"\");\n\tconst cxCache = path.resolve(root, \".griddo/cache\");\n\tconst components = resolveComponentsPath();\n\tconst exportsDir = path.join(root, \"exports/sites\");\n\tconst exportsDirBackup = path.join(root, \"exports-backup/sites\");\n\n\tconst data: RenderDB = {\n\t\tgriddoVersion,\n\t\tbuildReportFileName: \"build-report.json\",\n\t\tsortedDomains: [],\n\t\tneedsRollbackOnError: false,\n\t\tdomains: {},\n\t\tcurrentRenderingDomain: null,\n\t\tcommitHash: execSync(\"git rev-parse HEAD\").toString().trim(),\n\t\tcommitMessage: execSync(\"git log -1 --pretty=%B\").toString().trim(),\n\t\tpaths: {\n\t\t\tcomponents,\n\t\t\tcx,\n\t\t\tcxCache,\n\t\t\texportsDir,\n\t\t\troot,\n\t\t\tssg,\n\t\t\texportsDirBackup,\n\t\t},\n\t};\n\n\t// create the main cache folder for cx if it doesn't exist.\n\tif (!(await pathExists(cxCache))) {\n\t\tawait fsp.mkdir(cxCache, { recursive: true });\n\t}\n\n\tawait writeDB(data);\n}\n\nasync function prepareDomains() {\n\tawait AuthService.login();\n\n\tconst db = await readDB();\n\n\tconst __ssg = db.paths.ssg;\n\tconst domains = await getInstanceDomains();\n\tconst domainsWithNumberOfPendingPages = await getDomainsWithNumberOfPagesWithActivity(domains);\n\tconst domainSorted = getDomainsSortedByNumberOfPages(domainsWithNumberOfPendingPages);\n\n\tdb.sortedDomains = domainSorted.map(({ slug }) => slug);\n\tdb.domains = {};\n\n\t// @deprecated use db.json (only for infra)\n\tawait fsp.writeFile(\n\t\tpath.join(__ssg, \"domains.json\"),\n\t\tJSON.stringify(domainSorted.map(({ slug }) => slug)),\n\t);\n\n\tfor (const { domain, totalPendingPages } of domainsWithNumberOfPendingPages) {\n\t\tconst domainSlug = domain.slug;\n\t\tconst shouldBeRendered = totalPendingPages > 0;\n\t\tconst { renderMode, reason } = await resolveDomainRenderMode({\n\t\t\tdomain: domainSlug,\n\t\t\tshouldBeRendered,\n\t\t});\n\n\t\t// Log RenderModes/Reason\n\t\tGriddoLog.info(\n\t\t\t`(From Initial Render) [${domainSlug}]: Marked as ${renderMode} with the reason: ${reason}`,\n\t\t);\n\n\t\tdb.domains[domainSlug] = db.domains[domainSlug] || {};\n\t\tdb.domains[domainSlug].id = domain.id;\n\t\tdb.domains[domainSlug].renderMode = renderMode;\n\t\tdb.domains[domainSlug].shouldBeRendered = shouldBeRendered;\n\t\tdb.domains[domainSlug].renderModeReason = reason;\n\t}\n\n\tawait writeDB(db);\n}\n\nasync function clean() {\n\tconst db = await readDB();\n\tconst { root } = db.paths;\n\tawait rmDirs([path.join(root, \"apiCache\")]);\n}\n\nasync function main() {\n\tGRIDDO_SKIP_BUILD_CHECKS\n\t\t? GriddoLog.info(\"Build health check bypassed\")\n\t\t: checkEnvironmentHealth();\n\n\tawait initRender();\n\tawait prepareDomains();\n\tawait clean();\n}\n\nmain().catch((error) => {\n\tif (error instanceof Error) {\n\t\tGriddoLog.error(error.message);\n\t} else {\n\t\tGriddoLog.error(`An unexpected error occurred ${error}`);\n\t}\n\tprocess.exit(1);\n});\n", "{\n\t\"name\": \"@griddo/cx\",\n\t\"description\": \"Griddo SSG based on Gatsby\",\n\t\"version\": \"11.10.17-rc.1\",\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\": \"00364b55b0b2954da9c57dfc53bcb84530219e06\"\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", "//\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\tid?: number;\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);\nconst GRIDDO_RENDER_DISABLE_LLMS_TXT = envIsTruthy(env.GRIDDO_RENDER_DISABLE_LLMS_TXT);\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_RENDER_DISABLE_LLMS_TXT,\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 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", "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", "import { CheckHealthError } from \"../shared/errors\";\nimport { brush } from \"../shared/npm-modules/brush\";\nimport { throwError } from \"./errors\";\nimport { GriddoLog } from \"./GriddoLog\";\n\n// Environment variables that must be present (but value doesn't matter)\nconst REQUIRED_ENV_VARS: readonly string[] = [];\n\n// Environment variables that must have specific values\nconst REQUIRED_ENV_VALUES: readonly {\n\tkey: string;\n\texpected: string;\n\tdescription?: string;\n}[] = [];\n\n// Environment variables that are recommended but not required\n// These will show warnings if missing but won't fail the health check\nconst RECOMMENDED_ENV_VARS: readonly { key: string; description?: string }[] = [\n\t{\n\t\tkey: \"GRIDDO_BUILD_LOGS\",\n\t\tdescription: \"Recommended for detailed render logs\",\n\t},\n\t{\n\t\tkey: \"GRIDDO_API_CONCURRENCY_COUNT\",\n\t\tdescription: \"Recommended for better performance and memory management\",\n\t},\n];\n\n// Environment variables that must be present (but value doesn't matter)\nconst DEPRECATED_ENV_VARS: readonly { key: string; description?: string }[] = [\n\t{\n\t\tkey: \"GRIDDO_RENDER_SITE\",\n\t\tdescription:\n\t\t\t\"This environment variable no longer has any effect because it is incompatible with incremental rendering.\",\n\t},\n\t{\n\t\tkey: \"GRIDDO_RENDER_PAGES\",\n\t\tdescription:\n\t\t\t\"This environment variable no longer has any effect because it is incompatible with incremental rendering.\",\n\t},\n\t{\n\t\tkey: \"REACT_APP_API_ENDPOINT\",\n\t\tdescription: \"Use GRIDDO_API_URL\",\n\t},\n\t{\n\t\tkey: \"REACT_APP_PUBLIC_API_ENDPOINT\",\n\t\tdescription: \"Use GRIDDO_PUBLIC_API_URL\",\n\t},\n\t{\n\t\tkey: \"GRIDDO_RENDER_ALL_SITES\",\n\t\tdescription: \"This environment variable is deprecated, it has not effect anymore, remove it\",\n\t},\n\t{\n\t\tkey: \"GRIDDO_RENDER_BY_DOMAINS\",\n\t\tdescription: \"This environment variable is deprecated, it has not effect anymore, remove it\",\n\t},\n\t{\n\t\tkey: \"GRIDDO_EXPERIMENTAL_DO_NOT_USE_MATCH_PATH\",\n\t\tdescription: \"This environment variable is deprecated, it has not effect anymore, remove it\",\n\t},\n];\n\n/**\n * Check if required environment variables exist with any value.\n *\n * @returns An object containing:\n * - isValid: boolean indicating if all required environment variables are present.\n * - missing: an array of missing environment variable names.\n */\nfunction checkRequiredEnvVars(): { isValid: boolean; missing: string[] } {\n\tconst missing = REQUIRED_ENV_VARS.filter((envName) => !process.env[envName]);\n\n\tif (missing.length > 0) {\n\t\tGriddoLog.error(`Missing required environment variables: ${missing.join(\", \")}`);\n\t\treturn { isValid: false, missing };\n\t}\n\n\treturn { isValid: true, missing: [] };\n}\n\n/**\n * Check if environment variables have the expected values.\n *\n * @returns An object containing:\n * - isValid: boolean indicating if all required environment variables have the expected values.\n * - mismatches: an array of mismatched environment variable names and their expected and actual values.\n */\nfunction checkEnvVarValues(): {\n\tisValid: boolean;\n\tmismatches: { key: string; expected: string; actual: string }[];\n} {\n\tconst mismatches: { key: string; expected: string; actual: string }[] = [];\n\n\tfor (const { key, expected } of REQUIRED_ENV_VALUES) {\n\t\tconst actual = process.env[key];\n\n\t\tif (actual !== expected) {\n\t\t\tmismatches.push({ key, expected, actual: actual || \"(undefined)\" });\n\t\t}\n\t}\n\n\tif (mismatches.length > 0) {\n\t\treturn { isValid: false, mismatches };\n\t}\n\n\treturn { isValid: true, mismatches: [] };\n}\n\n/**\n * Check recommended environment variables and show warnings for missing ones.\n *\n * @returns An object containing:\n * - isValid: boolean indicating if all recommended environment variables are set.\n * - missing: an array of missing recommended environment variable names.\n */\nfunction checkRecommendedEnvVars() {\n\tconst missing = RECOMMENDED_ENV_VARS.filter(({ key }) => !process.env[key]);\n\n\tif (missing.length > 0) {\n\t\tGriddoLog.warn(\"Recommended environment variables not set:\");\n\n\t\tfor (const { key, description } of missing) {\n\t\t\tconst desc = description ? ` # ${description}` : \"\";\n\t\t\tGriddoLog.log(`\\t${brush.green(key)}${brush.dim(desc)}`);\n\t\t}\n\t}\n}\n\n/**\n * Check if set enviroment variables have been deprecated\n *\n * @returns An object containing:\n * - deprecated: an array of deprecated environment variable names.\n */\nfunction checkDeprecatedEnvVars() {\n\tconst deprecated = DEPRECATED_ENV_VARS.filter(({ key }) => process.env[key]);\n\n\tif (deprecated.length > 0) {\n\t\tconst deprecatedMessages = deprecated.map(({ key, description }) => {\n\t\t\tconst desc = description ? ` # ${description}` : \"\";\n\t\t\treturn `${brush.red(key)}${brush.dim(desc)}`;\n\t\t});\n\n\t\tGriddoLog.warn(\"Deprecated environment variables set:\");\n\t\tGriddoLog.log(`${deprecatedMessages.map((str) => `\\t${str}`).join(\"\\n\")}\\n`);\n\t}\n\n\treturn { deprecated: deprecated.map((key) => key) };\n}\n\n/**\n * Check if the environment is secure to launch a render.\n * If something fails then log an error message and exit from the process.\n * Otherwise just return true.\n *\n * @returns A boolean indicating if the environment is secure to launch a render.\n */\nfunction checkEnvironmentHealth() {\n\t// Check required environment variables\n\tconst envVarsCheck = checkRequiredEnvVars();\n\tconst envValuesCheck = checkEnvVarValues();\n\n\t// (warnings only)\n\tcheckRecommendedEnvVars();\n\tcheckDeprecatedEnvVars();\n\n\t// Render is safe if all required checks pass\n\tconst isSafeToRender = envVarsCheck.isValid && envValuesCheck.isValid;\n\n\tif (isSafeToRender) {\n\t\tGriddoLog.info(\"Build health check passed\");\n\t\treturn true;\n\t}\n\n\t// Generate consolidated error message\n\tconst allIssues: string[] = [];\n\n\tif (!envVarsCheck.isValid) {\n\t\tallIssues.push(`Missing:\\n${envVarsCheck.missing.map((str) => `\\t${str}`).join(\"\\n\")}`);\n\t}\n\n\tif (!envValuesCheck.isValid) {\n\t\tconst mismatchMessages = envValuesCheck.mismatches.map(\n\t\t\t({ key, expected, actual }) => `${key}=\"${actual || \"undefined\"}\" (expected \"${expected}\")`,\n\t\t);\n\t\tallIssues.push(`Incorrect values:\\n${mismatchMessages.map((str) => `\\t${str}`).join(\"\\n\")}`);\n\t}\n\n\t// Show what needs to be set\n\tconst requiredVarsMessage = REQUIRED_ENV_VALUES.map(({ key, expected, description }) => {\n\t\tconst desc = description ? ` # ${description}` : \"\";\n\t\treturn ` ${key}=\"${expected}\"${desc}`;\n\t}).join(\"\\n\");\n\n\tGriddoLog.error(`Environment health check failed:`);\n\tGriddoLog.log(`${allIssues.join(\"\\n\")}`);\n\tGriddoLog.warn(\"\\nRequired environment variables:\");\n\tGriddoLog.error(requiredVarsMessage);\n\n\tthrowError(CheckHealthError);\n}\n\nexport { checkEnvironmentHealth };\n", "import path from \"node:path\";\n\nimport { NoJSConfigFileFound } from \"../shared/errors\";\nimport { findUpSync } from \"../shared/npm-modules/find-up-simple\";\nimport { pkgDirSync } from \"../shared/npm-modules/pkg-dir\";\nimport { throwError } from \"./errors\";\n\n// Consts\nconst isComponentLibrary = __dirname.includes(\"node_modules\");\nconst componentLibraryPathAlias = getComponentsLibAliases();\n\n/**\n * Returns the instance or monorepo paths.\n *\n * @param customPath The path for the instance components\n */\nfunction resolveComponentsPath(customPath = \"\") {\n\treturn isComponentLibrary\n\t\t? path.resolve(pkgDirSync({ cwd: __dirname }) as string, \"../../../\", customPath)\n\t\t: path.resolve(pkgDirSync({ cwd: __dirname }) as string, \"../griddo-components\", customPath);\n}\n\n/**\n * Return the instance or monorepo components {t|j}sconfig.json file.\n */\nfunction getComponentsJSConfig() {\n\tconst jsConfigPath = findUpSync(\"jsconfig.json\", {\n\t\tcwd: resolveComponentsPath(),\n\t});\n\tconst tsConfigPath = findUpSync(\"tsconfig.json\", {\n\t\tcwd: resolveComponentsPath(),\n\t});\n\n\treturn tsConfigPath || jsConfigPath;\n}\n\n/**\n * Get the instance webpack aliases\n */\nfunction getComponentsLibAliases() {\n\tconst xsConfig = require(getComponentsJSConfig() as string);\n\n\tif (!xsConfig) {\n\t\tthrowError(NoJSConfigFileFound);\n\t}\n\n\treturn Object.keys(xsConfig.compilerOptions?.paths).reduce(\n\t\t(currentAlias, pathKey) => {\n\t\t\tconst [aliasKey] = pathKey.split(\"/\");\n\t\t\tconst [pathAtJsConfig] = xsConfig.compilerOptions.paths[pathKey];\n\t\t\tconst [relativePathToDir] = pathAtJsConfig.split(\"/*\");\n\t\t\tconst absolutePath = resolveComponentsPath(relativePathToDir);\n\n\t\t\treturn {\n\t\t\t\t// biome-ignore lint/performance/noAccumulatingSpread: to be fixed\n\t\t\t\t...currentAlias,\n\t\t\t\t[aliasKey]: absolutePath,\n\t\t\t};\n\t\t},\n\t\t{\n\t\t\t// Por este motivo se puede hacer `... import from \"@griddo-instance\" en\n\t\t\t// los packages del monorepo.\n\t\t\t\"@griddo-instance\": `${resolveComponentsPath()}/src/index.js`,\n\t\t},\n\t);\n}\n\nexport {\n\tcomponentLibraryPathAlias,\n\tgetComponentsJSConfig,\n\tgetComponentsLibAliases,\n\tisComponentLibrary,\n\tresolveComponentsPath,\n};\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// Domain\nconst DOMAIN_URI = `${GRIDDO_API_URL}/domains/`;\nconst LLMS = [DOMAIN_URI, \"/llms\"];\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\tLLMS,\n\tLOGIN,\n\tRESET_RENDER,\n\tROBOTS,\n\tSEARCH,\n\tSETTINGS,\n\tSOCIALS,\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 {\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 { 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\t// We use the commit saved at the beginning of the render, not the current\n\t// machine commit, thus avoiding problems if there is a deployment during\n\t// the render\n\tconst db = await readDB();\n\tconst currentCommit = db.commitHash;\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 { Domains } from \"../shared/types/global\";\n\nimport { throwError } from \"../core/errors\";\nimport { GriddoLog } from \"../core/GriddoLog\";\nimport { DOMAINS } from \"../shared/endpoints\";\nimport { NoDomainsFoundError } from \"../shared/errors\";\nimport { get } from \"./api\";\n\n/**\n * Return an array of domains name (string) of the current instance.\n */\nasync function getInstanceDomains() {\n\tconst domains = await get<Domains>({\n\t\tendpoint: DOMAINS,\n\t\tuseApiCacheDir: false,\n\t});\n\n\tif (!domains.length) {\n\t\tthrowError(NoDomainsFoundError);\n\t}\n\n\tGriddoLog.verbose(`getting domains names (${domains.length})`);\n\n\tconst filteredDomains = domains\n\t\t.filter(({ slug }) => !!slug)\n\t\t.map((domain) => {\n\t\t\treturn { ...domain, slug: domain.slug.replace(\"/\", \"\") };\n\t\t});\n\n\treturn [...new Set(filteredDomains)];\n}\n\nexport { getInstanceDomains };\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 { 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"],
5
+ "mappings": "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",
6
+ "names": ["import_node_child_process", "import_promises", "import_node_path", "version", "package_default", "version", "ArtifactError", "LoginError", "NoDomainsFoundError", "NoJSConfigFileFound", "CheckHealthError", "RESET", "CODES", "brush", "color", "key", "text", "RENDER_MODE", "import_promises", "import_node_path", "import_node_path", "import_node_fs", "import_promises", "import_node_path", "import_node_process", "import_node_url", "toPath", "urlOrPath", "findUp", "name", "options", "cwd", "process", "type", "stopAtOption", "directory", "path", "root", "stopAt", "isAbsoluteName", "filePath", "stats", "fsPromises", "findUpSync", "fs", "pkgDir", "options", "cwd", "filePath", "findUp", "path", "pkgDirSync", "findUpSync", "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", "GRIDDO_RENDER_DISABLE_LLMS_TXT", "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", "rmDirs", "dirs", "dir", "fsp", "GriddoLog", "error", "throwError", "ArtifactError", "pathExists", "dir", "fsp", "RenderError", "originalError", "throwError", "options", "stack", "error", "message", "expected", "hint", "errorColor", "GriddoLog", "brush", "extraText", "REQUIRED_ENV_VARS", "REQUIRED_ENV_VALUES", "RECOMMENDED_ENV_VARS", "DEPRECATED_ENV_VARS", "checkRequiredEnvVars", "missing", "envName", "GriddoLog", "checkEnvVarValues", "mismatches", "key", "expected", "actual", "checkRecommendedEnvVars", "description", "desc", "brush", "checkDeprecatedEnvVars", "deprecated", "deprecatedMessages", "str", "checkEnvironmentHealth", "envVarsCheck", "envValuesCheck", "allIssues", "mismatchMessages", "requiredVarsMessage", "throwError", "CheckHealthError", "import_node_path", "isComponentLibrary", "componentLibraryPathAlias", "getComponentsLibAliases", "resolveComponentsPath", "customPath", "path", "pkgDirSync", "getComponentsJSConfig", "jsConfigPath", "findUpSync", "xsConfig", "throwError", "NoJSConfigFileFound", "currentAlias", "pathKey", "aliasKey", "pathAtJsConfig", "relativePathToDir", "absolutePath", "GRIDDO_API_URL", "GRIDDO_PUBLIC_API_URL", "AI_EMBEDDINGS", "ALERT", "DOMAINS", "GET_ALL", "GET_PAGE", "LOGIN", "RESET_RENDER", "ROBOTS", "SEARCH", "SETTINGS", "DOMAIN_URI", "SITE_URI", "GRIDDO_API_URL", "LANGUAGES", "SITE_URI", "DEFAULT_HEADERS", "package_default", "AuthService", "response", "LOGIN", "DEFAULT_HEADERS", "GRIDDO_BOT_USER", "GRIDDO_BOT_PASSWORD", "token", "e", "throwError", "LoginError", "authService", "import_node_crypto", "import_promises", "import_node_path", "import_promises", "logBuffer", "logFilePath", "flushPromise", "LOG_BUFFER_FLUSH_THRESHOLD", "GRIDDO_BUILD_LOGS_BUFFER_SIZE", "LOG_TO_FILE_IS_DISABLED", "GRIDDO_BUILD_LOGS", "addLogToBuffer", "lineContent", "LOG_TO_FILE_IS_DISABLED", "logBuffer", "LOG_BUFFER_FLUSH_THRESHOLD", "flushLogsToFile", "error", "GriddoLog", "flushPromise", "logFilePath", "logsToFlush", "fsp", "import_node_child_process", "import_promises", "import_node_path", "resolveDomainRenderMode", "options", "domain", "shouldBeRendered", "db", "readDB", "__cache", "__exports", "getRenderPathsHydratedWithDomainFromDB", "exportsAreMissing", "pathExists", "path", "previousRenderFailed", "newDeployDetected", "hasNewCommit", "RENDER_MODE", "basePath", "commitFile", "currentCommit", "fsp", "getRenderPathsHydratedWithDomainFromDB", "options", "domain", "dbFilePath", "paths", "readDB", "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", "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", "getInstanceDomains", "domains", "getApi", "DOMAINS", "throwError", "NoDomainsFoundError", "GriddoLog", "filteredDomains", "slug", "domain", "getAllSites", "domain", "getApi", "GET_ALL", "getSiteLanguages", "id", "cacheKey", "prefix", "suffix", "LANGUAGES", "getApi", "getSitesToRender", "domain", "allSites", "getAllSites", "site", "items", "getSiteLanguages", "item", "sitesToPublish", "sitesToUnpublish", "getDomainsWithNumberOfPagesWithActivity", "domains", "domain", "sitesToPublish", "sitesToUnpublish", "getSitesToRender", "allSites", "GriddoLog", "pages", "site", "offlinePending", "uploadPending", "active", "siteHasNoPagesToRender", "ghostPage", "pagesWithPendingActivity", "totalPendingPages", "a", "b", "getDomainsSortedByNumberOfPages", "domainsInfo", "initRender", "root", "pkgDir", "path", "cx", "ssg", "cxCache", "components", "resolveComponentsPath", "exportsDir", "exportsDirBackup", "data", "version", "pathExists", "fsp", "writeDB", "prepareDomains", "authService", "db", "readDB", "__ssg", "getInstanceDomains", "domainsWithNumberOfPendingPages", "domainSorted", "slug", "domainSlug", "shouldBeRendered", "renderMode", "reason", "resolveDomainRenderMode", "clean", "rmDirs", "main", "GRIDDO_SKIP_BUILD_CHECKS", "checkEnvironmentHealth", "error"]
7
7
  }