@griddo/cx 11.11.8-rc.1 → 11.12.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.
Files changed (54) hide show
  1. package/build/commands/end-render.js +5 -5
  2. package/build/commands/end-render.js.map +4 -4
  3. package/build/commands/prepare-assets-directory.js +3 -3
  4. package/build/commands/prepare-assets-directory.js.map +4 -4
  5. package/build/commands/prepare-domains-render.js +9 -9
  6. package/build/commands/prepare-domains-render.js.map +4 -4
  7. package/build/commands/reset-render.js +8 -8
  8. package/build/commands/reset-render.js.map +4 -4
  9. package/build/commands/start-render.js +35 -33
  10. package/build/commands/start-render.js.map +4 -4
  11. package/build/commands/upload-search-content.js +6 -6
  12. package/build/commands/upload-search-content.js.map +4 -4
  13. package/build/core/paths.d.ts +2 -0
  14. package/build/index.js +25 -23
  15. package/build/services/generate-md.d.ts +8 -0
  16. package/build/services/llms.d.ts +2 -2
  17. package/build/shared/brush.d.ts +6 -0
  18. package/build/shared/context.d.ts +1 -0
  19. package/build/shared/envs.d.ts +2 -1
  20. package/build/shared/load-config.d.ts +16 -0
  21. package/build/ssg-adapters/gatsby/actions/index.d.ts +2 -0
  22. package/build/ssg-adapters/gatsby/actions/llms.d.ts +2 -0
  23. package/build/ssg-adapters/gatsby/shared/extract-assets.d.ts +4 -1
  24. package/cli.mjs +8 -0
  25. package/exporter/build.sh +4 -5
  26. package/exporter/core/GriddoLog.ts +1 -1
  27. package/exporter/core/check-env-health.ts +1 -1
  28. package/exporter/core/errors.ts +1 -1
  29. package/exporter/core/life-cycle.ts +1 -1
  30. package/exporter/core/paths.ts +3 -0
  31. package/exporter/core/print-logos.ts +1 -1
  32. package/exporter/services/api.ts +1 -1
  33. package/exporter/services/generate-md.ts +151 -0
  34. package/exporter/services/llms.ts +16 -12
  35. package/exporter/services/render.ts +1 -1
  36. package/exporter/services/store.ts +1 -1
  37. package/exporter/shared/brush.ts +30 -0
  38. package/exporter/shared/context.ts +1 -0
  39. package/exporter/shared/envs.ts +2 -0
  40. package/exporter/shared/load-config.ts +164 -0
  41. package/exporter/shared/npm-modules/README.md +0 -1
  42. package/exporter/ssg-adapters/gatsby/actions/index.ts +2 -0
  43. package/exporter/ssg-adapters/gatsby/actions/llms.ts +11 -0
  44. package/exporter/ssg-adapters/gatsby/actions/meta.ts +0 -2
  45. package/exporter/ssg-adapters/gatsby/actions/relocation.ts +5 -3
  46. package/exporter/ssg-adapters/gatsby/actions/sync.ts +5 -3
  47. package/exporter/ssg-adapters/gatsby/index.ts +2 -3
  48. package/exporter/ssg-adapters/gatsby/shared/extract-assets.ts +16 -21
  49. package/exporter/ssg-adapters/gatsby/shared/sync-render.ts +37 -10
  50. package/package.json +6 -4
  51. package/tsconfig.exporter.json +2 -2
  52. package/build/shared/npm-modules/brush.d.ts +0 -18
  53. package/exporter/commands/generate-md.noop +0 -109
  54. package/exporter/shared/npm-modules/brush.ts +0 -39
@@ -1,6 +1,5 @@
1
1
  import type { RenderContext } from "@shared/context";
2
2
 
3
- import { generateLLMs } from "@services/llms";
4
3
  import { generateRobots } from "@services/robots";
5
4
  import { generateSitemaps } from "@services/sitemaps";
6
5
 
@@ -9,5 +8,4 @@ export async function metaAction(context: RenderContext) {
9
8
 
10
9
  await generateSitemaps(domain);
11
10
  await generateRobots(domain);
12
- await generateLLMs(domain);
13
11
  }
@@ -8,8 +8,10 @@ export async function relocationAction(context: RenderContext) {
8
8
  pathsHydratedWithDomain: { __root, __ssg },
9
9
  } = context;
10
10
 
11
- const src = path.join(__ssg, "public");
12
- const dst = path.join(__root, "current-dist");
11
+ const gatsbyWorkingDir = path.join(__ssg, "public");
12
+ const workingDistDir = path.join(__root, "current-dist");
13
13
 
14
- await fsp.rename(src, dst);
14
+ context.workingDistDir = workingDistDir;
15
+
16
+ await fsp.rename(gatsbyWorkingDir, workingDistDir);
15
17
  }
@@ -25,8 +25,10 @@ export async function syncAction(context: RenderContext<SSG>) {
25
25
  const previousDist = path.join(__exports, "dist");
26
26
 
27
27
  // caching...
28
- await mvDirs(__root, __cache, renderArtifacts.cacheables, { override: true });
29
- await mvDirs(__ssg, __cache, ssgArtifacts.cacheables, { override: true });
28
+ await Promise.all([
29
+ mvDirs(__root, __cache, renderArtifacts.cacheables, { override: true }),
30
+ mvDirs(__ssg, __cache, ssgArtifacts.cacheables, { override: true }),
31
+ ]);
30
32
 
31
33
  if (renderMode === RENDER_MODE.FROM_SCRATCH) {
32
34
  await deleteDisposableSiteDirs(currentDist);
@@ -57,7 +59,7 @@ export async function syncAction(context: RenderContext<SSG>) {
57
59
 
58
60
  if (needsAssetPrefix) {
59
61
  // TODO: Mejorar performance
60
- await extractAssetsFromDist(domain);
62
+ await extractAssetsFromDist(domain, { root: __root, exports: __exports });
61
63
  }
62
64
 
63
65
  // rsync assets
@@ -109,10 +109,9 @@ export async function gatsbyRenderDomain(domain: string) {
109
109
 
110
110
  await doLifeCycle("Data", async () => actions.data(context));
111
111
  await doLifeCycle("SSG", async () => actions.ssg(context), { skip: isDryRender });
112
- await doLifeCycle("Relocation", async () => actions.relocation(context), {
113
- skip: isDryRender,
114
- });
112
+ await doLifeCycle("Relocation", async () => actions.relocation(context), { skip: isDryRender });
115
113
  await doLifeCycle("Meta", async () => actions.meta(context), { skip: isDryRender });
114
+ await doLifeCycle("LLMS", async () => actions.llms(context), { skip: isDryRender });
116
115
  await doLifeCycle("Report", async () => actions.report(context));
117
116
  await doLifeCycle("DryRunSync", async () => actions.dryRenderSync(context), {
118
117
  skip: isWetRender,
@@ -2,18 +2,17 @@ import fsp from "node:fs/promises";
2
2
  import path from "node:path";
3
3
 
4
4
  import { pathExists } from "../../../core/fs";
5
- import { getRenderPathsHydratedWithDomainFromDB } from "../../../services/render";
6
5
 
7
6
  /**
8
7
  * Update the Griddo's `/dist` dir with the contents from `public` dir only
9
8
  * with files of type: js, json and css.
10
9
  * TODO: Explicar que el static se copia a assets porque el js va en el subdominio de assets.
11
10
  */
12
- async function extractAssetsFromDist(domain: string) {
13
- const { __root, __exports } = await getRenderPathsHydratedWithDomainFromDB({ domain });
11
+ async function extractAssetsFromDist(domain: string, dirs: { root: string; exports: string }) {
12
+ const { exports, root } = dirs;
14
13
 
15
14
  // Archivos (no carpetas) válidos de public
16
- const filesFromDist = (await fsp.readdir(path.join(__exports, "dist"))).filter(
15
+ const filesFromDist = (await fsp.readdir(path.join(exports, "dist"))).filter(
17
16
  (file) =>
18
17
  path.extname(file) === ".js" ||
19
18
  path.extname(file) === ".json" ||
@@ -21,35 +20,31 @@ async function extractAssetsFromDist(domain: string) {
21
20
  );
22
21
 
23
22
  // Creamos assets si es necesario (needsAssetPrefix)
24
- await fsp.mkdir(path.join(__root, "assets"), { recursive: true });
23
+ await fsp.mkdir(path.join(root, "assets"), { recursive: true });
25
24
  // page-data folder
26
- await fsp.cp(
27
- path.join(__exports, "dist", "page-data"),
28
- path.join(__root, "assets", "page-data"),
29
- {
30
- preserveTimestamps: true,
31
- recursive: true,
32
- },
33
- );
25
+ await fsp.cp(path.join(exports, "dist", "page-data"), path.join(root, "assets", "page-data"), {
26
+ preserveTimestamps: true,
27
+ recursive: true,
28
+ });
34
29
  // static folder si existe
35
- if (await pathExists(path.join(__root, "static"))) {
36
- await fsp.cp(path.join(__root, "static"), path.join(__root, "assets"), {
30
+ if (await pathExists(path.join(root, "static"))) {
31
+ await fsp.cp(path.join(root, "static"), path.join(root, "assets"), {
37
32
  force: false,
38
33
  preserveTimestamps: true,
39
34
  recursive: true,
40
35
  });
41
36
  }
42
37
  // dist/static -> assets/static
43
- if (await pathExists(path.join(__exports, "dist", "static"))) {
44
- await fsp.cp(path.join(__exports, "dist", "static"), path.join(__root, "assets", "static"), {
38
+ if (await pathExists(path.join(exports, "dist", "static"))) {
39
+ await fsp.cp(path.join(exports, "dist", "static"), path.join(root, "assets", "static"), {
45
40
  force: false,
46
41
  preserveTimestamps: true,
47
42
  recursive: true,
48
43
  });
49
44
  }
50
45
  // otro static...
51
- if (await pathExists(path.join(__root, "static"))) {
52
- await fsp.cp(path.join(__root, "static"), path.join(__exports, "dist", domain), {
46
+ if (await pathExists(path.join(root, "static"))) {
47
+ await fsp.cp(path.join(root, "static"), path.join(exports, "dist", domain), {
53
48
  preserveTimestamps: true,
54
49
  recursive: true,
55
50
  force: false,
@@ -64,8 +59,8 @@ async function extractAssetsFromDist(domain: string) {
64
59
  // }
65
60
 
66
61
  const arraysOfPromises: Promise<void>[] = filesFromDist.map((file) => {
67
- const fileSrc = path.join(__exports, "dist", file);
68
- const fileDest = path.join(__root, "assets", file);
62
+ const fileSrc = path.join(exports, "dist", file);
63
+ const fileDest = path.join(root, "assets", file);
69
64
  return fsp.cp(fileSrc, fileDest, { preserveTimestamps: true, recursive: true });
70
65
  });
71
66
 
@@ -3,9 +3,10 @@ import path from "node:path";
3
3
 
4
4
  import pLimit from "p-limit";
5
5
 
6
- import { findFilesBySuffix } from "../../../core/fs";
6
+ import { findFilesBySuffix, pathExists } from "../../../core/fs";
7
7
  import { GriddoLog } from "../../../core/GriddoLog";
8
8
  import { addLogToBuffer } from "../../../core/logger";
9
+ import { removeTrailingSlash } from "../../../core/paths";
9
10
  import { GRIDDO_SSG_BUNDLE_ANALYZER } from "../../../shared/envs";
10
11
  import { getAssetsDiffBetweenRenders, patchHtmlFile } from "./diff-assets";
11
12
 
@@ -21,16 +22,19 @@ interface CopyFilePath {
21
22
  to: string;
22
23
  }
23
24
  interface SyncState {
25
+ mdToAdd: CopyFilePath[];
24
26
  htmlToAdd: CopyFilePath[];
25
27
  jsonToAdd: CopyFilePath[];
26
28
  htmlToDelete: string[];
27
29
  jsonToDelete: string[];
30
+ mdToDelete: string[];
28
31
  }
29
32
  interface PageInfo {
30
33
  id: number;
31
34
  composePath: string; // p.ej. '/about-us' o '/'
32
35
  htmlPath: string; // p.ej. '/path/to/public/about-us/index.html'
33
36
  jsonPath: string; // p.ej. '/path/to/public/page-data/about-us/page-data.json'
37
+ mdPath: string; // p.ej. '/path/to/public/about-us.md'
34
38
  }
35
39
  interface GatsbyPageData {
36
40
  result: {
@@ -56,10 +60,12 @@ class SyncRender {
56
60
  private assetArtifacts: string[];
57
61
 
58
62
  private state: SyncState = {
63
+ mdToAdd: [],
59
64
  htmlToAdd: [],
60
65
  jsonToAdd: [],
61
66
  htmlToDelete: [],
62
67
  jsonToDelete: [],
68
+ mdToDelete: [],
63
69
  };
64
70
 
65
71
  constructor(config: SyncRenderConfig) {
@@ -91,17 +97,18 @@ class SyncRender {
91
97
  }
92
98
 
93
99
  private async setPagesToDelete() {
100
+ // -------------------------------------------------------
94
101
  // INCLUIMOS LAS PÁGINAS A CREAR EN LAS CANDIDATAS A BORRAR
95
- // =======================================================
102
+ // -------------------------------------------------------
96
103
  // El set de ids incluye tanto las páginas a borrar como las que se van
97
104
  // a crear para manejar correctamente los cambios de slug.
98
105
  //
99
- // Ejemplo: Si la página `id=3` tiene slug `about` y después viene con
100
- // `slug=about-us`, necesitamos borrar la página `id=3` del render previo
101
- // y volver a crearla con la nueva ruta.
106
+ // Ejemplo: Si la página `id=3` tiene `slug=about` y después viene con
107
+ // `slug=about-us`, necesitamos borrar la página `id=3` del render
108
+ // previo y volver a crearla con la nueva ruta.
102
109
  //
103
- // ¿Por qué? Porque el slug determina dónde se guarda la página:
104
- // - /about/index.html -> /about-us/index.html
110
+ // ¿Por qué? Porque el slug determina dónde se guarda la página: -
111
+ // /about/index.html -> /about-us/index.html
105
112
  //
106
113
  // Si no la borrásemos previamente, tendríamos ambas páginas:
107
114
  // `/about/index.html` y `/about-us/index.html`
@@ -112,10 +119,12 @@ class SyncRender {
112
119
  if (candidateIdsToDelete.has(page.id)) {
113
120
  this.state.htmlToDelete.push(page.htmlPath);
114
121
  this.state.jsonToDelete.push(page.jsonPath);
122
+ this.state.mdToDelete.push(page.mdPath);
115
123
  }
116
124
  }
117
125
 
118
126
  GriddoLog.verbose(`${this.state.htmlToDelete.length} pages HTML to delete`);
127
+ GriddoLog.verbose(`${this.state.mdToDelete.length} pages Markdown to delete`);
119
128
  GriddoLog.verbose(`${this.state.jsonToDelete.length} pages JSON to delete`);
120
129
  }
121
130
 
@@ -126,11 +135,23 @@ class SyncRender {
126
135
  for (const page of newPages) {
127
136
  if (candidateIdsToCreate.has(page.id)) {
128
137
  const htmlTo = path.join(this.bundleDir, page.composePath, "index.html");
138
+ const mdTo = path.join(this.bundleDir, `${page.composePath}.md`);
139
+
140
+ // El page-data.json del índice principal tiene como slug solo
141
+ // la barra (`/`) por eso gatsby lo guarda en el directorio
142
+ // `index` de forma "reservada".
143
+ // Ejemplos
144
+ // ../page-data/about-us/page-data.json // página con slug
145
+ // ../page-data/programs/page-data.json // página con slug
146
+ // ../page-data/index/page-data.json // <---- ¡página root index!
129
147
  const normalizedCompose = page.composePath === "/" ? "index" : page.composePath;
130
148
  const jsonTo = path.join(this.bundleDir, "page-data", normalizedCompose, "page-data.json");
131
149
 
132
150
  this.state.htmlToAdd.push({ from: page.htmlPath, to: htmlTo });
133
151
  this.state.jsonToAdd.push({ from: page.jsonPath, to: jsonTo });
152
+ if (await pathExists(page.mdPath)) {
153
+ this.state.mdToAdd.push({ from: page.mdPath, to: mdTo });
154
+ }
134
155
  }
135
156
  }
136
157
 
@@ -140,7 +161,11 @@ class SyncRender {
140
161
 
141
162
  private async sync() {
142
163
  // Delete...
143
- const allFilesToDelete = [...this.state.htmlToDelete, ...this.state.jsonToDelete];
164
+ const allFilesToDelete = [
165
+ ...this.state.htmlToDelete,
166
+ ...this.state.jsonToDelete,
167
+ ...this.state.mdToDelete,
168
+ ];
144
169
  for (const file of allFilesToDelete) {
145
170
  try {
146
171
  // Usar `force: true` para no fallar si el archivo ya no existe.
@@ -155,7 +180,7 @@ class SyncRender {
155
180
  await this.restoreWebpackCompilationHash();
156
181
 
157
182
  // Copy...
158
- const allFilesToAdd = [...this.state.htmlToAdd, ...this.state.jsonToAdd];
183
+ const allFilesToAdd = [...this.state.htmlToAdd, ...this.state.jsonToAdd, ...this.state.mdToAdd];
159
184
  for (const file of allFilesToAdd) {
160
185
  try {
161
186
  await fsp.mkdir(path.dirname(file.to), { recursive: true });
@@ -267,6 +292,7 @@ class SyncRender {
267
292
  path.join(dir, "page-data"),
268
293
  "page-data.json",
269
294
  );
295
+
270
296
  const processingPromises: Promise<PageInfo | null>[] = [];
271
297
  for await (const file of gatsbyPageDataGenerator) {
272
298
  processingPromises.push(
@@ -276,12 +302,13 @@ class SyncRender {
276
302
  const content = JSON.parse(fileContent) as GatsbyPageData;
277
303
 
278
304
  const id = content.result.pageContext.id;
279
- const composePath = content.result.pageContext.fullPath.compose;
305
+ const composePath = removeTrailingSlash(content.result.pageContext.fullPath.compose);
280
306
 
281
307
  return {
282
308
  id,
283
309
  composePath,
284
310
  htmlPath: path.join(dir, composePath, "index.html"),
311
+ mdPath: path.join(dir, `${composePath}.md`),
285
312
  jsonPath: file,
286
313
  };
287
314
  } catch (e) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@griddo/cx",
3
3
  "description": "Griddo SSG based on Gatsby",
4
- "version": "11.11.8-rc.1",
4
+ "version": "11.12.0",
5
5
  "authors": [
6
6
  "Hisco <francis.vega@griddo.io>"
7
7
  ],
@@ -56,12 +56,14 @@
56
56
  "watch:ts-lint": "tsc --noEmit --watch"
57
57
  },
58
58
  "dependencies": {
59
+ "@kreuzberg/html-to-markdown": "2.24.5",
59
60
  "gatsby": "5.15.0",
60
- "html-react-parser": "5.2.11"
61
+ "html-react-parser": "5.2.11",
62
+ "jiti": "^2.6.1"
61
63
  },
62
64
  "devDependencies": {
63
65
  "@biomejs/biome": "2.3.4",
64
- "@griddo/core": "11.11.8-rc.1",
66
+ "@griddo/core": "11.12.0",
65
67
  "@types/node": "20.19.4",
66
68
  "@typescript/native-preview": "7.0.0-dev.20260108.1",
67
69
  "cheerio": "1.1.2",
@@ -94,5 +96,5 @@
94
96
  "publishConfig": {
95
97
  "access": "public"
96
98
  },
97
- "gitHead": "a40684db16cac0b3d08bb0437fad6a825d8451e6"
99
+ "gitHead": "47dd37fe46a7bb09187b0c475c4ece29a6abc289"
98
100
  }
@@ -3,8 +3,8 @@
3
3
  "target": "es2022",
4
4
  "lib": ["dom", "esnext"],
5
5
  "jsx": "react-jsx",
6
- "module": "esnext",
7
- "moduleResolution": "node",
6
+ "moduleResolution": "NodeNext",
7
+ "module": "NodeNext",
8
8
  "esModuleInterop": true,
9
9
  "forceConsistentCasingInFileNames": true,
10
10
  "strict": true,
@@ -1,18 +0,0 @@
1
- declare const CODES: {
2
- readonly black: "\u001B[30m";
3
- readonly red: "\u001B[31m";
4
- readonly green: "\u001B[32m";
5
- readonly yellow: "\u001B[33m";
6
- readonly blue: "\u001B[34m";
7
- readonly magenta: "\u001B[35m";
8
- readonly cyan: "\u001B[36m";
9
- readonly white: "\u001B[37m";
10
- readonly gray: "\u001B[90m";
11
- readonly bold: "\u001B[1m";
12
- readonly dim: "\u001B[2m";
13
- };
14
- type ColorFunction = (text: string | number) => string;
15
- type ColorName = keyof typeof CODES;
16
- type Brush = Record<ColorName, ColorFunction>;
17
- declare const brush: Brush;
18
- export { brush };
@@ -1,109 +0,0 @@
1
- import fsp from "node:fs/promises";
2
- import path from "node:path";
3
-
4
- import TurndownService from "turndown";
5
-
6
- // import { gfm } from "turndown-plugin-gfm";
7
-
8
- import { throwError, withErrorHandler } from "../core/errors";
9
- import { GriddoLog } from "../core/GriddoLog";
10
- import { getRenderPathsHydratedWithDomainFromDB } from "../services/render";
11
- import { ReadFromStoreError } from "../shared/errors";
12
-
13
- /**
14
- * Converts HTML to Markdown.
15
- * @param html - The HTML content to convert.
16
- * @returns The Markdown content.
17
- */
18
- function htmlToMarkdown(html: string): string {
19
- const turndown = new TurndownService({
20
- headingStyle: "atx",
21
- codeBlockStyle: "fenced",
22
- bulletListMarker: "-",
23
- emDelimiter: "*",
24
- strongDelimiter: "**",
25
- linkStyle: "inlined", // evita ruido
26
- hr: "---",
27
- });
28
-
29
- // añade soporte GitHub-like
30
- // turndown.use(gfm);
31
-
32
- // elimina tags que hacen ruido para LLMs
33
- turndown.remove([
34
- "style",
35
- "script",
36
- "noscript",
37
- "iframe",
38
- "form",
39
- "input",
40
- "button",
41
- "nav",
42
- "footer",
43
- "object",
44
- ]);
45
-
46
- let md = turndown.turndown(html);
47
-
48
- md = md
49
- .replace(/&nbsp;/g, " ")
50
- .replace(/&amp;/g, "&")
51
- .replace(/\n{3,}/g, "\n\n") // compacta saltos
52
- .trim();
53
-
54
- return md;
55
- }
56
-
57
- /**
58
- * Walk recursively in a basePath and return an array of pages with json
59
- * extension with the full absolute path and the path includes "page-data".
60
- *
61
- * @param basePath The path to walk recursively.
62
- * @returns An array of pages with json extension with the full absolute path
63
- * and the path includes "page-data".
64
- */
65
- async function* walkRecursively(basePath: string): AsyncGenerator<string> {
66
- const filesHandle = await fsp.opendir(basePath);
67
-
68
- for await (const fileDirent of filesHandle) {
69
- if (fileDirent.isDirectory()) {
70
- yield* walkRecursively(path.join(basePath, fileDirent.name));
71
- } else if (fileDirent.isFile() && path.extname(fileDirent.name) === ".html") {
72
- yield path.join(basePath, fileDirent.name);
73
- }
74
- }
75
- }
76
-
77
- async function* getPageDataPagesFromExports(
78
- basePath: string,
79
- ): AsyncGenerator<{ path: string; content: string }> {
80
- const jsonFiles = walkRecursively(basePath);
81
-
82
- for await (const filePath of jsonFiles) {
83
- try {
84
- const fileContent = await fsp.readFile(filePath, "utf8");
85
- const content = htmlToMarkdown(fileContent);
86
- yield { path: filePath, content };
87
- } catch (error) {
88
- throwError(ReadFromStoreError, error);
89
- }
90
- }
91
- }
92
-
93
- async function generateMD() {
94
- const [domain] = process.argv.slice(2);
95
- const { __exports } = await getRenderPathsHydratedWithDomainFromDB({ domain });
96
-
97
- const pages = getPageDataPagesFromExports(path.join(__exports, "dist"));
98
-
99
- for await (const page of pages) {
100
- await fsp.writeFile(path.join(page.path.replace(".html", ".md")), page.content);
101
- GriddoLog.info(`Generating MD for a ${page.path}`);
102
- }
103
- }
104
-
105
- async function main() {
106
- await generateMD();
107
- }
108
-
109
- withErrorHandler(main);
@@ -1,39 +0,0 @@
1
- //
2
- // Brush adds color to a string|number, it does not print it!
3
- // Its simple, no log, no chains, just color in a string|number
4
- // usage:
5
- // console.log(brush.green("sucess!"))
6
- //
7
-
8
- // This is a global variable to check if the code is running in a CI environment
9
- // TODO: Temporarily set to true to avoid color in CI environment
10
- const NO_COLORS = process.env.NO_COLORS;
11
-
12
- const RESET = "\x1b[0m";
13
- const CODES = {
14
- black: "\x1b[30m",
15
- red: "\x1b[31m",
16
- green: "\x1b[32m",
17
- yellow: "\x1b[33m",
18
- blue: "\x1b[34m",
19
- magenta: "\x1b[35m",
20
- cyan: "\x1b[36m",
21
- white: "\x1b[37m",
22
- gray: "\x1b[90m",
23
- bold: "\x1b[1m",
24
- dim: "\x1b[2m",
25
- } as const;
26
-
27
- type ColorFunction = (text: string | number) => string;
28
- type ColorName = keyof typeof CODES;
29
- type Brush = Record<ColorName, ColorFunction>;
30
-
31
- const brush = {} as Brush;
32
-
33
- for (const color in CODES) {
34
- const key = color as ColorName;
35
- brush[key] = (text: string | number) =>
36
- NO_COLORS ? (text as string).toString() : `${CODES[key]}${text}${RESET}`;
37
- }
38
-
39
- export { brush };