@uxf/scripts 11.122.5 → 11.124.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 (36) hide show
  1. package/README.md +1 -38
  2. package/package.json +12 -16
  3. package/src/cli-args.js +43 -0
  4. package/src/cli-args.test.js +61 -0
  5. package/src/{GitLab.js → gitlab.js} +43 -21
  6. package/src/gitlab.test.js +207 -0
  7. package/src/{GoogleChat.js → google-chat.js} +10 -12
  8. package/src/google-chat.test.js +95 -0
  9. package/src/http.js +86 -0
  10. package/src/http.test.js +155 -0
  11. package/src/sitemap.js +80 -0
  12. package/src/sitemap.test.js +64 -0
  13. package/src/{Slack.js → slack.js} +9 -8
  14. package/src/slack.test.js +81 -0
  15. package/src/uxf-i18n-namespaces-gen/dependency-tree.js +102 -0
  16. package/src/uxf-i18n-namespaces-gen/dependency-tree.test.js +46 -0
  17. package/src/uxf-i18n-namespaces-gen/index.js +62 -44
  18. package/src/uxf-i18n-namespaces-gen/index.test.js +32 -1
  19. package/src/uxf-merge-requests-notifier/cli.js +9 -12
  20. package/src/uxf-merge-requests-notifier/index.js +44 -10
  21. package/src/uxf-merge-requests-notifier/index.test.js +103 -0
  22. package/src/uxf-push-notifier/cli.js +14 -13
  23. package/src/uxf-push-notifier/index.js +32 -23
  24. package/src/uxf-release/index.js +3 -3
  25. package/src/uxf-sitemap-check/index.js +6 -2
  26. package/src/uxf-sitemap-check/index.test.js +2 -2
  27. package/src/uxf-sitemap-meta-export/index.js +3 -3
  28. package/bin/uxf-lunch.js +0 -8
  29. package/bin/uxf-unused.js +0 -9
  30. package/src/Logger.js +0 -12
  31. package/src/Sitemap.js +0 -60
  32. package/src/shared/load-page-imports.js +0 -60
  33. package/src/uxf-lunch/cli.js +0 -44
  34. package/src/uxf-lunch/index.js +0 -50
  35. package/src/uxf-unused/cli.js +0 -30
  36. package/src/uxf-unused/index.js +0 -59
@@ -1,30 +1,36 @@
1
- const { create } = require("axios");
2
1
  const process = require("process");
2
+ const { request } = require("../http");
3
3
 
4
4
  const { GITLAB_TOKEN, CI_SERVER_URL, CI_COMMIT_SHA, CI_COMMIT_BEFORE_SHA, CI_PROJECT_ID, CI_COMMIT_REF_NAME } =
5
5
  process.env;
6
6
 
7
- const gitlabAxios = create({
8
- baseURL: `${CI_SERVER_URL}/api/v4`,
9
- headers: {
10
- Authorization: `Bearer ${GITLAB_TOKEN}`,
11
- },
12
- });
13
-
14
- const googleChatAxios = create({});
7
+ /**
8
+ * @param {string} url
9
+ * @param {{params?: Record<string, any>}} options
10
+ */
11
+ function gitlabRequest(url, options = {}) {
12
+ return request(url, {
13
+ ...options,
14
+ baseUrl: `${CI_SERVER_URL}/api/v4`,
15
+ headers: { Authorization: `Bearer ${GITLAB_TOKEN}` },
16
+ });
17
+ }
15
18
 
16
19
  function findCurrentlyMergedMergeRequest() {
17
- return gitlabAxios
18
- .get(
19
- `/projects/${CI_PROJECT_ID}/merge_requests?state=merged&target_branch=${CI_COMMIT_REF_NAME}&order_by=updated_at&sort=desc`,
20
- )
21
- .then((response) => (response.data?.[0]?.sha === CI_COMMIT_SHA ? response.data[0] : null));
20
+ return gitlabRequest(`/projects/${CI_PROJECT_ID}/merge_requests`, {
21
+ params: {
22
+ state: "merged",
23
+ target_branch: CI_COMMIT_REF_NAME,
24
+ order_by: "updated_at",
25
+ sort: "desc",
26
+ },
27
+ }).then((response) => (response.data?.[0]?.sha === CI_COMMIT_SHA ? response.data[0] : null));
22
28
  }
23
29
 
24
30
  function getApprovalUserNames(iid) {
25
- return gitlabAxios
26
- .get(`/projects/${CI_PROJECT_ID}/merge_requests/${iid}/approvals`)
27
- .then((response) => response.data.approved_by.map((item) => item.user.name));
31
+ return gitlabRequest(`/projects/${CI_PROJECT_ID}/merge_requests/${iid}/approvals`).then((response) =>
32
+ response.data.approved_by.map((item) => item.user.name),
33
+ );
28
34
  }
29
35
 
30
36
  function getPushedCommits() {
@@ -35,9 +41,9 @@ function getPushedCommits() {
35
41
  return Promise.resolve([]);
36
42
  }
37
43
 
38
- return gitlabAxios
39
- .get(`/projects/${CI_PROJECT_ID}/repository/compare?from=${CI_COMMIT_BEFORE_SHA}&to=${CI_COMMIT_SHA}`)
40
- .then((response) => response.data.commits);
44
+ return gitlabRequest(`/projects/${CI_PROJECT_ID}/repository/compare`, {
45
+ params: { from: CI_COMMIT_BEFORE_SHA, to: CI_COMMIT_SHA },
46
+ }).then((response) => response.data.commits);
41
47
  }
42
48
 
43
49
  module.exports = async function (googleChatWebhookUrl) {
@@ -54,15 +60,18 @@ Autor: ${mr.author.name}
54
60
  Schválil: ${isApproved ? approvalUserNames.join(", ") : "*bez schválení*"}
55
61
  Zamergoval: ${mr.merged_by.name}`;
56
62
 
57
- await googleChatAxios.post(googleChatWebhookUrl, { text });
63
+ await request(googleChatWebhookUrl, { method: "POST", body: { text } });
58
64
  } else {
59
65
  const commits = (await getPushedCommits()).map(
60
66
  (commit) => `${commit.author_name} - <${commit.web_url}|${commit.title}>`,
61
67
  );
62
68
 
63
- await googleChatAxios.post(googleChatWebhookUrl, {
64
- text: `❗ Bylo pushnuto do developu.
69
+ await request(googleChatWebhookUrl, {
70
+ method: "POST",
71
+ body: {
72
+ text: `❗ Bylo pushnuto do developu.
65
73
  ${commits.join("\n")}`,
74
+ },
66
75
  });
67
76
  }
68
77
  };
@@ -1,6 +1,6 @@
1
- const GitLab = require("../GitLab");
2
- const Slack = require("../Slack");
3
- const GoogleChat = require("../GoogleChat");
1
+ const GitLab = require("../gitlab");
2
+ const Slack = require("../slack");
3
+ const GoogleChat = require("../google-chat");
4
4
  const parseCommitMessage = require("./utils/parse-commit-message");
5
5
 
6
6
  function generateSlackCommitMessage(commit) {
@@ -1,8 +1,8 @@
1
- const Sitemap = require("../Sitemap");
1
+ const Sitemap = require("../sitemap");
2
2
  const { performance } = require("perf_hooks");
3
3
  const { stdout } = require("process");
4
4
  const cheerio = require("cheerio");
5
- const GoogleChat = require("../GoogleChat");
5
+ const GoogleChat = require("../google-chat");
6
6
  const robotsTxtParser = require("robots-txt-parser");
7
7
 
8
8
  const got = (url, init) => import("got").then((mod) => mod.default(url, init));
@@ -78,6 +78,10 @@ function fetcher(url, options) {
78
78
  return got(url, {
79
79
  throwHttpErrors: false,
80
80
  decompress: false,
81
+ // BEZPEČNOST: vypnuté ověřování TLS certifikátu — platí na VŠECHNY procházené
82
+ // URL, tedy i externí a produkční, ne jen na staging se self-signed certem.
83
+ // Crawler tím nepozná podvržený certifikát (MITM). Čistší by bylo podmínit to
84
+ // env proměnnou nebo přidat CA do trust storu. Stejná poznámka je v sitemap.js.
81
85
  https: {
82
86
  rejectUnauthorized: false,
83
87
  },
@@ -2,8 +2,8 @@
2
2
  * @jest-environment node
3
3
  */
4
4
 
5
- jest.mock("../Sitemap");
6
- jest.mock("../GoogleChat");
5
+ jest.mock("../sitemap");
6
+ jest.mock("../google-chat");
7
7
  jest.mock("cheerio");
8
8
  jest.mock("got");
9
9
  jest.mock("robots-txt-parser", () => () => ({ useRobotsFor: jest.fn(), canCrawl: jest.fn() }));
@@ -1,4 +1,4 @@
1
- const Sitemap = require("../Sitemap");
1
+ const Sitemap = require("../sitemap");
2
2
  const cheerio = require("cheerio");
3
3
  const fs = require("fs");
4
4
 
@@ -17,9 +17,9 @@ module.exports = async function run() {
17
17
  for (const url of urls) {
18
18
  process.stdout.write(`${++i} / ${urls.length} ${url} \n`);
19
19
  try {
20
- const response = await Sitemap.axios.get(url);
20
+ const body = await Sitemap.fetchPage(url);
21
21
 
22
- const $ = cheerio.load(response.data, { xmlMode: true, decodeEntities: false });
22
+ const $ = cheerio.load(body, { xmlMode: true, decodeEntities: false });
23
23
 
24
24
  let title = "";
25
25
  let ogTitle = "";
package/bin/uxf-lunch.js DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env node
2
- require("../src/uxf-lunch/cli")()
3
- .then((exitCode) => {
4
- process.exitCode = exitCode;
5
- })
6
- .catch(() => {
7
- process.exitCode = 1;
8
- });
package/bin/uxf-unused.js DELETED
@@ -1,9 +0,0 @@
1
- #!/usr/bin/env node
2
- require("../src/uxf-unused/cli")()
3
- .then((exitCode) => {
4
- process.exitCode = exitCode;
5
- })
6
- .catch((e) => {
7
- console.error(e);
8
- process.exitCode = 1;
9
- });
package/src/Logger.js DELETED
@@ -1,12 +0,0 @@
1
- function debug(message) {
2
- console.debug(message);
3
- }
4
-
5
- function info(message) {
6
- console.info(message);
7
- }
8
-
9
- module.exports = {
10
- debug,
11
- info,
12
- };
package/src/Sitemap.js DELETED
@@ -1,60 +0,0 @@
1
- const https = require("https");
2
- const { create } = require("axios");
3
- const cheerio = require("cheerio");
4
-
5
- const { HTTP_USERNAME, HTTP_PASSWORD } = process.env;
6
-
7
- async function getSitemap(xml) {
8
- const { data } = await axios.get(xml);
9
- const $ = cheerio.load(data, { xmlMode: true });
10
-
11
- const urls = [];
12
-
13
- $("loc").each(function () {
14
- urls.push($(this).text());
15
- });
16
-
17
- return urls;
18
- }
19
-
20
- const agent = new https.Agent({
21
- rejectUnauthorized: false,
22
- });
23
-
24
- const axios = create({
25
- auth:
26
- HTTP_PASSWORD && HTTP_USERNAME
27
- ? {
28
- username: HTTP_USERNAME,
29
- password: HTTP_PASSWORD,
30
- }
31
- : undefined,
32
- withCredentials: true,
33
- maxRedirects: 0,
34
- timeout: 20000,
35
- httpsAgent: agent,
36
- headers: {
37
- "User-Agent":
38
- "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36",
39
- Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
40
- "Accept-Encoding": "gzip, deflate, br",
41
- "Accept-Language": "en-US,en;q=0.9,cs-CZ;q=0.8,cs;q=0.7,de;q=0.6",
42
- "Cache-Control": "no-cache",
43
- Connection: "keep-alive",
44
- Pragma: "no-cache",
45
- "Sec-Ch-Ua": '"Google Chrome";v="111", "Not(A:Brand";v="8", "Chromium";v="111"',
46
- "Sec-Ch-Ua-Arch": '"x86"',
47
- "Sec-Ch-Ua-Mobile": "?0",
48
- "Sec-Ch-Ua-Platform": '"Windows"',
49
- "Sec-Fetch-Dest": "document",
50
- "Sec-Fetch-Mode": "navigate",
51
- "Sec-Fetch-Site": "cross-site",
52
- "Sec-Fetch-User": "?1",
53
- "Sec-Fetch-User-Agent": "?1",
54
- },
55
- });
56
-
57
- module.exports = {
58
- getSitemap,
59
- axios,
60
- };
@@ -1,60 +0,0 @@
1
- const fg = require("fast-glob");
2
- const madge = require("madge");
3
- const path = require("path");
4
- const fs = require("fs");
5
-
6
- function getTSConfig() {
7
- const tsConfigPath = path.resolve(process.cwd(), "tsconfig.json");
8
-
9
- if (fs.existsSync(tsConfigPath)) {
10
- console.log("TS config loaded: " + tsConfigPath);
11
- return tsConfigPath;
12
- }
13
-
14
- console.log("TS config not found.");
15
- return undefined;
16
- }
17
-
18
- function getTree(subtree, tree, destination, viewedFiles = []) {
19
- if (!subtree || subtree.length === 0) {
20
- return;
21
- }
22
-
23
- for (let child of subtree) {
24
- if (viewedFiles.includes(child)) {
25
- continue;
26
- }
27
-
28
- const nextSubtree = tree[child];
29
-
30
- viewedFiles.push(child);
31
-
32
- if (nextSubtree) {
33
- destination.push(nextSubtree);
34
- }
35
-
36
- if (nextSubtree && nextSubtree.length > 0) {
37
- getTree(nextSubtree, tree, destination, viewedFiles);
38
- }
39
- }
40
- }
41
-
42
- module.exports = function loadPageImports(directory, fileExtensions = ["ts", "tsx"]) {
43
- const pages = fg.sync(directory).map(path.normalize);
44
-
45
- return madge(process.cwd(), { tsConfig: getTSConfig(), fileExtensions }).then((res) => {
46
- const tree = res.obj();
47
-
48
- return pages.reduce((previousValue, currentValue) => {
49
- const filesOnPath = [];
50
- getTree([currentValue], tree, filesOnPath);
51
-
52
- const uniqueImports = Array.from(new Set(filesOnPath.flat(Number.POSITIVE_INFINITY)));
53
- uniqueImports.sort();
54
-
55
- previousValue[currentValue] = uniqueImports;
56
-
57
- return previousValue;
58
- }, {});
59
- });
60
- };
@@ -1,44 +0,0 @@
1
- const { argv, env } = require("process");
2
-
3
- module.exports = async () => {
4
- const cli = require("yargs")()
5
- .command("$0", "UXF release helper", (yargs) => {
6
- yargs.demandCommand(0, 0).usage(`UXF lunch
7
- Usage:
8
- uxf-lunch [options]
9
-
10
- Environment variables:
11
- SLACK_TOKEN - required`);
12
- })
13
- .option("slack-channel", {
14
- describe: "Slack channel",
15
- type: "string",
16
- group: "Options",
17
- })
18
- .option("h", { alias: "help", group: "Options" })
19
- .strict(false)
20
- .exitProcess(false);
21
-
22
- try {
23
- const { help, ...options } = cli.parse(argv.slice(2));
24
-
25
- if (Boolean(help)) {
26
- return 0;
27
- }
28
-
29
- if (!env.SLACK_TOKEN) {
30
- console.log("Slack token must be set. Use environment variable SLACK_TOKEN.");
31
- return 1;
32
- }
33
-
34
- if (!options["slack-channel"]) {
35
- console.log("Slack channel must be set. Use parameter --slack-channel");
36
- return 1;
37
- }
38
-
39
- await require("./index")(options["slack-channel"]);
40
- } catch (e) {
41
- console.error(e);
42
- return 1;
43
- }
44
- };
@@ -1,50 +0,0 @@
1
- const { get } = require("axios");
2
- const Slack = require("../Slack");
3
-
4
- const numbers = [":keycap_star:", ":one:", ":two:", ":three:", ":four:", ":five:", ":six:", ":seven:"];
5
- const paymentsUrl = "https://gitlab.uxf.cz/Vejvoda/obedy/-/wikis/%C4%8C%C3%ADsla-%C3%BA%C4%8Dt%C5%AF";
6
-
7
- module.exports = async (slackChannel) => {
8
- const { data } = await get("https://hotel.servispc-liberec.cz/server/api/data-jidelak");
9
-
10
- const menu = data.ListekPolozky.filter(({ druh }) => druh === "1").map((v) => ({
11
- ...v,
12
- cena: Number.parseInt(v.cena),
13
- }));
14
-
15
- const blocks = [
16
- {
17
- type: "section",
18
- text: {
19
- type: "mrkdwn",
20
- text: "*Hotel Radnice*",
21
- },
22
- },
23
- ];
24
-
25
- menu.forEach((menuItem, index) => {
26
- const { polozka, cena } = menuItem;
27
- blocks.push({
28
- type: "section",
29
- text: {
30
- type: "mrkdwn",
31
- text: `${numbers[index]} ${polozka} - \`${cena}Kč\``,
32
- },
33
- });
34
- });
35
- blocks.push({
36
- type: "context",
37
- elements: [
38
- {
39
- type: "mrkdwn",
40
- text: `:eyes: Ceny neobsahují *10Kč* za krabičku (máme vlastní krabičky)\n:moneybag: QR kódy a čísla účtů <${paymentsUrl}|zde> - po zaplacení přidat :white_check_mark:`,
41
- },
42
- {
43
- type: "mrkdwn",
44
- text: ":bulb: Objednávky ideálně formou přidání reakce :keycap_star:, :one:, :two:, ... Ať objednávající nemusí sčítat :-)",
45
- },
46
- ],
47
- });
48
-
49
- await Slack.chatPostMessage(slackChannel, { blocks });
50
- };
@@ -1,30 +0,0 @@
1
- const { argv, env } = require("process");
2
-
3
- module.exports = async () => {
4
- const cli = require("yargs")()
5
- .command("$0", "UXF find and remove unused files NextJS project", (yargs) => {
6
- yargs.demandCommand(0, 0).usage(`
7
- Usage:
8
- uxf-unused [options]`);
9
- })
10
- .option("p", { alias: "pagesDirectory", default: "src/pages/**/*.(ts|tsx)" })
11
- .option("f", { alias: "allFilesDirectory", default: "src/**/*.(ts|tsx)" })
12
- .option("r", { alias: "removeFiles", boolean: true, default: false })
13
- .option("d", { alias: "debug", boolean: true, default: false })
14
- .option("h", { alias: "help" })
15
- .strict(false)
16
- .exitProcess(false);
17
-
18
- try {
19
- const { help, pagesDirectory, allFilesDirectory, removeFiles, debug } = cli.parse(argv.slice(2));
20
-
21
- if (Boolean(help)) {
22
- return 0;
23
- }
24
-
25
- await require("./index")(pagesDirectory, allFilesDirectory, removeFiles, debug);
26
- } catch (e) {
27
- console.error(e);
28
- return 1;
29
- }
30
- };
@@ -1,59 +0,0 @@
1
- #!/usr/bin/env node
2
- const loadPageImports = require("../shared/load-page-imports");
3
- const fg = require("fast-glob");
4
- const path = require("path");
5
- const fs = require("fs");
6
-
7
- function unique(value, index, array) {
8
- return array.indexOf(value) === index;
9
- }
10
-
11
- async function main(pagesDirectory, allFilesDirectory, shouldRemoveFiles, isDebug = false) {
12
- const pageImports = await loadPageImports(pagesDirectory);
13
-
14
- if (isDebug) {
15
- fs.writeFileSync(
16
- path.resolve(process.cwd(), "uxf-unused-1-page-imports.json"),
17
- JSON.stringify(pageImports, null, " "),
18
- );
19
- }
20
-
21
- const pages = Object.keys(pageImports);
22
-
23
- const usedFiles = Object.values(pageImports).flat().filter(unique).map(path.normalize);
24
-
25
- if (isDebug) {
26
- fs.writeFileSync(
27
- path.resolve(process.cwd(), "uxf-unused-2-used-files.json"),
28
- JSON.stringify(usedFiles, null, " "),
29
- );
30
- }
31
-
32
- const allFiles = fg.sync(allFilesDirectory).map(path.normalize);
33
-
34
- if (isDebug) {
35
- fs.writeFileSync(
36
- path.resolve(process.cwd(), "uxf-unused-3-all-files.json"),
37
- JSON.stringify(allFiles, null, " "),
38
- );
39
- }
40
-
41
- const unusedFiles = allFiles.filter((e) => !usedFiles.includes(e) && !pages.includes(e));
42
- unusedFiles.sort();
43
-
44
- if (isDebug) {
45
- fs.writeFileSync(
46
- path.resolve(process.cwd(), "uxf-unused-4-unused-files.json"),
47
- JSON.stringify(unusedFiles, null, " "),
48
- );
49
- }
50
-
51
- unusedFiles.forEach((unusedFile) => {
52
- if (shouldRemoveFiles) {
53
- fs.rmSync(unusedFile);
54
- }
55
- console.log(unusedFile);
56
- });
57
- }
58
-
59
- module.exports = main;