@griddo/cx 10.3.13 → 10.3.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -30
- package/build/build-complete.js +24 -20
- package/build/download-data.js +53 -0
- package/build/index.js +35 -47
- package/build/reset-render.js +25 -21
- package/exporter/adapters/astro/index.ts +37 -0
- package/exporter/adapters/astro/utils.ts +29 -0
- package/exporter/adapters/gatsby/index.ts +86 -0
- package/exporter/adapters/gatsby/utils.ts +352 -0
- package/exporter/adapters/index.ts +5 -0
- package/{scripts → exporter}/build-complete.ts +16 -14
- package/exporter/download-data.ts +6 -0
- package/exporter/index-width-adapter.ts +25 -0
- package/exporter/index.ts +14 -0
- package/exporter/reset-render.ts +12 -0
- package/{src → exporter}/services/auth.ts +0 -2
- package/{src → exporter}/services/distributors.ts +10 -1
- package/{src → exporter}/services/robots.ts +9 -6
- package/exporter/services/store.ts +351 -0
- package/{src → exporter}/types/api.ts +6 -0
- package/{src → exporter}/types/pages.ts +18 -17
- package/{src → exporter}/types/sites.ts +1 -1
- package/{src → exporter}/utils/api.ts +10 -7
- package/{src → exporter}/utils/cache.ts +14 -8
- package/{src → exporter}/utils/domains.ts +3 -3
- package/exporter/utils/download-build-data.ts +22 -0
- package/exporter/utils/folders.ts +49 -0
- package/{src → exporter}/utils/health-checks.ts +8 -7
- package/{src → exporter}/utils/instance.ts +1 -1
- package/{src/utils/integrations.tsx → exporter/utils/integrations.ts} +6 -4
- package/{src → exporter}/utils/pages.ts +21 -24
- package/exporter/utils/runners.ts +53 -0
- package/{src → exporter}/utils/shared.ts +31 -29
- package/{src → exporter}/utils/sites.ts +7 -7
- package/exporter/utils/store.ts +56 -0
- package/gatsby-config.ts +1 -1
- package/gatsby-node.ts +38 -72
- package/index.js +4 -1
- package/package.json +13 -10
- package/src/README.md +7 -0
- package/src/components/Head.tsx +3 -3
- package/src/components/template.tsx +3 -4
- package/src/gatsby-node-utils.ts +154 -0
- package/src/html.tsx +1 -1
- package/src/types.ts +98 -0
- package/src/{components/utils.ts → utils.ts} +6 -8
- package/static/robots.txt +1 -0
- package/scripts/griddo-exporter.ts +0 -431
- package/scripts/reset-render.ts +0 -9
- package/src/components/types.ts +0 -40
- package/src/services/store.ts +0 -423
- package/src/utils/folders.ts +0 -125
- package/src/utils/gatsby.ts +0 -47
- /package/{src → exporter}/services/domains.ts +0 -0
- /package/{src → exporter}/services/navigation.ts +0 -0
- /package/{src → exporter}/services/settings.ts +0 -0
- /package/{src → exporter}/services/sites.ts +0 -0
- /package/{src → exporter}/types/global.ts +0 -0
- /package/{src → exporter}/types/navigation.ts +0 -0
- /package/{src → exporter}/types/templates.ts +0 -0
- /package/{src → exporter}/utils/searches.ts +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Robots } from "../types/global";
|
|
2
2
|
|
|
3
|
-
import fs from "fs";
|
|
4
|
-
import path from "path";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
5
|
|
|
6
6
|
dotenv.config();
|
|
7
7
|
|
|
@@ -28,7 +28,7 @@ class RobotsService {
|
|
|
28
28
|
/**
|
|
29
29
|
* TODO: JSDoc
|
|
30
30
|
*/
|
|
31
|
-
async
|
|
31
|
+
private async getRobots() {
|
|
32
32
|
try {
|
|
33
33
|
const apiRobots = await get<Robots>({
|
|
34
34
|
endpoint: this.endpoint,
|
|
@@ -46,10 +46,11 @@ class RobotsService {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
/**
|
|
49
|
-
*
|
|
49
|
+
* Write robots.txt files for the current rendering domain.
|
|
50
50
|
*/
|
|
51
51
|
async writeFiles(basePath: string) {
|
|
52
|
-
|
|
52
|
+
await this.getRobots();
|
|
53
|
+
|
|
53
54
|
const robot = this.robots.find(
|
|
54
55
|
({ path }) => path === `/${process.env.DOMAIN}`
|
|
55
56
|
);
|
|
@@ -60,7 +61,9 @@ class RobotsService {
|
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
if (fs.existsSync(basePath)) {
|
|
63
|
-
const fileLocation =
|
|
64
|
+
const fileLocation = JSON.parse(
|
|
65
|
+
process.env.GRIDDO_EXPORT_STRIP_DOMAIN_FROM_PATH || "false"
|
|
66
|
+
)
|
|
64
67
|
? path.join(basePath, "robots.txt")
|
|
65
68
|
: path.join(basePath, robot.path, "robots.txt");
|
|
66
69
|
fs.writeFileSync(fileLocation, robot?.content);
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
import type { BuildProcessData } from "../types/global";
|
|
2
|
+
import type {
|
|
3
|
+
GriddoListPage,
|
|
4
|
+
GriddoMultiPage,
|
|
5
|
+
GriddoPageObject,
|
|
6
|
+
GriddoSinglePage,
|
|
7
|
+
PageAdditionalInfo,
|
|
8
|
+
} from "../types/pages";
|
|
9
|
+
import type { Site } from "../types/sites";
|
|
10
|
+
|
|
11
|
+
import fs from "node:fs";
|
|
12
|
+
import fsp from "node:fs/promises";
|
|
13
|
+
import path from "node:path";
|
|
14
|
+
|
|
15
|
+
import dotenv from "dotenv";
|
|
16
|
+
import fsx from "fs-extra";
|
|
17
|
+
import pLimit from "p-limit";
|
|
18
|
+
|
|
19
|
+
import { DistributorService } from "./distributors";
|
|
20
|
+
import { NavigationService } from "./navigation";
|
|
21
|
+
import { SettingsService } from "./settings";
|
|
22
|
+
import { SitesService } from "./sites";
|
|
23
|
+
import { version as griddoVersion } from "../../package.json";
|
|
24
|
+
import { createSha256, updatedSiteHash } from "../utils/cache";
|
|
25
|
+
import { deleteSites } from "../utils/folders";
|
|
26
|
+
import {
|
|
27
|
+
createGriddoListPages,
|
|
28
|
+
createGriddoMultiPages,
|
|
29
|
+
createGriddoSinglePage,
|
|
30
|
+
getMultiPageElements,
|
|
31
|
+
getPaginatedPages,
|
|
32
|
+
} from "../utils/pages";
|
|
33
|
+
import { logInfo, removeProperties, siteList } from "../utils/shared";
|
|
34
|
+
import { checkSites, getSiteData, unpublishSites } from "../utils/sites";
|
|
35
|
+
|
|
36
|
+
dotenv.config();
|
|
37
|
+
|
|
38
|
+
// Envs
|
|
39
|
+
const API_URL = process.env.API_URL as string;
|
|
40
|
+
const CXBRANCH = process.env.CXBRANCH;
|
|
41
|
+
// prettier-ignore
|
|
42
|
+
const REACT_APP_INSTANCE = process.env.GRIDDO_REACT_APP_INSTANCE || process.env.REACT_APP_INSTANCE;
|
|
43
|
+
// prettier-ignore
|
|
44
|
+
const API_CONCURRENCY_COUNT = parseInt(process.env.GRIDDO_API_CONCURRENCY_COUNT || "") || 10;
|
|
45
|
+
const PUBLIC_API_URL = process.env.PUBLIC_API_URL as string;
|
|
46
|
+
// prettier-ignore
|
|
47
|
+
const RENDER_ID = process.env.GRIDDO_RENDERID || new Date().valueOf().toString();
|
|
48
|
+
|
|
49
|
+
// Consts
|
|
50
|
+
const CREATED_PAGES: Array<number> = [];
|
|
51
|
+
const BUILD_PROCESS_DATA: BuildProcessData = {};
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Fetch, process and save object pages and sites data into the file system to
|
|
55
|
+
* be consumed by other services (Griddo itself, Adapters, etc.)
|
|
56
|
+
*/
|
|
57
|
+
async function createStore(storeFolder: string) {
|
|
58
|
+
console.info(`API calls with ${API_CONCURRENCY_COUNT} threads`);
|
|
59
|
+
|
|
60
|
+
// Remove old store
|
|
61
|
+
if (fs.existsSync(storeFolder)) {
|
|
62
|
+
fs.rmSync(storeFolder, { recursive: true });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Create fresh folders for store and store/metadata
|
|
66
|
+
fs.mkdirSync(storeFolder);
|
|
67
|
+
fs.mkdirSync(path.resolve(storeFolder, "metadata"));
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
// Get sites objects to publish and unpublish.
|
|
71
|
+
const { sitesToPublish, sitesToUnpublish } = await checkSites();
|
|
72
|
+
|
|
73
|
+
// The settings will be extracted below in this process.
|
|
74
|
+
await SettingsService.getAll();
|
|
75
|
+
|
|
76
|
+
// If no activity in sites, exit
|
|
77
|
+
if (!(sitesToPublish.length || sitesToUnpublish.length)) {
|
|
78
|
+
console.warn("There are no sites to update");
|
|
79
|
+
process.exit(0);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
console.info(`Sites to publish: ${siteList(sitesToPublish)}`);
|
|
83
|
+
console.info(`Sites to unpublish: ${siteList(sitesToUnpublish)}`);
|
|
84
|
+
|
|
85
|
+
// Unpublish (API) and delete sites
|
|
86
|
+
// TODO: Manage this to save end data to the __report-build__ file ???
|
|
87
|
+
await unpublishSites(sitesToUnpublish);
|
|
88
|
+
|
|
89
|
+
// Delete (clean) sites to publish
|
|
90
|
+
// SPREAD: await deleteSites(sitesToPublish);
|
|
91
|
+
await deleteSites([...sitesToPublish]);
|
|
92
|
+
|
|
93
|
+
for (const site of sitesToPublish) {
|
|
94
|
+
const { id: siteId, slug: siteSlug, theme, favicon } = site;
|
|
95
|
+
|
|
96
|
+
const {
|
|
97
|
+
siteInfo,
|
|
98
|
+
validPagesIds,
|
|
99
|
+
siteHash,
|
|
100
|
+
unpublishHashes,
|
|
101
|
+
siteLangs,
|
|
102
|
+
defaultLang,
|
|
103
|
+
headers,
|
|
104
|
+
footers,
|
|
105
|
+
socials,
|
|
106
|
+
} = await getSiteData(siteId);
|
|
107
|
+
|
|
108
|
+
const {
|
|
109
|
+
cloudinaryName,
|
|
110
|
+
useMetaTitle,
|
|
111
|
+
useMetaKeywords,
|
|
112
|
+
showBasicMetaRobots,
|
|
113
|
+
avoidHrefLangsOnCanonicals,
|
|
114
|
+
avoidSelfReferenceCanonicals,
|
|
115
|
+
avoidHrefLangXDefault,
|
|
116
|
+
avoidDebugMetas,
|
|
117
|
+
} = SettingsService.settings;
|
|
118
|
+
|
|
119
|
+
BUILD_PROCESS_DATA[siteId] = {
|
|
120
|
+
siteHash,
|
|
121
|
+
unpublishHashes,
|
|
122
|
+
publishHashes: [],
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const NavService = new NavigationService();
|
|
126
|
+
|
|
127
|
+
// Set `headers` and `footers` to the NavService to use later in this process.
|
|
128
|
+
NavService.navigations = { headers, footers };
|
|
129
|
+
|
|
130
|
+
site.languages = siteLangs;
|
|
131
|
+
|
|
132
|
+
const shouldUpdateSite = updatedSiteHash(siteId, siteHash);
|
|
133
|
+
|
|
134
|
+
const siteScript = siteInfo.siteScript;
|
|
135
|
+
|
|
136
|
+
const siteMetadata = {
|
|
137
|
+
siteUrl: siteInfo.slug,
|
|
138
|
+
title: siteInfo.name,
|
|
139
|
+
favicon,
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const additionalInfo = {
|
|
143
|
+
baseUrl: API_URL,
|
|
144
|
+
publicBaseUrl: PUBLIC_API_URL,
|
|
145
|
+
instance: REACT_APP_INSTANCE,
|
|
146
|
+
siteSlug,
|
|
147
|
+
theme,
|
|
148
|
+
siteMetadata,
|
|
149
|
+
socials,
|
|
150
|
+
siteLangs,
|
|
151
|
+
cloudinaryName,
|
|
152
|
+
griddoVersion,
|
|
153
|
+
siteOptions: {
|
|
154
|
+
useMetaTitle,
|
|
155
|
+
useMetaKeywords,
|
|
156
|
+
showBasicMetaRobots,
|
|
157
|
+
avoidHrefLangsOnCanonicals,
|
|
158
|
+
avoidSelfReferenceCanonicals,
|
|
159
|
+
avoidHrefLangXDefault,
|
|
160
|
+
avoidDebugMetas,
|
|
161
|
+
},
|
|
162
|
+
BUILD_MODE: CXBRANCH,
|
|
163
|
+
siteScript,
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
logInfo(`${site.name} site`);
|
|
167
|
+
|
|
168
|
+
// -------------------------------------------------------------------------
|
|
169
|
+
// Pages loop promise creation
|
|
170
|
+
// -------------------------------------------------------------------------
|
|
171
|
+
// Async function that process every page for one site to use later in the
|
|
172
|
+
// `Promise.all` with pLimit.
|
|
173
|
+
const fetchPageAndSaveToStore = async (pageId: number) => {
|
|
174
|
+
// Here will be store every page returned by the API and processed by
|
|
175
|
+
// Griddo CX.
|
|
176
|
+
let griddoPageObjects: Array<GriddoPageObject> = [];
|
|
177
|
+
|
|
178
|
+
// Get page data
|
|
179
|
+
const page = await SitesService.getPage(pageId, shouldUpdateSite);
|
|
180
|
+
|
|
181
|
+
// Probably a 404
|
|
182
|
+
if (!page) return;
|
|
183
|
+
|
|
184
|
+
// Update Array of page ids
|
|
185
|
+
CREATED_PAGES.push(pageId);
|
|
186
|
+
|
|
187
|
+
// TODO: Use structuredClone() when node 18 is available.
|
|
188
|
+
// SHAME: This new pageAdditionalInfo needs to be a copy because
|
|
189
|
+
// additionalInfo referenced from outside this function and
|
|
190
|
+
// its used by other pages.
|
|
191
|
+
const pageAdditionalInfo = JSON.parse(
|
|
192
|
+
JSON.stringify(additionalInfo)
|
|
193
|
+
) as PageAdditionalInfo;
|
|
194
|
+
|
|
195
|
+
// Updated with navigations (header & footer)
|
|
196
|
+
pageAdditionalInfo.navigations = NavService.getPageNavigations(page);
|
|
197
|
+
|
|
198
|
+
// Content Type Data Query
|
|
199
|
+
// Where the pair `hasDistributorData:true` and `data` prop exists, this
|
|
200
|
+
// function will attach a `queriedItems` prop with the result of the fetch
|
|
201
|
+
// for the data.
|
|
202
|
+
const template = await DistributorService.getDistributorData({
|
|
203
|
+
page,
|
|
204
|
+
cacheKey: RENDER_ID,
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// MultiPage Query
|
|
208
|
+
// Where the pair `hasGriddoMultiPage:true` prop exists, this function
|
|
209
|
+
// will process the schema and return a multiPageElemtens array to use
|
|
210
|
+
// in `createGriddoMultiPages()`
|
|
211
|
+
const multiPageElements = await getMultiPageElements(template);
|
|
212
|
+
|
|
213
|
+
// -----------------------------------------------------------------------
|
|
214
|
+
// Build Griddo page objects.
|
|
215
|
+
// -----------------------------------------------------------------------
|
|
216
|
+
// A page from the API could be one of those:
|
|
217
|
+
// - List with pagination (static list template): needs to be splitted in n pages
|
|
218
|
+
// - Multi-page module: needs to be splitted in n pages
|
|
219
|
+
// - Single: just one page
|
|
220
|
+
|
|
221
|
+
// Griddo page types
|
|
222
|
+
const isStaticListPage = page?.mode === "list";
|
|
223
|
+
const isMultiPage = !isStaticListPage && multiPageElements;
|
|
224
|
+
const isSinglePage = !isMultiPage && !isStaticListPage;
|
|
225
|
+
|
|
226
|
+
// >> List (static list template) <<
|
|
227
|
+
if (isStaticListPage) {
|
|
228
|
+
const griddoListPage = {
|
|
229
|
+
page: page,
|
|
230
|
+
pages: getPaginatedPages(template),
|
|
231
|
+
isRoot: false,
|
|
232
|
+
defaultLang: defaultLang,
|
|
233
|
+
template: template,
|
|
234
|
+
totalQueriedItems: template.queriedItems,
|
|
235
|
+
} as GriddoListPage;
|
|
236
|
+
|
|
237
|
+
// pageObjects = await createGriddoListPages({ adapter: "Gatsby" })
|
|
238
|
+
griddoPageObjects = await createGriddoListPages(
|
|
239
|
+
griddoListPage,
|
|
240
|
+
pageAdditionalInfo
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// >> Multi-page <<
|
|
245
|
+
if (isMultiPage) {
|
|
246
|
+
const griddoMultipage = page as GriddoMultiPage;
|
|
247
|
+
|
|
248
|
+
// The `template` key with the (maybe) distributor data items queried
|
|
249
|
+
griddoMultipage.template = template;
|
|
250
|
+
griddoMultipage.multiPageElements = multiPageElements;
|
|
251
|
+
griddoMultipage.defaultLang = defaultLang;
|
|
252
|
+
|
|
253
|
+
griddoPageObjects = await createGriddoMultiPages(
|
|
254
|
+
griddoMultipage,
|
|
255
|
+
pageAdditionalInfo
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// >> Single template <<
|
|
260
|
+
if (isSinglePage) {
|
|
261
|
+
const griddoSinglePage = page as GriddoSinglePage;
|
|
262
|
+
|
|
263
|
+
// The `template` key with the (maybe) distributor data items queried
|
|
264
|
+
griddoSinglePage.template = template;
|
|
265
|
+
griddoSinglePage.defaultLang = defaultLang;
|
|
266
|
+
|
|
267
|
+
griddoPageObjects = [
|
|
268
|
+
await createGriddoSinglePage(griddoSinglePage, pageAdditionalInfo),
|
|
269
|
+
];
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Update hashes
|
|
273
|
+
BUILD_PROCESS_DATA[siteId].publishHashes.push(page.hash);
|
|
274
|
+
|
|
275
|
+
// Save build data to store
|
|
276
|
+
await savePagesInStore(storeFolder, griddoPageObjects); // gatsbyPageObjects is always an array regardless of whether it's just one page
|
|
277
|
+
setSitesToPublish(storeFolder, sitesToPublish);
|
|
278
|
+
setBuildProcessData(storeFolder, BUILD_PROCESS_DATA);
|
|
279
|
+
setCreatedPages(storeFolder, CREATED_PAGES);
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
// Create the pLimit array of promises
|
|
283
|
+
const limit = pLimit(API_CONCURRENCY_COUNT);
|
|
284
|
+
const pagesToRender = validPagesIds.map((id: number) =>
|
|
285
|
+
limit(() => fetchPageAndSaveToStore(id))
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
await Promise.all(pagesToRender);
|
|
289
|
+
}
|
|
290
|
+
} catch (e) {
|
|
291
|
+
const error = e as { message: string };
|
|
292
|
+
console.error(error.message);
|
|
293
|
+
process.exit(1);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Set the build process data in the Store.
|
|
299
|
+
*/
|
|
300
|
+
function setBuildProcessData(
|
|
301
|
+
basePath: string,
|
|
302
|
+
buildProcessData: BuildProcessData
|
|
303
|
+
) {
|
|
304
|
+
fsx.writeJSONSync(
|
|
305
|
+
path.resolve(basePath, "metadata", "buildProcessData.json"),
|
|
306
|
+
buildProcessData
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Set the created pages in the Store.
|
|
312
|
+
*/
|
|
313
|
+
function setCreatedPages(basePath: string, pages: Array<number>) {
|
|
314
|
+
fsx.writeJSONSync(
|
|
315
|
+
path.resolve(basePath, "metadata", "createdPages.json"),
|
|
316
|
+
pages
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Set site to publish data in the Store.
|
|
322
|
+
*/
|
|
323
|
+
function setSitesToPublish(basePath: string, sites: Array<Site>) {
|
|
324
|
+
fsx.writeJSONSync(
|
|
325
|
+
path.resolve(basePath, "metadata", "sitesToPublish.json"),
|
|
326
|
+
sites
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Save the pages into the file system.
|
|
332
|
+
*/
|
|
333
|
+
async function savePagesInStore(
|
|
334
|
+
basePath: string,
|
|
335
|
+
pages: Array<GriddoPageObject>
|
|
336
|
+
) {
|
|
337
|
+
pages.forEach((page) =>
|
|
338
|
+
removeProperties(page, ["editorID", "parentEditorID"])
|
|
339
|
+
);
|
|
340
|
+
|
|
341
|
+
const promises = pages.map(async (pageObject) => {
|
|
342
|
+
const filename = `${createSha256(pageObject.path)}.json`;
|
|
343
|
+
const fileContent = JSON.stringify(pageObject);
|
|
344
|
+
const filePath = path.resolve(basePath, filename);
|
|
345
|
+
await fsp.writeFile(filePath, fileContent);
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
await Promise.all(promises);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
export { createStore };
|
|
@@ -96,14 +96,28 @@ export interface PageAdditionalInfo extends AdditionalInfo {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
// TODO: JSDoc
|
|
99
|
-
export type
|
|
99
|
+
export type MultiPageElement = {
|
|
100
|
+
component: string;
|
|
101
|
+
title: string | Required<Fields.Heading>;
|
|
102
|
+
elements: Array<Record<string, unknown>>;
|
|
103
|
+
componentModules: Array<Record<string, unknown>>;
|
|
104
|
+
sectionSlug: string;
|
|
105
|
+
metaTitle: string;
|
|
106
|
+
metaDescription: string;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// TODO: JSDoc
|
|
110
|
+
export type MultiPageElements = Array<MultiPageElement>;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Gatsby page object format.
|
|
114
|
+
*/
|
|
115
|
+
export type GriddoPageObject = {
|
|
100
116
|
matchPath?: string;
|
|
101
117
|
path: string;
|
|
102
|
-
component: string;
|
|
103
118
|
/** Page size in bytes */
|
|
104
119
|
size?: number;
|
|
105
120
|
context: {
|
|
106
|
-
// Page
|
|
107
121
|
BUILD_MODE?: string;
|
|
108
122
|
cloudinaryName?: string;
|
|
109
123
|
footer: Record<string, unknown> | null;
|
|
@@ -141,20 +155,7 @@ export type GatsbyPageObject = {
|
|
|
141
155
|
siteOptions: AdditionalInfo["siteOptions"];
|
|
142
156
|
siteScript: string;
|
|
143
157
|
socials: SocialsResponse;
|
|
158
|
+
// The three Griddo page types
|
|
144
159
|
page: GriddoSinglePage | GriddoListPage | GriddoMultiPage;
|
|
145
160
|
};
|
|
146
161
|
};
|
|
147
|
-
|
|
148
|
-
// TODO: JSDoc
|
|
149
|
-
export type MultiPageElement = {
|
|
150
|
-
component: string;
|
|
151
|
-
title: string | Required<Fields.Heading>;
|
|
152
|
-
elements: Array<Record<string, unknown>>;
|
|
153
|
-
componentModules: Array<Record<string, unknown>>;
|
|
154
|
-
sectionSlug: string;
|
|
155
|
-
metaTitle: string;
|
|
156
|
-
metaDescription: string;
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
// TODO: JSDoc
|
|
160
|
-
export type MultiPageElements = Array<MultiPageElement>;
|
|
@@ -4,7 +4,7 @@ import type { Core } from "@griddo/core";
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Describes a Griddo site object from API.
|
|
7
|
-
* This takes some type props from Core.Site
|
|
7
|
+
* This takes some type props from Core.Site.
|
|
8
8
|
*/
|
|
9
9
|
export interface Site
|
|
10
10
|
extends Required<
|
|
@@ -89,13 +89,16 @@ async function requestAPI<T extends APIResponses>(
|
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
if (attempt > parseInt(RETRY_ATTEMPTS)) {
|
|
92
|
-
console.log(
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
92
|
+
console.log(`
|
|
93
|
+
Max attempts ${RETRY_ATTEMPTS} reached
|
|
94
|
+
--------------------------------------
|
|
95
|
+
- ${method.toUpperCase()} ${endpoint}
|
|
96
|
+
- BODY: ${JSON.stringify(body)}
|
|
97
|
+
- HEADERS: ${JSON.stringify(headers)}
|
|
98
|
+
- RESPONSE: ${(error.response?.status, JSON.stringify(error.response?.data))}
|
|
99
|
+
--------------------------------------
|
|
100
|
+
`);
|
|
101
|
+
|
|
99
102
|
process.exit(1);
|
|
100
103
|
}
|
|
101
104
|
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
import type { Petition } from "../types/global";
|
|
2
2
|
import type { HashSites, SiteHash } from "../types/sites";
|
|
3
3
|
|
|
4
|
-
import crypto from "crypto";
|
|
5
|
-
import fs from "fs";
|
|
6
|
-
import path from "path";
|
|
4
|
+
import crypto from "node:crypto";
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
7
7
|
|
|
8
8
|
import fsx from "fs-extra";
|
|
9
9
|
|
|
10
10
|
// Consts
|
|
11
|
-
const API_CACHE_DIR_PATH = path.resolve(__dirname, "
|
|
11
|
+
const API_CACHE_DIR_PATH = path.resolve(__dirname, "./../apiCache");
|
|
12
12
|
const SITE_HASH_FILENAME = `${API_CACHE_DIR_PATH}/siteHash.json`;
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
15
|
+
* Creates an `apiCache` folder to store pages fetched from them API.
|
|
16
16
|
*/
|
|
17
|
-
function
|
|
17
|
+
function createAPICacheFolder() {
|
|
18
18
|
if (!fs.existsSync(API_CACHE_DIR_PATH)) {
|
|
19
19
|
fs.mkdirSync(API_CACHE_DIR_PATH);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
console.
|
|
22
|
+
console.info("Cache initialized");
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
/**
|
|
@@ -119,4 +119,10 @@ function updatedSiteHash(siteId: number, siteHash: SiteHash) {
|
|
|
119
119
|
return currentHash.toString();
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
export {
|
|
122
|
+
export {
|
|
123
|
+
createSha256,
|
|
124
|
+
updatedSiteHash,
|
|
125
|
+
searchCacheData,
|
|
126
|
+
saveCache,
|
|
127
|
+
createAPICacheFolder,
|
|
128
|
+
};
|
|
@@ -4,9 +4,9 @@ import { AuthService } from "../services/auth";
|
|
|
4
4
|
import { DomainsService } from "../services/domains";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Return an array of
|
|
7
|
+
* Return an array of domains name (string) of the current instance.
|
|
8
8
|
*/
|
|
9
|
-
async function
|
|
9
|
+
async function getInstanceDomains() {
|
|
10
10
|
await AuthService.login();
|
|
11
11
|
const domains = await DomainsService.getAll();
|
|
12
12
|
|
|
@@ -27,4 +27,4 @@ function getDomainSlugs(domains: Domains) {
|
|
|
27
27
|
return [...new Set(filteredDomains)];
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
export {
|
|
30
|
+
export { getInstanceDomains };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
|
|
3
|
+
import { createAPICacheFolder } from "./cache";
|
|
4
|
+
import { sanitizeAPICacheFolder } from "./shared";
|
|
5
|
+
import { createStore } from "../services/store";
|
|
6
|
+
|
|
7
|
+
const storeFolder = path.resolve(__dirname, "../store/");
|
|
8
|
+
const apiCacheFolder = path.resolve(__dirname, "../apiCache");
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Download all data: sites, pages etc.. from the instance private Griddo API.
|
|
12
|
+
* Then you can use the generator funcion `getBuildPages()` to get the pages and
|
|
13
|
+
* `getBuildMetadata()` to get build and sites metadata as objects. Both from
|
|
14
|
+
* exporter utils sites folder.
|
|
15
|
+
*/
|
|
16
|
+
async function downloadBuildData() {
|
|
17
|
+
createAPICacheFolder();
|
|
18
|
+
await createStore(storeFolder);
|
|
19
|
+
sanitizeAPICacheFolder(apiCacheFolder);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export { downloadBuildData };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Site } from "../types/sites";
|
|
2
|
+
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
import fs from "fs-extra";
|
|
6
|
+
|
|
7
|
+
import { logInfo } from "./shared";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Delete sites folders that will be updated from de file system.
|
|
11
|
+
*
|
|
12
|
+
* @param updateSites An array of sites to be updated.
|
|
13
|
+
*/
|
|
14
|
+
async function deleteSites(updatedSites: Array<Site>) {
|
|
15
|
+
for await (const site of updatedSites) {
|
|
16
|
+
for (const domain of site.domains) {
|
|
17
|
+
const mappedDomain = Object.values(domain)[0];
|
|
18
|
+
const dir = path.resolve(__dirname, `../../dist${mappedDomain}`);
|
|
19
|
+
const pageDataDir = path.resolve(
|
|
20
|
+
__dirname,
|
|
21
|
+
`../../assets/page-data${mappedDomain}`
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
logInfo(`Site dir ${dir}`);
|
|
25
|
+
logInfo(`Page data dir ${pageDataDir}`);
|
|
26
|
+
|
|
27
|
+
// delete directory recursively
|
|
28
|
+
if (!fs.existsSync(dir)) return;
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
await fs.rm(dir, { recursive: true });
|
|
32
|
+
logInfo(`${dir} is deleted!`);
|
|
33
|
+
} catch (err) {
|
|
34
|
+
console.log(err);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (!fs.existsSync(pageDataDir)) return;
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
await fs.rm(pageDataDir, { recursive: true });
|
|
41
|
+
console.info(`${pageDataDir} is deleted!`);
|
|
42
|
+
} catch (err) {
|
|
43
|
+
console.log(err);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export { deleteSites };
|
|
@@ -5,12 +5,13 @@ const GRIDDO_ENVS_VARS: ReadonlyArray<string> = [];
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Check if the environment is secure to launch a render.
|
|
8
|
-
* If something fails
|
|
8
|
+
* If something fails then log an error message and exit from the process.
|
|
9
|
+
* Otherwise just return true.
|
|
9
10
|
*/
|
|
10
|
-
function
|
|
11
|
+
function checkRenderHealthOrExit() {
|
|
11
12
|
// Bypass the check using this env var, handy for local renders.
|
|
12
13
|
if (GRIDDO_SKIP_BUILD_CHECKS) {
|
|
13
|
-
console.info(
|
|
14
|
+
console.info(`Build health check skipped`);
|
|
14
15
|
|
|
15
16
|
return true;
|
|
16
17
|
}
|
|
@@ -23,7 +24,7 @@ function buildHealthCheck() {
|
|
|
23
24
|
|
|
24
25
|
// The environment is suitable for a build-render
|
|
25
26
|
if (renderingIsSave) {
|
|
26
|
-
console.info("
|
|
27
|
+
console.info("Build health check passed");
|
|
27
28
|
|
|
28
29
|
return true;
|
|
29
30
|
}
|
|
@@ -47,8 +48,8 @@ function checkEnvsVars(envs: ReadonlyArray<string>) {
|
|
|
47
48
|
|
|
48
49
|
if (missingEnvs.length) {
|
|
49
50
|
const missingEnvsMsg = missingEnvs.join("\n");
|
|
50
|
-
console.
|
|
51
|
-
`
|
|
51
|
+
console.error(
|
|
52
|
+
`Env check failed. These envs vars are missing: \n\n${missingEnvsMsg}`
|
|
52
53
|
);
|
|
53
54
|
|
|
54
55
|
return false;
|
|
@@ -57,4 +58,4 @@ function checkEnvsVars(envs: ReadonlyArray<string>) {
|
|
|
57
58
|
return true;
|
|
58
59
|
}
|
|
59
60
|
|
|
60
|
-
export {
|
|
61
|
+
export { checkRenderHealthOrExit };
|