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