@griddo/cx 11.9.7 → 11.9.8-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 (222) hide show
  1. package/README.md +78 -193
  2. package/build/commands/end-render.js +31 -0
  3. package/build/commands/end-render.js.map +7 -0
  4. package/build/commands/prepare-assets-directory.js +9 -0
  5. package/build/commands/prepare-assets-directory.js.map +7 -0
  6. package/build/commands/prepare-domains-render.js +38 -0
  7. package/build/commands/prepare-domains-render.js.map +7 -0
  8. package/build/commands/reset-render.js +31 -0
  9. package/build/commands/reset-render.js.map +7 -0
  10. package/build/commands/start-embeddings.js +31 -0
  11. package/build/commands/start-embeddings.js.map +7 -0
  12. package/build/commands/start-render.js +66 -0
  13. package/build/commands/start-render.js.map +7 -0
  14. package/build/commands/upload-search-content.js +31 -0
  15. package/build/commands/upload-search-content.js.map +7 -0
  16. package/build/core/GriddoLog.d.ts +16 -0
  17. package/build/core/db.d.ts +4 -0
  18. package/build/core/dist-rollback.d.ts +2 -0
  19. package/build/{errors/index.d.ts → core/errors.d.ts} +5 -4
  20. package/build/core/fs.d.ts +69 -0
  21. package/build/core/logger.d.ts +18 -0
  22. package/build/index.d.ts +10 -29
  23. package/build/index.js +406 -73
  24. package/build/services/auth.d.ts +2 -5
  25. package/build/services/manage-store.d.ts +48 -0
  26. package/build/services/render.d.ts +70 -0
  27. package/build/shared/envs.d.ts +19 -0
  28. package/build/{errors/errors-data.d.ts → shared/errors.d.ts} +5 -3
  29. package/build/shared/npm-modules/brush.d.ts +18 -0
  30. package/build/shared/npm-modules/find-up-simple.d.ts +34 -0
  31. package/build/shared/npm-modules/pkg-dir.d.ts +7 -0
  32. package/build/{types → shared/types}/api.d.ts +18 -18
  33. package/build/{types → shared/types}/global.d.ts +15 -16
  34. package/build/{types → shared/types}/navigation.d.ts +5 -5
  35. package/build/{types → shared/types}/pages.d.ts +9 -9
  36. package/build/shared/types/render.d.ts +54 -0
  37. package/build/{types → shared/types}/sites.d.ts +18 -19
  38. package/cli.mjs +239 -0
  39. package/exporter/build-esbuild.noop +42 -0
  40. package/exporter/build.sh +17 -28
  41. package/exporter/commands/README.md +151 -0
  42. package/exporter/commands/end-render.ts +65 -86
  43. package/exporter/commands/prepare-assets-directory.ts +34 -0
  44. package/exporter/commands/prepare-domains-render.ts +143 -35
  45. package/exporter/commands/reset-render.ts +12 -7
  46. package/exporter/commands/single-domain-upload-search-content.noop +206 -0
  47. package/exporter/commands/start-embeddings.ts +29 -0
  48. package/exporter/commands/start-render.ts +26 -64
  49. package/exporter/commands/upload-search-content.ts +201 -26
  50. package/exporter/core/GriddoLog.ts +45 -0
  51. package/exporter/core/check-env-health.ts +200 -0
  52. package/exporter/core/db-class.ts +54 -0
  53. package/exporter/core/db.ts +33 -0
  54. package/exporter/core/dist-rollback.ts +40 -0
  55. package/exporter/core/errors.ts +82 -0
  56. package/exporter/core/fs.ts +385 -0
  57. package/exporter/{utils → core}/images.ts +1 -6
  58. package/exporter/{utils → core}/instance.ts +9 -13
  59. package/exporter/core/life-cycle.ts +73 -0
  60. package/exporter/core/logger.ts +141 -0
  61. package/exporter/core/objects.ts +37 -0
  62. package/exporter/core/print-logos.ts +21 -0
  63. package/exporter/index.ts +14 -56
  64. package/exporter/services/api.ts +306 -0
  65. package/exporter/services/auth.ts +8 -10
  66. package/exporter/services/domains.ts +23 -8
  67. package/exporter/services/manage-sites.ts +116 -0
  68. package/exporter/services/manage-store.ts +235 -0
  69. package/exporter/services/navigation.ts +12 -18
  70. package/exporter/{utils → services}/pages.ts +27 -92
  71. package/exporter/services/reference-fields.ts +14 -32
  72. package/exporter/services/render-artifacts.ts +44 -0
  73. package/exporter/services/render.ts +229 -0
  74. package/exporter/services/robots.ts +33 -61
  75. package/exporter/services/sitemaps.ts +129 -0
  76. package/exporter/services/sites.ts +40 -28
  77. package/exporter/services/store.ts +386 -319
  78. package/exporter/shared/context.ts +49 -0
  79. package/exporter/{constants → shared}/endpoints.ts +12 -11
  80. package/exporter/shared/envs.ts +62 -0
  81. package/exporter/{errors/errors-data.ts → shared/errors.ts} +24 -14
  82. package/exporter/shared/npm-modules/README.md +36 -0
  83. package/exporter/shared/npm-modules/brush.ts +34 -0
  84. package/exporter/shared/npm-modules/find-up-simple.ts +100 -0
  85. package/exporter/shared/npm-modules/pkg-dir.ts +17 -0
  86. package/exporter/shared/npm-modules/xml-parser.ts +57 -0
  87. package/exporter/{types → shared/types}/api.ts +40 -41
  88. package/exporter/{types → shared/types}/global.ts +17 -21
  89. package/exporter/{types → shared/types}/navigation.ts +3 -3
  90. package/exporter/{types → shared/types}/pages.ts +10 -11
  91. package/exporter/shared/types/render.ts +63 -0
  92. package/exporter/{types → shared/types}/sites.ts +18 -19
  93. package/exporter/ssg-adapters/gatsby/actions/clean.ts +26 -0
  94. package/exporter/ssg-adapters/gatsby/actions/close.ts +17 -0
  95. package/exporter/ssg-adapters/gatsby/actions/data.ts +22 -0
  96. package/exporter/ssg-adapters/gatsby/actions/healthCheck.ts +10 -0
  97. package/exporter/ssg-adapters/gatsby/actions/init.ts +12 -0
  98. package/exporter/ssg-adapters/gatsby/actions/logs.ts +10 -0
  99. package/exporter/ssg-adapters/gatsby/actions/meta.ts +13 -0
  100. package/exporter/ssg-adapters/gatsby/actions/prepare.ts +9 -0
  101. package/exporter/ssg-adapters/gatsby/actions/relocation.ts +15 -0
  102. package/exporter/ssg-adapters/gatsby/actions/restore.ts +21 -0
  103. package/exporter/ssg-adapters/gatsby/actions/ssg.ts +12 -0
  104. package/exporter/ssg-adapters/gatsby/actions/sync.ts +65 -0
  105. package/exporter/ssg-adapters/gatsby/index.ts +114 -0
  106. package/exporter/ssg-adapters/gatsby/shared/artifacts.ts +16 -0
  107. package/exporter/ssg-adapters/gatsby/shared/diff-assets.ts +128 -0
  108. package/exporter/ssg-adapters/gatsby/shared/extract-assets.ts +75 -0
  109. package/exporter/ssg-adapters/gatsby/shared/gatsby-build.ts +58 -0
  110. package/exporter/ssg-adapters/gatsby/shared/sync-render.ts +300 -0
  111. package/exporter/ssg-adapters/gatsby/shared/types.ts +35 -0
  112. package/exporter/ssg-adapters/gatsby/shared/utils.ts +33 -0
  113. package/gatsby-browser.tsx +41 -58
  114. package/gatsby-config.ts +10 -17
  115. package/gatsby-node.ts +20 -80
  116. package/gatsby-ssr.tsx +2 -1
  117. package/package.json +41 -92
  118. package/plugins/gatsby-plugin-svgr-loader/gatsby-node.js +55 -0
  119. package/plugins/gatsby-plugin-svgr-loader/package.json +8 -0
  120. package/react/DynamicScript/index.tsx +33 -0
  121. package/{exporter/react/Favicon → react/GriddoFavicon}/index.tsx +3 -9
  122. package/{exporter/react → react}/GriddoIntegrations/index.tsx +17 -23
  123. package/{exporter/react → react}/GriddoIntegrations/utils.ts +24 -12
  124. package/react/GriddoOpenGraph/index.tsx +39 -0
  125. package/src/components/Head.tsx +30 -73
  126. package/src/components/template.tsx +8 -30
  127. package/src/gatsby-node-utils.ts +76 -2
  128. package/src/html.tsx +2 -11
  129. package/src/types.ts +5 -5
  130. package/tsconfig.commands.json +36 -0
  131. package/tsconfig.exporter.json +20 -0
  132. package/tsconfig.json +5 -3
  133. package/build/adapters/gatsby/index.d.ts +0 -4
  134. package/build/adapters/gatsby/utils.d.ts +0 -22
  135. package/build/artifacts/index.d.ts +0 -6
  136. package/build/commands/end-render.d.ts +0 -2
  137. package/build/commands/move-assets.d.ts +0 -1
  138. package/build/commands/prepare-domains-render.d.ts +0 -1
  139. package/build/commands/reset-render.d.ts +0 -2
  140. package/build/commands/start-render.d.ts +0 -2
  141. package/build/commands/upload-search-content.d.ts +0 -2
  142. package/build/constants/envs.d.ts +0 -37
  143. package/build/constants/index.d.ts +0 -57
  144. package/build/end-render.js +0 -74
  145. package/build/end-render.js.map +0 -7
  146. package/build/index.js.map +0 -7
  147. package/build/prepare-domains-render.js +0 -73
  148. package/build/prepare-domains-render.js.map +0 -7
  149. package/build/react/Favicon/index.d.ts +0 -5
  150. package/build/react/Favicon/utils.d.ts +0 -9
  151. package/build/react/GriddoIntegrations/index.d.ts +0 -20
  152. package/build/react/GriddoIntegrations/utils.d.ts +0 -26
  153. package/build/react/index.d.ts +0 -3
  154. package/build/react/index.js +0 -3
  155. package/build/registers/api.d.ts +0 -9
  156. package/build/registers/gatsby.d.ts +0 -9
  157. package/build/registers/index.d.ts +0 -3
  158. package/build/reset-render.js +0 -74
  159. package/build/reset-render.js.map +0 -7
  160. package/build/services/domains.d.ts +0 -6
  161. package/build/services/navigation.d.ts +0 -50
  162. package/build/services/reference-fields.d.ts +0 -20
  163. package/build/services/register.d.ts +0 -36
  164. package/build/services/robots.d.ts +0 -19
  165. package/build/services/settings.d.ts +0 -4
  166. package/build/services/sites.d.ts +0 -29
  167. package/build/services/store.d.ts +0 -6
  168. package/build/start-render.js +0 -100
  169. package/build/start-render.js.map +0 -7
  170. package/build/types/templates.d.ts +0 -8
  171. package/build/upload-search-content.js +0 -74
  172. package/build/upload-search-content.js.map +0 -7
  173. package/build/utils/alerts.d.ts +0 -3
  174. package/build/utils/api.d.ts +0 -23
  175. package/build/utils/cache.d.ts +0 -35
  176. package/build/utils/core-utils.d.ts +0 -107
  177. package/build/utils/create-build-data.d.ts +0 -8
  178. package/build/utils/domains.d.ts +0 -13
  179. package/build/utils/folders.d.ts +0 -53
  180. package/build/utils/health-checks.d.ts +0 -7
  181. package/build/utils/images.d.ts +0 -16
  182. package/build/utils/loggin.d.ts +0 -51
  183. package/build/utils/pages.d.ts +0 -34
  184. package/build/utils/render.d.ts +0 -13
  185. package/build/utils/searches.d.ts +0 -15
  186. package/build/utils/sites.d.ts +0 -31
  187. package/build/utils/store.d.ts +0 -81
  188. package/cx.config.d.ts +0 -5
  189. package/cx.config.js +0 -36
  190. package/exporter/adapters/gatsby/index.ts +0 -162
  191. package/exporter/adapters/gatsby/utils.ts +0 -161
  192. package/exporter/artifacts/README.md +0 -34
  193. package/exporter/artifacts/index.ts +0 -33
  194. package/exporter/commands/move-assets.ts +0 -11
  195. package/exporter/constants/envs.ts +0 -94
  196. package/exporter/constants/index.ts +0 -129
  197. package/exporter/errors/index.ts +0 -40
  198. package/exporter/react/index.tsx +0 -11
  199. package/exporter/registers/api.ts +0 -14
  200. package/exporter/registers/gatsby.ts +0 -14
  201. package/exporter/registers/index.ts +0 -4
  202. package/exporter/services/register.ts +0 -113
  203. package/exporter/services/settings.ts +0 -17
  204. package/exporter/utils/alerts.ts +0 -29
  205. package/exporter/utils/api.ts +0 -243
  206. package/exporter/utils/cache.ts +0 -142
  207. package/exporter/utils/core-utils.ts +0 -458
  208. package/exporter/utils/create-build-data.ts +0 -17
  209. package/exporter/utils/domains.ts +0 -39
  210. package/exporter/utils/folders.ts +0 -320
  211. package/exporter/utils/health-checks.ts +0 -64
  212. package/exporter/utils/loggin.ts +0 -184
  213. package/exporter/utils/render.ts +0 -71
  214. package/exporter/utils/searches.ts +0 -156
  215. package/exporter/utils/sites.ts +0 -312
  216. package/exporter/utils/store.ts +0 -314
  217. package/src/README.md +0 -7
  218. package/start-render.js +0 -7
  219. /package/build/{utils → core}/instance.d.ts +0 -0
  220. /package/build/{constants → shared}/endpoints.d.ts +0 -0
  221. /package/exporter/{types → shared/types}/templates.ts +0 -0
  222. /package/{exporter/react/Favicon → react/GriddoFavicon}/utils.ts +0 -0
@@ -1,102 +1,191 @@
1
- import type { BuildProcessData } from "../types/global";
1
+ import type { BuildProcessData, Settings } from "../shared/types/global";
2
2
  import type {
3
3
  GriddoListPage,
4
4
  GriddoMultiPage,
5
5
  GriddoPageObject,
6
6
  GriddoSinglePage,
7
7
  PageAdditionalInfo,
8
- } from "../types/pages";
8
+ } from "../shared/types/pages";
9
+ import type { HashSites, Site, SiteHash } from "../shared/types/sites";
9
10
 
10
- import fs from "node:fs";
11
+ import fsp from "node:fs/promises";
11
12
  import path from "node:path";
12
13
 
13
14
  import pLimit from "p-limit";
14
15
 
15
- import { envs } from "../constants";
16
- import { NavigationService } from "./navigation";
17
- import { getReferenceFieldData } from "./reference-fields";
18
- import { getAllSettings } from "./settings";
19
- import { getPage } from "./sites";
20
- import { updatedSiteHash } from "../utils/cache";
21
- import { getConfig, removeAllSiteDirsFromStore } from "../utils/core-utils";
22
- import { buildLog, listSitesLog } from "../utils/loggin";
16
+ import { GriddoLog } from "../core/GriddoLog";
17
+ import { SETTINGS } from "../shared/endpoints";
23
18
  import {
24
- createGriddoListPages,
25
- createGriddoMultiPages,
26
- createGriddoSinglePage,
27
- getMultiPageElements,
28
- getPaginatedPages,
29
- } from "../utils/pages";
30
- import { getSiteData, getSitesToRender, unpublishSites } from "../utils/sites";
19
+ GRIDDO_API_CONCURRENCY_COUNT,
20
+ GRIDDO_API_URL,
21
+ GRIDDO_PUBLIC_API_URL,
22
+ GRIDDO_REACT_APP_INSTANCE,
23
+ } from "../shared/envs";
24
+ import { brush } from "../shared/npm-modules/brush";
25
+ import { RENDER_MODE, type RenderMode } from "../shared/types/render";
26
+ import { get } from "./api";
27
+ import { getSiteData, getSitesToRender, unpublishSites } from "./manage-sites";
31
28
  import {
32
- getMissingPublishedPagesInStore,
33
29
  getZombiePagesInStore,
34
30
  removeOrphanSites,
35
31
  removeSitePagesFromStore,
36
32
  saveRenderInfoInStore,
37
33
  saveSitePagesInStore,
38
- } from "../utils/store";
34
+ } from "./manage-store";
35
+ import { NavigationService } from "./navigation";
36
+ import {
37
+ createGriddoListPages,
38
+ createGriddoMultiPages,
39
+ createGriddoSinglePage,
40
+ getMultiPageElements,
41
+ getPaginatedPages,
42
+ } from "./pages";
43
+ import { getReferenceFieldData } from "./reference-fields";
44
+ import { getRenderPathsHydratedWithDomainFromDB } from "./render";
45
+ import { getPage } from "./sites";
39
46
 
40
- const renderId = new Date().valueOf().toString();
41
- const { griddoVersion, paths } = getConfig();
42
- const { __cx } = paths();
43
- const storeDir = path.join(__cx, "store");
47
+ const renderId = Date.now().toString();
44
48
 
45
- /**
46
- * Fetch, process and save object pages and sites data into the file system to
47
- * be consumed by other services (Griddo itself, Adapters, etc.)
48
- */
49
- async function createStore(domain: string) {
50
- console.info(`API calls with ${envs.GRIDDO_API_CONCURRENCY_COUNT} threads`);
51
- console.info(`API URL ${envs.GRIDDO_API_URL as string}`);
49
+ function guessSiteNeedsToBeRenderedFromScratch() {
50
+ return false;
51
+ }
52
52
 
53
- try {
54
- // Vars to save later in the report file
55
- const createdPages: Array<number> = [];
56
- const buildProcessData: BuildProcessData = {};
53
+ function listSitesLog(title: string, sites: Site[]) {
54
+ const maxline = Math.max(
55
+ ...sites.map((s) => s.name.length + (s.shouldBeUpdated ? 1 : 0) + s.id.toString().length),
56
+ );
57
57
 
58
- // Get sites objects to publish and unpublish from this domain
59
- const { sitesToPublish, sitesToUnpublish } = await getSitesToRender(domain);
58
+ const sitesStr = sites.map((s) => {
59
+ const shouldBeUpdated = s.shouldBeUpdated ? "*" : "";
60
+ const lineLen = s.name.length + shouldBeUpdated.length + s.id.toString().length;
61
+ const padding = " ".repeat(maxline - lineLen);
62
+ return `${brush.bold(s.name)} ${brush.dim(`(${s.id})`)} ${shouldBeUpdated} ${padding}${brush.dim("-")} ${brush.dim(s.slug)}`;
63
+ });
60
64
 
61
- const domainHasSites =
62
- sitesToPublish.length > 0 || sitesToUnpublish.length > 0;
65
+ const sitesOutput = sitesStr.length > 0 ? `\n\n${sitesStr.join("\n")}` : brush.dim("--none--\n");
63
66
 
64
- if (!domainHasSites) {
65
- console.warn(`There are no sites to update in the domain ${domain}`);
66
- }
67
+ GriddoLog.log(`
68
+ ${title} ${sitesOutput}`);
69
+ }
67
70
 
68
- listSitesLog("Sites to publish:", sitesToPublish);
69
- listSitesLog("Sites to unpublish:", sitesToUnpublish);
70
-
71
- // Send unpublished sites to API.
72
- // @todo ¿mover esta llamada al final del proceso de render?
73
- // Aquí también se están eliminado físicamente los archivos json del
74
- // store de los sites para despublicar.
75
- await unpublishSites(sitesToUnpublish);
76
-
77
- // Eliminamos posibles sites que estén en el store pero que no deberían
78
- // porque han sido cambiados de dominio. Si han sido despublicados ya se
79
- // despublican bien porque entran en `sitesToUnpublish`
80
- removeOrphanSites(sitesToPublish, domain);
81
-
82
- // Solo los sites to publish...
83
- for (const site of sitesToPublish) {
84
- const { id: siteId, slug: siteSlug, theme, favicon, pagesStatus } = site;
85
- const siteDirName = siteId.toString();
86
-
87
- const {
88
- siteInfo,
89
- siteHash,
90
- unpublishHashes,
91
- siteLangs,
92
- defaultLang,
93
- headers,
94
- footers,
95
- socials,
96
- } = await getSiteData(siteId);
97
-
98
- const {
99
- cloudinaryName,
71
+ /**
72
+ * Fetch, process and save object pages and sites data into the file system to
73
+ * be consumed by other services (Griddo itself, Adapters, etc.)
74
+ */
75
+ async function createStore(options: {
76
+ domain: string;
77
+ renderMode: RenderMode;
78
+ griddoVersion: string;
79
+ basePath: string;
80
+ }) {
81
+ console.info(`API calls with ${GRIDDO_API_CONCURRENCY_COUNT} threads`);
82
+ console.info(`API URL ${GRIDDO_API_URL as string}`);
83
+
84
+ const { renderMode, domain, griddoVersion, basePath } = options;
85
+ const renderFromScratch = renderMode === RENDER_MODE.FROM_SCRATCH;
86
+ const storeDir = path.join(basePath, "store");
87
+
88
+ // Vars to save later in the report file
89
+ const createdPages: number[] = [];
90
+ const buildProcessData: BuildProcessData = {};
91
+
92
+ // Get sites objects to publish and unpublish from this domain
93
+ const { sitesToPublish, sitesToUnpublish } = await getSitesToRender(domain);
94
+
95
+ listSitesLog("Sites to publish:", sitesToPublish);
96
+ listSitesLog("Sites to unpublish:", sitesToUnpublish);
97
+
98
+ // Send unpublished sites to API.
99
+ await unpublishSites(sitesToUnpublish);
100
+
101
+ // Eliminamos posibles sites que estén en el store pero que no deberían
102
+ // porque han sido cambiados de dominio. Si han sido despublicados ya se
103
+ // despublican bien porque entran en `sitesToUnpublish`
104
+ await removeOrphanSites(sitesToPublish, domain);
105
+
106
+ const allPagesToRemoveFromBuild: number[] = [];
107
+ // let numberOfFinalActivePages: number[] = [];
108
+
109
+ for (const site of sitesToUnpublish) {
110
+ const { pagesStatus } = site;
111
+
112
+ // Añadimos a allPagesToRemoveFromBuild todas las páginas de un site
113
+ // para despublicar.
114
+ allPagesToRemoveFromBuild.push(
115
+ ...pagesStatus.active,
116
+ ...pagesStatus.offlinePending,
117
+ ...pagesStatus.uploadPending,
118
+ ...pagesStatus.deleted,
119
+ ...pagesStatus.offline,
120
+ );
121
+ }
122
+
123
+ for (const site of sitesToPublish) {
124
+ const { id: siteId, slug: siteSlug, theme, favicon, pagesStatus } = site;
125
+ const siteDirName = siteId.toString();
126
+ // numberOfFinalActivePages.push(
127
+ // ...pagesStatus.active,
128
+ // ...pagesStatus.uploadPending,
129
+ // );
130
+
131
+ allPagesToRemoveFromBuild.push(...pagesStatus.offlinePending, ...pagesStatus.deleted);
132
+
133
+ const {
134
+ siteInfo,
135
+ siteHash,
136
+ unpublishHashes,
137
+ siteLangs,
138
+ defaultLang,
139
+ headers,
140
+ footers,
141
+ socials,
142
+ } = await getSiteData(siteId);
143
+
144
+ const {
145
+ cloudinaryName,
146
+ useMetaTitle,
147
+ useMetaKeywords,
148
+ showBasicMetaRobots,
149
+ avoidHrefLangsOnCanonicals,
150
+ avoidSelfReferenceCanonicals,
151
+ avoidHrefLangXDefault,
152
+ avoidDebugMetas,
153
+ } = await get<Settings>({ endpoint: SETTINGS });
154
+
155
+ buildProcessData[siteId] = {
156
+ siteHash,
157
+ unpublishHashes,
158
+ publishHashes: [],
159
+ publishPagesIds: [],
160
+ };
161
+
162
+ const NavService = new NavigationService();
163
+ NavService.navigations = { headers, footers };
164
+
165
+ site.languages = siteLangs;
166
+
167
+ const shouldUpdateSite = await updatedSiteHash(siteId, siteHash);
168
+
169
+ const siteScript = siteInfo.siteScript;
170
+
171
+ const siteMetadata = {
172
+ siteUrl: siteInfo.slug,
173
+ title: siteInfo.name,
174
+ favicon,
175
+ };
176
+
177
+ const additionalInfo = {
178
+ baseUrl: GRIDDO_API_URL,
179
+ publicBaseUrl: GRIDDO_PUBLIC_API_URL,
180
+ instance: GRIDDO_REACT_APP_INSTANCE,
181
+ siteSlug,
182
+ theme,
183
+ siteMetadata,
184
+ socials,
185
+ siteLangs,
186
+ cloudinaryName,
187
+ griddoVersion,
188
+ siteOptions: {
100
189
  useMetaTitle,
101
190
  useMetaKeywords,
102
191
  showBasicMetaRobots,
@@ -104,257 +193,235 @@ async function createStore(domain: string) {
104
193
  avoidSelfReferenceCanonicals,
105
194
  avoidHrefLangXDefault,
106
195
  avoidDebugMetas,
107
- } = await getAllSettings();
108
-
109
- buildProcessData[siteId] = {
110
- siteHash,
111
- unpublishHashes,
112
- publishHashes: [],
113
- publishPagesIds: [],
114
- };
115
-
116
- const NavService = new NavigationService();
117
- NavService.navigations = { headers, footers };
118
-
119
- site.languages = siteLangs;
120
-
121
- const shouldUpdateSite = updatedSiteHash(siteId, siteHash);
122
-
123
- const siteScript = siteInfo.siteScript;
124
-
125
- const siteMetadata = {
126
- siteUrl: siteInfo.slug,
127
- title: siteInfo.name,
128
- favicon,
129
- };
130
-
131
- const additionalInfo = {
132
- baseUrl: envs.GRIDDO_API_URL,
133
- publicBaseUrl: envs.GRIDDO_PUBLIC_API_URL,
134
- instance: envs.GRIDDO_REACT_APP_INSTANCE,
135
- siteSlug,
136
- theme,
137
- siteMetadata,
138
- socials,
139
- siteLangs,
140
- cloudinaryName,
141
- griddoVersion,
142
- siteOptions: {
143
- useMetaTitle,
144
- useMetaKeywords,
145
- showBasicMetaRobots,
146
- avoidHrefLangsOnCanonicals,
147
- avoidSelfReferenceCanonicals,
148
- avoidHrefLangXDefault,
149
- avoidDebugMetas,
150
- },
151
- siteScript,
152
- };
153
-
154
- buildLog(`${site.name} site`);
155
-
156
- /// Creates the store directory for each site using the id
157
- fs.mkdirSync(path.join(storeDir, siteDirName), {
158
- recursive: true,
196
+ },
197
+ siteScript,
198
+ };
199
+
200
+ GriddoLog.info(`Getting pages from ${site.name} site`);
201
+
202
+ /// Creates the store directory for each site using the id
203
+ await fsp.mkdir(path.join(storeDir, siteDirName), {
204
+ recursive: true,
205
+ });
206
+
207
+ // -------------------------------------------------------------------------
208
+ // Pages loop promise creation
209
+ // -------------------------------------------------------------------------
210
+ // Async function that process every page for one site to use later in the
211
+ // `Promise.all` with pLimit.
212
+ const fetchSitePageAndSaveInStore = async (siteIdName: string, pageId: number) => {
213
+ // Here will be store every page returned by the API and processed
214
+ let griddoPageObjects: GriddoPageObject[] = [];
215
+
216
+ // Get page data
217
+ const page = await getPage(pageId, shouldUpdateSite);
218
+
219
+ // Probably a 404
220
+ if (!page) {
221
+ return;
222
+ }
223
+
224
+ // Update Array of page ids
225
+ createdPages.push(pageId);
226
+
227
+ // TODO: Use structuredClone() when node 18 is available.
228
+ // SHAME: This new pageAdditionalInfo needs to be a copy because
229
+ // additionalInfo referenced from outside this function and
230
+ // its used by other pages.
231
+ const pageAdditionalInfo = JSON.parse(JSON.stringify(additionalInfo)) as PageAdditionalInfo;
232
+
233
+ // Updated with navigations (header & footer)
234
+ pageAdditionalInfo.navigations = NavService.getPageNavigations(page);
235
+
236
+ // Content Type Data Query.
237
+ // Where the pair `hasDistributorData:true` /
238
+ // `getStaticData:true` and `data` prop exists, this function
239
+ // will attach a `queriedItems` prop with the result of the
240
+ // fetch for the data.
241
+ const template = await getReferenceFieldData({
242
+ page,
243
+ cacheKey: renderId,
159
244
  });
160
245
 
161
- // -------------------------------------------------------------------------
162
- // Pages loop promise creation
163
- // -------------------------------------------------------------------------
164
- // Async function that process every page for one site to use later in the
165
- // `Promise.all` with pLimit.
166
- const fetchSitePageAndSaveInStore = async (
167
- siteIdName: string,
168
- pageId: number,
169
- ) => {
170
- // Here will be store every page returned by the API and processed
171
- let griddoPageObjects: Array<GriddoPageObject> = [];
172
-
173
- // Get page data
174
- const page = await getPage(pageId, shouldUpdateSite);
175
-
176
- // Probably a 404
177
- if (!page) {
178
- return;
179
- }
180
-
181
- // Update Array of page ids
182
- createdPages.push(pageId);
183
-
184
- // TODO: Use structuredClone() when node 18 is available.
185
- // SHAME: This new pageAdditionalInfo needs to be a copy because
186
- // additionalInfo referenced from outside this function and
187
- // its used by other pages.
188
- const pageAdditionalInfo = JSON.parse(
189
- JSON.stringify(additionalInfo),
190
- ) as PageAdditionalInfo;
191
-
192
- // Updated with navigations (header & footer)
193
- pageAdditionalInfo.navigations = NavService.getPageNavigations(page);
194
-
195
- // Content Type Data Query.
196
- // Where the pair `hasDistributorData:true` /
197
- // `getStaticData:true` and `data` prop exists, this function
198
- // will attach a `queriedItems` prop with the result of the
199
- // fetch for the data.
200
- const template = await getReferenceFieldData({
201
- page,
202
- cacheKey: renderId,
203
- });
204
-
205
- // MultiPage Query
206
- // Where the pair `hasGriddoMultiPage:true` prop exists, this function
207
- // will process the schema and return a multiPageElemtens array to use
208
- // in `createGriddoMultiPages()`
209
- const multiPageElements = await getMultiPageElements(template);
210
-
211
- // -----------------------------------------------------------------------
212
- // Build Griddo page objects.
213
- // -----------------------------------------------------------------------
214
- // A page from the API could be one of those:
215
- // - List with pagination (static list template): needs to be splitted in n pages
216
- // - Multi-page module: needs to be splitted in n pages
217
- // - Single: just one page
218
-
219
- // Griddo page types
220
- const isStaticListPage =
221
- page?.mode === "list" || page?.mode === "paginated-data";
222
- const isMultiPage = !isStaticListPage && multiPageElements;
223
- const isSinglePage = !isMultiPage && !isStaticListPage;
224
-
225
- // >> List (static list template) <<
226
- if (isStaticListPage) {
227
- const griddoListPage = {
228
- page: page,
229
- pages: getPaginatedPages(template),
230
- isRoot: false,
231
- defaultLang: defaultLang,
232
- template: template,
233
- totalQueriedItems: template.queriedItems,
234
- } as GriddoListPage;
235
-
236
- // pageObjects = await createGriddoListPages({ adapter: "Gatsby" })
237
- griddoPageObjects = await createGriddoListPages(
238
- griddoListPage,
239
- pageAdditionalInfo,
240
- );
241
- }
242
-
243
- // >> Multi-page <<
244
- if (isMultiPage) {
245
- const griddoMultipage = page as GriddoMultiPage;
246
-
247
- // The `template` key with the (maybe) data (ReferenceField) items queried
248
- griddoMultipage.template = template;
249
- griddoMultipage.multiPageElements = multiPageElements;
250
- griddoMultipage.defaultLang = defaultLang;
251
-
252
- griddoPageObjects = await createGriddoMultiPages(
253
- griddoMultipage,
254
- pageAdditionalInfo,
255
- );
256
- }
257
-
258
- // >> Single template <<
259
- if (isSinglePage) {
260
- const griddoSinglePage = page as GriddoSinglePage;
261
-
262
- // The `template` key with the (maybe) data (ReferenceField) items queried
263
- griddoSinglePage.template = template;
264
- griddoSinglePage.defaultLang = defaultLang;
265
-
266
- griddoPageObjects = [
267
- await createGriddoSinglePage(griddoSinglePage, pageAdditionalInfo),
268
- ];
269
- }
270
-
271
- // Upload only the valid pages hashes or ids of pages that has
272
- // been changed or created.
273
- if (page.hash !== null) {
274
- buildProcessData[siteId].publishHashes.push(page.hash);
275
- buildProcessData[siteId].publishPagesIds.push(page.id);
276
- }
277
-
278
- // Save build data to store
279
- saveSitePagesInStore(siteIdName, griddoPageObjects);
280
- };
281
-
282
- // Pages that needs to be fetched from the API and written to the
283
- // store.
284
- const pagesToFetchFromAPI = [
285
- // These pages are news or has been updated.
286
- ...pagesStatus.uploadPending,
287
- // You should take into account the pages that, even though they are
288
- // already published and therefore should be avoided from requesting
289
- // them to the API, are not in the store, probably due to a failed
290
- // render. In that case, you have to request them again from the API
291
- // to include them in the store.
292
- ...getMissingPublishedPagesInStore(siteDirName, pagesStatus.active),
293
- ];
294
-
295
- // Create pages to the store. First requesting from API,
296
- // transform, etc., and then writing them to disk.
297
- const limit = pLimit(envs.GRIDDO_API_CONCURRENCY_COUNT);
298
- const pagesToStore = pagesToFetchFromAPI.map((id: number) =>
299
- limit(() => fetchSitePageAndSaveInStore(siteDirName, id)),
300
- );
301
-
302
- await Promise.all(pagesToStore);
246
+ // MultiPage Query
247
+ // Where the pair `hasGriddoMultiPage:true` prop exists, this function
248
+ // will process the schema and return a multiPageElemtens array to use
249
+ // in `createGriddoMultiPages()`
250
+ const multiPageElements = await getMultiPageElements(template);
251
+
252
+ // -----------------------------------------------------------------------
253
+ // Build Griddo page objects.
254
+ // -----------------------------------------------------------------------
255
+ // A page from the API could be one of those:
256
+ // - List with pagination (static list template): needs to be splitted in n pages
257
+ // - Multi-page module: needs to be splitted in n pages
258
+ // - Single: just one page
259
+
260
+ // Griddo page types
261
+ const isStaticListPage = page?.mode === "list" || page?.mode === "paginated-data";
262
+ const isMultiPage = !isStaticListPage && multiPageElements;
263
+ const isSinglePage = !isMultiPage && !isStaticListPage;
264
+
265
+ // >> List (static list template) <<
266
+ if (isStaticListPage) {
267
+ const griddoListPage = {
268
+ page: page,
269
+ pages: getPaginatedPages(template),
270
+ isRoot: false,
271
+ defaultLang: defaultLang,
272
+ template: template,
273
+ totalQueriedItems: template.queriedItems,
274
+ } as GriddoListPage;
275
+
276
+ // pageObjects = await createGriddoListPages({ adapter: "Gatsby" })
277
+ griddoPageObjects = await createGriddoListPages(griddoListPage, pageAdditionalInfo);
278
+
279
+ // ¿Por qué la añadimos a las páginas para borrar?
280
+ // Porque este tipo de páginas no está manejada por API y se crean varias páginas con el mismo ID.
281
+ // Esto hace que no se pueda rastrear bien el render.
282
+ allPagesToRemoveFromBuild.push(page.id);
283
+ }
284
+
285
+ // >> Multi-page <<
286
+ if (isMultiPage) {
287
+ const griddoMultipage = page as GriddoMultiPage;
288
+
289
+ // The `template` key with the (maybe) data (ReferenceField) items queried
290
+ griddoMultipage.template = template;
291
+ griddoMultipage.multiPageElements = multiPageElements;
292
+ griddoMultipage.defaultLang = defaultLang;
293
+
294
+ griddoPageObjects = await createGriddoMultiPages(griddoMultipage, pageAdditionalInfo);
295
+
296
+ // ¿Por qué la añadimos a las páginas para borrar?
297
+ // Porque este tipo de páginas no está manejada por API y se crean varias páginas con el mismo ID.
298
+ // Esto hace que no se pueda rastrear bien el render.
299
+ allPagesToRemoveFromBuild.push(page.id);
300
+ }
301
+
302
+ // >> Single template <<
303
+ if (isSinglePage) {
304
+ const griddoSinglePage = page as GriddoSinglePage;
305
+
306
+ // The `template` key with the (maybe) data (ReferenceField) items queried
307
+ griddoSinglePage.template = template;
308
+ griddoSinglePage.defaultLang = defaultLang;
309
+
310
+ griddoPageObjects = [await createGriddoSinglePage(griddoSinglePage, pageAdditionalInfo)];
311
+ }
312
+
313
+ // Upload only the valid pages hashes or ids of pages that has
314
+ // been changed or created.
315
+ if (page.hash !== null) {
316
+ buildProcessData[siteId].publishHashes.push(page.hash);
317
+ buildProcessData[siteId].publishPagesIds.push(page.id);
318
+ }
319
+
320
+ // Save build data to store
321
+ await saveSitePagesInStore(siteIdName, griddoPageObjects);
322
+ };
323
+
324
+ // Pages that needs to be fetched from the API and written to the store.
325
+ const pagesToFetchFromAPI = pagesStatus.uploadPending;
326
+
327
+ // Esto es necesario porque en la BBDD las páginas pueden estar
328
+ // marcadas como activas (online) pero si es una máquina nueva hace
329
+ // falta hacerlas de nuevo...
330
+ // const sitePendingOfPublishing = site.isPublished && site.shouldBeUpdated;
331
+ const sitePendingOfPublishing = guessSiteNeedsToBeRenderedFromScratch();
332
+ // @todo: necesito tener un sistema par publicar todo de un site (cuando un site esté pending to publish)
333
+ // algo como site.status = pending | published | unpublished...
334
+ if (renderFromScratch || sitePendingOfPublishing) {
335
+ pagesToFetchFromAPI.push(...pagesStatus.active);
336
+ }
303
337
 
338
+ // Create pages to the store. First requesting from API,
339
+ // transform, etc., and then writing them to disk.
340
+ const limit = pLimit(GRIDDO_API_CONCURRENCY_COUNT);
341
+ const pagesToStore = pagesToFetchFromAPI.map((id: number) =>
342
+ limit(() => fetchSitePageAndSaveInStore(siteDirName, id)),
343
+ );
344
+
345
+ await Promise.all(pagesToStore);
346
+
347
+ // @ts-expect-error Mutate pagesStatus for reading pourposes.
348
+ pagesStatus.zombie = await getZombiePagesInStore(siteDirName, [
349
+ ...pagesStatus.active,
350
+ ...pagesStatus.uploadPending,
351
+ ]);
352
+
353
+ // Delete pages from the store removing them from disk.
354
+ await removeSitePagesFromStore(siteDirName, [
355
+ pagesStatus.deleted,
356
+ pagesStatus.offline,
357
+ pagesStatus.offlinePending,
304
358
  // @ts-expect-error Mutate pagesStatus for reading pourposes.
305
- pagesStatus.zombie = getZombiePagesInStore(siteDirName, [
306
- ...pagesStatus.active,
307
- ...pagesStatus.uploadPending,
308
- ]);
309
-
310
- // Delete pages from the store removing them from disk.
311
- removeSitePagesFromStore(siteDirName, [
312
- pagesStatus.deleted,
313
- pagesStatus.offline,
314
- pagesStatus.offlinePending,
315
- // @ts-expect-error Mutate pagesStatus for reading pourposes.
316
- pagesStatus.zombie,
317
- ]);
318
- }
359
+ pagesStatus.zombie,
360
+ ]);
361
+ }
319
362
 
320
- // Después de guardar en el store todos los sites y sus páginas (las que
321
- // sean que hayan cambiado etc.) guardamos un archivo con la información
322
- // del render para usos posteriores.
323
-
324
- // Tenemos dos casos:
325
-
326
- // ( 1 ) - Render de dominios con sites para publicar o despublicar. Se
327
- // guarda la infor del render normalmente.
328
-
329
- // ( 2 ) - Render de un dominio que no tiene sites ni para publicar ni para
330
- // despublicar, lo que llamamos un dominio "vacío".
331
- // Entonces se eliminan las páginas "huérfanas" de la carpeta `store`
332
- // así el proceso de SSG se encontrará efectivamente con un dominio "sin
333
- // páginas" y "borrará" lo que exista en ese momento en el store para
334
- // ese dominio y se guarda la información del render con arrays vacíos
335
- // directamente en `createdPages` y `sitesToPublish`.
336
-
337
- if (domainHasSites) {
338
- // ( 1 )
339
- saveRenderInfoInStore({
340
- buildProcessData,
341
- createdPages,
342
- sitesToPublish,
343
- });
344
- } else {
345
- // ( 2 )
346
- removeAllSiteDirsFromStore();
347
- saveRenderInfoInStore({
348
- buildProcessData,
349
- createdPages: [],
350
- sitesToPublish: [],
351
- });
352
- }
353
- } catch (e) {
354
- const error = e as { message: string };
355
- console.error(error.message);
356
- process.exit(1);
363
+ // Después de guardar en el store todos los sites y sus páginas (las que
364
+ // sean que hayan cambiado etc.) guardamos un archivo con la información
365
+ // del render para usos posteriores.
366
+
367
+ // Render de dominios con sites para publicar o despublicar. Se
368
+ // guarda la infor del render normalmente.
369
+
370
+ await saveRenderInfoInStore(
371
+ {
372
+ buildProcessData,
373
+ createdPages,
374
+ sitesToPublish,
375
+ },
376
+ domain,
377
+ );
378
+
379
+ return {
380
+ pagesToCreate: createdPages,
381
+ pagesToDelete: allPagesToRemoveFromBuild,
382
+ };
383
+ }
384
+
385
+ /**
386
+ * Get site hashes from the file as an object
387
+ */
388
+ async function getHashSites(): Promise<HashSites> {
389
+ const { __root } = await getRenderPathsHydratedWithDomainFromDB();
390
+ const apiCacheDir = path.join(__root, "apiCache");
391
+ const siteHasFilename = `${apiCacheDir}/siteHash.json`;
392
+
393
+ try {
394
+ const fileContent = await fsp.readFile(siteHasFilename, "utf8");
395
+ const jsonData = JSON.parse(fileContent);
396
+ return jsonData || {};
397
+ } catch {
398
+ return {};
357
399
  }
358
400
  }
359
401
 
402
+ /**
403
+ * Update (write) the site hash file.
404
+ *
405
+ * @param siteId The id of the site.
406
+ * @param siteHash The has of the site.
407
+ */
408
+ async function updatedSiteHash(siteId: number, siteHash: SiteHash) {
409
+ const allHash = await getHashSites();
410
+ const lastHash = allHash[siteId];
411
+ const currentHash = siteHash || lastHash || Date.now();
412
+
413
+ const { __root } = await getRenderPathsHydratedWithDomainFromDB();
414
+ const apiCacheDir = path.join(__root, "apiCache");
415
+ const siteHasFilename = `${apiCacheDir}/siteHash.json`;
416
+
417
+ if (currentHash !== lastHash) {
418
+ allHash[siteId] = currentHash;
419
+ await fsp.writeFile(siteHasFilename, JSON.stringify(allHash), {
420
+ encoding: "utf-8",
421
+ });
422
+ }
423
+
424
+ return currentHash.toString();
425
+ }
426
+
360
427
  export { createStore };