@griddo/cx 1.75.193 → 1.75.196

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.
@@ -1,13 +1,13 @@
1
- // Types
2
- import type { Core, Fields } from "@griddo/core";
3
1
  import type { FetchDataProps } from "../types/global";
4
2
  import type { APIPageObject } from "../types/pages";
3
+ import type { Core, Fields } from "@griddo/core";
4
+ import type {
5
+ QueriedData,
6
+ Reference,
7
+ } from "@griddo/core/dist/types/api-response-fields";
5
8
 
6
- // Utils
7
- import { logBox } from "../utils/shared";
8
-
9
- // Services
10
9
  import { SitesService } from "./sites";
10
+ import { logBox } from "../utils/shared";
11
11
 
12
12
  /**
13
13
  * Service to work with distributors.
@@ -15,6 +15,7 @@ import { SitesService } from "./sites";
15
15
  class DistributorService {
16
16
  /**
17
17
  * Get the body data from a ReferenceField in auto or manual mode.
18
+ *
18
19
  * @param data The ReferenceField props.
19
20
  * @returns The props for one of the ReferenceField mode.
20
21
  */
@@ -118,9 +119,10 @@ class DistributorService {
118
119
  try {
119
120
  const { template } = page;
120
121
  const checkDistributors = async (
121
- // No puede ser Core.Page['template'] porque a medida que va bajando en
122
- // el árbol ya no es la estructura de un template.
123
- templateChunk: Record<string, any>, // Core.Page['template'],
122
+ templateChunk: {
123
+ hasDistributorData?: boolean;
124
+ queriedItems: QueriedData<unknown>;
125
+ },
124
126
  level = 1
125
127
  ) => {
126
128
  // If it doesn't a "template strcuture"
@@ -138,7 +140,12 @@ class DistributorService {
138
140
  // Si la key es `queriedItems` saltamos al siguiente `key`
139
141
  if (key === "queriedItems") continue;
140
142
 
141
- const component = templateChunk[key];
143
+ const _key = key as "hasDistributorData" | "queriedItems";
144
+ const component = templateChunk[_key] as unknown as {
145
+ data: Reference<unknown>;
146
+ queriedItems: QueriedData<unknown>;
147
+ hasDistributorData: boolean;
148
+ };
142
149
 
143
150
  // Si el elemento no existe o no es un objeto saltamos al siguiente `key`
144
151
  if (!component || typeof component !== "object") continue;
@@ -147,8 +154,8 @@ class DistributorService {
147
154
  if (component.hasDistributorData) {
148
155
  component.queriedItems = await this.fetchContentTypeData({
149
156
  page,
150
- component,
151
157
  cached,
158
+ component,
152
159
  });
153
160
  }
154
161
 
@@ -157,7 +164,9 @@ class DistributorService {
157
164
  };
158
165
 
159
166
  const getDistributors = async (template: Core.Page["template"]) => {
160
- await checkDistributors([template]); // ==> En array para que también revise la propia template como objeto.
167
+ // `template` es un array para que también revise la propia template como objeto.
168
+ // @ts-expect-error remove the array
169
+ await checkDistributors([template]);
161
170
 
162
171
  return template;
163
172
  };
@@ -1,13 +1,11 @@
1
- // Types
2
1
  import type { Domains } from "../types/global";
3
2
 
4
- // Utils
5
3
  import { get } from "../utils/api";
6
4
 
7
5
  // Envs
8
6
  const API_URL = process.env.API_URL;
9
7
 
10
- // Constants
8
+ // Consts
11
9
  const ENDPOINTS = {
12
10
  GET_ALL: `${API_URL}/domains`,
13
11
  };
@@ -1,4 +1,3 @@
1
- // Types
2
1
  import type { Footer, Header } from "../types/navigation";
3
2
  import type { APIPageObject } from "../types/pages";
4
3
 
@@ -1,11 +1,8 @@
1
- // Types
2
1
  import type { Robots } from "../types/global";
3
2
 
4
- // External libraries
5
3
  import fs from "fs";
6
4
  import path from "path";
7
5
 
8
- // Utils
9
6
  import { get } from "../utils/api";
10
7
 
11
8
  /**
@@ -47,7 +44,7 @@ class RobotsService {
47
44
  /**
48
45
  * TODO: JSDoc
49
46
  */
50
- async writeFiles(basePath = "") {
47
+ async writeFiles(basePath: string) {
51
48
  for (const robot of this.robots) {
52
49
  const basePathLocation = path.join(basePath, robot.path);
53
50
  const fileLocation = path.join(basePathLocation, "robots.txt");
@@ -1,7 +1,5 @@
1
- // Types
2
1
  import type { Settings } from "../types/global";
3
2
 
4
- // Utils
5
3
  import { get, post } from "../utils/api";
6
4
 
7
5
  /**
@@ -1,5 +1,3 @@
1
- // Types
2
- import type { Core } from "@griddo/core";
3
1
  import type {
4
2
  AllPagesResponse,
5
3
  AllSitesReponse,
@@ -14,11 +12,10 @@ import type {
14
12
  StartPageRenderResponse,
15
13
  } from "../types/api";
16
14
  import type { Site } from "../types/sites";
15
+ import type { Core } from "@griddo/core";
17
16
 
18
- // External libraries
19
17
  import dotenv from "dotenv";
20
18
 
21
- // Utils
22
19
  import { get, post } from "../utils/api";
23
20
 
24
21
  dotenv.config();
@@ -26,7 +23,7 @@ dotenv.config();
26
23
  // Envs
27
24
  const API_URL = process.env.API_URL;
28
25
 
29
- // Constants
26
+ // Consts
30
27
  const WITH_URI = `${API_URL}/site/`;
31
28
  const ENDPOINTS = {
32
29
  GET_ALL: `${API_URL}/sites/all`,
@@ -21,28 +21,24 @@
21
21
  // │ Build metadata │ //
22
22
  // └─────────────────────────┘ //
23
23
 
24
- // Types
25
24
  import type { BuildProcessData, StoreMode } from "../types/global";
26
25
  import type { GatsbyPageObject, PageAdditionalInfo } from "../types/pages";
27
26
  import type { Site } from "../types/sites";
28
27
 
29
- // External libraries
30
- import chalk from "chalk";
31
- import dotenv from "dotenv";
32
28
  import fs from "fs";
33
29
  import fsp from "fs/promises";
34
- import pLimit from "p-limit";
35
30
  import path from "path";
36
31
  import v8 from "v8";
37
32
 
38
- // Services
33
+ import chalk from "chalk";
34
+ import dotenv from "dotenv";
35
+ import pLimit from "p-limit";
36
+
39
37
  import { DistributorService } from "./distributors";
40
38
  import { NavigationService } from "./navigation";
41
39
  import { RobotsService } from "./robots";
42
40
  import { SettingsService } from "./settings";
43
41
  import { SitesService } from "./sites";
44
-
45
- // Utils
46
42
  import { version as griddoVersion } from "../../package.json";
47
43
  import { createSha256, updatedSiteHash } from "../utils/cache";
48
44
  import { deleteSites } from "../utils/folders";
@@ -53,7 +49,7 @@ import {
53
49
  getMultiPageElements,
54
50
  getPaginatedPages,
55
51
  } from "../utils/pages";
56
- import { logInfo, walk } from "../utils/shared";
52
+ import { logInfo, removeProperties, siteList, walk } from "../utils/shared";
57
53
  import { checkSites, getSiteData, unpublishSites } from "../utils/sites";
58
54
 
59
55
  dotenv.config();
@@ -66,16 +62,17 @@ const GRIDDO_API_CONCURRENCY_COUNT = process.env.GRIDDO_API_CONCURRENCY_COUNT;
66
62
  const PUBLIC_API_URL = process.env.PUBLIC_API_URL as string;
67
63
  const RENDER_ID = process.env.RENDERID || new Date().valueOf().toString();
68
64
 
69
- // Constants shared between Gatsby phases.
65
+ // Consts
70
66
  const CREATED_PAGES: Array<number> = [];
71
67
  const BUILD_PROCESS_DATA: BuildProcessData = {};
68
+ const UNWANTED_PAGE_PROPS = ["editorID", "parentEditorID"];
72
69
 
73
70
  /**
74
- * Store service to fetch, process and save temporarily final pages and site
71
+ * Store service to fetch, process and save temporarily object pages and site
75
72
  * data to be consumed by external services (Griddo itself, Gatsby, etc.)
76
73
  *
77
74
  * Modes:
78
- * - File mode will save the final page objects in individual files in the file system.
75
+ * - File mode will save the final page objects in individual json files in the file system.
79
76
  * - Memory mode will save the final page objects in an array of objects in memory.
80
77
  *
81
78
  * @example
@@ -91,6 +88,7 @@ const BUILD_PROCESS_DATA: BuildProcessData = {};
91
88
  class StoreService {
92
89
  static basePath: string;
93
90
  static mode: "file" | "memory";
91
+ static sanitize? = false;
94
92
  static pages: Array<GatsbyPageObject> = [];
95
93
  static sitesToPublish: Array<Site>;
96
94
  static buildProcessData: BuildProcessData;
@@ -99,14 +97,18 @@ class StoreService {
99
97
  // Public methods
100
98
 
101
99
  /**
102
- * Initialize the Store with a path to store the files in file mode and an option object to set the mode.
100
+ * Initialize the Store with a path to save files (file mode) and an option object to configure the Store.
103
101
  *
104
102
  * @param basePath The path to store the page files.
105
103
  * @param options An object configuration
106
104
  * @param options.mode Store mode
107
105
  * @todo Avoid initialize the Store with a `basePath` in memory mode.
108
106
  */
109
- public static init(basePath: string, options: { mode: StoreMode }) {
107
+ public static init(
108
+ basePath: string,
109
+ options: { mode: StoreMode; sanitize?: boolean }
110
+ ) {
111
+ this.sanitize = options?.sanitize;
110
112
  const { mode } = options;
111
113
  const griddoCxThreads = parseInt(GRIDDO_API_CONCURRENCY_COUNT || "10");
112
114
  const modeString = mode === "file" ? "File mode" : "Memory mode";
@@ -114,6 +116,10 @@ class StoreService {
114
116
  console.log(`🧶 Processing API page calls with ${griddoCxThreads} threads`);
115
117
  console.log(`📦 Griddo Store initialized - ${chalk.italic(modeString)}`);
116
118
 
119
+ if (this.sanitize) {
120
+ console.log(`🏥 Sanitize pages enabled`);
121
+ }
122
+
117
123
  if (mode === "file") {
118
124
  this.basePath = basePath;
119
125
  this.mode = mode;
@@ -133,9 +139,9 @@ class StoreService {
133
139
  }
134
140
 
135
141
  /**
136
- * Save the build data to the Store.
142
+ * Create a complete build fetching the necessary data from API.
137
143
  */
138
- public static async saveBuildData() {
144
+ public static async createBuildSource() {
139
145
  try {
140
146
  // Get sites objects to publish and unpublish.
141
147
  const { sitesToPublish, sitesToUnpublish } = await checkSites();
@@ -146,27 +152,15 @@ class StoreService {
146
152
  // If no activity in sites, exit
147
153
  if (!(sitesToPublish.length || sitesToUnpublish.length)) {
148
154
  console.warn("There are no sites to update");
149
-
150
155
  process.exit(0);
151
156
  }
152
157
 
153
- // Publish and unpublis sites
154
158
  console.log(
155
- chalk.green(
156
- "\n⬆️ ",
157
- `(${sitesToPublish.length}) Sites to publish:`,
158
- sitesToPublish.map(({ name }) => name).join(", "),
159
- "\n"
160
- )
159
+ chalk.green(`\n⬆ Sites to publish: ${siteList(sitesToPublish)}`)
161
160
  );
162
161
 
163
162
  console.log(
164
- chalk.red(
165
- "⬇️ ",
166
- `(${sitesToUnpublish.length}) Sites to unpublish:`,
167
- sitesToUnpublish.map(({ name }) => name).join(", "),
168
- "\n"
169
- )
163
+ chalk.red(`\n⬇ Sites to unpublish: ${siteList(sitesToUnpublish)}\n`)
170
164
  );
171
165
 
172
166
  // Unpublish (API) and delete sites
@@ -178,9 +172,8 @@ class StoreService {
178
172
  // Set robots information to use later in the `onPostBuild` phase.
179
173
  await RobotsService.loadRobots();
180
174
 
181
- // Array of sites (Promises)
182
- for (const site of sitesToPublish) {
183
- // Gets
175
+ const siteToPublishPromises = sitesToPublish.map(async (site) => {
176
+ // for (const site of sitesToPublish) {
184
177
  const { id: siteId, slug: siteSlug, theme, favicon } = site;
185
178
 
186
179
  const {
@@ -193,7 +186,6 @@ class StoreService {
193
186
  headers,
194
187
  footers,
195
188
  socials,
196
- // TODO: Check the false here...
197
189
  } = await getSiteData(siteId, false);
198
190
 
199
191
  const {
@@ -206,8 +198,6 @@ class StoreService {
206
198
  avoidDebugMetas,
207
199
  } = SettingsService.settings;
208
200
 
209
- // Sets
210
-
211
201
  BUILD_PROCESS_DATA[siteId] = {
212
202
  siteHash,
213
203
  unpublishHashes,
@@ -254,7 +244,7 @@ class StoreService {
254
244
  siteScript,
255
245
  };
256
246
 
257
- logInfo(`${validPagesIds.length} valid pages`);
247
+ logInfo(`𝍌 ${site.name} site`);
258
248
 
259
249
  // -------------------------------------------------------------------------
260
250
  // Pages loop promise creation
@@ -382,7 +372,15 @@ class StoreService {
382
372
  );
383
373
 
384
374
  await Promise.all(pagesToRender);
385
- }
375
+ });
376
+
377
+ // Create the pLimit array of promises
378
+ const limit = pLimit(1);
379
+ const sitesToPublishAwaited = siteToPublishPromises.map((site) =>
380
+ limit(() => site)
381
+ );
382
+
383
+ await Promise.all(sitesToPublishAwaited);
386
384
  } catch (e) {
387
385
  const error = e as { message: string };
388
386
 
@@ -393,7 +391,9 @@ class StoreService {
393
391
  }
394
392
 
395
393
  /**
396
- * Get the pages saved previously from the Store.
394
+ * Get all pages data from the Store.
395
+ * If the Store is in file mode `getPages` will return a Generator of pages.
396
+ * If the Store is in memory mode `getPages` will return an array of pages.
397
397
  */
398
398
  public static getPages() {
399
399
  if (this.mode === "file") {
@@ -409,6 +409,12 @@ class StoreService {
409
409
  * @param pages An array of pages to save in the store.
410
410
  */
411
411
  public static async savePages(pages: Array<GatsbyPageObject>) {
412
+ // WARNS: This mutate the page objects and could hurt the build render
413
+ // performance.
414
+ if (this.sanitize) {
415
+ pages.forEach((page) => removeProperties(page, UNWANTED_PAGE_PROPS));
416
+ }
417
+
412
418
  if (this.mode === "file") {
413
419
  await this.savePagesToFiles(pages);
414
420
  } else {
@@ -464,6 +470,7 @@ class StoreService {
464
470
  );
465
471
 
466
472
  for (const filePath of jsonFilePaths) {
473
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
467
474
  const page = require(filePath) as GatsbyPageObject;
468
475
  page.size = fs.statSync(filePath).size / 1024;
469
476
  yield { ...page };
package/src/types/api.ts CHANGED
@@ -1,8 +1,7 @@
1
- // Types
2
- import type { Core, Fields } from "@griddo/core";
3
1
  import type { Domains, Robots, Settings } from "./global";
4
2
  import type { APIPageObject } from "./pages";
5
3
  import type { Site } from "./sites";
4
+ import type { Core, Fields } from "@griddo/core";
6
5
 
7
6
  /** EndSiteRender Body */
8
7
  export type EndSiteRenderBody = {
@@ -20,7 +19,7 @@ export interface DistributorBody {
20
19
  order?: string;
21
20
  source?: Array<string>;
22
21
  quantity?: number;
23
- filter?: Array<any>;
22
+ filter?: Array<unknown>;
24
23
  fullRelations?: boolean;
25
24
  allLanguages?: boolean;
26
25
  fixed?: Array<number>;
@@ -112,13 +111,13 @@ export interface APIRequest {
112
111
  /** The URL of the API endpoint. */
113
112
  endpoint: string;
114
113
  /** The parameters to be sent in the request body. */
115
- body?: any;
114
+ body?: unknown;
116
115
  /** Indicates whether to use the cache to get the response from the API. */
117
116
  cached?: unknown;
118
117
  /** Number of connection attempts (in case it fails on the first attempt). */
119
118
  attempt?: number;
120
119
  /** Headers for the post api fetch */
121
- headers?: any;
120
+ headers?: Record<string, unknown>;
122
121
  }
123
122
 
124
123
  /** Type with the POST request properties. */
@@ -186,3 +185,14 @@ export type APIResponses =
186
185
  | DistributorResponse
187
186
  | PostSearchInfoResponse
188
187
  | AllPagesResponse;
188
+
189
+ // TODO: JSDoc
190
+ export interface ShowApiErrorOptions {
191
+ callInfo: {
192
+ endpoint?: string;
193
+ body?: unknown;
194
+ headers?: unknown;
195
+ attempt?: number;
196
+ };
197
+ breakProcess: boolean;
198
+ }
@@ -1,9 +1,10 @@
1
- // Types
2
- import type { Core, Fields } from "@griddo/core";
3
1
  import type { EndSiteRenderBody } from "./api";
2
+ import type { Core, Fields } from "@griddo/core";
4
3
 
4
+ // TODO: JSDoc
5
5
  export type StoreMode = "memory" | "file";
6
6
 
7
+ // TODO: JSDoc
7
8
  export interface Settings {
8
9
  apiVersion?: string;
9
10
  avoidCanonicalsOnSitemaps?: boolean;
@@ -27,9 +28,10 @@ export interface Settings {
27
28
  welcomeText2?: string;
28
29
  }
29
30
 
30
- /** ??? */
31
+ // TODO: JSDoc
31
32
  export type Petition = Record<string, unknown>;
32
33
 
34
+ // TODO: JSDoc
33
35
  export interface PostSearchInfoProps {
34
36
  title?: string;
35
37
  description: string;
@@ -42,6 +44,7 @@ export interface PostSearchInfoProps {
42
44
  url?: string;
43
45
  }
44
46
 
47
+ // TODO: JSDoc
45
48
  export interface FetchDataProps {
46
49
  page: Core.Page;
47
50
  component: {
@@ -50,6 +53,7 @@ export interface FetchDataProps {
50
53
  cached: boolean;
51
54
  }
52
55
 
56
+ // TODO: JSDoc
53
57
  export type Domains = Array<{
54
58
  id: number;
55
59
  slug: string;
@@ -59,6 +63,8 @@ export type Domains = Array<{
59
63
  /** Describes the type of build process data object. */
60
64
  export type BuildProcessData = Record<string, EndSiteRenderBody>;
61
65
 
66
+ // TODO: JSDoc
62
67
  export type Robot = { path: string; content: string };
63
68
 
69
+ // TODO: JSDoc
64
70
  export type Robots = Array<Robot>;
@@ -1,8 +1,7 @@
1
- // Types
2
- import type { Core, Fields } from "@griddo/core";
3
1
  import type { SocialsResponse } from "./api";
4
2
  import type { Settings } from "./global";
5
3
  import type { Site } from "./sites";
4
+ import type { Core, Fields } from "@griddo/core";
6
5
 
7
6
  // TODO: In @griddo/core the type Core.Page has header/footer as React-Types,
8
7
  // but API return `number | null`.
@@ -11,11 +10,13 @@ export type APIPageObject = Core.Page & {
11
10
  footer: number | null;
12
11
  };
13
12
 
13
+ // TODO: JSDoc
14
14
  export type CleanPage = Core.Page & {
15
15
  isRoot: boolean;
16
16
  defaultLang?: Core.SiteLanguage | undefined;
17
17
  };
18
18
 
19
+ // TODO: JSDoc
19
20
  export type RenderPage = Core.Page & {
20
21
  isRoot?: boolean;
21
22
  multiPageElements: MultiPageElements;
@@ -30,17 +31,19 @@ export type RenderPage = Core.Page & {
30
31
  mode: "list";
31
32
  };
32
33
 
34
+ // TODO: JSDoc
33
35
  export type GriddoSinglePage = Core.Page & {
34
36
  defaultLang?: Core.SiteLanguage;
35
37
  };
36
38
 
39
+ // TODO: JSDoc
37
40
  export type GriddoListPage = Core.Page & {
38
41
  page: APIPageObject;
39
42
  pages: Array<Array<Fields.QueriedDataItem>>;
40
43
  isRoot?: boolean;
41
44
  defaultLang?: Core.SiteLanguage;
42
45
  template: {
43
- [key: string]: any;
46
+ [key: string]: unknown;
44
47
  type: "template";
45
48
  templateType: string;
46
49
  activeSectionSlug: string;
@@ -49,6 +52,7 @@ export type GriddoListPage = Core.Page & {
49
52
  totalQueriedItems: Array<Fields.QueriedDataItem>;
50
53
  };
51
54
 
55
+ // TODO: JSDoc
52
56
  export type GriddoMultiPage = Core.Page & {
53
57
  header: number | null;
54
58
  footer: number | null;
@@ -57,6 +61,7 @@ export type GriddoMultiPage = Core.Page & {
57
61
  defaultLang?: Core.SiteLanguage | undefined;
58
62
  };
59
63
 
64
+ // TODO: JSDoc
60
65
  export interface AdditionalInfo {
61
66
  baseUrl: string;
62
67
  BUILD_MODE?: string;
@@ -81,6 +86,7 @@ export interface AdditionalInfo {
81
86
  theme: string;
82
87
  }
83
88
 
89
+ // TODO: JSDoc
84
90
  export interface PageAdditionalInfo extends AdditionalInfo {
85
91
  navigations: {
86
92
  header: Record<string, unknown> | null;
@@ -88,6 +94,7 @@ export interface PageAdditionalInfo extends AdditionalInfo {
88
94
  };
89
95
  }
90
96
 
97
+ // TODO: JSDoc
91
98
  export type GatsbyPageObject = {
92
99
  matchPath?: string;
93
100
  path: string;
@@ -134,6 +141,7 @@ export type GatsbyPageObject = {
134
141
  };
135
142
  };
136
143
 
144
+ // TODO: JSDoc
137
145
  export type MultiPageElements = Array<{
138
146
  component: string;
139
147
  title: string | Required<Fields.Heading>;
@@ -1,7 +1,6 @@
1
- // Types
2
- import type { Core } from "@griddo/core";
3
1
  import type { AllPagesResponse, SocialsResponse } from "./api";
4
2
  import type { Footer, Header } from "./navigation";
3
+ import type { Core } from "@griddo/core";
5
4
 
6
5
  /**
7
6
  * Describe a Griddo site object from API.
@@ -46,11 +45,12 @@ export interface Site
46
45
  updated: boolean;
47
46
  }
48
47
 
48
+ // TODO: JSDoc
49
49
  export interface SiteData {
50
50
  siteInfo: Site;
51
- validPagesIds: number[];
51
+ validPagesIds: Array<number>;
52
52
  siteHash: string | null;
53
- unpublishHashes: string[];
53
+ unpublishHashes: Array<string>;
54
54
  siteLangs: Array<Core.SiteLanguage>;
55
55
  defaultLang: Core.SiteLanguage | undefined;
56
56
  headers: Array<Header>;
@@ -59,6 +59,8 @@ export interface SiteData {
59
59
  sitePages: AllPagesResponse;
60
60
  }
61
61
 
62
+ // TODO: JSDoc
62
63
  export type SiteHash = string | null;
63
64
 
65
+ // TODO: JSDoc
64
66
  export type HashSites = Record<string, number | string>;
@@ -1,4 +1,3 @@
1
- // Types
2
1
  import type { Core, Fields } from "@griddo/core";
3
2
 
4
3
  /** Describe a template object from a Griddo Page */