@griddo/cx 11.9.12-rc.0 → 11.9.13

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 (254) hide show
  1. package/README.md +240 -13
  2. package/build/adapters/gatsby/index.d.ts +4 -0
  3. package/build/adapters/gatsby/utils.d.ts +26 -0
  4. package/build/artifacts/index.d.ts +6 -0
  5. package/build/commands/end-render.d.ts +1 -0
  6. package/build/commands/reset-render.d.ts +1 -0
  7. package/build/commands/start-render.d.ts +1 -0
  8. package/build/commands/upload-search-content.d.ts +1 -0
  9. package/build/constants/envs.d.ts +37 -0
  10. package/build/constants/index.d.ts +57 -0
  11. package/build/end-render.js +74 -0
  12. package/build/end-render.js.map +7 -0
  13. package/build/{shared/errors.d.ts → errors/errors-data.d.ts} +3 -5
  14. package/build/errors/index.d.ts +15 -0
  15. package/build/index.d.ts +29 -10
  16. package/build/index.js +73 -406
  17. package/build/index.js.map +7 -0
  18. package/build/prepare-domains-render.js +73 -0
  19. package/build/prepare-domains-render.js.map +7 -0
  20. package/build/react/Favicon/index.d.ts +5 -0
  21. package/build/react/GriddoIntegrations/index.d.ts +4 -3
  22. package/build/react/GriddoIntegrations/utils.d.ts +6 -7
  23. package/build/react/index.d.ts +2 -3
  24. package/build/react/index.js +3 -1
  25. package/build/registers/api.d.ts +9 -0
  26. package/build/registers/gatsby.d.ts +9 -0
  27. package/build/registers/index.d.ts +3 -0
  28. package/build/reset-render.js +74 -0
  29. package/build/reset-render.js.map +7 -0
  30. package/build/services/auth.d.ts +5 -2
  31. package/build/services/domains.d.ts +4 -3
  32. package/build/services/navigation.d.ts +16 -16
  33. package/build/services/reference-fields.d.ts +3 -3
  34. package/build/services/register.d.ts +36 -0
  35. package/build/services/robots.d.ts +19 -2
  36. package/build/services/settings.d.ts +4 -0
  37. package/build/services/sites.d.ts +5 -8
  38. package/build/services/store.d.ts +1 -10
  39. package/build/start-render.js +100 -0
  40. package/build/start-render.js.map +7 -0
  41. package/build/{shared/types → types}/api.d.ts +18 -18
  42. package/build/{shared/types → types}/global.d.ts +16 -15
  43. package/build/{shared/types → types}/navigation.d.ts +5 -5
  44. package/build/{shared/types → types}/pages.d.ts +9 -9
  45. package/build/{shared/types → types}/sites.d.ts +19 -18
  46. package/build/upload-search-content.js +74 -0
  47. package/build/upload-search-content.js.map +7 -0
  48. package/build/utils/alerts.d.ts +3 -0
  49. package/build/{services → utils}/api.d.ts +1 -1
  50. package/build/utils/cache.d.ts +35 -0
  51. package/build/utils/core-utils.d.ts +107 -0
  52. package/build/utils/create-build-data.d.ts +8 -0
  53. package/build/utils/domains.d.ts +13 -0
  54. package/build/utils/folders.d.ts +53 -0
  55. package/build/{core/check-env-health.d.ts → utils/health-checks.d.ts} +2 -4
  56. package/build/utils/loggin.d.ts +51 -0
  57. package/build/{services → utils}/pages.d.ts +3 -3
  58. package/build/utils/render.d.ts +13 -0
  59. package/build/utils/searches.d.ts +15 -0
  60. package/build/utils/sites.d.ts +31 -0
  61. package/build/utils/store.d.ts +81 -0
  62. package/cx.config.d.ts +5 -0
  63. package/cx.config.js +36 -0
  64. package/exporter/adapters/gatsby/index.ts +182 -0
  65. package/exporter/adapters/gatsby/utils.ts +186 -0
  66. package/exporter/artifacts/README.md +34 -0
  67. package/exporter/artifacts/index.ts +33 -0
  68. package/exporter/build.sh +24 -16
  69. package/exporter/commands/end-render.ts +86 -65
  70. package/exporter/commands/move-assets.ts +11 -0
  71. package/exporter/commands/prepare-domains-render.ts +35 -132
  72. package/exporter/commands/reset-render.ts +8 -13
  73. package/exporter/commands/start-render.ts +64 -26
  74. package/exporter/commands/upload-search-content.ts +26 -204
  75. package/exporter/{shared → constants}/endpoints.ts +11 -12
  76. package/exporter/constants/envs.ts +94 -0
  77. package/exporter/constants/index.ts +129 -0
  78. package/exporter/{shared/errors.ts → errors/errors-data.ts} +14 -24
  79. package/exporter/errors/index.ts +40 -0
  80. package/exporter/index.ts +56 -14
  81. package/exporter/react/{GriddoFavicon → Favicon}/index.tsx +9 -3
  82. package/exporter/react/GriddoIntegrations/index.tsx +23 -17
  83. package/exporter/react/GriddoIntegrations/utils.ts +12 -24
  84. package/exporter/react/index.tsx +9 -3
  85. package/exporter/registers/api.ts +14 -0
  86. package/exporter/registers/gatsby.ts +14 -0
  87. package/exporter/registers/index.ts +4 -0
  88. package/exporter/services/auth.ts +10 -8
  89. package/exporter/services/domains.ts +8 -23
  90. package/exporter/services/navigation.ts +18 -12
  91. package/exporter/services/reference-fields.ts +32 -14
  92. package/exporter/services/register.ts +113 -0
  93. package/exporter/services/robots.ts +61 -33
  94. package/exporter/services/settings.ts +17 -0
  95. package/exporter/services/sites.ts +28 -40
  96. package/exporter/services/store.ts +321 -354
  97. package/exporter/{shared/types → types}/api.ts +41 -40
  98. package/exporter/{shared/types → types}/global.ts +21 -17
  99. package/exporter/{shared/types → types}/navigation.ts +3 -3
  100. package/exporter/{shared/types → types}/pages.ts +11 -10
  101. package/exporter/{shared/types → types}/sites.ts +19 -18
  102. package/exporter/utils/alerts.ts +29 -0
  103. package/exporter/utils/api.ts +243 -0
  104. package/exporter/utils/cache.ts +142 -0
  105. package/exporter/utils/core-utils.ts +458 -0
  106. package/exporter/utils/create-build-data.ts +17 -0
  107. package/exporter/utils/domains.ts +39 -0
  108. package/exporter/utils/folders.ts +320 -0
  109. package/exporter/utils/health-checks.ts +64 -0
  110. package/exporter/{core → utils}/images.ts +6 -1
  111. package/exporter/{core → utils}/instance.ts +13 -9
  112. package/exporter/utils/loggin.ts +184 -0
  113. package/exporter/{services → utils}/pages.ts +92 -27
  114. package/exporter/utils/render.ts +71 -0
  115. package/exporter/utils/searches.ts +156 -0
  116. package/exporter/utils/sites.ts +312 -0
  117. package/exporter/utils/store.ts +314 -0
  118. package/gatsby-browser.tsx +58 -41
  119. package/gatsby-config.ts +17 -10
  120. package/gatsby-node.ts +79 -20
  121. package/gatsby-ssr.tsx +1 -2
  122. package/package.json +80 -41
  123. package/src/README.md +7 -0
  124. package/src/components/Head.tsx +73 -28
  125. package/src/components/template.tsx +29 -6
  126. package/src/gatsby-node-utils.ts +2 -76
  127. package/src/html.tsx +11 -2
  128. package/src/types.ts +3 -3
  129. package/start-render.js +7 -0
  130. package/tsconfig.json +3 -5
  131. package/build/commands/end-render.js +0 -31
  132. package/build/commands/end-render.js.map +0 -7
  133. package/build/commands/prepare-assets-directory.js +0 -9
  134. package/build/commands/prepare-assets-directory.js.map +0 -7
  135. package/build/commands/prepare-domains-render.js +0 -38
  136. package/build/commands/prepare-domains-render.js.map +0 -7
  137. package/build/commands/reset-render.js +0 -31
  138. package/build/commands/reset-render.js.map +0 -7
  139. package/build/commands/single-domain-upload-search-content.d.ts +0 -1
  140. package/build/commands/start-render.js +0 -66
  141. package/build/commands/start-render.js.map +0 -7
  142. package/build/commands/upload-search-content.js +0 -32
  143. package/build/commands/upload-search-content.js.map +0 -7
  144. package/build/core/GriddoLog.d.ts +0 -16
  145. package/build/core/db-class.d.ts +0 -11
  146. package/build/core/db.d.ts +0 -4
  147. package/build/core/dist-rollback.d.ts +0 -11
  148. package/build/core/errors.d.ts +0 -26
  149. package/build/core/fs.d.ts +0 -69
  150. package/build/core/life-cycle.d.ts +0 -26
  151. package/build/core/logger.d.ts +0 -18
  152. package/build/core/objects.d.ts +0 -11
  153. package/build/core/print-logos.d.ts +0 -5
  154. package/build/react/DynamicScript/index.d.ts +0 -4
  155. package/build/react/GriddoFavicon/index.d.ts +0 -4
  156. package/build/react/GriddoOpenGraph/index.d.ts +0 -10
  157. package/build/services/manage-sites.d.ts +0 -22
  158. package/build/services/manage-store.d.ts +0 -32
  159. package/build/services/render-artifacts.d.ts +0 -6
  160. package/build/services/render.d.ts +0 -70
  161. package/build/services/sitemaps.d.ts +0 -5
  162. package/build/shared/context.d.ts +0 -36
  163. package/build/shared/envs.d.ts +0 -19
  164. package/build/shared/npm-modules/brush.d.ts +0 -18
  165. package/build/shared/npm-modules/find-up-simple.d.ts +0 -34
  166. package/build/shared/npm-modules/pkg-dir.d.ts +0 -7
  167. package/build/shared/npm-modules/xml-parser.d.ts +0 -4
  168. package/build/shared/types/render.d.ts +0 -54
  169. package/build/shared/types.d.ts +0 -15
  170. package/build/ssg-adapters/gatsby/actions/clean.d.ts +0 -3
  171. package/build/ssg-adapters/gatsby/actions/close.d.ts +0 -3
  172. package/build/ssg-adapters/gatsby/actions/data.d.ts +0 -2
  173. package/build/ssg-adapters/gatsby/actions/healthCheck.d.ts +0 -2
  174. package/build/ssg-adapters/gatsby/actions/init.d.ts +0 -2
  175. package/build/ssg-adapters/gatsby/actions/logs.d.ts +0 -3
  176. package/build/ssg-adapters/gatsby/actions/meta.d.ts +0 -2
  177. package/build/ssg-adapters/gatsby/actions/prepare.d.ts +0 -2
  178. package/build/ssg-adapters/gatsby/actions/relocation.d.ts +0 -2
  179. package/build/ssg-adapters/gatsby/actions/restore.d.ts +0 -3
  180. package/build/ssg-adapters/gatsby/actions/ssg.d.ts +0 -3
  181. package/build/ssg-adapters/gatsby/actions/sync.d.ts +0 -3
  182. package/build/ssg-adapters/gatsby/index.d.ts +0 -9
  183. package/build/ssg-adapters/gatsby/shared/artifacts.d.ts +0 -4
  184. package/build/ssg-adapters/gatsby/shared/diff-assets.d.ts +0 -15
  185. package/build/ssg-adapters/gatsby/shared/extract-assets.d.ts +0 -7
  186. package/build/ssg-adapters/gatsby/shared/gatsby-build.d.ts +0 -7
  187. package/build/ssg-adapters/gatsby/shared/render-rollback.d.ts +0 -18
  188. package/build/ssg-adapters/gatsby/shared/sync-render.d.ts +0 -26
  189. package/build/ssg-adapters/gatsby/shared/types.d.ts +0 -34
  190. package/cli.mjs +0 -231
  191. package/exporter/build-esbuild.noop +0 -42
  192. package/exporter/commands/README.md +0 -151
  193. package/exporter/commands/prepare-assets-directory.ts +0 -35
  194. package/exporter/commands/single-domain-upload-search-content.ts +0 -206
  195. package/exporter/core/GriddoLog.ts +0 -45
  196. package/exporter/core/check-env-health.ts +0 -204
  197. package/exporter/core/db-class.ts +0 -54
  198. package/exporter/core/db.ts +0 -33
  199. package/exporter/core/dist-rollback.ts +0 -49
  200. package/exporter/core/errors.ts +0 -93
  201. package/exporter/core/fs.ts +0 -385
  202. package/exporter/core/life-cycle.ts +0 -73
  203. package/exporter/core/logger.ts +0 -141
  204. package/exporter/core/objects.ts +0 -37
  205. package/exporter/core/print-logos.ts +0 -21
  206. package/exporter/react/DynamicScript/index.tsx +0 -33
  207. package/exporter/react/GriddoOpenGraph/index.tsx +0 -39
  208. package/exporter/services/api.ts +0 -306
  209. package/exporter/services/manage-sites.ts +0 -116
  210. package/exporter/services/manage-store.ts +0 -173
  211. package/exporter/services/render-artifacts.ts +0 -44
  212. package/exporter/services/render.ts +0 -229
  213. package/exporter/services/sitemaps.ts +0 -129
  214. package/exporter/shared/context.ts +0 -49
  215. package/exporter/shared/envs.ts +0 -62
  216. package/exporter/shared/npm-modules/README.md +0 -36
  217. package/exporter/shared/npm-modules/brush.ts +0 -34
  218. package/exporter/shared/npm-modules/find-up-simple.ts +0 -100
  219. package/exporter/shared/npm-modules/pkg-dir.ts +0 -17
  220. package/exporter/shared/npm-modules/xml-parser.ts +0 -57
  221. package/exporter/shared/types/render.ts +0 -63
  222. package/exporter/shared/types.ts +0 -15
  223. package/exporter/ssg-adapters/gatsby/actions/clean.ts +0 -26
  224. package/exporter/ssg-adapters/gatsby/actions/close.ts +0 -17
  225. package/exporter/ssg-adapters/gatsby/actions/data.ts +0 -22
  226. package/exporter/ssg-adapters/gatsby/actions/healthCheck.ts +0 -10
  227. package/exporter/ssg-adapters/gatsby/actions/init.ts +0 -12
  228. package/exporter/ssg-adapters/gatsby/actions/logs.ts +0 -10
  229. package/exporter/ssg-adapters/gatsby/actions/meta.ts +0 -13
  230. package/exporter/ssg-adapters/gatsby/actions/prepare.ts +0 -9
  231. package/exporter/ssg-adapters/gatsby/actions/relocation.ts +0 -15
  232. package/exporter/ssg-adapters/gatsby/actions/restore.ts +0 -21
  233. package/exporter/ssg-adapters/gatsby/actions/ssg.ts +0 -12
  234. package/exporter/ssg-adapters/gatsby/actions/sync.ts +0 -65
  235. package/exporter/ssg-adapters/gatsby/index.ts +0 -114
  236. package/exporter/ssg-adapters/gatsby/shared/artifacts.ts +0 -17
  237. package/exporter/ssg-adapters/gatsby/shared/diff-assets.ts +0 -128
  238. package/exporter/ssg-adapters/gatsby/shared/extract-assets.ts +0 -75
  239. package/exporter/ssg-adapters/gatsby/shared/gatsby-build.ts +0 -58
  240. package/exporter/ssg-adapters/gatsby/shared/render-rollback.ts +0 -33
  241. package/exporter/ssg-adapters/gatsby/shared/sync-render.ts +0 -298
  242. package/exporter/ssg-adapters/gatsby/shared/types.ts +0 -35
  243. package/plugins/gatsby-plugin-svgr-loader/gatsby-node.js +0 -55
  244. package/plugins/gatsby-plugin-svgr-loader/package.json +0 -8
  245. package/tsconfig.commands.json +0 -36
  246. package/tsconfig.exporter.json +0 -21
  247. /package/build/commands/{prepare-assets-directory.d.ts → move-assets.d.ts} +0 -0
  248. /package/build/{shared → constants}/endpoints.d.ts +0 -0
  249. /package/build/react/{GriddoFavicon → Favicon}/utils.d.ts +0 -0
  250. /package/build/{shared/types → types}/templates.d.ts +0 -0
  251. /package/build/{core → utils}/images.d.ts +0 -0
  252. /package/build/{core → utils}/instance.d.ts +0 -0
  253. /package/exporter/react/{GriddoFavicon → Favicon}/utils.ts +0 -0
  254. /package/exporter/{shared/types → types}/templates.ts +0 -0
@@ -0,0 +1,142 @@
1
+ import type { Petition } from "../types/global";
2
+ import type { HashSites, SiteHash } from "../types/sites";
3
+
4
+ import crypto from "node:crypto";
5
+ import fs from "node:fs";
6
+ import path from "node:path";
7
+
8
+ import fsx from "fs-extra";
9
+
10
+ import { getConfig } from "./core-utils";
11
+
12
+ const config = getConfig();
13
+
14
+ /**
15
+ * Creates an `apiCache` dir to store pages fetched from them API.
16
+ */
17
+ function createAPICacheDir() {
18
+ const { __cx } = config.paths();
19
+ const apiCacheDir = path.join(__cx, "apiCache");
20
+
21
+ if (!fs.existsSync(apiCacheDir)) {
22
+ fs.mkdirSync(apiCacheDir);
23
+ }
24
+
25
+ console.info("Cache initialized");
26
+ }
27
+
28
+ /**
29
+ * Generate a filename with a hash using a Petition object
30
+ *
31
+ * @todo Merge with createSha256
32
+ * @param petition An object
33
+ */
34
+ function generateFilenameWithHash(petition: Petition) {
35
+ const { __cx } = config.paths();
36
+ const apiCacheDir = path.join(__cx, "apiCache");
37
+
38
+ const hashSum = crypto.createHash("sha256");
39
+ hashSum.update(JSON.stringify(petition));
40
+
41
+ return `${apiCacheDir}/${hashSum.digest("hex")}`;
42
+ }
43
+
44
+ /**
45
+ * Generate a filename with a hash using a string.
46
+ *
47
+ * @todo Merge with generateFilenameWithHash
48
+ * @param data A string to create a sha256 based on.
49
+ */
50
+ function createSha256(data: string) {
51
+ const uniqueString = crypto.randomBytes(16).toString("hex");
52
+ const hash = crypto.createHash("sha256");
53
+ hash.update(`${data}${uniqueString}`);
54
+
55
+ return hash.digest("hex");
56
+ }
57
+
58
+ /**
59
+ * Save a file using a hash name.
60
+ *
61
+ * @param petition An object.
62
+ * @param content Content to be saved.
63
+ */
64
+ function saveCache<T>(petition: Petition, content: T) {
65
+ const stringContent =
66
+ typeof content === "string" ? content : JSON.stringify(content);
67
+ const filename = generateFilenameWithHash(petition);
68
+ const filepath = path.dirname(filename);
69
+ if (!fs.existsSync(filepath)) {
70
+ fs.mkdirSync(filepath, { recursive: true });
71
+ }
72
+ fs.writeFileSync(filename, stringContent, "utf8");
73
+ }
74
+
75
+ /**
76
+ * Search in the `apiCache` dir for a file using the petition as hash generator.
77
+ * Return the file content if found or null if not.
78
+ *
79
+ * @param petition An object
80
+ */
81
+ function searchCacheData<T>(petition: Petition) {
82
+ try {
83
+ const file = generateFilenameWithHash(petition);
84
+ const jsonData = fsx.readJSONSync(file, {
85
+ encoding: "utf-8",
86
+ });
87
+ return jsonData as T;
88
+ } catch {
89
+ return null;
90
+ }
91
+ }
92
+
93
+ /**
94
+ * Get site hashes from the file as an object
95
+ */
96
+ function getHashSites(): HashSites {
97
+ const { __cx } = config.paths();
98
+ const apiCacheDir = path.join(__cx, "apiCache");
99
+ const siteHasFilename = `${apiCacheDir}/siteHash.json`;
100
+
101
+ try {
102
+ const jsonData = fsx.readJSONSync(siteHasFilename, {
103
+ encoding: "utf-8",
104
+ });
105
+ return jsonData || {};
106
+ } catch {
107
+ return {};
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Update (write) the site hash file.
113
+ *
114
+ * @param siteId The id of the site.
115
+ * @param siteHash The has of the site.
116
+ */
117
+ function updatedSiteHash(siteId: number, siteHash: SiteHash) {
118
+ const allHash = getHashSites();
119
+ const lastHash = allHash[siteId];
120
+ const currentHash = siteHash || lastHash || new Date().valueOf();
121
+
122
+ const { __cx } = config.paths();
123
+ const apiCacheDir = path.join(__cx, "apiCache");
124
+ const siteHasFilename = `${apiCacheDir}/siteHash.json`;
125
+
126
+ if (currentHash !== lastHash) {
127
+ allHash[siteId] = currentHash;
128
+ fs.writeFileSync(siteHasFilename, JSON.stringify(allHash), {
129
+ encoding: "utf-8",
130
+ });
131
+ }
132
+
133
+ return currentHash.toString();
134
+ }
135
+
136
+ export {
137
+ createAPICacheDir,
138
+ createSha256,
139
+ saveCache,
140
+ searchCacheData,
141
+ updatedSiteHash,
142
+ };
@@ -0,0 +1,458 @@
1
+ import type { APIResponses } from "../types/api";
2
+ import type {
3
+ CXConfig,
4
+ LifeCyclesNames,
5
+ LifeCycleSteps,
6
+ } from "../types/global";
7
+ import type { APIPageObject } from "../types/pages";
8
+
9
+ import fs from "node:fs";
10
+ import path from "node:path";
11
+
12
+ import fsx from "fs-extra";
13
+ import kleur from "kleur";
14
+ import { bgRed, black } from "kleur/colors";
15
+ import pkgDir from "pkg-dir";
16
+
17
+ import { envs } from "../constants";
18
+ import { throwError } from "../errors";
19
+ import { prependFileSync } from "./folders";
20
+ import { boxLog, infoLog, successLog } from "./loggin";
21
+ import { generateBuildReport, generateSitemaps } from "./sites";
22
+ import { LifecycleExecutionError } from "../errors/errors-data";
23
+ import { RobotsService } from "../services/robots";
24
+
25
+ const config = getConfig();
26
+
27
+ const instanceRootDir = pkgDir.sync()!; // instance root dir
28
+
29
+ /**
30
+ * Returns the configuration file content.
31
+ *
32
+ * @example
33
+ * const config = getConfig()
34
+ * const { __cx } = config.paths()
35
+ * const { griddoVersion, proDomain } = config
36
+ */
37
+ function getConfig(): CXConfig {
38
+ try {
39
+ const configModule = require("../../cx.config.js");
40
+ const config = configModule.default;
41
+
42
+ return config;
43
+ } catch (error) {
44
+ console.log(error);
45
+ throw new Error("Error while reading configuration file");
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Returns true for "true", "on", true and positive numbers.
51
+ * Returns false for "false", "off", false, 0, negative integers and anything else.
52
+ */
53
+ function isTruthy(value: any): boolean {
54
+ // Return if Boolean
55
+ if (typeof value === "boolean") {
56
+ return value;
57
+ }
58
+
59
+ // Return false if null or undefined
60
+ if (value === undefined || value === null) {
61
+ return false;
62
+ }
63
+
64
+ // If the String is true or false
65
+ if (value.toLowerCase() === "true") {
66
+ return true;
67
+ }
68
+ if (value.toLowerCase() === "false") {
69
+ return false;
70
+ }
71
+
72
+ // "on" | "off", We love them in Griddo ^^.
73
+ if (value.toLowerCase() === "on") {
74
+ return true;
75
+ }
76
+ if (value.toLowerCase() === "off") {
77
+ return false;
78
+ }
79
+
80
+ // Now check if it's a number
81
+ const number = Number.parseInt(value, 10);
82
+ if (Number.isNaN(number)) {
83
+ return false;
84
+ }
85
+ if (number > 0) {
86
+ return true;
87
+ }
88
+
89
+ // Default to false
90
+ return false;
91
+ }
92
+
93
+ /**
94
+ * Walk a directory and returns the file pathts.
95
+ *
96
+ * @param dir A directory path.
97
+ */
98
+ function walk(dir: string) {
99
+ const results: Array<string> = [];
100
+ const list = fs.readdirSync(dir);
101
+ for (const file of list) {
102
+ results.push(path.join(dir, file));
103
+ }
104
+
105
+ return results;
106
+ }
107
+
108
+ /**
109
+ * Walk a directory and returns the JSON file absolute paths with one level of depth.
110
+ * Bypass the `metadata` folder.
111
+ * /abs/.../sotre/<siteId>/jsonfile.json
112
+ * /abs/.../sotre/<siteId>/jsonfile.json
113
+ * /abs/.../sotre/<siteId>/jsonfile.json
114
+ * /abs/.../sotre/<siteId>/jsonfile.json
115
+ */
116
+ function walkStore(dir: string): Array<string> {
117
+ const results: Array<string> = [];
118
+
119
+ // Listamos todas las subcarpetas y evitamos entrar en 'metadata'
120
+ const subdirs = fs.readdirSync(dir).filter((file) => {
121
+ const fullPath = path.join(dir, file);
122
+ return fs.statSync(fullPath).isDirectory() && file !== "metadata";
123
+ });
124
+
125
+ // Iteramos sobre las subcarpetas
126
+ for (const subdir of subdirs) {
127
+ const subdirPath = path.join(dir, subdir);
128
+
129
+ // Listamos los archivos en cada subcarpeta y filtramos los .json
130
+ const files = fs
131
+ .readdirSync(subdirPath)
132
+ .filter((file) => file.endsWith(".json"));
133
+
134
+ for (const file of files) {
135
+ results.push(path.join(subdirPath, file));
136
+ }
137
+ }
138
+
139
+ return results;
140
+ }
141
+
142
+ /**
143
+ * Custom delay using the "promise hack",
144
+ *
145
+ * @param ms Amount of miliseconds to be delayed
146
+ */
147
+ function delay(ms: number) {
148
+ return new Promise((res) => setTimeout(res, ms));
149
+ }
150
+
151
+ /**
152
+ * Converts milliseconds to seconds with a fixed number of decimals.
153
+ *
154
+ * @param ms The number in milliseconds.
155
+ * @param fixed The amount of fixed decimals.
156
+ * @returns The converted number in seconds with the fixed number of decimals.
157
+ */
158
+ function msToSec(ms: number, decimals = 3) {
159
+ return (ms / 1000).toFixed(decimals);
160
+ }
161
+
162
+ /**
163
+ * Return a siteID from a response object if exist
164
+ * @param response A response object
165
+ */
166
+ function getSafeSiteId(response: APIResponses) {
167
+ if (typeof response === "string") {
168
+ return undefined;
169
+ }
170
+
171
+ return "site" in response && response.site ? response?.site : undefined;
172
+ }
173
+
174
+ /**
175
+ * Remove props from an object
176
+ *
177
+ * @param obj The object
178
+ * @param props An array of props to be removed
179
+ */
180
+ function removeProperties(obj: Record<string, unknown>, props: Array<string>) {
181
+ for (const key in obj) {
182
+ if (props.includes(key)) {
183
+ delete obj[key];
184
+ } else if (typeof obj[key] === "object") {
185
+ removeProperties(obj[key] as Record<string, unknown>, props);
186
+ }
187
+ }
188
+ }
189
+
190
+ /**
191
+ * Remove unused files (old) inside the `apiCache` dir
192
+ *
193
+ * @todo remove other file types: sites, socials, etc..
194
+ */
195
+ function sanitizeAPICacheDir() {
196
+ const { __cx } = config.paths();
197
+ const dirPath = path.join(__cx, "apiCache");
198
+ const allCachedFiles = fs.readdirSync(dirPath);
199
+
200
+ // Object to store the the more rencent file names
201
+ // Record<string, string> = { "234856872634", "3268746238747238.json"};
202
+ const filesByIdMap: Record<string, string> = {};
203
+ // ^id ^path
204
+
205
+ // Page files.
206
+ // We only need files that describes a page object.
207
+ const pageFilePaths = allCachedFiles.filter((fileName) => {
208
+ const filePath = `${dirPath}/${fileName}`;
209
+ const fileObject = fsx.readJSONSync(filePath, "utf-8") as APIPageObject;
210
+ const { id, entity, fullUrl } = fileObject;
211
+
212
+ // Is a page file if has id, entity and fullUrl
213
+ return !!(id && entity && fullUrl);
214
+ });
215
+
216
+ // Fill the filesById object
217
+ for (const fileName of pageFilePaths) {
218
+ const filePath = `${dirPath}/${fileName}`;
219
+ const fileObject = fsx.readJSONSync(filePath, "utf-8") as APIPageObject;
220
+ const fileCreationDate = fs.statSync(filePath).mtimeMs;
221
+
222
+ const { id } = fileObject;
223
+
224
+ // Is a valid page if doesn't exists in the store object or is newer
225
+ // that the stored one.
226
+ const validPageFile =
227
+ !filesByIdMap[id] ||
228
+ fileCreationDate > fs.statSync(`${dirPath}/${filesByIdMap[id]}`).mtimeMs;
229
+
230
+ if (validPageFile) {
231
+ filesByIdMap[id] = fileName;
232
+ }
233
+ }
234
+
235
+ let counter = 0;
236
+
237
+ // Delete files using the store object filesById as reference map.
238
+ for (const fileName of pageFilePaths) {
239
+ const filePath = `${dirPath}/${fileName}`;
240
+ const fileObject = fsx.readJSONSync(filePath, "utf-8") as APIPageObject;
241
+
242
+ const { id } = fileObject;
243
+
244
+ // If the filename is not present in the map, remove it!
245
+ if (fileName !== filesByIdMap[id]) {
246
+ fs.unlinkSync(filePath);
247
+ counter++;
248
+ }
249
+ }
250
+
251
+ console.log(`Sanitize apiCache dir for ${counter} files`);
252
+ }
253
+
254
+ /**
255
+ * Measures the execution time of a series of sync or async functions.
256
+ *
257
+ * @async
258
+ * @param functions - Functions to be executed to measure their execution time.
259
+ * @returns A promise that resolves with the total execution time in seconds.
260
+ */
261
+ async function measureExecutionTime(
262
+ functions: Array<(...args: Array<unknown>) => unknown | Promise<unknown>>,
263
+ ) {
264
+ const start = process.hrtime();
265
+
266
+ for (const func of functions) {
267
+ await func();
268
+ }
269
+
270
+ const [seconds, miliseconds] = process.hrtime(start);
271
+ const timeInSeconds = seconds + miliseconds / 1e9;
272
+
273
+ return +timeInSeconds.toFixed(3);
274
+ }
275
+
276
+ /**
277
+ * Pause the process until a key is pressed.
278
+ *
279
+ * @param title
280
+ * @returns
281
+ */
282
+ function pause(title: string) {
283
+ const isPauseEnabled = !!envs.GRIDDO_RENDER_BREAKPOINTS_FEATURE;
284
+
285
+ if (!isPauseEnabled) {
286
+ return;
287
+ }
288
+
289
+ return new Promise<void>((resolve) => {
290
+ console.log("\n");
291
+ boxLog(`⌛️ ${title}`, "", 1, 0);
292
+ process.stdin.once("data", () => {
293
+ resolve();
294
+ });
295
+ });
296
+ }
297
+
298
+ /**
299
+ * Executes a life cycle process, which involves executing an array of
300
+ * functions, printing to the console, and handling errors with optional
301
+ * retries.
302
+ *
303
+ * @async
304
+ * @param name - The name of the life cycle.
305
+ * @param options - The arguments object.
306
+ * @param options.steps - An array of functions to execute.
307
+ * @returns - A promise that resolves when the life cycle process is completed.
308
+ */
309
+ async function doLifeCycle(name: LifeCyclesNames, steps: LifeCycleSteps) {
310
+ const attemptsByLifeCycleName: Record<LifeCyclesNames, number> = {
311
+ Init: envs.GRIDDO_ARCHIVE_LIFECYCLE_MAX_ATTEMPTS,
312
+ Archive: envs.GRIDDO_ARCHIVE_LIFECYCLE_MAX_ATTEMPTS,
313
+ Data: envs.GRIDDO_DATA_LIFECYCLE_MAX_ATTEMPTS,
314
+ Meta: envs.GRIDDO_META_LIFECYCLE_MAX_ATTEMPTS,
315
+ Relocation: envs.GRIDDO_RELOCATION_LIFECYCLE_MAX_ATTEMPTS,
316
+ Clean: envs.GRIDDO_CLEAN_LIFECYCLE_MAX_ATTEMPTS,
317
+ Restore: envs.GRIDDO_RESTORE_LIFECYCLE_MAX_ATTEMPTS,
318
+ Prepare: envs.GRIDDO_PREPARE_LIFECYCLE_MAX_ATTEMPTS,
319
+ Close: envs.GRIDDO_CLOSE_LIFECYCLE_MAX_ATTEMPTS,
320
+ SSG: envs.GRIDDO_SSG_LIFECYCLE_MAX_ATTEMPTS,
321
+ HealthCheck: 1,
322
+ __DEBUG__: 1,
323
+ };
324
+
325
+ let trysCount = 0;
326
+ const maxTrysAccepted = attemptsByLifeCycleName[name] || 1;
327
+
328
+ while (trysCount < maxTrysAccepted) {
329
+ try {
330
+ infoLog(`start ${name} life-cycle`);
331
+ const exeTime = await measureExecutionTime(steps);
332
+ successLog(`${name} - ${exeTime}s\n`);
333
+ // if no errors, print and go out
334
+ await pause(`${name} LifeCycle`);
335
+ break;
336
+ } catch (error) {
337
+ const errorString = bgRed(black(` Error in ${name} LifeCycle `));
338
+ const attemptsString = kleur.yellow(`Attempt (${trysCount + 1})`);
339
+ console.log(`\n${errorString} ${attemptsString}\n`);
340
+ console.log(error);
341
+ console.log();
342
+
343
+ trysCount++;
344
+ }
345
+ }
346
+
347
+ if (trysCount === maxTrysAccepted) {
348
+ throwError(LifecycleExecutionError(maxTrysAccepted, name));
349
+ }
350
+ }
351
+
352
+ /**
353
+ * Creates additional files after the render: sitemaps, robots and a report of
354
+ * the finished render.
355
+ *
356
+ * @async
357
+ * @param domain
358
+ */
359
+ async function createDomainMetadata(domain: string) {
360
+ await generateBuildReport();
361
+ await generateSitemaps();
362
+ await RobotsService.writeFiles(domain);
363
+ }
364
+
365
+ function removeAllSiteDirsFromStore() {
366
+ const { __cx } = config.paths();
367
+ const storeDir = path.join(__cx, "store");
368
+ const allDirs = fs.readdirSync(storeDir);
369
+
370
+ const allSiteDirs = allDirs.filter((dirname) => dirname !== "metadata");
371
+
372
+ const allSiteDirsFullPath = allSiteDirs.map((name) =>
373
+ path.join(storeDir, name),
374
+ );
375
+
376
+ // Remove all site directories except "metadata" directory.
377
+ for (const site of allSiteDirsFullPath) {
378
+ fs.rmSync(site, { recursive: true, force: true });
379
+ }
380
+ }
381
+
382
+ function getFormattedDateTime() {
383
+ const now = new Date();
384
+ const date = [
385
+ String(now.getDate()).padStart(2, "0"),
386
+ String(now.getMonth() + 1).padStart(2, "0"),
387
+ now.getFullYear(),
388
+ ].join("-");
389
+
390
+ const time = [
391
+ String(now.getHours()).padStart(2, "0"),
392
+ String(now.getMinutes()).padStart(2, "0"),
393
+ String(now.getSeconds()).padStart(2, "0"),
394
+ ].join(":");
395
+
396
+ return `${date}_${time}`;
397
+ }
398
+
399
+ /**
400
+ * Save render information to a file to use as debug log.
401
+ *
402
+ * This information will **not** be sent to any API.
403
+ */
404
+ function saveBuildEndLogs() {
405
+ const { __cx } = config.paths();
406
+ const { sitesToPublish, createdPages, buildProcessData } = fsx.readJSONSync(
407
+ path.join(__cx, "render-metadata.json"),
408
+ );
409
+
410
+ const dateString = getFormattedDateTime();
411
+ const buildEndLogsDir = path.join(__cx, "debug", "build-end");
412
+
413
+ if (!fs.existsSync(buildEndLogsDir)) {
414
+ fs.mkdirSync(buildEndLogsDir, { recursive: true });
415
+ }
416
+
417
+ // Log
418
+ fs.writeFileSync(
419
+ path.join(buildEndLogsDir, `${dateString}.json`),
420
+ JSON.stringify(
421
+ {
422
+ date: new Date().toLocaleString(),
423
+ log: {
424
+ sitesToPublish,
425
+ createdPages,
426
+ buildProcessData,
427
+ },
428
+ },
429
+ null,
430
+ 2,
431
+ ),
432
+ );
433
+
434
+ // Update index
435
+ prependFileSync(
436
+ path.join(buildEndLogsDir, "index.html"),
437
+ `<pre><a href="${dateString}.json">${dateString}</a></pre>\n`,
438
+ );
439
+ }
440
+
441
+ export {
442
+ createDomainMetadata,
443
+ delay,
444
+ doLifeCycle,
445
+ getConfig,
446
+ getSafeSiteId,
447
+ instanceRootDir,
448
+ isTruthy,
449
+ measureExecutionTime,
450
+ msToSec,
451
+ pause,
452
+ removeAllSiteDirsFromStore,
453
+ removeProperties,
454
+ sanitizeAPICacheDir,
455
+ saveBuildEndLogs,
456
+ walk,
457
+ walkStore,
458
+ };
@@ -0,0 +1,17 @@
1
+ import { createAPICacheDir } from "./cache";
2
+ import { sanitizeAPICacheDir } from "./core-utils";
3
+ import { createStore } from "../services/store";
4
+
5
+ /**
6
+ * Download all data: sites, pages etc.. from the instance private Griddo API.
7
+ * Then you can use the generator funcion `getBuildPagesFromStore()` to get the pages and
8
+ * `getBuildMetadata()` to get build and sites metadata as objects. Both from
9
+ * exporter utils sites dir.
10
+ */
11
+ async function createDomainRenderData(domain: string) {
12
+ createAPICacheDir();
13
+ await createStore(domain);
14
+ sanitizeAPICacheDir();
15
+ }
16
+
17
+ export { createDomainRenderData };
@@ -0,0 +1,39 @@
1
+ import type { Domains } from "../types/global";
2
+
3
+ import { verboseLog } from "./loggin";
4
+ import { throwError } from "../errors";
5
+ import { NoDomainsFoundError } from "../errors/errors-data";
6
+ import { AuthService } from "../services/auth";
7
+ import { getAllDomains } from "../services/domains";
8
+
9
+ /**
10
+ * Return an array of domains name (string) of the current instance.
11
+ */
12
+ async function getInstanceDomains() {
13
+ await AuthService.login();
14
+ const domains = await getAllDomains();
15
+
16
+ if (!domains.length) {
17
+ throwError(NoDomainsFoundError);
18
+ }
19
+
20
+ verboseLog(`getting domains names (${domains.length})`);
21
+
22
+ return getDomainSlugs(domains);
23
+ }
24
+
25
+ /**
26
+ * Return an unique array of domains, filtered without "/".
27
+ *
28
+ * @param domains An array of domains
29
+ * @see Domains
30
+ */
31
+ function getDomainSlugs(domains: Domains) {
32
+ const filteredDomains = domains
33
+ .filter(({ slug }) => !!slug)
34
+ .map(({ slug }) => slug.replace("/", ""));
35
+
36
+ return [...new Set(filteredDomains)];
37
+ }
38
+
39
+ export { getInstanceDomains, getDomainSlugs };