@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.
Files changed (61) hide show
  1. package/README.md +53 -30
  2. package/build/build-complete.js +24 -20
  3. package/build/download-data.js +53 -0
  4. package/build/index.js +35 -47
  5. package/build/reset-render.js +25 -21
  6. package/exporter/adapters/astro/index.ts +37 -0
  7. package/exporter/adapters/astro/utils.ts +29 -0
  8. package/exporter/adapters/gatsby/index.ts +86 -0
  9. package/exporter/adapters/gatsby/utils.ts +352 -0
  10. package/exporter/adapters/index.ts +5 -0
  11. package/{scripts → exporter}/build-complete.ts +16 -14
  12. package/exporter/download-data.ts +6 -0
  13. package/exporter/index-width-adapter.ts +25 -0
  14. package/exporter/index.ts +14 -0
  15. package/exporter/reset-render.ts +12 -0
  16. package/{src → exporter}/services/auth.ts +0 -2
  17. package/{src → exporter}/services/distributors.ts +10 -1
  18. package/{src → exporter}/services/robots.ts +9 -6
  19. package/exporter/services/store.ts +351 -0
  20. package/{src → exporter}/types/api.ts +6 -0
  21. package/{src → exporter}/types/pages.ts +18 -17
  22. package/{src → exporter}/types/sites.ts +1 -1
  23. package/{src → exporter}/utils/api.ts +10 -7
  24. package/{src → exporter}/utils/cache.ts +14 -8
  25. package/{src → exporter}/utils/domains.ts +3 -3
  26. package/exporter/utils/download-build-data.ts +22 -0
  27. package/exporter/utils/folders.ts +49 -0
  28. package/{src → exporter}/utils/health-checks.ts +8 -7
  29. package/{src → exporter}/utils/instance.ts +1 -1
  30. package/{src/utils/integrations.tsx → exporter/utils/integrations.ts} +6 -4
  31. package/{src → exporter}/utils/pages.ts +21 -24
  32. package/exporter/utils/runners.ts +53 -0
  33. package/{src → exporter}/utils/shared.ts +31 -29
  34. package/{src → exporter}/utils/sites.ts +7 -7
  35. package/exporter/utils/store.ts +56 -0
  36. package/gatsby-config.ts +1 -1
  37. package/gatsby-node.ts +38 -72
  38. package/index.js +4 -1
  39. package/package.json +13 -10
  40. package/src/README.md +7 -0
  41. package/src/components/Head.tsx +3 -3
  42. package/src/components/template.tsx +3 -4
  43. package/src/gatsby-node-utils.ts +154 -0
  44. package/src/html.tsx +1 -1
  45. package/src/types.ts +98 -0
  46. package/src/{components/utils.ts → utils.ts} +6 -8
  47. package/static/robots.txt +1 -0
  48. package/scripts/griddo-exporter.ts +0 -431
  49. package/scripts/reset-render.ts +0 -9
  50. package/src/components/types.ts +0 -40
  51. package/src/services/store.ts +0 -423
  52. package/src/utils/folders.ts +0 -125
  53. package/src/utils/gatsby.ts +0 -47
  54. /package/{src → exporter}/services/domains.ts +0 -0
  55. /package/{src → exporter}/services/navigation.ts +0 -0
  56. /package/{src → exporter}/services/settings.ts +0 -0
  57. /package/{src → exporter}/services/sites.ts +0 -0
  58. /package/{src → exporter}/types/global.ts +0 -0
  59. /package/{src → exporter}/types/navigation.ts +0 -0
  60. /package/{src → exporter}/types/templates.ts +0 -0
  61. /package/{src → exporter}/utils/searches.ts +0 -0
@@ -1,423 +0,0 @@
1
- import type { BuildProcessData } from "../types/global";
2
- import type {
3
- GatsbyPageObject,
4
- GriddoListPage,
5
- GriddoMultiPage,
6
- GriddoSinglePage,
7
- PageAdditionalInfo,
8
- } from "../types/pages";
9
- import type { Site } from "../types/sites";
10
-
11
- import fs from "fs";
12
- import fsp from "fs/promises";
13
- import path from "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 { RobotsService } from "./robots";
22
- import { SettingsService } from "./settings";
23
- import { SitesService } from "./sites";
24
- import { version as griddoVersion } from "../../package.json";
25
- import { createSha256, updatedSiteHash } from "../utils/cache";
26
- import { deleteSites } from "../utils/folders";
27
- import {
28
- createGriddoListPagesForGatsby,
29
- createGriddoMultiPagesForGatsby,
30
- createGriddoSinglePageForGatsby,
31
- getMultiPageElements,
32
- getPaginatedPages,
33
- } from "../utils/pages";
34
- import { logInfo, removeProperties, siteList, walk } from "../utils/shared";
35
- import { checkSites, getSiteData, unpublishSites } from "../utils/sites";
36
-
37
- dotenv.config();
38
-
39
- // Envs
40
- const API_URL = process.env.API_URL as string;
41
- const CXBRANCH = process.env.CXBRANCH;
42
- const REACT_APP_INSTANCE =
43
- process.env.GRIDDO_REACT_APP_INSTANCE || process.env.REACT_APP_INSTANCE;
44
- const API_CONCURRENCY_COUNT =
45
- parseInt(process.env.GRIDDO_API_CONCURRENCY_COUNT || "") || 10;
46
- const PUBLIC_API_URL = process.env.PUBLIC_API_URL as string;
47
- const RENDER_ID =
48
- process.env.GRIDDO_RENDERID || new Date().valueOf().toString();
49
-
50
- // Consts
51
- const CREATED_PAGES: Array<number> = [];
52
- const BUILD_PROCESS_DATA: BuildProcessData = {};
53
-
54
- /**
55
- * Store service to fetch, process and save object pages and sites data to be
56
- * consumed by other services (Griddo itself, Gatsby, etc.)
57
- *
58
- * @example
59
- * import { StoreService } from "./store"
60
- *
61
- * // Init the store service.
62
- * StoreService.init("foo/pages")
63
- * // Save the data into files.
64
- * await StoreService.createBuildSource()
65
- * // Consume the pages as an interator.
66
- * const pages = StoreService.getPages()
67
- */
68
- class StoreService {
69
- static basePath: string;
70
- static pages: Array<GatsbyPageObject> = [];
71
- static sitesToPublish: Array<Site>;
72
- static buildProcessData: BuildProcessData;
73
- static createdPages: Array<number>;
74
-
75
- /**
76
- * Initialize the Store with a path to save files (file mode) and an option object to configure the Store.
77
- *
78
- * @param basePath The path to store the page files.
79
- * @param options An object configuration
80
- * @param options.mode Store mode
81
- */
82
- public static init(basePath: string) {
83
- console.log(
84
- `🧶 Processing API page calls with ${API_CONCURRENCY_COUNT} threads`
85
- );
86
- console.log(`📦 Griddo Store initialized`);
87
-
88
- this.basePath = basePath;
89
-
90
- // Remove old store
91
- if (fs.existsSync(basePath)) {
92
- fs.rmSync(basePath, { recursive: true });
93
- }
94
-
95
- // Create new store
96
- if (!fs.existsSync(basePath)) {
97
- fs.mkdirSync(basePath);
98
- }
99
- }
100
-
101
- /**
102
- * Create a complete build fetching the necessary data from API.
103
- */
104
- public static async createBuildSource() {
105
- try {
106
- // Get sites objects to publish and unpublish.
107
- const { sitesToPublish, sitesToUnpublish } = await checkSites();
108
-
109
- // The settings will be extracted below in this process.
110
- await SettingsService.getAll();
111
-
112
- // If no activity in sites, exit
113
- if (!(sitesToPublish.length || sitesToUnpublish.length)) {
114
- console.warn("There are no sites to update");
115
- process.exit(0);
116
- }
117
-
118
- console.log(`\n⬆ Sites to publish: ${siteList(sitesToPublish)}`);
119
- console.log(`\n⬇ Sites to unpublish: ${siteList(sitesToUnpublish)}\n`);
120
-
121
- // Unpublish (API) and delete sites
122
- // TODO: Manage this to save end data to the __report-build__ file ???
123
- await unpublishSites(sitesToUnpublish);
124
-
125
- // Delete (clean) sites to publish
126
- // SPREAD: await deleteSites(sitesToPublish);
127
- await deleteSites([...sitesToPublish]);
128
-
129
- // Set robots information to use later in the `onPostBuild` phase.
130
- await RobotsService.loadRobots();
131
-
132
- for (const site of sitesToPublish) {
133
- const { id: siteId, slug: siteSlug, theme, favicon } = site;
134
-
135
- const {
136
- siteInfo,
137
- validPagesIds,
138
- siteHash,
139
- unpublishHashes,
140
- siteLangs,
141
- defaultLang,
142
- headers,
143
- footers,
144
- socials,
145
- } = await getSiteData(siteId);
146
-
147
- const {
148
- cloudinaryName,
149
- useMetaTitle,
150
- useMetaKeywords,
151
- showBasicMetaRobots,
152
- avoidHrefLangsOnCanonicals,
153
- avoidSelfReferenceCanonicals,
154
- avoidHrefLangXDefault,
155
- avoidDebugMetas,
156
- } = SettingsService.settings;
157
-
158
- BUILD_PROCESS_DATA[siteId] = {
159
- siteHash,
160
- unpublishHashes,
161
- publishHashes: [],
162
- };
163
-
164
- const NavService = new NavigationService();
165
-
166
- // Set `headers` and `footers` to the NavService to use later in this process.
167
- NavService.navigations = { headers, footers };
168
-
169
- site.languages = siteLangs;
170
-
171
- const shouldUpdateSite = updatedSiteHash(siteId, siteHash);
172
-
173
- const siteScript = siteInfo.siteScript;
174
-
175
- const siteMetadata = {
176
- siteUrl: siteInfo.slug,
177
- title: siteInfo.name,
178
- favicon,
179
- };
180
-
181
- const additionalInfo = {
182
- baseUrl: API_URL,
183
- publicBaseUrl: PUBLIC_API_URL,
184
- instance: REACT_APP_INSTANCE,
185
- siteSlug,
186
- theme,
187
- siteMetadata,
188
- socials,
189
- siteLangs,
190
- cloudinaryName,
191
- griddoVersion,
192
- siteOptions: {
193
- useMetaTitle,
194
- useMetaKeywords,
195
- showBasicMetaRobots,
196
- avoidHrefLangsOnCanonicals,
197
- avoidSelfReferenceCanonicals,
198
- avoidHrefLangXDefault,
199
- avoidDebugMetas,
200
- },
201
- BUILD_MODE: CXBRANCH,
202
- siteScript,
203
- };
204
-
205
- logInfo(`𝍌 ${site.name} site`);
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 fetchPageAndSaveToStore = async (pageId: number) => {
213
- // Here will be store every page returned by the API and processed by
214
- // Griddo CX.
215
- let gatsbyPageObjects: Array<GatsbyPageObject> = [];
216
-
217
- // Get page data
218
- const page = await SitesService.getPage(pageId, shouldUpdateSite);
219
-
220
- // Probably a 404
221
- if (!page) return;
222
-
223
- // Update Array of page ids
224
- CREATED_PAGES.push(pageId);
225
-
226
- // TODO: Use structuredClone() when node 18 is available.
227
- // SHAME: This new pageAdditionalInfo needs to be a copy because
228
- // additionalInfo referenced from outside this function and
229
- // its used by other pages.
230
- const pageAdditionalInfo = JSON.parse(
231
- JSON.stringify(additionalInfo)
232
- ) as PageAdditionalInfo;
233
-
234
- // Updated with navigations (header & footer)
235
- pageAdditionalInfo.navigations = NavService.getPageNavigations(page);
236
-
237
- // Content Type Data Query
238
- // Where the pair `hasDistributorData:true` and `data` prop exists, this
239
- // function will attach a `queriedItems` prop with the result of the fetch
240
- // for the data.
241
- const template = await DistributorService.getDistributorData({
242
- page,
243
- cacheKey: RENDER_ID,
244
- });
245
-
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 `createGriddoMultiPagesForGatsby()`
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";
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
- gatsbyPageObjects = await createGriddoListPagesForGatsby(
278
- griddoListPage,
279
- pageAdditionalInfo
280
- );
281
- }
282
-
283
- // >> Multi-page <<
284
- if (isMultiPage) {
285
- const griddoMultipage = page as GriddoMultiPage;
286
-
287
- // The `template` key with the (maybe) distributor data items queried
288
- griddoMultipage.template = template;
289
- griddoMultipage.multiPageElements = multiPageElements;
290
- griddoMultipage.defaultLang = defaultLang;
291
-
292
- gatsbyPageObjects = await createGriddoMultiPagesForGatsby(
293
- griddoMultipage,
294
- pageAdditionalInfo
295
- );
296
- }
297
-
298
- // >> Single template <<
299
- if (isSinglePage) {
300
- const griddoSinglePage = page as GriddoSinglePage;
301
-
302
- // The `template` key with the (maybe) distributor data items queried
303
- griddoSinglePage.template = template;
304
- griddoSinglePage.defaultLang = defaultLang;
305
-
306
- gatsbyPageObjects = [
307
- await createGriddoSinglePageForGatsby(
308
- griddoSinglePage,
309
- pageAdditionalInfo
310
- ),
311
- ];
312
- }
313
-
314
- // Update hashes
315
- BUILD_PROCESS_DATA[siteId].publishHashes.push(page.hash);
316
-
317
- // Save build data to store
318
- await this.savePages(gatsbyPageObjects); // gatsbyPageObjects is always an array regardless of whether it's just one page
319
- this.setSitesToPublish(sitesToPublish);
320
- this.setBuildProcessData(BUILD_PROCESS_DATA);
321
- this.setCreatedPages(CREATED_PAGES);
322
- };
323
-
324
- // Create the pLimit array of promises
325
- const limit = pLimit(API_CONCURRENCY_COUNT);
326
- const pagesToRender = validPagesIds.map((id: number) =>
327
- limit(() => fetchPageAndSaveToStore(id))
328
- );
329
-
330
- await Promise.all(pagesToRender);
331
- }
332
- } catch (e) {
333
- const error = e as { message: string };
334
-
335
- console.error(error.message);
336
-
337
- process.exit(1);
338
- }
339
- }
340
-
341
- /**
342
- * Save the pages into the file system.
343
- *
344
- * @param pages An array of pages to save in the store.
345
- */
346
- public static async savePages(pages: Array<GatsbyPageObject>) {
347
- pages.forEach((page) =>
348
- removeProperties(page, ["editorID", "parentEditorID"])
349
- );
350
-
351
- const promises = pages.map(async (pageObject) => {
352
- const filename = `${createSha256(pageObject.path)}.json`;
353
- const fileContent = JSON.stringify(pageObject);
354
- const filePath = path.resolve(this.basePath, filename);
355
- await fsp.writeFile(filePath, fileContent);
356
- });
357
-
358
- await Promise.all(promises);
359
- }
360
-
361
- /**
362
- * Set site to publish data in the Store.
363
- *
364
- * @param sites An array of sites to be published.
365
- */
366
- public static setSitesToPublish(sites: Array<Site>) {
367
- this.sitesToPublish = sites;
368
- }
369
-
370
- /**
371
- * Set the build process data in the Store.
372
- *
373
- * @param buildProcessData An object that represents a build process data.
374
- */
375
- public static setBuildProcessData(buildProcessData: BuildProcessData) {
376
- this.buildProcessData = buildProcessData;
377
- }
378
-
379
- /**
380
- * Set the created pages in the Store.
381
- *
382
- * @param pages An array of pages ids.
383
- */
384
- public static setCreatedPages(pages: Array<number>) {
385
- this.createdPages = pages;
386
- }
387
-
388
- /**
389
- * Get the build metadata from the Store.
390
- */
391
- public static getMetadata() {
392
- return {
393
- buildProcessData: this.buildProcessData,
394
- createdPages: this.createdPages,
395
- sitesToPublish: this.sitesToPublish,
396
- };
397
- }
398
-
399
- /**
400
- * Return an iterator with pages read from the file system.
401
- */
402
- public static async *getPages() {
403
- const pagesDirPath = path.resolve(this.basePath);
404
- const jsonFilePaths = walk(pagesDirPath).filter(
405
- (file) => path.extname(file) === ".json"
406
- );
407
-
408
- for (const filePath of jsonFilePaths) {
409
- try {
410
- const fileStats = await fsp.stat(filePath);
411
- const page = (await fsx.readJSON(filePath, {
412
- encoding: "utf-8",
413
- })) as GatsbyPageObject;
414
- page.size = fileStats.size / 1024;
415
- yield page;
416
- } catch (error) {
417
- console.error(`Error: The file ${filePath} doesn't exist`, error);
418
- }
419
- }
420
- }
421
- }
422
-
423
- export { StoreService };
@@ -1,125 +0,0 @@
1
- import type { Site } from "../types/sites";
2
-
3
- import path from "path";
4
-
5
- import fs from "fs-extra";
6
-
7
- import { resolveComponentsPath } from "./instance";
8
- import { logInfo } from "./shared";
9
-
10
- /**
11
- * Delete sites folders that will be updated from de file system.
12
- *
13
- * @param updateSites An array of sites to be updated.
14
- */
15
- async function deleteSites(updatedSites: Array<Site>) {
16
- for await (const site of updatedSites) {
17
- for (const domain of site.domains) {
18
- const mappedDomain = Object.values(domain)[0];
19
- const dir = path.resolve(__dirname, `../../dist${mappedDomain}`);
20
- const pageDataDir = path.resolve(
21
- __dirname,
22
- `../../assets/page-data${mappedDomain}`
23
- );
24
-
25
- logInfo(`Site dir ${dir}`);
26
- logInfo(`Page data dir ${pageDataDir}`);
27
-
28
- // delete directory recursively
29
- if (!fs.existsSync(dir)) return;
30
-
31
- try {
32
- await fs.rm(dir, { recursive: true });
33
- logInfo(`${dir} is deleted!`);
34
- } catch (err) {
35
- console.log(err);
36
- }
37
-
38
- if (!fs.existsSync(pageDataDir)) return;
39
-
40
- try {
41
- await fs.rm(pageDataDir, { recursive: true });
42
- console.log(`${pageDataDir} is deleted!`);
43
- } catch (err) {
44
- console.log(err);
45
- }
46
- }
47
- }
48
- }
49
-
50
- /**
51
- * Update the Griddo's `/dist` folder with the contents from `/public` only with files of type:
52
- * - js
53
- * - json
54
- * - css
55
- */
56
- async function updateDist() {
57
- const src = "./public";
58
- const dest = "./dist";
59
-
60
- const domainDestPath = `${dest}/${process.env.DOMAIN}`;
61
-
62
- const files = fs
63
- .readdirSync(src)
64
- .filter(
65
- (file) =>
66
- path.extname(file) === ".js" ||
67
- path.extname(file) === ".json" ||
68
- path.extname(file) === ".css"
69
- );
70
-
71
- const assetsDest = "./assets";
72
-
73
- const pageDataSrc = `${src}/page-data`;
74
- const pageDataDest = `${assetsDest}/page-data`;
75
-
76
- const projectStaticSrc = "./static";
77
- const projectStaticDest = assetsDest;
78
-
79
- const gatsbyStaticSrc = `${dest}/static`;
80
- const gatsbyStaticDest = `${assetsDest}/static`;
81
-
82
- try {
83
- fs.mkdirSync(assetsDest, { recursive: true });
84
- fs.copySync(src, dest);
85
-
86
- if (process.env.NEEDS_ASSET_DOMAIN_PREFIX) {
87
- fs.copySync(pageDataSrc, pageDataDest);
88
- fs.copySync(projectStaticSrc, projectStaticDest, { overwrite: false });
89
- fs.copySync(gatsbyStaticSrc, gatsbyStaticDest, { overwrite: false });
90
- fs.copySync(projectStaticSrc, domainDestPath, { overwrite: false });
91
-
92
- files.map(async (file) => {
93
- const fileSrc = `${src}/${file}`;
94
- const fileDest = `${assetsDest}/${file}`;
95
- fs.copySync(fileSrc, fileDest);
96
- });
97
- }
98
- } catch (err) {
99
- console.error(err);
100
- }
101
- }
102
-
103
- /**
104
- * Copy the instance's `/static` folder into the Gatsby's to take it into account for bundle.
105
- */
106
- function prepareStaticFolder() {
107
- const src = resolveComponentsPath("static");
108
- const dest = "./static";
109
-
110
- const files = fs.readdirSync(src);
111
-
112
- try {
113
- files.map(async (file) => {
114
- const fileSrc = `${src}/${file}`;
115
- const fileDest = `${dest}/${file}`;
116
- fs.copySync(fileSrc, fileDest);
117
- });
118
-
119
- console.log("📁 Components static folder copied");
120
- } catch (err) {
121
- console.error(err);
122
- }
123
- }
124
-
125
- export { deleteSites, updateDist, prepareStaticFolder };
@@ -1,47 +0,0 @@
1
- import type { GatsbyNode } from "gatsby";
2
-
3
- import { IS_COMPONENT_LIBRARY, PROJECT_ALIASES } from "./instance";
4
-
5
- // TODO: Use webpack types
6
- const onCreateWebpackConfig: GatsbyNode["onCreateWebpackConfig"] = ({
7
- actions,
8
- plugins,
9
- loaders,
10
- getConfig,
11
- stage,
12
- }) => {
13
- if (IS_COMPONENT_LIBRARY) {
14
- const config = getConfig();
15
- config.module.rules = [
16
- // Omit the default rule where test === '\.jsx?$'
17
- ...config.module.rules.filter(
18
- (rule: { test: string }) => String(rule.test) !== String(/\.jsx?$/)
19
- ),
20
- // Recreate it with custom exclude filter
21
- {
22
- ...loaders.js(),
23
- test: /\.jsx?$/,
24
- // Exclude all node_modules from transpilation, except for '@griddo/cx'
25
- exclude: (modulePath: string) =>
26
- /node_modules/.test(modulePath) && !/@griddo\/cx/.test(modulePath),
27
- },
28
- ];
29
- actions.replaceWebpackConfig(config);
30
- }
31
-
32
- // Add component-system aliases to Webpack's Resolve:
33
- actions.setWebpackConfig({
34
- resolve: {
35
- fallback: { path: false },
36
- alias: PROJECT_ALIASES,
37
- },
38
- plugins: [plugins.provide({ process: "process/browser", React: "react" })],
39
- });
40
-
41
- // No sourcemaps on builds
42
- if (stage === "build-javascript") {
43
- actions.setWebpackConfig({ devtool: false });
44
- }
45
- };
46
-
47
- export { onCreateWebpackConfig };
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes