@griddo/cx 11.9.11 → 11.9.12-rc.0
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 +13 -240
- package/build/commands/end-render.d.ts +0 -1
- package/build/commands/end-render.js +31 -0
- package/build/commands/end-render.js.map +7 -0
- package/build/commands/prepare-assets-directory.js +9 -0
- package/build/commands/prepare-assets-directory.js.map +7 -0
- package/build/commands/prepare-domains-render.js +38 -0
- package/build/commands/prepare-domains-render.js.map +7 -0
- package/build/commands/reset-render.d.ts +0 -1
- package/build/commands/reset-render.js +31 -0
- package/build/commands/reset-render.js.map +7 -0
- package/build/commands/single-domain-upload-search-content.d.ts +1 -0
- package/build/commands/start-render.d.ts +0 -1
- package/build/commands/start-render.js +66 -0
- package/build/commands/start-render.js.map +7 -0
- package/build/commands/upload-search-content.d.ts +0 -1
- package/build/commands/upload-search-content.js +32 -0
- package/build/commands/upload-search-content.js.map +7 -0
- package/build/core/GriddoLog.d.ts +16 -0
- package/build/{utils/health-checks.d.ts → core/check-env-health.d.ts} +4 -2
- package/build/core/db-class.d.ts +11 -0
- package/build/core/db.d.ts +4 -0
- package/build/core/dist-rollback.d.ts +11 -0
- package/build/core/errors.d.ts +26 -0
- package/build/core/fs.d.ts +69 -0
- package/build/core/life-cycle.d.ts +26 -0
- package/build/core/logger.d.ts +18 -0
- package/build/core/objects.d.ts +11 -0
- package/build/core/print-logos.d.ts +5 -0
- package/build/index.d.ts +10 -29
- package/build/index.js +406 -73
- package/build/react/DynamicScript/index.d.ts +4 -0
- package/build/react/GriddoFavicon/index.d.ts +4 -0
- package/build/react/GriddoIntegrations/index.d.ts +3 -4
- package/build/react/GriddoIntegrations/utils.d.ts +7 -6
- package/build/react/GriddoOpenGraph/index.d.ts +10 -0
- package/build/react/index.d.ts +3 -2
- package/build/react/index.js +1 -3
- package/build/{utils → services}/api.d.ts +1 -1
- package/build/services/auth.d.ts +2 -5
- package/build/services/domains.d.ts +3 -4
- package/build/services/manage-sites.d.ts +22 -0
- package/build/services/manage-store.d.ts +32 -0
- package/build/services/navigation.d.ts +16 -16
- package/build/{utils → services}/pages.d.ts +3 -3
- package/build/services/reference-fields.d.ts +3 -3
- package/build/services/render-artifacts.d.ts +6 -0
- package/build/services/render.d.ts +70 -0
- package/build/services/robots.d.ts +2 -19
- package/build/services/sitemaps.d.ts +5 -0
- package/build/services/sites.d.ts +8 -5
- package/build/services/store.d.ts +10 -1
- package/build/shared/context.d.ts +36 -0
- package/build/shared/envs.d.ts +19 -0
- package/build/{errors/errors-data.d.ts → shared/errors.d.ts} +5 -3
- package/build/shared/npm-modules/brush.d.ts +18 -0
- package/build/shared/npm-modules/find-up-simple.d.ts +34 -0
- package/build/shared/npm-modules/pkg-dir.d.ts +7 -0
- package/build/shared/npm-modules/xml-parser.d.ts +4 -0
- package/build/{types → shared/types}/api.d.ts +18 -18
- package/build/{types → shared/types}/global.d.ts +15 -16
- package/build/{types → shared/types}/navigation.d.ts +5 -5
- package/build/{types → shared/types}/pages.d.ts +9 -9
- package/build/shared/types/render.d.ts +54 -0
- package/build/{types → shared/types}/sites.d.ts +18 -19
- package/build/shared/types.d.ts +15 -0
- package/build/ssg-adapters/gatsby/actions/clean.d.ts +3 -0
- package/build/ssg-adapters/gatsby/actions/close.d.ts +3 -0
- package/build/ssg-adapters/gatsby/actions/data.d.ts +2 -0
- package/build/ssg-adapters/gatsby/actions/healthCheck.d.ts +2 -0
- package/build/ssg-adapters/gatsby/actions/init.d.ts +2 -0
- package/build/ssg-adapters/gatsby/actions/logs.d.ts +3 -0
- package/build/ssg-adapters/gatsby/actions/meta.d.ts +2 -0
- package/build/ssg-adapters/gatsby/actions/prepare.d.ts +2 -0
- package/build/ssg-adapters/gatsby/actions/relocation.d.ts +2 -0
- package/build/ssg-adapters/gatsby/actions/restore.d.ts +3 -0
- package/build/ssg-adapters/gatsby/actions/ssg.d.ts +3 -0
- package/build/ssg-adapters/gatsby/actions/sync.d.ts +3 -0
- package/build/ssg-adapters/gatsby/index.d.ts +9 -0
- package/build/ssg-adapters/gatsby/shared/artifacts.d.ts +4 -0
- package/build/ssg-adapters/gatsby/shared/diff-assets.d.ts +15 -0
- package/build/ssg-adapters/gatsby/shared/extract-assets.d.ts +7 -0
- package/build/ssg-adapters/gatsby/shared/gatsby-build.d.ts +7 -0
- package/build/ssg-adapters/gatsby/shared/render-rollback.d.ts +18 -0
- package/build/ssg-adapters/gatsby/shared/sync-render.d.ts +26 -0
- package/build/ssg-adapters/gatsby/shared/types.d.ts +34 -0
- package/cli.mjs +231 -0
- package/exporter/build-esbuild.noop +42 -0
- package/exporter/build.sh +16 -24
- package/exporter/commands/README.md +151 -0
- package/exporter/commands/end-render.ts +65 -86
- package/exporter/commands/prepare-assets-directory.ts +35 -0
- package/exporter/commands/prepare-domains-render.ts +132 -35
- package/exporter/commands/reset-render.ts +13 -8
- package/exporter/commands/single-domain-upload-search-content.ts +206 -0
- package/exporter/commands/start-render.ts +26 -64
- package/exporter/commands/upload-search-content.ts +204 -26
- package/exporter/core/GriddoLog.ts +45 -0
- package/exporter/core/check-env-health.ts +204 -0
- package/exporter/core/db-class.ts +54 -0
- package/exporter/core/db.ts +33 -0
- package/exporter/core/dist-rollback.ts +49 -0
- package/exporter/core/errors.ts +93 -0
- package/exporter/core/fs.ts +385 -0
- package/exporter/{utils → core}/images.ts +1 -6
- package/exporter/{utils → core}/instance.ts +9 -13
- package/exporter/core/life-cycle.ts +73 -0
- package/exporter/core/logger.ts +141 -0
- package/exporter/core/objects.ts +37 -0
- package/exporter/core/print-logos.ts +21 -0
- package/exporter/index.ts +14 -56
- package/exporter/react/DynamicScript/index.tsx +33 -0
- package/exporter/react/{Favicon → GriddoFavicon}/index.tsx +3 -9
- package/exporter/react/GriddoIntegrations/index.tsx +17 -23
- package/exporter/react/GriddoIntegrations/utils.ts +24 -12
- package/exporter/react/GriddoOpenGraph/index.tsx +39 -0
- package/exporter/react/index.tsx +3 -9
- package/exporter/services/api.ts +306 -0
- package/exporter/services/auth.ts +8 -10
- package/exporter/services/domains.ts +23 -8
- package/exporter/services/manage-sites.ts +116 -0
- package/exporter/services/manage-store.ts +173 -0
- package/exporter/services/navigation.ts +12 -18
- package/exporter/{utils → services}/pages.ts +27 -92
- package/exporter/services/reference-fields.ts +14 -32
- package/exporter/services/render-artifacts.ts +44 -0
- package/exporter/services/render.ts +229 -0
- package/exporter/services/robots.ts +33 -61
- package/exporter/services/sitemaps.ts +129 -0
- package/exporter/services/sites.ts +40 -28
- package/exporter/services/store.ts +354 -321
- package/exporter/shared/context.ts +49 -0
- package/exporter/{constants → shared}/endpoints.ts +12 -11
- package/exporter/shared/envs.ts +62 -0
- package/exporter/{errors/errors-data.ts → shared/errors.ts} +24 -14
- package/exporter/shared/npm-modules/README.md +36 -0
- package/exporter/shared/npm-modules/brush.ts +34 -0
- package/exporter/shared/npm-modules/find-up-simple.ts +100 -0
- package/exporter/shared/npm-modules/pkg-dir.ts +17 -0
- package/exporter/shared/npm-modules/xml-parser.ts +57 -0
- package/exporter/{types → shared/types}/api.ts +40 -41
- package/exporter/{types → shared/types}/global.ts +17 -21
- package/exporter/{types → shared/types}/navigation.ts +3 -3
- package/exporter/{types → shared/types}/pages.ts +10 -11
- package/exporter/shared/types/render.ts +63 -0
- package/exporter/{types → shared/types}/sites.ts +18 -19
- package/exporter/shared/types.ts +15 -0
- package/exporter/ssg-adapters/gatsby/actions/clean.ts +26 -0
- package/exporter/ssg-adapters/gatsby/actions/close.ts +17 -0
- package/exporter/ssg-adapters/gatsby/actions/data.ts +22 -0
- package/exporter/ssg-adapters/gatsby/actions/healthCheck.ts +10 -0
- package/exporter/ssg-adapters/gatsby/actions/init.ts +12 -0
- package/exporter/ssg-adapters/gatsby/actions/logs.ts +10 -0
- package/exporter/ssg-adapters/gatsby/actions/meta.ts +13 -0
- package/exporter/ssg-adapters/gatsby/actions/prepare.ts +9 -0
- package/exporter/ssg-adapters/gatsby/actions/relocation.ts +15 -0
- package/exporter/ssg-adapters/gatsby/actions/restore.ts +21 -0
- package/exporter/ssg-adapters/gatsby/actions/ssg.ts +12 -0
- package/exporter/ssg-adapters/gatsby/actions/sync.ts +65 -0
- package/exporter/ssg-adapters/gatsby/index.ts +114 -0
- package/exporter/ssg-adapters/gatsby/shared/artifacts.ts +17 -0
- package/exporter/ssg-adapters/gatsby/shared/diff-assets.ts +128 -0
- package/exporter/ssg-adapters/gatsby/shared/extract-assets.ts +75 -0
- package/exporter/ssg-adapters/gatsby/shared/gatsby-build.ts +58 -0
- package/exporter/ssg-adapters/gatsby/shared/render-rollback.ts +33 -0
- package/exporter/ssg-adapters/gatsby/shared/sync-render.ts +298 -0
- package/exporter/ssg-adapters/gatsby/shared/types.ts +35 -0
- package/gatsby-browser.tsx +41 -58
- package/gatsby-config.ts +10 -17
- package/gatsby-node.ts +20 -79
- package/gatsby-ssr.tsx +2 -1
- package/package.json +41 -80
- package/plugins/gatsby-plugin-svgr-loader/gatsby-node.js +55 -0
- package/plugins/gatsby-plugin-svgr-loader/package.json +8 -0
- package/src/components/Head.tsx +28 -73
- package/src/components/template.tsx +6 -29
- package/src/gatsby-node-utils.ts +76 -2
- package/src/html.tsx +2 -11
- package/src/types.ts +3 -3
- package/tsconfig.commands.json +36 -0
- package/tsconfig.exporter.json +21 -0
- package/tsconfig.json +5 -3
- package/build/adapters/gatsby/index.d.ts +0 -4
- package/build/adapters/gatsby/utils.d.ts +0 -22
- package/build/artifacts/index.d.ts +0 -6
- package/build/constants/envs.d.ts +0 -37
- package/build/constants/index.d.ts +0 -57
- package/build/end-render.js +0 -74
- package/build/end-render.js.map +0 -7
- package/build/errors/index.d.ts +0 -15
- package/build/index.js.map +0 -7
- package/build/prepare-domains-render.js +0 -73
- package/build/prepare-domains-render.js.map +0 -7
- package/build/react/Favicon/index.d.ts +0 -5
- package/build/registers/api.d.ts +0 -9
- package/build/registers/gatsby.d.ts +0 -9
- package/build/registers/index.d.ts +0 -3
- package/build/reset-render.js +0 -74
- package/build/reset-render.js.map +0 -7
- package/build/services/register.d.ts +0 -36
- package/build/services/settings.d.ts +0 -4
- package/build/start-render.js +0 -100
- package/build/start-render.js.map +0 -7
- package/build/upload-search-content.js +0 -74
- package/build/upload-search-content.js.map +0 -7
- package/build/utils/alerts.d.ts +0 -3
- package/build/utils/cache.d.ts +0 -35
- package/build/utils/core-utils.d.ts +0 -107
- package/build/utils/create-build-data.d.ts +0 -8
- package/build/utils/domains.d.ts +0 -13
- package/build/utils/folders.d.ts +0 -53
- package/build/utils/loggin.d.ts +0 -51
- package/build/utils/render.d.ts +0 -13
- package/build/utils/searches.d.ts +0 -15
- package/build/utils/sites.d.ts +0 -31
- package/build/utils/store.d.ts +0 -81
- package/cx.config.d.ts +0 -5
- package/cx.config.js +0 -36
- package/exporter/adapters/gatsby/index.ts +0 -162
- package/exporter/adapters/gatsby/utils.ts +0 -161
- package/exporter/artifacts/README.md +0 -34
- package/exporter/artifacts/index.ts +0 -33
- package/exporter/commands/move-assets.ts +0 -11
- package/exporter/constants/envs.ts +0 -94
- package/exporter/constants/index.ts +0 -129
- package/exporter/errors/index.ts +0 -40
- package/exporter/registers/api.ts +0 -14
- package/exporter/registers/gatsby.ts +0 -14
- package/exporter/registers/index.ts +0 -4
- package/exporter/services/register.ts +0 -113
- package/exporter/services/settings.ts +0 -17
- package/exporter/utils/alerts.ts +0 -29
- package/exporter/utils/api.ts +0 -243
- package/exporter/utils/cache.ts +0 -142
- package/exporter/utils/core-utils.ts +0 -458
- package/exporter/utils/create-build-data.ts +0 -17
- package/exporter/utils/domains.ts +0 -39
- package/exporter/utils/folders.ts +0 -320
- package/exporter/utils/health-checks.ts +0 -64
- package/exporter/utils/loggin.ts +0 -184
- package/exporter/utils/render.ts +0 -71
- package/exporter/utils/searches.ts +0 -156
- package/exporter/utils/sites.ts +0 -312
- package/exporter/utils/store.ts +0 -314
- package/src/README.md +0 -7
- package/start-render.js +0 -7
- /package/build/commands/{move-assets.d.ts → prepare-assets-directory.d.ts} +0 -0
- /package/build/{utils → core}/images.d.ts +0 -0
- /package/build/{utils → core}/instance.d.ts +0 -0
- /package/build/react/{Favicon → GriddoFavicon}/utils.d.ts +0 -0
- /package/build/{constants → shared}/endpoints.d.ts +0 -0
- /package/build/{types → shared/types}/templates.d.ts +0 -0
- /package/exporter/react/{Favicon → GriddoFavicon}/utils.ts +0 -0
- /package/exporter/{types → shared/types}/templates.ts +0 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import type { RenderModeTuple } from "../shared/types/render";
|
|
2
|
+
|
|
3
|
+
import { execSync } from "node:child_process";
|
|
4
|
+
import fsp from "node:fs/promises";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
|
|
7
|
+
import { readDB, writeDB } from "../core/db";
|
|
8
|
+
import { throwError } from "../core/errors";
|
|
9
|
+
import { pathExists } from "../core/fs";
|
|
10
|
+
import { GriddoLog } from "../core/GriddoLog";
|
|
11
|
+
import { RenderUUIDError } from "../shared/errors";
|
|
12
|
+
import { brush } from "../shared/npm-modules/brush";
|
|
13
|
+
import { RENDER_MODE } from "../shared/types/render";
|
|
14
|
+
import { AuthService } from "./auth";
|
|
15
|
+
import { getBuildMetadata } from "./manage-store";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Creates a sentinel file with the current date and time.
|
|
19
|
+
* This file is used to track later if node_modules/@griddo/cx was cleaned by a
|
|
20
|
+
* npm install coming from a deploy.
|
|
21
|
+
*/
|
|
22
|
+
async function markRenderAsStarted(options: { domain: string; basePath: string }) {
|
|
23
|
+
const { domain } = options;
|
|
24
|
+
|
|
25
|
+
const db = await readDB();
|
|
26
|
+
db.domains[domain].isRendering = true;
|
|
27
|
+
await writeDB(db);
|
|
28
|
+
|
|
29
|
+
// Creamos un archivo centinela, si al terminar el render este archivo no
|
|
30
|
+
// existe es que ha habido un deploy por medio y hay que invalidar el render
|
|
31
|
+
const { __ssg } = await getRenderPathsHydratedWithDomainFromDB();
|
|
32
|
+
|
|
33
|
+
const renderSentinelFile = path.join(__ssg, `.render-sentinel-${domain}`);
|
|
34
|
+
await fsp.writeFile(renderSentinelFile, new Date().toISOString());
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async function markRenderAsCompleted(domain: string) {
|
|
38
|
+
const db = await readDB();
|
|
39
|
+
db.domains[domain].isRendering = false;
|
|
40
|
+
db.currentRenderingDomain = null;
|
|
41
|
+
db.domains[domain].renderMode = RENDER_MODE.COMPLETED;
|
|
42
|
+
// db.domains[domain].shouldBeRendered = false;
|
|
43
|
+
await writeDB(db);
|
|
44
|
+
|
|
45
|
+
// Borramos finalmente el archivo centinela
|
|
46
|
+
const { __ssg } = await getRenderPathsHydratedWithDomainFromDB();
|
|
47
|
+
const renderSentinelFile = path.join(__ssg, `.render-sentinel-${domain}`);
|
|
48
|
+
await fsp.unlink(renderSentinelFile);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async function assertRenderIsValid(domain: string) {
|
|
52
|
+
// Comprobamos que .render-sentinel exista, si no es que un deploy lo borro
|
|
53
|
+
// y hay que invalidar el render.
|
|
54
|
+
const { __ssg } = await getRenderPathsHydratedWithDomainFromDB();
|
|
55
|
+
const renderSentinelFile = path.join(__ssg, `.render-sentinel-${domain}`);
|
|
56
|
+
if (!(await pathExists(renderSentinelFile))) {
|
|
57
|
+
throwError(RenderUUIDError);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Determines the appropriate render mode for a given domain based on its current state,
|
|
63
|
+
* previous render errors, deployment status, and whether rendering is required.
|
|
64
|
+
*
|
|
65
|
+
* @param options - An object containing:
|
|
66
|
+
* - `domain`: The domain name to resolve the render mode for.
|
|
67
|
+
* - `shouldBeRendered`: A boolean indicating if the domain should be rendered.
|
|
68
|
+
* @returns An object with:
|
|
69
|
+
* - `renderMode`: The resolved render mode (`FROM_SCRATCH`, `INCREMENTAL`, or `IDLE`).
|
|
70
|
+
* - `reason`: A string describing the reason for the chosen render mode.
|
|
71
|
+
*
|
|
72
|
+
* @remarks
|
|
73
|
+
* The function checks for missing exports, previous render errors, new deployments,
|
|
74
|
+
* and whether rendering is necessary to decide the render mode.
|
|
75
|
+
*
|
|
76
|
+
* @todo
|
|
77
|
+
* Improve ifs and reason concatenations...
|
|
78
|
+
*/
|
|
79
|
+
async function resolveDomainRenderMode(options: { domain: string; shouldBeRendered: boolean }) {
|
|
80
|
+
const { domain, shouldBeRendered } = options;
|
|
81
|
+
|
|
82
|
+
const db = await readDB();
|
|
83
|
+
|
|
84
|
+
const { __cache, __exports } = await getRenderPathsHydratedWithDomainFromDB({ domain });
|
|
85
|
+
const exportsAreMissing = !(await pathExists(path.join(__exports)));
|
|
86
|
+
const previousRenderFailed = db.domains[domain]?.isRendering;
|
|
87
|
+
const newDeployDetected = await hasNewCommit(__cache);
|
|
88
|
+
|
|
89
|
+
if (exportsAreMissing) {
|
|
90
|
+
return {
|
|
91
|
+
renderMode: RENDER_MODE.FROM_SCRATCH,
|
|
92
|
+
reason: "missing exports directory",
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (previousRenderFailed) {
|
|
97
|
+
return {
|
|
98
|
+
renderMode: RENDER_MODE.FROM_SCRATCH,
|
|
99
|
+
reason: "error in previous render",
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (newDeployDetected) {
|
|
104
|
+
return {
|
|
105
|
+
renderMode: RENDER_MODE.FROM_SCRATCH,
|
|
106
|
+
reason: "new commit hash",
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (!shouldBeRendered) {
|
|
111
|
+
return {
|
|
112
|
+
renderMode: RENDER_MODE.IDLE,
|
|
113
|
+
reason: "no activity",
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
renderMode: RENDER_MODE.INCREMENTAL,
|
|
119
|
+
reason: "has changes",
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async function hasNewCommit(basePath: string): Promise<boolean> {
|
|
124
|
+
const commitFile = path.join(basePath, "commit");
|
|
125
|
+
const currentCommit = execSync("git rev-parse HEAD").toString().trim();
|
|
126
|
+
|
|
127
|
+
if (await pathExists(commitFile)) {
|
|
128
|
+
const savedCommit = (await fsp.readFile(commitFile, "utf-8")).trim();
|
|
129
|
+
if (savedCommit === currentCommit) {
|
|
130
|
+
return false; // No hay nuevo commit
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
async function updateCommitFile(options: { basePath: string }) {
|
|
140
|
+
const { basePath } = options;
|
|
141
|
+
const currentCommit = execSync("git rev-parse HEAD").toString().trim();
|
|
142
|
+
await fsp.writeFile(path.join(basePath, "commit"), currentCommit);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
async function getRenderModeFromDB(domain: string): Promise<RenderModeTuple> {
|
|
146
|
+
const db = await readDB();
|
|
147
|
+
|
|
148
|
+
if (!db.domains[domain]) {
|
|
149
|
+
throw new Error(brush.red(`[!] Error: Domain ${domain} not found in DB`));
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (!db.domains[domain].renderMode) {
|
|
153
|
+
throw new Error(brush.red(`[!] Error: Render mode not found for domain ${domain}`));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return {
|
|
157
|
+
renderMode: db.domains[domain].renderMode,
|
|
158
|
+
reason: db.domains[domain].renderModeReason,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
async function getRenderPathsHydratedWithDomainFromDB(options?: {
|
|
163
|
+
domain?: string;
|
|
164
|
+
dbFilePath?: string;
|
|
165
|
+
}) {
|
|
166
|
+
const { domain, dbFilePath } = options || {};
|
|
167
|
+
|
|
168
|
+
const db = await readDB(dbFilePath);
|
|
169
|
+
const paths = db.paths;
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
__root: paths.root,
|
|
173
|
+
__cache: path.join(paths.cxCache, domain || ""),
|
|
174
|
+
__components: paths.components,
|
|
175
|
+
__cx: paths.cx,
|
|
176
|
+
__sites: paths.exportsDir,
|
|
177
|
+
__exports: path.join(paths.exportsDir, domain || ""),
|
|
178
|
+
__exports_backup: path.join(paths.exportsDirBackup, domain || ""),
|
|
179
|
+
__ssg: paths.ssg,
|
|
180
|
+
__exports_dist: path.join(paths.exportsDir, domain || "", "dist"),
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
async function getRenderMetadataFromDB() {
|
|
185
|
+
const db = await readDB();
|
|
186
|
+
return {
|
|
187
|
+
griddoVersion: db.griddoVersion,
|
|
188
|
+
buildReportFileName: db.buildReportFileName,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Save a file with the end of build process to use as `end-render` signal.
|
|
194
|
+
*/
|
|
195
|
+
async function generateBuildReport(domain: string) {
|
|
196
|
+
const authControl = await AuthService.login();
|
|
197
|
+
|
|
198
|
+
const { __root } = await getRenderPathsHydratedWithDomainFromDB();
|
|
199
|
+
const { buildReportFileName } = await getRenderMetadataFromDB();
|
|
200
|
+
const { buildProcessData } = await getBuildMetadata(domain);
|
|
201
|
+
|
|
202
|
+
const buildSitesInfo = Object.keys(buildProcessData).map((siteID) => ({
|
|
203
|
+
...buildProcessData[siteID],
|
|
204
|
+
siteId: Number.parseInt(siteID),
|
|
205
|
+
}));
|
|
206
|
+
|
|
207
|
+
const report = {
|
|
208
|
+
authControl,
|
|
209
|
+
sites: buildSitesInfo,
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
const reportFilePath = path.join(__root, "current-dist", buildReportFileName);
|
|
213
|
+
|
|
214
|
+
await fsp.writeFile(reportFilePath, JSON.stringify(report));
|
|
215
|
+
|
|
216
|
+
GriddoLog.verbose(`build report saved in ${reportFilePath}`);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export {
|
|
220
|
+
assertRenderIsValid,
|
|
221
|
+
generateBuildReport,
|
|
222
|
+
getRenderMetadataFromDB,
|
|
223
|
+
getRenderModeFromDB,
|
|
224
|
+
getRenderPathsHydratedWithDomainFromDB,
|
|
225
|
+
markRenderAsCompleted,
|
|
226
|
+
markRenderAsStarted,
|
|
227
|
+
resolveDomainRenderMode,
|
|
228
|
+
updateCommitFile,
|
|
229
|
+
};
|
|
@@ -1,71 +1,43 @@
|
|
|
1
|
-
import type { Robots } from "../types/global";
|
|
1
|
+
import type { Robots } from "../shared/types/global";
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import fsp from "node:fs/promises";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
import { pathExists } from "../core/fs";
|
|
7
|
+
import { GriddoLog } from "../core/GriddoLog";
|
|
8
|
+
import { ROBOTS } from "../shared/endpoints";
|
|
9
|
+
import { get } from "./api";
|
|
10
|
+
import { getRenderPathsHydratedWithDomainFromDB } from "./render";
|
|
11
|
+
|
|
12
|
+
async function fetchRobots() {
|
|
13
|
+
const apiRobots = await get<Robots>({ endpoint: ROBOTS });
|
|
14
|
+
return (
|
|
15
|
+
apiRobots
|
|
16
|
+
?.filter((r) => !!r.path)
|
|
17
|
+
.map(({ path, content }) => ({
|
|
18
|
+
path,
|
|
19
|
+
content: content || "User-agent: *\n\r\n\rAllow: /",
|
|
20
|
+
})) || []
|
|
21
|
+
);
|
|
22
|
+
}
|
|
12
23
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
robots: Robots;
|
|
18
|
-
settings: Record<string, unknown>;
|
|
24
|
+
async function generateRobots(domain: string) {
|
|
25
|
+
const { __root } = await getRenderPathsHydratedWithDomainFromDB({ domain });
|
|
26
|
+
const distDirectory = path.join(__root, "current-dist");
|
|
27
|
+
const robot = (await fetchRobots()).find(({ path }) => path === `/${domain}`);
|
|
19
28
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
29
|
+
if (!robot) {
|
|
30
|
+
GriddoLog.info(`Robots not found for ${domain}`);
|
|
31
|
+
return;
|
|
23
32
|
}
|
|
24
33
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
this.robots =
|
|
32
|
-
apiRobots
|
|
33
|
-
?.filter((r) => !!r.path)
|
|
34
|
-
.map(({ path, content }) => ({
|
|
35
|
-
path,
|
|
36
|
-
content: content || "User-agent: *\n\r\n\rAllow: /",
|
|
37
|
-
})) || [];
|
|
38
|
-
} catch (e) {
|
|
39
|
-
console.warn(`${this.constructor.name}: ${(e as Error).message}`);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Write robots.txt files for the domain.
|
|
45
|
-
*/
|
|
46
|
-
async writeFiles(domain: string) {
|
|
47
|
-
const { __cx } = config.paths(domain);
|
|
48
|
-
const distDirectory = path.join(__cx, "dist");
|
|
49
|
-
|
|
50
|
-
await this.getRobots();
|
|
51
|
-
|
|
52
|
-
const robot = this.robots.find(({ path }) => path === `/${domain}`);
|
|
53
|
-
|
|
54
|
-
if (!robot) {
|
|
55
|
-
console.log(`Robots not found for ${domain}`);
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (fs.existsSync(distDirectory)) {
|
|
60
|
-
const fileLocation = path.join(distDirectory, "robots.txt");
|
|
61
|
-
fs.writeFileSync(fileLocation, robot?.content);
|
|
62
|
-
verboseLog(`wrote robots.txt to ${fileLocation}`);
|
|
63
|
-
} else {
|
|
64
|
-
console.log(`${distDirectory} not found`);
|
|
65
|
-
}
|
|
34
|
+
if (await pathExists(distDirectory)) {
|
|
35
|
+
const fileLocation = path.join(distDirectory, "robots.txt");
|
|
36
|
+
await fsp.writeFile(fileLocation, robot?.content);
|
|
37
|
+
GriddoLog.verbose(`wrote robots.txt to ${fileLocation}`);
|
|
38
|
+
} else {
|
|
39
|
+
GriddoLog.info(`${distDirectory} not found`);
|
|
66
40
|
}
|
|
67
41
|
}
|
|
68
42
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
export { robotsService as RobotsService };
|
|
43
|
+
export { generateRobots };
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import fsp from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
|
|
4
|
+
import { pathExists } from "../core/fs";
|
|
5
|
+
import { GriddoLog } from "../core/GriddoLog";
|
|
6
|
+
import { generateSitemapIndexXml, generateUrlsetXml } from "../shared/npm-modules/xml-parser";
|
|
7
|
+
import { AuthService } from "./auth";
|
|
8
|
+
import { getBuildMetadata } from "./manage-store";
|
|
9
|
+
import { getRenderPathsHydratedWithDomainFromDB } from "./render";
|
|
10
|
+
import { getSitemap } from "./sites";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Generate sitemaps and save them into file system.
|
|
14
|
+
*/
|
|
15
|
+
async function generateSitemaps(domain: string) {
|
|
16
|
+
const { __root } = await getRenderPathsHydratedWithDomainFromDB();
|
|
17
|
+
const { sitesToPublish } = await getBuildMetadata(domain);
|
|
18
|
+
const distDir = path.join(__root, "current-dist");
|
|
19
|
+
const templateSitemapPrefix = "sitemap-";
|
|
20
|
+
|
|
21
|
+
const isGriddoSitemapFile = (file: string) =>
|
|
22
|
+
file === "sitemap.xml" || (file.startsWith(templateSitemapPrefix) && file.endsWith(".xml"));
|
|
23
|
+
|
|
24
|
+
for (const site of sitesToPublish) {
|
|
25
|
+
const { id, languages } = site;
|
|
26
|
+
|
|
27
|
+
for (const lang of languages) {
|
|
28
|
+
// Local copy of headers to avoid mutating the shared object
|
|
29
|
+
const localHeaders: Record<string, string> = AuthService.headers
|
|
30
|
+
? { ...AuthService.headers }
|
|
31
|
+
: {};
|
|
32
|
+
localHeaders.lang = lang.id.toString();
|
|
33
|
+
|
|
34
|
+
const response = await getSitemap({ siteId: id, headers: localHeaders });
|
|
35
|
+
|
|
36
|
+
if (!response) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const { items: sitemapPagesGroup, url } = response;
|
|
41
|
+
const { home, domain } = url;
|
|
42
|
+
|
|
43
|
+
if (!home) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const domainLanguage = site.domains.find(
|
|
48
|
+
(domain) => Object.keys(domain)[0] === lang.id.toString(),
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
if (!domainLanguage) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const slug = Object.values(domainLanguage)[0];
|
|
56
|
+
const sitemaps: string[] = [];
|
|
57
|
+
const sitemapPageGroupKeys = Object.keys(sitemapPagesGroup);
|
|
58
|
+
const sitemapBasePath = path.join(distDir, slug.replace(domain, ""));
|
|
59
|
+
|
|
60
|
+
/** delete every griddo sitemap file before create the new ones */
|
|
61
|
+
if (await pathExists(sitemapBasePath)) {
|
|
62
|
+
try {
|
|
63
|
+
const files = await fsp.readdir(sitemapBasePath);
|
|
64
|
+
for (const file of files) {
|
|
65
|
+
if (isGriddoSitemapFile(file)) {
|
|
66
|
+
const filePath = path.join(sitemapBasePath, file);
|
|
67
|
+
try {
|
|
68
|
+
await fsp.rm(filePath);
|
|
69
|
+
} catch (err) {
|
|
70
|
+
GriddoLog.error(`Error deleting file ${filePath}:`, err);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
} catch (err) {
|
|
75
|
+
GriddoLog.error(`Error reading ${sitemapBasePath}:`, err);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
for (const templateId of sitemapPageGroupKeys) {
|
|
80
|
+
const sitemapPages = sitemapPagesGroup[templateId];
|
|
81
|
+
|
|
82
|
+
if (!sitemapPages.length) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const siteMap = generateUrlsetXml(sitemapPages);
|
|
87
|
+
|
|
88
|
+
const sitemapName = `/${templateSitemapPrefix}${templateId.toLowerCase()}.xml`;
|
|
89
|
+
const exactPath = path.join(sitemapBasePath, sitemapName);
|
|
90
|
+
|
|
91
|
+
await saveFile(exactPath, siteMap);
|
|
92
|
+
GriddoLog.verbose(`sitemap generated in ${exactPath}`);
|
|
93
|
+
|
|
94
|
+
sitemaps.push(`${home.endsWith("/") ? home.slice(0, -1) : home}${sitemapName}`);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (!sitemaps.length) {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const siteMap = generateSitemapIndexXml(sitemaps);
|
|
102
|
+
|
|
103
|
+
const exactPath = path.join(sitemapBasePath, "sitemap.xml");
|
|
104
|
+
|
|
105
|
+
await saveFile(exactPath, siteMap);
|
|
106
|
+
GriddoLog.verbose(`sitemap generated in ${exactPath}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Saves the content to a file specified by its path. If the file exists, it will be overwritten.
|
|
113
|
+
*
|
|
114
|
+
* @param filePath The path of the file to save the content to.
|
|
115
|
+
* @param content The content to save to the file.
|
|
116
|
+
*/
|
|
117
|
+
async function saveFile(filePath: string, content: string) {
|
|
118
|
+
try {
|
|
119
|
+
const pathName = path.dirname(filePath);
|
|
120
|
+
if (!(await pathExists(pathName))) {
|
|
121
|
+
await fsp.mkdir(pathName, { recursive: true });
|
|
122
|
+
}
|
|
123
|
+
await fsp.writeFile(filePath, content);
|
|
124
|
+
} catch (_error) {
|
|
125
|
+
throw new Error(`Error saving a file`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export { generateSitemaps };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Core } from "@griddo/core";
|
|
1
2
|
import type {
|
|
2
3
|
AllSitesReponse,
|
|
3
4
|
EndPageInfoResponse,
|
|
@@ -9,19 +10,28 @@ import type {
|
|
|
9
10
|
SitemapAPIResponse,
|
|
10
11
|
SocialsResponse,
|
|
11
12
|
StartPageRenderResponse,
|
|
12
|
-
} from "../types/api";
|
|
13
|
-
import type { Site } from "../types/sites";
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
} from "../shared/types/api";
|
|
14
|
+
import type { Site } from "../shared/types/sites";
|
|
15
|
+
|
|
16
|
+
import {
|
|
17
|
+
BUILD_END,
|
|
18
|
+
BUILD_START,
|
|
19
|
+
GET_ALL,
|
|
20
|
+
GET_PAGE,
|
|
21
|
+
GET_REFERENCE_FIELD_DATA,
|
|
22
|
+
GET_SITEMAP,
|
|
23
|
+
INFO,
|
|
24
|
+
LANGUAGES,
|
|
25
|
+
SOCIALS,
|
|
26
|
+
} from "../shared/endpoints";
|
|
27
|
+
import { get, post } from "./api";
|
|
18
28
|
|
|
19
29
|
/**
|
|
20
30
|
* Get a list of site objects.
|
|
21
31
|
*/
|
|
22
32
|
async function getAllSites(domain: string) {
|
|
23
|
-
return
|
|
24
|
-
endpoint: `${
|
|
33
|
+
return get<AllSitesReponse>({
|
|
34
|
+
endpoint: `${GET_ALL}?domainSlug=${domain}`,
|
|
25
35
|
});
|
|
26
36
|
}
|
|
27
37
|
|
|
@@ -29,7 +39,7 @@ async function getAllSites(domain: string) {
|
|
|
29
39
|
* Get a list of site objects from a domain.
|
|
30
40
|
*/
|
|
31
41
|
async function getAllSitesFromDomain(domain: string) {
|
|
32
|
-
const allSites = await get<AllSitesReponse>({ endpoint:
|
|
42
|
+
const allSites = await get<AllSitesReponse>({ endpoint: GET_ALL });
|
|
33
43
|
|
|
34
44
|
if (allSites.length) {
|
|
35
45
|
for (const site of allSites) {
|
|
@@ -40,8 +50,7 @@ async function getAllSitesFromDomain(domain: string) {
|
|
|
40
50
|
site.domains = items
|
|
41
51
|
.filter(
|
|
42
52
|
(item) =>
|
|
43
|
-
item.domain &&
|
|
44
|
-
(item.domain.slug === domain || item.domain.slug === `/${domain}`),
|
|
53
|
+
item.domain && (item.domain.slug === domain || item.domain.slug === `/${domain}`),
|
|
45
54
|
)
|
|
46
55
|
.map((item) => ({ [item.id]: `${item.domain.slug}${item.path}` }));
|
|
47
56
|
}
|
|
@@ -54,8 +63,8 @@ async function getAllSitesFromDomain(domain: string) {
|
|
|
54
63
|
* Fetch a page object from API.
|
|
55
64
|
*/
|
|
56
65
|
async function getPage(id: number, cacheKey: string) {
|
|
57
|
-
return
|
|
58
|
-
endpoint: `${
|
|
66
|
+
return get<PageResponse>({
|
|
67
|
+
endpoint: `${GET_PAGE}/${id}`,
|
|
59
68
|
cacheKey,
|
|
60
69
|
});
|
|
61
70
|
}
|
|
@@ -64,27 +73,27 @@ async function getPage(id: number, cacheKey: string) {
|
|
|
64
73
|
* Get site info
|
|
65
74
|
*/
|
|
66
75
|
async function getSiteInfo(id: number, cacheKey = "") {
|
|
67
|
-
const [prefix, suffix] =
|
|
76
|
+
const [prefix, suffix] = INFO;
|
|
68
77
|
|
|
69
|
-
return
|
|
78
|
+
return get<Site>({
|
|
70
79
|
endpoint: `${prefix}${id}${suffix}`,
|
|
71
80
|
cacheKey,
|
|
72
81
|
});
|
|
73
82
|
}
|
|
74
83
|
|
|
75
84
|
async function getSiteLanguages(id: number, cacheKey = "") {
|
|
76
|
-
const [prefix, suffix] =
|
|
85
|
+
const [prefix, suffix] = LANGUAGES;
|
|
77
86
|
|
|
78
|
-
return
|
|
87
|
+
return get<LanguagesResponse>({
|
|
79
88
|
endpoint: `${prefix}${id}${suffix}`,
|
|
80
89
|
cacheKey,
|
|
81
90
|
});
|
|
82
91
|
}
|
|
83
92
|
|
|
84
93
|
async function startSiteRender(id: number) {
|
|
85
|
-
const [prefix, suffix] =
|
|
94
|
+
const [prefix, suffix] = BUILD_START;
|
|
86
95
|
|
|
87
|
-
return
|
|
96
|
+
return get<StartPageRenderResponse>({
|
|
88
97
|
endpoint: `${prefix}${id}${suffix}`,
|
|
89
98
|
});
|
|
90
99
|
}
|
|
@@ -93,12 +102,13 @@ async function startSiteRender(id: number) {
|
|
|
93
102
|
* Send the end signal to API for a render site.
|
|
94
103
|
*/
|
|
95
104
|
async function endSiteRender(id: number, body: EndSiteRenderBody) {
|
|
96
|
-
const [prefix, suffix] =
|
|
105
|
+
const [prefix, suffix] = BUILD_END;
|
|
97
106
|
|
|
98
|
-
|
|
107
|
+
await post<EndPageInfoResponse>({
|
|
99
108
|
endpoint: `${prefix}${id}${suffix}`,
|
|
100
109
|
body,
|
|
101
110
|
useApiCacheDir: false,
|
|
111
|
+
logToFile: false,
|
|
102
112
|
});
|
|
103
113
|
}
|
|
104
114
|
|
|
@@ -109,11 +119,11 @@ async function getReferenceFieldSiteData(
|
|
|
109
119
|
dataSiteId?: number,
|
|
110
120
|
dataLangID?: number,
|
|
111
121
|
) {
|
|
112
|
-
const [prefix, suffix] =
|
|
122
|
+
const [prefix, suffix] = GET_REFERENCE_FIELD_DATA;
|
|
113
123
|
const site = dataSiteId || page.site;
|
|
114
124
|
const lang = dataLangID || page.language;
|
|
115
125
|
|
|
116
|
-
return
|
|
126
|
+
return post<ReferenceFieldResponse>({
|
|
117
127
|
endpoint: `${prefix}${site}${suffix}`,
|
|
118
128
|
body,
|
|
119
129
|
headers: { lang },
|
|
@@ -121,18 +131,20 @@ async function getReferenceFieldSiteData(
|
|
|
121
131
|
});
|
|
122
132
|
}
|
|
123
133
|
|
|
124
|
-
async function getSitemap(
|
|
125
|
-
const
|
|
134
|
+
async function getSitemap(options: { siteId: number; headers?: Record<string, string> }) {
|
|
135
|
+
const { siteId, headers } = options;
|
|
136
|
+
const [prefix, suffix] = GET_SITEMAP;
|
|
126
137
|
|
|
127
138
|
return get<SitemapAPIResponse>({
|
|
128
|
-
endpoint: `${prefix}${
|
|
139
|
+
endpoint: `${prefix}${siteId}${suffix}`,
|
|
140
|
+
headers,
|
|
129
141
|
});
|
|
130
142
|
}
|
|
131
143
|
|
|
132
144
|
async function getSiteSocials(id: number, cacheKey = "") {
|
|
133
|
-
const [prefix, suffix] =
|
|
145
|
+
const [prefix, suffix] = SOCIALS;
|
|
134
146
|
|
|
135
|
-
return
|
|
147
|
+
return get<SocialsResponse>({
|
|
136
148
|
endpoint: `${prefix}${id}${suffix}`,
|
|
137
149
|
cacheKey,
|
|
138
150
|
});
|