@intlayer/cli 5.8.1 → 6.0.0-canary.1
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/dist/cjs/IntlayerEventListener.cjs +241 -0
- package/dist/cjs/IntlayerEventListener.cjs.map +1 -0
- package/dist/cjs/cli.cjs +29 -7
- package/dist/cjs/cli.cjs.map +1 -1
- package/dist/cjs/config.cjs +5 -1
- package/dist/cjs/config.cjs.map +1 -1
- package/dist/cjs/fill/autoFill.cjs +105 -0
- package/dist/cjs/fill/autoFill.cjs.map +1 -0
- package/dist/cjs/fill/formatAutoFillData.cjs +108 -0
- package/dist/cjs/fill/formatAutoFillData.cjs.map +1 -0
- package/dist/cjs/fill/formatAutoFilledFilePath.cjs +46 -0
- package/dist/cjs/fill/formatAutoFilledFilePath.cjs.map +1 -0
- package/dist/cjs/fill/getTargetDictionary.cjs +86 -0
- package/dist/cjs/fill/getTargetDictionary.cjs.map +1 -0
- package/dist/cjs/fill/index.cjs +257 -0
- package/dist/cjs/fill/index.cjs.map +1 -0
- package/dist/cjs/index.cjs +4 -2
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/listContentDeclaration.cjs +37 -19
- package/dist/cjs/listContentDeclaration.cjs.map +1 -1
- package/dist/cjs/liveSync.cjs +254 -0
- package/dist/cjs/liveSync.cjs.map +1 -0
- package/dist/cjs/pull.cjs +119 -117
- package/dist/cjs/pull.cjs.map +1 -1
- package/dist/cjs/pullLog.cjs +146 -0
- package/dist/cjs/pullLog.cjs.map +1 -0
- package/dist/cjs/push.cjs +74 -88
- package/dist/cjs/push.cjs.map +1 -1
- package/dist/cjs/pushConfig.cjs +10 -25
- package/dist/cjs/pushConfig.cjs.map +1 -1
- package/dist/cjs/pushLog.cjs +130 -0
- package/dist/cjs/pushLog.cjs.map +1 -0
- package/dist/cjs/reviewDoc.cjs +45 -36
- package/dist/cjs/reviewDoc.cjs.map +1 -1
- package/dist/cjs/test/index.cjs +91 -0
- package/dist/cjs/test/index.cjs.map +1 -0
- package/dist/cjs/test/listMissingTranslations.cjs +73 -0
- package/dist/cjs/test/listMissingTranslations.cjs.map +1 -0
- package/dist/cjs/translateDoc.cjs +42 -34
- package/dist/cjs/translateDoc.cjs.map +1 -1
- package/dist/cjs/utils/checkAIAccess.cjs +5 -1
- package/dist/cjs/utils/checkAIAccess.cjs.map +1 -1
- package/dist/cjs/utils/chunkInference.cjs +7 -14
- package/dist/cjs/utils/chunkInference.cjs.map +1 -1
- package/dist/esm/IntlayerEventListener.mjs +207 -0
- package/dist/esm/IntlayerEventListener.mjs.map +1 -0
- package/dist/esm/cli.mjs +26 -4
- package/dist/esm/cli.mjs.map +1 -1
- package/dist/esm/config.mjs +5 -1
- package/dist/esm/config.mjs.map +1 -1
- package/dist/esm/fill/autoFill.mjs +92 -0
- package/dist/esm/fill/autoFill.mjs.map +1 -0
- package/dist/esm/fill/formatAutoFillData.mjs +84 -0
- package/dist/esm/fill/formatAutoFillData.mjs.map +1 -0
- package/dist/esm/fill/formatAutoFilledFilePath.mjs +22 -0
- package/dist/esm/fill/formatAutoFilledFilePath.mjs.map +1 -0
- package/dist/esm/fill/getTargetDictionary.mjs +51 -0
- package/dist/esm/fill/getTargetDictionary.mjs.map +1 -0
- package/dist/esm/fill/index.mjs +240 -0
- package/dist/esm/fill/index.mjs.map +1 -0
- package/dist/esm/index.mjs +2 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/listContentDeclaration.mjs +38 -17
- package/dist/esm/listContentDeclaration.mjs.map +1 -1
- package/dist/esm/liveSync.mjs +220 -0
- package/dist/esm/liveSync.mjs.map +1 -0
- package/dist/esm/pull.mjs +123 -108
- package/dist/esm/pull.mjs.map +1 -1
- package/dist/esm/pullLog.mjs +127 -0
- package/dist/esm/pullLog.mjs.map +1 -0
- package/dist/esm/push.mjs +81 -90
- package/dist/esm/push.mjs.map +1 -1
- package/dist/esm/pushConfig.mjs +11 -26
- package/dist/esm/pushConfig.mjs.map +1 -1
- package/dist/esm/pushLog.mjs +111 -0
- package/dist/esm/pushLog.mjs.map +1 -0
- package/dist/esm/reviewDoc.mjs +55 -38
- package/dist/esm/reviewDoc.mjs.map +1 -1
- package/dist/esm/test/index.mjs +74 -0
- package/dist/esm/test/index.mjs.map +1 -0
- package/dist/esm/test/listMissingTranslations.mjs +41 -0
- package/dist/esm/test/listMissingTranslations.mjs.map +1 -0
- package/dist/esm/translateDoc.mjs +52 -37
- package/dist/esm/translateDoc.mjs.map +1 -1
- package/dist/esm/utils/checkAIAccess.mjs +5 -1
- package/dist/esm/utils/checkAIAccess.mjs.map +1 -1
- package/dist/esm/utils/chunkInference.mjs +14 -16
- package/dist/esm/utils/chunkInference.mjs.map +1 -1
- package/dist/types/IntlayerEventListener.d.ts +85 -0
- package/dist/types/IntlayerEventListener.d.ts.map +1 -0
- package/dist/types/cli.d.ts.map +1 -1
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/fill/autoFill.d.ts +4 -0
- package/dist/types/fill/autoFill.d.ts.map +1 -0
- package/dist/types/fill/formatAutoFillData.d.ts +9 -0
- package/dist/types/fill/formatAutoFillData.d.ts.map +1 -0
- package/dist/types/fill/formatAutoFilledFilePath.d.ts +3 -0
- package/dist/types/fill/formatAutoFilledFilePath.d.ts.map +1 -0
- package/dist/types/fill/getTargetDictionary.d.ts +4 -0
- package/dist/types/fill/getTargetDictionary.d.ts.map +1 -0
- package/dist/types/{fill.d.ts → fill/index.d.ts} +2 -5
- package/dist/types/fill/index.d.ts.map +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/listContentDeclaration.d.ts +4 -5
- package/dist/types/listContentDeclaration.d.ts.map +1 -1
- package/dist/types/liveSync.d.ts +6 -0
- package/dist/types/liveSync.d.ts.map +1 -0
- package/dist/types/pull.d.ts.map +1 -1
- package/dist/types/pullLog.d.ts +24 -0
- package/dist/types/pullLog.d.ts.map +1 -0
- package/dist/types/push.d.ts +1 -1
- package/dist/types/push.d.ts.map +1 -1
- package/dist/types/pushConfig.d.ts +0 -1
- package/dist/types/pushConfig.d.ts.map +1 -1
- package/dist/types/pushLog.d.ts +23 -0
- package/dist/types/pushLog.d.ts.map +1 -0
- package/dist/types/reviewDoc.d.ts +1 -1
- package/dist/types/reviewDoc.d.ts.map +1 -1
- package/dist/types/test/index.d.ts +8 -0
- package/dist/types/test/index.d.ts.map +1 -0
- package/dist/types/test/listMissingTranslations.d.ts +12 -0
- package/dist/types/test/listMissingTranslations.d.ts.map +1 -0
- package/dist/types/translateDoc.d.ts +1 -1
- package/dist/types/translateDoc.d.ts.map +1 -1
- package/dist/types/utils/checkAIAccess.d.ts.map +1 -1
- package/dist/types/utils/chunkInference.d.ts +2 -1
- package/dist/types/utils/chunkInference.d.ts.map +1 -1
- package/package.json +19 -15
- package/dist/cjs/fill.cjs +0 -405
- package/dist/cjs/fill.cjs.map +0 -1
- package/dist/esm/fill.mjs +0 -385
- package/dist/esm/fill.mjs.map +0 -1
- package/dist/types/fill.d.ts.map +0 -1
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ANSIColors,
|
|
3
|
+
colorize,
|
|
4
|
+
getConfiguration,
|
|
5
|
+
spinnerFrames
|
|
6
|
+
} from "@intlayer/config";
|
|
7
|
+
class PullLogger {
|
|
8
|
+
statuses = [];
|
|
9
|
+
spinnerTimer = null;
|
|
10
|
+
spinnerIndex = 0;
|
|
11
|
+
renderedLines = 0;
|
|
12
|
+
spinnerFrames = spinnerFrames;
|
|
13
|
+
isFinished = false;
|
|
14
|
+
prefix;
|
|
15
|
+
lastRenderedState = "";
|
|
16
|
+
constructor() {
|
|
17
|
+
const configuration = getConfiguration();
|
|
18
|
+
this.prefix = configuration.log.prefix;
|
|
19
|
+
}
|
|
20
|
+
update(newStatuses) {
|
|
21
|
+
if (this.isFinished) return;
|
|
22
|
+
for (const status of newStatuses) {
|
|
23
|
+
const index = this.statuses.findIndex(
|
|
24
|
+
(s) => s.dictionaryKey === status.dictionaryKey
|
|
25
|
+
);
|
|
26
|
+
if (index >= 0) {
|
|
27
|
+
this.statuses[index] = status;
|
|
28
|
+
} else {
|
|
29
|
+
this.statuses.push(status);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
this.startSpinner();
|
|
33
|
+
this.render();
|
|
34
|
+
}
|
|
35
|
+
finish() {
|
|
36
|
+
this.isFinished = true;
|
|
37
|
+
this.stopSpinner();
|
|
38
|
+
this.render();
|
|
39
|
+
}
|
|
40
|
+
startSpinner() {
|
|
41
|
+
if (this.spinnerTimer || this.isFinished) return;
|
|
42
|
+
this.spinnerTimer = setInterval(() => {
|
|
43
|
+
this.spinnerIndex = (this.spinnerIndex + 1) % this.spinnerFrames.length;
|
|
44
|
+
this.render();
|
|
45
|
+
}, 100);
|
|
46
|
+
}
|
|
47
|
+
stopSpinner() {
|
|
48
|
+
if (!this.spinnerTimer) return;
|
|
49
|
+
clearInterval(this.spinnerTimer);
|
|
50
|
+
this.spinnerTimer = null;
|
|
51
|
+
}
|
|
52
|
+
render() {
|
|
53
|
+
const { total, done, success, errors } = this.computeProgress();
|
|
54
|
+
const frame = this.spinnerFrames[this.spinnerIndex];
|
|
55
|
+
const lines = [];
|
|
56
|
+
const isDone = done === total;
|
|
57
|
+
const progressLabel = `dictionaries: ${done}/${total}`;
|
|
58
|
+
const details = [];
|
|
59
|
+
if (success > 0) details.push(`ok: ${success}`);
|
|
60
|
+
if (errors > 0) details.push(colorize(`errors: ${errors}`, ANSIColors.RED));
|
|
61
|
+
const suffix = details.length > 0 ? ` (${details.join(", ")})` : "";
|
|
62
|
+
if (isDone) {
|
|
63
|
+
lines.push(
|
|
64
|
+
`${this.prefix} ${colorize("\u2714", ANSIColors.GREEN)} fetched ${progressLabel}${suffix}`
|
|
65
|
+
);
|
|
66
|
+
} else {
|
|
67
|
+
lines.push(
|
|
68
|
+
`${this.prefix} ${colorize(frame, ANSIColors.BLUE)} fetching ${progressLabel}${suffix}`
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
const currentState = lines.join("\n");
|
|
72
|
+
if (currentState === this.lastRenderedState) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
this.lastRenderedState = currentState;
|
|
76
|
+
if (this.renderedLines > 0) {
|
|
77
|
+
process.stdout.write(`\x1B[${this.renderedLines}F`);
|
|
78
|
+
}
|
|
79
|
+
const totalLinesToClear = Math.max(this.renderedLines, lines.length);
|
|
80
|
+
for (let i = 0; i < totalLinesToClear; i++) {
|
|
81
|
+
process.stdout.write("\x1B[2K");
|
|
82
|
+
const line = lines[i];
|
|
83
|
+
if (line !== void 0) {
|
|
84
|
+
process.stdout.write(line);
|
|
85
|
+
}
|
|
86
|
+
process.stdout.write("\n");
|
|
87
|
+
}
|
|
88
|
+
this.renderedLines = lines.length;
|
|
89
|
+
}
|
|
90
|
+
computeProgress() {
|
|
91
|
+
const keys = new Set(this.statuses.map((s) => s.dictionaryKey));
|
|
92
|
+
const doneSet = /* @__PURE__ */ new Set([
|
|
93
|
+
"fetched",
|
|
94
|
+
"imported",
|
|
95
|
+
"updated",
|
|
96
|
+
"up-to-date",
|
|
97
|
+
"reimported in JSON",
|
|
98
|
+
"new content file",
|
|
99
|
+
"error"
|
|
100
|
+
]);
|
|
101
|
+
const successesSet = /* @__PURE__ */ new Set([
|
|
102
|
+
"fetched",
|
|
103
|
+
"imported",
|
|
104
|
+
"updated",
|
|
105
|
+
"up-to-date",
|
|
106
|
+
"reimported in JSON",
|
|
107
|
+
"new content file"
|
|
108
|
+
]);
|
|
109
|
+
const done = this.statuses.filter(
|
|
110
|
+
(s) => doneSet.has(s.status)
|
|
111
|
+
).length;
|
|
112
|
+
const success = this.statuses.filter(
|
|
113
|
+
(s) => successesSet.has(s.status)
|
|
114
|
+
).length;
|
|
115
|
+
const errors = this.statuses.filter((s) => s.status === "error").length;
|
|
116
|
+
return {
|
|
117
|
+
total: keys.size,
|
|
118
|
+
done,
|
|
119
|
+
success,
|
|
120
|
+
errors
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
export {
|
|
125
|
+
PullLogger
|
|
126
|
+
};
|
|
127
|
+
//# sourceMappingURL=pullLog.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/pullLog.ts"],"sourcesContent":["import { type DictionaryStatus } from '@intlayer/chokidar';\nimport {\n ANSIColors,\n colorize,\n getConfiguration,\n spinnerFrames,\n} from '@intlayer/config';\n\nexport type PullStatus = {\n dictionaryKey: string;\n status: DictionaryStatus | 'pending' | 'fetching';\n errorMessage?: string;\n};\n\nexport class PullLogger {\n private statuses: PullStatus[] = [];\n private spinnerTimer: NodeJS.Timeout | null = null;\n private spinnerIndex = 0;\n private renderedLines = 0;\n private readonly spinnerFrames = spinnerFrames;\n private isFinished = false;\n private readonly prefix: string;\n private lastRenderedState: string = '';\n\n constructor() {\n const configuration = getConfiguration();\n this.prefix = configuration.log.prefix;\n }\n\n update(newStatuses: PullStatus[]) {\n if (this.isFinished) return;\n for (const status of newStatuses) {\n const index = this.statuses.findIndex(\n (s) => s.dictionaryKey === status.dictionaryKey\n );\n if (index >= 0) {\n this.statuses[index] = status;\n } else {\n this.statuses.push(status);\n }\n }\n\n this.startSpinner();\n this.render();\n }\n\n finish() {\n this.isFinished = true;\n this.stopSpinner();\n this.render();\n }\n\n private startSpinner() {\n if (this.spinnerTimer || this.isFinished) return;\n this.spinnerTimer = setInterval(() => {\n this.spinnerIndex = (this.spinnerIndex + 1) % this.spinnerFrames.length;\n this.render();\n }, 100);\n }\n\n private stopSpinner() {\n if (!this.spinnerTimer) return;\n clearInterval(this.spinnerTimer);\n this.spinnerTimer = null;\n }\n\n private render() {\n const { total, done, success, errors } = this.computeProgress();\n\n const frame = this.spinnerFrames[this.spinnerIndex];\n const lines: string[] = [];\n\n const isDone = done === total;\n const progressLabel = `dictionaries: ${done}/${total}`;\n const details: string[] = [];\n if (success > 0) details.push(`ok: ${success}`);\n if (errors > 0) details.push(colorize(`errors: ${errors}`, ANSIColors.RED));\n\n const suffix = details.length > 0 ? ` (${details.join(', ')})` : '';\n\n if (isDone) {\n lines.push(\n `${this.prefix} ${colorize('✔', ANSIColors.GREEN)} fetched ${progressLabel}${suffix}`\n );\n } else {\n lines.push(\n `${this.prefix} ${colorize(frame, ANSIColors.BLUE)} fetching ${progressLabel}${suffix}`\n );\n }\n\n const currentState = lines.join('\\n');\n if (currentState === this.lastRenderedState) {\n return;\n }\n this.lastRenderedState = currentState;\n\n if (this.renderedLines > 0) {\n process.stdout.write(`\\x1b[${this.renderedLines}F`);\n }\n\n const totalLinesToClear = Math.max(this.renderedLines, lines.length);\n for (let i = 0; i < totalLinesToClear; i++) {\n process.stdout.write('\\x1b[2K');\n const line = lines[i];\n if (line !== undefined) {\n process.stdout.write(line);\n }\n process.stdout.write('\\n');\n }\n\n this.renderedLines = lines.length;\n }\n\n private computeProgress() {\n const keys = new Set(this.statuses.map((s) => s.dictionaryKey));\n\n const doneSet = new Set<DictionaryStatus | 'error'>([\n 'fetched',\n 'imported',\n 'updated',\n 'up-to-date',\n 'reimported in JSON',\n 'new content file',\n 'error',\n ] as const);\n\n const successesSet = new Set<DictionaryStatus>([\n 'fetched',\n 'imported',\n 'updated',\n 'up-to-date',\n 'reimported in JSON',\n 'new content file',\n ] as const);\n\n const done = this.statuses.filter((s) =>\n doneSet.has(s.status as any)\n ).length;\n const success = this.statuses.filter((s) =>\n successesSet.has(s.status as any)\n ).length;\n const errors = this.statuses.filter((s) => s.status === 'error').length;\n\n return {\n total: keys.size,\n done,\n success,\n errors,\n } as const;\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/esm/push.mjs
CHANGED
|
@@ -1,24 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { listGitFiles } from "@intlayer/chokidar";
|
|
1
|
+
import { getIntlayerAPIProxy } from "@intlayer/api";
|
|
3
2
|
import {
|
|
3
|
+
formatPath,
|
|
4
|
+
listGitFiles,
|
|
5
|
+
parallelize
|
|
6
|
+
} from "@intlayer/chokidar";
|
|
7
|
+
import {
|
|
8
|
+
ANSIColors,
|
|
4
9
|
getAppLogger,
|
|
5
10
|
getConfiguration
|
|
6
11
|
} from "@intlayer/config";
|
|
7
12
|
import dictionariesRecord from "@intlayer/dictionaries-entry";
|
|
8
13
|
import * as fsPromises from "fs/promises";
|
|
9
|
-
import pLimit from "p-limit";
|
|
10
|
-
import { relative } from "path";
|
|
11
14
|
import * as readline from "readline";
|
|
12
|
-
|
|
13
|
-
const RESET = "\x1B[0m";
|
|
14
|
-
const GREEN = "\x1B[32m";
|
|
15
|
-
const RED = "\x1B[31m";
|
|
16
|
-
const BLUE = "\x1B[34m";
|
|
17
|
-
const GREY = "\x1B[90m";
|
|
18
|
-
const GREY_DARK = "\x1B[90m";
|
|
15
|
+
import { PushLogger } from "./pushLog.mjs";
|
|
19
16
|
const push = async (options) => {
|
|
20
17
|
const config = getConfiguration(options?.configOptions);
|
|
21
|
-
const appLogger = getAppLogger(config
|
|
18
|
+
const appLogger = getAppLogger(config, {
|
|
19
|
+
config: {
|
|
20
|
+
prefix: ""
|
|
21
|
+
}
|
|
22
|
+
});
|
|
22
23
|
const { clientId, clientSecret } = config.editor;
|
|
23
24
|
try {
|
|
24
25
|
if (!clientId || !clientSecret) {
|
|
@@ -26,9 +27,7 @@ const push = async (options) => {
|
|
|
26
27
|
"Missing OAuth2 client ID or client secret. To get access token go to https://intlayer.org/dashboard/project."
|
|
27
28
|
);
|
|
28
29
|
}
|
|
29
|
-
const
|
|
30
|
-
const oAuth2TokenResult = await intlayerAuthAPI.getOAuth2AccessToken();
|
|
31
|
-
const oAuth2AccessToken = oAuth2TokenResult.data?.accessToken;
|
|
30
|
+
const intlayerAPI = getIntlayerAPIProxy(void 0, config);
|
|
32
31
|
let dictionaries = Object.values(dictionariesRecord);
|
|
33
32
|
const existingDictionariesKeys = Object.keys(dictionariesRecord);
|
|
34
33
|
if (options?.dictionaries) {
|
|
@@ -60,41 +59,42 @@ const push = async (options) => {
|
|
|
60
59
|
}
|
|
61
60
|
appLogger("Pushing dictionaries:", {});
|
|
62
61
|
const dictionariesStatuses = dictionaries.map(
|
|
63
|
-
(dictionary
|
|
62
|
+
(dictionary) => ({
|
|
64
63
|
dictionary,
|
|
65
|
-
|
|
66
|
-
status: "pending",
|
|
67
|
-
index,
|
|
68
|
-
spinnerFrameIndex: 0
|
|
64
|
+
status: "pending"
|
|
69
65
|
})
|
|
70
66
|
);
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
67
|
+
const logger = new PushLogger();
|
|
68
|
+
logger.update(
|
|
69
|
+
dictionariesStatuses.map((s) => ({
|
|
70
|
+
dictionaryKey: s.dictionary.key,
|
|
71
|
+
status: "pending"
|
|
72
|
+
}))
|
|
73
|
+
);
|
|
74
74
|
const successfullyPushedDictionaries = [];
|
|
75
|
-
const spinnerTimer = setInterval(() => {
|
|
76
|
-
updateAllStatusLines(dictionariesStatuses);
|
|
77
|
-
}, 100);
|
|
78
75
|
const processDictionary = async (statusObj) => {
|
|
79
76
|
statusObj.status = "pushing";
|
|
77
|
+
logger.update([
|
|
78
|
+
{ dictionaryKey: statusObj.dictionary.key, status: "pushing" }
|
|
79
|
+
]);
|
|
80
80
|
try {
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
{
|
|
85
|
-
headers: {
|
|
86
|
-
Authorization: `Bearer ${oAuth2AccessToken}`
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
);
|
|
81
|
+
const pushResult = await intlayerAPI.dictionary.pushDictionaries([
|
|
82
|
+
statusObj.dictionary
|
|
83
|
+
]);
|
|
90
84
|
const updatedDictionaries = pushResult.data?.updatedDictionaries || [];
|
|
91
85
|
const newDictionaries = pushResult.data?.newDictionaries || [];
|
|
92
86
|
if (updatedDictionaries.includes(statusObj.dictionary.key)) {
|
|
93
87
|
statusObj.status = "modified";
|
|
94
88
|
successfullyPushedDictionaries.push(statusObj.dictionary);
|
|
89
|
+
logger.update([
|
|
90
|
+
{ dictionaryKey: statusObj.dictionary.key, status: "modified" }
|
|
91
|
+
]);
|
|
95
92
|
} else if (newDictionaries.includes(statusObj.dictionary.key)) {
|
|
96
93
|
statusObj.status = "pushed";
|
|
97
94
|
successfullyPushedDictionaries.push(statusObj.dictionary);
|
|
95
|
+
logger.update([
|
|
96
|
+
{ dictionaryKey: statusObj.dictionary.key, status: "pushed" }
|
|
97
|
+
]);
|
|
98
98
|
} else {
|
|
99
99
|
statusObj.status = "unknown";
|
|
100
100
|
}
|
|
@@ -102,15 +102,42 @@ const push = async (options) => {
|
|
|
102
102
|
statusObj.status = "error";
|
|
103
103
|
statusObj.error = error;
|
|
104
104
|
statusObj.errorMessage = `Error pushing dictionary ${statusObj.dictionary.key}: ${error}`;
|
|
105
|
+
logger.update([
|
|
106
|
+
{ dictionaryKey: statusObj.dictionary.key, status: "error" }
|
|
107
|
+
]);
|
|
105
108
|
}
|
|
106
109
|
};
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
110
|
+
await parallelize(dictionariesStatuses, processDictionary, 5);
|
|
111
|
+
logger.finish();
|
|
112
|
+
const iconFor = (status) => {
|
|
113
|
+
switch (status) {
|
|
114
|
+
case "pushed":
|
|
115
|
+
case "modified":
|
|
116
|
+
return "\u2714";
|
|
117
|
+
case "error":
|
|
118
|
+
return "\u2716";
|
|
119
|
+
default:
|
|
120
|
+
return "\u23F2";
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
const colorFor = (status) => {
|
|
124
|
+
switch (status) {
|
|
125
|
+
case "pushed":
|
|
126
|
+
case "modified":
|
|
127
|
+
return ANSIColors.GREEN;
|
|
128
|
+
case "error":
|
|
129
|
+
return ANSIColors.RED;
|
|
130
|
+
default:
|
|
131
|
+
return ANSIColors.BLUE;
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
for (const s of dictionariesStatuses) {
|
|
135
|
+
const icon = iconFor(s.status);
|
|
136
|
+
const color = colorFor(s.status);
|
|
137
|
+
appLogger(
|
|
138
|
+
` - ${s.dictionary.key} ${ANSIColors.GREY}[${color}${icon} ${s.status}${ANSIColors.GREY}]${ANSIColors.RESET}`
|
|
139
|
+
);
|
|
140
|
+
}
|
|
114
141
|
for (const statusObj of dictionariesStatuses) {
|
|
115
142
|
if (statusObj.errorMessage) {
|
|
116
143
|
appLogger(statusObj.errorMessage, {
|
|
@@ -156,8 +183,11 @@ const askUser = (question) => {
|
|
|
156
183
|
};
|
|
157
184
|
const deleteLocalDictionaries = async (dictionariesToDelete, options) => {
|
|
158
185
|
const config = getConfiguration(options?.configOptions);
|
|
159
|
-
const appLogger = getAppLogger(config
|
|
160
|
-
|
|
186
|
+
const appLogger = getAppLogger(config, {
|
|
187
|
+
config: {
|
|
188
|
+
prefix: ""
|
|
189
|
+
}
|
|
190
|
+
});
|
|
161
191
|
const filePathsSet = /* @__PURE__ */ new Set();
|
|
162
192
|
for (const dictionary of dictionariesToDelete) {
|
|
163
193
|
const { filePath } = dictionary;
|
|
@@ -170,65 +200,26 @@ const deleteLocalDictionaries = async (dictionariesToDelete, options) => {
|
|
|
170
200
|
filePathsSet.add(filePath);
|
|
171
201
|
}
|
|
172
202
|
for (const filePath of filePathsSet) {
|
|
173
|
-
const relativePath = relative(baseDir, filePath);
|
|
174
203
|
try {
|
|
175
204
|
const stats = await fsPromises.lstat(filePath);
|
|
176
205
|
if (stats.isFile()) {
|
|
177
206
|
await fsPromises.unlink(filePath);
|
|
178
|
-
appLogger(`Deleted file ${
|
|
207
|
+
appLogger(`Deleted file ${formatPath(filePath)}`, {});
|
|
179
208
|
} else if (stats.isDirectory()) {
|
|
180
|
-
appLogger(`Path is a directory ${
|
|
209
|
+
appLogger(`Path is a directory ${formatPath(filePath)}, skipping.`, {});
|
|
181
210
|
} else {
|
|
182
|
-
appLogger(
|
|
211
|
+
appLogger(
|
|
212
|
+
`Unknown file type for ${formatPath(filePath)}, skipping.`,
|
|
213
|
+
{}
|
|
214
|
+
);
|
|
183
215
|
}
|
|
184
216
|
} catch (err) {
|
|
185
|
-
appLogger(`Error deleting ${
|
|
217
|
+
appLogger(`Error deleting ${formatPath(filePath)}: ${err}`, {
|
|
186
218
|
level: "error"
|
|
187
219
|
});
|
|
188
220
|
}
|
|
189
221
|
}
|
|
190
222
|
};
|
|
191
|
-
const getStatusIcon = (status) => {
|
|
192
|
-
const statusIcons = {
|
|
193
|
-
pending: "\u23F2",
|
|
194
|
-
pushing: "",
|
|
195
|
-
// Spinner handled separately
|
|
196
|
-
modified: "\u2714",
|
|
197
|
-
pushed: "\u2714",
|
|
198
|
-
error: "\u2716"
|
|
199
|
-
};
|
|
200
|
-
return statusIcons[status] || "";
|
|
201
|
-
};
|
|
202
|
-
const getStatusLine = (statusObj) => {
|
|
203
|
-
let icon = getStatusIcon(statusObj.status);
|
|
204
|
-
let colorStart = "";
|
|
205
|
-
let colorEnd = "";
|
|
206
|
-
if (statusObj.status === "pushing") {
|
|
207
|
-
icon = spinnerFrames[statusObj.spinnerFrameIndex % spinnerFrames.length];
|
|
208
|
-
colorStart = BLUE;
|
|
209
|
-
colorEnd = RESET;
|
|
210
|
-
} else if (statusObj.status === "error") {
|
|
211
|
-
colorStart = RED;
|
|
212
|
-
colorEnd = RESET;
|
|
213
|
-
} else if (statusObj.status === "pushed" || statusObj.status === "modified") {
|
|
214
|
-
colorStart = GREEN;
|
|
215
|
-
colorEnd = RESET;
|
|
216
|
-
} else {
|
|
217
|
-
colorStart = GREY;
|
|
218
|
-
colorEnd = RESET;
|
|
219
|
-
}
|
|
220
|
-
return `- ${statusObj.dictionary.key} ${GREY_DARK}[${colorStart}${icon}${statusObj.status}${GREY_DARK}]${colorEnd}`;
|
|
221
|
-
};
|
|
222
|
-
const updateAllStatusLines = (dictionariesStatuses) => {
|
|
223
|
-
readline.moveCursor(process.stdout, 0, -dictionariesStatuses.length);
|
|
224
|
-
for (const statusObj of dictionariesStatuses) {
|
|
225
|
-
readline.clearLine(process.stdout, 0);
|
|
226
|
-
if (statusObj.status === "pushing") {
|
|
227
|
-
statusObj.spinnerFrameIndex = (statusObj.spinnerFrameIndex + 1) % spinnerFrames.length;
|
|
228
|
-
}
|
|
229
|
-
process.stdout.write(getStatusLine(statusObj) + "\n");
|
|
230
|
-
}
|
|
231
|
-
};
|
|
232
223
|
export {
|
|
233
224
|
push
|
|
234
225
|
};
|
package/dist/esm/push.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/push.ts"],"sourcesContent":["import { getDictionaryAPI, getOAuthAPI } from '@intlayer/api';\nimport { listGitFiles, ListGitFilesOptions } from '@intlayer/chokidar';\nimport {\n getAppLogger,\n getConfiguration,\n GetConfigurationOptions,\n} from '@intlayer/config';\nimport type { Dictionary } from '@intlayer/core';\nimport dictionariesRecord from '@intlayer/dictionaries-entry';\nimport * as fsPromises from 'fs/promises';\nimport pLimit from 'p-limit';\nimport { relative } from 'path';\nimport * as readline from 'readline';\n\ntype PushOptions = {\n deleteLocaleDictionary?: boolean;\n keepLocaleDictionary?: boolean;\n dictionaries?: string[];\n gitOptions?: ListGitFilesOptions;\n configOptions?: GetConfigurationOptions;\n};\n\ntype DictionariesStatus = {\n dictionary: Dictionary;\n status: 'pending' | 'pushing' | 'modified' | 'pushed' | 'unknown' | 'error';\n icon: string;\n index: number;\n error?: Error;\n errorMessage?: string;\n spinnerFrameIndex?: number;\n};\n\nconst spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n\nconst RESET = '\\x1b[0m';\nconst GREEN = '\\x1b[32m';\nconst RED = '\\x1b[31m';\nconst BLUE = '\\x1b[34m';\nconst GREY = '\\x1b[90m';\nconst GREY_DARK = '\\x1b[90m';\n\n/**\n * Get all locale dictionaries and push them simultaneously.\n */\nexport const push = async (options?: PushOptions): Promise<void> => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config);\n const { clientId, clientSecret } = config.editor;\n try {\n if (!clientId || !clientSecret) {\n throw new Error(\n 'Missing OAuth2 client ID or client secret. To get access token go to https://intlayer.org/dashboard/project.'\n );\n }\n\n const intlayerAuthAPI = getOAuthAPI(config);\n const oAuth2TokenResult = await intlayerAuthAPI.getOAuth2AccessToken();\n\n const oAuth2AccessToken = oAuth2TokenResult.data?.accessToken;\n\n let dictionaries: Dictionary[] = Object.values(dictionariesRecord);\n const existingDictionariesKeys: string[] = Object.keys(dictionariesRecord);\n\n if (options?.dictionaries) {\n // Check if the provided dictionaries exist\n const noneExistingDictionariesOption = options.dictionaries.filter(\n (dictionaryId) => !existingDictionariesKeys.includes(dictionaryId)\n );\n\n if (noneExistingDictionariesOption.length > 0) {\n appLogger(\n `The following dictionaries do not exist: ${noneExistingDictionariesOption.join(\n ', '\n )} and have been ignored.`,\n {\n level: 'error',\n }\n );\n }\n\n // Filter the dictionaries from the provided list of IDs\n dictionaries = dictionaries.filter((dictionary) =>\n options.dictionaries!.includes(dictionary.key)\n );\n }\n\n if (options?.gitOptions) {\n const gitFiles = await listGitFiles(options.gitOptions);\n }\n\n // Check if the dictionaries list is empty\n if (dictionaries.length === 0) {\n appLogger('No local dictionaries found', {\n level: 'error',\n });\n return;\n }\n\n appLogger('Pushing dictionaries:', {});\n\n // Prepare dictionaries statuses\n const dictionariesStatuses: DictionariesStatus[] = dictionaries.map(\n (dictionary, index) => ({\n dictionary,\n icon: getStatusIcon('pending'),\n status: 'pending',\n index,\n spinnerFrameIndex: 0,\n })\n );\n\n // Output initial statuses\n for (const statusObj of dictionariesStatuses) {\n process.stdout.write(getStatusLine(statusObj) + '\\n');\n }\n\n const successfullyPushedDictionaries: Dictionary[] = [];\n\n // Start spinner timer\n const spinnerTimer = setInterval(() => {\n updateAllStatusLines(dictionariesStatuses);\n }, 100); // Update every 100ms\n\n const processDictionary = async (\n statusObj: DictionariesStatus\n ): Promise<void> => {\n statusObj.status = 'pushing';\n\n try {\n const intlayerDictionaryAPI = getDictionaryAPI(undefined, config);\n const pushResult = await intlayerDictionaryAPI.pushDictionaries(\n [statusObj.dictionary],\n {\n headers: {\n Authorization: `Bearer ${oAuth2AccessToken}`,\n },\n }\n );\n\n const updatedDictionaries = pushResult.data?.updatedDictionaries || [];\n const newDictionaries = pushResult.data?.newDictionaries || [];\n\n if (updatedDictionaries.includes(statusObj.dictionary.key)) {\n statusObj.status = 'modified';\n successfullyPushedDictionaries.push(statusObj.dictionary);\n } else if (newDictionaries.includes(statusObj.dictionary.key)) {\n statusObj.status = 'pushed';\n successfullyPushedDictionaries.push(statusObj.dictionary);\n } else {\n statusObj.status = 'unknown';\n }\n } catch (error) {\n statusObj.status = 'error';\n statusObj.error = error as Error;\n statusObj.errorMessage = `Error pushing dictionary ${statusObj.dictionary.key}: ${error}`;\n }\n };\n\n // Process dictionaries in parallel with a concurrency limit\n const limit = pLimit(5); // Limit the number of concurrent requests\n const pushPromises = dictionariesStatuses.map((statusObj) =>\n limit(() => processDictionary(statusObj))\n );\n await Promise.all(pushPromises);\n\n // Stop the spinner timer\n clearInterval(spinnerTimer);\n\n // Update statuses one last time\n updateAllStatusLines(dictionariesStatuses);\n\n // Output any error messages\n for (const statusObj of dictionariesStatuses) {\n if (statusObj.errorMessage) {\n appLogger(statusObj.errorMessage, {\n level: 'error',\n });\n }\n }\n\n // Handle delete or keep options\n const deleteOption = options?.deleteLocaleDictionary;\n const keepOption = options?.keepLocaleDictionary;\n\n if (deleteOption && keepOption) {\n throw new Error(\n 'Cannot specify both --deleteLocaleDictionary and --keepLocaleDictionary options.'\n );\n }\n\n if (deleteOption) {\n // Delete only the successfully pushed dictionaries\n await deleteLocalDictionaries(successfullyPushedDictionaries, options);\n } else if (keepOption) {\n // Do nothing, keep the local dictionaries\n } else {\n // Ask the user\n const answer = await askUser(\n 'Do you want to delete the local dictionaries that were successfully pushed? (yes/no): '\n );\n if (answer.toLowerCase() === 'yes' || answer.toLowerCase() === 'y') {\n await deleteLocalDictionaries(successfullyPushedDictionaries, options);\n }\n }\n } catch (error) {\n appLogger(error, {\n level: 'error',\n });\n }\n};\n\nconst askUser = (question: string): Promise<string> => {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n return new Promise((resolve) => {\n rl.question(question, (answer: string) => {\n rl.close();\n resolve(answer);\n });\n });\n};\n\nconst deleteLocalDictionaries = async (\n dictionariesToDelete: Dictionary[],\n options?: PushOptions\n): Promise<void> => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config);\n const { baseDir } = config.content;\n\n // Use a Set to collect all unique file paths\n const filePathsSet: Set<string> = new Set();\n\n for (const dictionary of dictionariesToDelete) {\n const { filePath } = dictionary;\n\n if (!filePath) {\n appLogger(`Dictionary ${dictionary.key} does not have a file path`, {\n level: 'error',\n });\n continue;\n }\n\n filePathsSet.add(filePath);\n }\n\n for (const filePath of filePathsSet) {\n const relativePath = relative(baseDir, filePath);\n\n try {\n const stats = await fsPromises.lstat(filePath);\n\n if (stats.isFile()) {\n await fsPromises.unlink(filePath);\n appLogger(`Deleted file ${relativePath}`, {});\n } else if (stats.isDirectory()) {\n appLogger(`Path is a directory ${relativePath}, skipping.`, {});\n } else {\n appLogger(`Unknown file type for ${relativePath}, skipping.`, {});\n }\n } catch (err) {\n appLogger(`Error deleting ${relativePath}: ${err}`, {\n level: 'error',\n });\n }\n }\n};\n\nconst getStatusIcon = (status: string): string => {\n const statusIcons: Record<string, string> = {\n pending: '⏲',\n pushing: '', // Spinner handled separately\n modified: '✔',\n pushed: '✔',\n error: '✖',\n };\n return statusIcons[status] || '';\n};\n\nconst getStatusLine = (statusObj: DictionariesStatus): string => {\n let icon = getStatusIcon(statusObj.status);\n let colorStart = '';\n let colorEnd = '';\n\n if (statusObj.status === 'pushing') {\n // Use spinner frame\n icon = spinnerFrames[statusObj.spinnerFrameIndex! % spinnerFrames.length];\n colorStart = BLUE;\n colorEnd = RESET;\n } else if (statusObj.status === 'error') {\n colorStart = RED;\n colorEnd = RESET;\n } else if (statusObj.status === 'pushed' || statusObj.status === 'modified') {\n colorStart = GREEN;\n colorEnd = RESET;\n } else {\n colorStart = GREY;\n colorEnd = RESET;\n }\n\n return `- ${statusObj.dictionary.key} ${GREY_DARK}[${colorStart}${icon}${statusObj.status}${GREY_DARK}]${colorEnd}`;\n};\n\nconst updateAllStatusLines = (dictionariesStatuses: DictionariesStatus[]) => {\n // Move cursor up to the first status line\n readline.moveCursor(process.stdout, 0, -dictionariesStatuses.length);\n for (const statusObj of dictionariesStatuses) {\n // Clear the line\n readline.clearLine(process.stdout, 0);\n\n if (statusObj.status === 'pushing') {\n // Update spinner frame\n statusObj.spinnerFrameIndex =\n (statusObj.spinnerFrameIndex! + 1) % spinnerFrames.length;\n }\n\n // Write the status line\n process.stdout.write(getStatusLine(statusObj) + '\\n');\n }\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/push.ts"],"sourcesContent":["import { getIntlayerAPIProxy } from '@intlayer/api';\nimport {\n formatPath,\n listGitFiles,\n ListGitFilesOptions,\n parallelize,\n} from '@intlayer/chokidar';\nimport {\n ANSIColors,\n getAppLogger,\n getConfiguration,\n GetConfigurationOptions,\n} from '@intlayer/config';\nimport type { Dictionary } from '@intlayer/core';\nimport dictionariesRecord from '@intlayer/dictionaries-entry';\nimport * as fsPromises from 'fs/promises';\nimport * as readline from 'readline';\nimport { PushLogger, type PushStatus } from './pushLog';\n\ntype PushOptions = {\n deleteLocaleDictionary?: boolean;\n keepLocaleDictionary?: boolean;\n dictionaries?: string[];\n gitOptions?: ListGitFilesOptions;\n configOptions?: GetConfigurationOptions;\n};\n\ntype DictionariesStatus = {\n dictionary: Dictionary;\n status: 'pending' | 'pushing' | 'modified' | 'pushed' | 'unknown' | 'error';\n error?: Error;\n errorMessage?: string;\n};\n\n/**\n * Get all local dictionaries and push them simultaneously.\n */\nexport const push = async (options?: PushOptions): Promise<void> => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config, {\n config: {\n prefix: '',\n },\n });\n const { clientId, clientSecret } = config.editor;\n try {\n if (!clientId || !clientSecret) {\n throw new Error(\n 'Missing OAuth2 client ID or client secret. To get access token go to https://intlayer.org/dashboard/project.'\n );\n }\n\n const intlayerAPI = getIntlayerAPIProxy(undefined, config);\n\n let dictionaries: Dictionary[] = Object.values(dictionariesRecord);\n const existingDictionariesKeys: string[] = Object.keys(dictionariesRecord);\n\n if (options?.dictionaries) {\n // Check if the provided dictionaries exist\n const noneExistingDictionariesOption = options.dictionaries.filter(\n (dictionaryId) => !existingDictionariesKeys.includes(dictionaryId)\n );\n\n if (noneExistingDictionariesOption.length > 0) {\n appLogger(\n `The following dictionaries do not exist: ${noneExistingDictionariesOption.join(\n ', '\n )} and have been ignored.`,\n {\n level: 'error',\n }\n );\n }\n\n // Filter the dictionaries from the provided list of IDs\n dictionaries = dictionaries.filter((dictionary) =>\n options.dictionaries!.includes(dictionary.key)\n );\n }\n\n if (options?.gitOptions) {\n const gitFiles = await listGitFiles(options.gitOptions);\n }\n\n // Check if the dictionaries list is empty\n if (dictionaries.length === 0) {\n appLogger('No local dictionaries found', {\n level: 'error',\n });\n return;\n }\n\n appLogger('Pushing dictionaries:', {});\n\n // Prepare dictionaries statuses\n const dictionariesStatuses: DictionariesStatus[] = dictionaries.map(\n (dictionary) => ({\n dictionary,\n status: 'pending',\n })\n );\n\n // Initialize aggregated logger similar to loadDictionaries\n const logger = new PushLogger();\n logger.update(\n dictionariesStatuses.map<PushStatus>((s) => ({\n dictionaryKey: s.dictionary.key,\n status: 'pending',\n }))\n );\n\n const successfullyPushedDictionaries: Dictionary[] = [];\n\n const processDictionary = async (\n statusObj: DictionariesStatus\n ): Promise<void> => {\n statusObj.status = 'pushing';\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'pushing' },\n ]);\n\n try {\n const pushResult = await intlayerAPI.dictionary.pushDictionaries([\n statusObj.dictionary,\n ]);\n\n const updatedDictionaries = pushResult.data?.updatedDictionaries || [];\n const newDictionaries = pushResult.data?.newDictionaries || [];\n\n if (updatedDictionaries.includes(statusObj.dictionary.key)) {\n statusObj.status = 'modified';\n successfullyPushedDictionaries.push(statusObj.dictionary);\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'modified' },\n ]);\n } else if (newDictionaries.includes(statusObj.dictionary.key)) {\n statusObj.status = 'pushed';\n successfullyPushedDictionaries.push(statusObj.dictionary);\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'pushed' },\n ]);\n } else {\n statusObj.status = 'unknown';\n }\n } catch (error) {\n statusObj.status = 'error';\n statusObj.error = error as Error;\n statusObj.errorMessage = `Error pushing dictionary ${statusObj.dictionary.key}: ${error}`;\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'error' },\n ]);\n }\n };\n\n // Process dictionaries in parallel with a concurrency limit (reuse parallelize)\n await parallelize(dictionariesStatuses, processDictionary, 5);\n\n // Stop the logger and render final state\n logger.finish();\n\n // Print per-dictionary summary similar to loadDictionaries\n const iconFor = (status: DictionariesStatus['status']) => {\n switch (status) {\n case 'pushed':\n case 'modified':\n return '✔';\n case 'error':\n return '✖';\n default:\n return '⏲';\n }\n };\n\n const colorFor = (status: DictionariesStatus['status']) => {\n switch (status) {\n case 'pushed':\n case 'modified':\n return ANSIColors.GREEN;\n case 'error':\n return ANSIColors.RED;\n default:\n return ANSIColors.BLUE;\n }\n };\n\n for (const s of dictionariesStatuses) {\n const icon = iconFor(s.status);\n const color = colorFor(s.status);\n appLogger(\n ` - ${s.dictionary.key} ${ANSIColors.GREY}[${color}${icon} ${s.status}${ANSIColors.GREY}]${ANSIColors.RESET}`\n );\n }\n\n // Output any error messages\n for (const statusObj of dictionariesStatuses) {\n if (statusObj.errorMessage) {\n appLogger(statusObj.errorMessage, {\n level: 'error',\n });\n }\n }\n\n // Handle delete or keep options\n const deleteOption = options?.deleteLocaleDictionary;\n const keepOption = options?.keepLocaleDictionary;\n\n if (deleteOption && keepOption) {\n throw new Error(\n 'Cannot specify both --deleteLocaleDictionary and --keepLocaleDictionary options.'\n );\n }\n\n if (deleteOption) {\n // Delete only the successfully pushed dictionaries\n await deleteLocalDictionaries(successfullyPushedDictionaries, options);\n } else if (keepOption) {\n // Do nothing, keep the local dictionaries\n } else {\n // Ask the user\n const answer = await askUser(\n 'Do you want to delete the local dictionaries that were successfully pushed? (yes/no): '\n );\n if (answer.toLowerCase() === 'yes' || answer.toLowerCase() === 'y') {\n await deleteLocalDictionaries(successfullyPushedDictionaries, options);\n }\n }\n } catch (error) {\n appLogger(error, {\n level: 'error',\n });\n }\n};\n\nconst askUser = (question: string): Promise<string> => {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n return new Promise((resolve) => {\n rl.question(question, (answer: string) => {\n rl.close();\n resolve(answer);\n });\n });\n};\n\nconst deleteLocalDictionaries = async (\n dictionariesToDelete: Dictionary[],\n options?: PushOptions\n): Promise<void> => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config, {\n config: {\n prefix: '',\n },\n });\n\n // Use a Set to collect all unique file paths\n const filePathsSet: Set<string> = new Set();\n\n for (const dictionary of dictionariesToDelete) {\n const { filePath } = dictionary;\n\n if (!filePath) {\n appLogger(`Dictionary ${dictionary.key} does not have a file path`, {\n level: 'error',\n });\n continue;\n }\n\n filePathsSet.add(filePath);\n }\n\n for (const filePath of filePathsSet) {\n try {\n const stats = await fsPromises.lstat(filePath);\n\n if (stats.isFile()) {\n await fsPromises.unlink(filePath);\n appLogger(`Deleted file ${formatPath(filePath)}`, {});\n } else if (stats.isDirectory()) {\n appLogger(`Path is a directory ${formatPath(filePath)}, skipping.`, {});\n } else {\n appLogger(\n `Unknown file type for ${formatPath(filePath)}, skipping.`,\n {}\n );\n }\n } catch (err) {\n appLogger(`Error deleting ${formatPath(filePath)}: ${err}`, {\n level: 'error',\n });\n }\n }\n};\n\n// Legacy per-line spinner output removed in favor of aggregated PushLogger\n"],"mappings":"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","names":[]}
|
package/dist/esm/pushConfig.mjs
CHANGED
|
@@ -1,47 +1,32 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getIntlayerAPIProxy } from "@intlayer/api";
|
|
2
2
|
import {
|
|
3
3
|
getAppLogger,
|
|
4
4
|
getConfiguration
|
|
5
5
|
} from "@intlayer/config";
|
|
6
6
|
const pushConfig = async (options) => {
|
|
7
7
|
const config = getConfiguration(options?.configOptions);
|
|
8
|
-
const appLogger = getAppLogger(config
|
|
8
|
+
const appLogger = getAppLogger(config, {
|
|
9
|
+
config: {
|
|
10
|
+
prefix: ""
|
|
11
|
+
}
|
|
12
|
+
});
|
|
9
13
|
const { clientId, clientSecret } = config.editor;
|
|
10
14
|
if (!clientId || !clientSecret) {
|
|
11
15
|
appLogger(
|
|
12
16
|
"Missing OAuth2 client ID or client secret. To get access token go to https://intlayer.org/dashboard/project.",
|
|
13
17
|
{
|
|
14
|
-
level: "error"
|
|
15
|
-
config: {
|
|
16
|
-
prefix: options?.logPrefix
|
|
17
|
-
}
|
|
18
|
+
level: "error"
|
|
18
19
|
}
|
|
19
20
|
);
|
|
20
21
|
return;
|
|
21
22
|
}
|
|
22
|
-
const intlayerAPI =
|
|
23
|
-
const
|
|
24
|
-
const oAuth2AccessToken = oAuth2TokenResult.data?.accessToken;
|
|
25
|
-
const getDictionariesKeysResult = await intlayerAPI.project.pushProjectConfiguration(config, {
|
|
26
|
-
...oAuth2AccessToken && {
|
|
27
|
-
headers: {
|
|
28
|
-
Authorization: `Bearer ${oAuth2AccessToken}`
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
});
|
|
23
|
+
const intlayerAPI = getIntlayerAPIProxy(void 0, config);
|
|
24
|
+
const getDictionariesKeysResult = await intlayerAPI.project.pushProjectConfiguration(config);
|
|
32
25
|
if (!getDictionariesKeysResult.data) {
|
|
33
26
|
throw new Error("Error pushing project configuration");
|
|
34
27
|
}
|
|
35
|
-
appLogger("Project configuration pushed successfully"
|
|
36
|
-
|
|
37
|
-
prefix: options?.logPrefix
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
appLogger(JSON.stringify(getDictionariesKeysResult.data, null, 2), {
|
|
41
|
-
config: {
|
|
42
|
-
prefix: options?.logPrefix
|
|
43
|
-
}
|
|
44
|
-
});
|
|
28
|
+
appLogger("Project configuration pushed successfully");
|
|
29
|
+
appLogger(JSON.stringify(getDictionariesKeysResult.data, null, 2));
|
|
45
30
|
};
|
|
46
31
|
export {
|
|
47
32
|
pushConfig
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/pushConfig.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"sources":["../../src/pushConfig.ts"],"sourcesContent":["import { getIntlayerAPIProxy } from '@intlayer/api';\nimport {\n getAppLogger,\n getConfiguration,\n type GetConfigurationOptions,\n} from '@intlayer/config';\n\ntype PushOptions = {\n configOptions?: GetConfigurationOptions;\n};\n\nexport const pushConfig = async (options?: PushOptions) => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config, {\n config: {\n prefix: '',\n },\n });\n\n const { clientId, clientSecret } = config.editor;\n\n if (!clientId || !clientSecret) {\n appLogger(\n 'Missing OAuth2 client ID or client secret. To get access token go to https://intlayer.org/dashboard/project.',\n {\n level: 'error',\n }\n );\n return;\n }\n\n const intlayerAPI = getIntlayerAPIProxy(undefined, config);\n\n // Push the project configuration\n const getDictionariesKeysResult =\n await intlayerAPI.project.pushProjectConfiguration(config);\n\n if (!getDictionariesKeysResult.data) {\n throw new Error('Error pushing project configuration');\n }\n\n appLogger('Project configuration pushed successfully');\n\n appLogger(JSON.stringify(getDictionariesKeysResult.data, null, 2));\n};\n"],"mappings":"AAAA,SAAS,2BAA2B;AACpC;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AAMA,MAAM,aAAa,OAAO,YAA0B;AACzD,QAAM,SAAS,iBAAiB,SAAS,aAAa;AACtD,QAAM,YAAY,aAAa,QAAQ;AAAA,IACrC,QAAQ;AAAA,MACN,QAAQ;AAAA,IACV;AAAA,EACF,CAAC;AAED,QAAM,EAAE,UAAU,aAAa,IAAI,OAAO;AAE1C,MAAI,CAAC,YAAY,CAAC,cAAc;AAC9B;AAAA,MACE;AAAA,MACA;AAAA,QACE,OAAO;AAAA,MACT;AAAA,IACF;AACA;AAAA,EACF;AAEA,QAAM,cAAc,oBAAoB,QAAW,MAAM;AAGzD,QAAM,4BACJ,MAAM,YAAY,QAAQ,yBAAyB,MAAM;AAE3D,MAAI,CAAC,0BAA0B,MAAM;AACnC,UAAM,IAAI,MAAM,qCAAqC;AAAA,EACvD;AAEA,YAAU,2CAA2C;AAErD,YAAU,KAAK,UAAU,0BAA0B,MAAM,MAAM,CAAC,CAAC;AACnE;","names":[]}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ANSIColors,
|
|
3
|
+
colorize,
|
|
4
|
+
getConfiguration,
|
|
5
|
+
spinnerFrames
|
|
6
|
+
} from "@intlayer/config";
|
|
7
|
+
class PushLogger {
|
|
8
|
+
statuses = [];
|
|
9
|
+
spinnerTimer = null;
|
|
10
|
+
spinnerIndex = 0;
|
|
11
|
+
renderedLines = 0;
|
|
12
|
+
spinnerFrames = spinnerFrames;
|
|
13
|
+
isFinished = false;
|
|
14
|
+
prefix;
|
|
15
|
+
lastRenderedState = "";
|
|
16
|
+
constructor() {
|
|
17
|
+
const configuration = getConfiguration();
|
|
18
|
+
this.prefix = configuration.log.prefix;
|
|
19
|
+
}
|
|
20
|
+
update(newStatuses) {
|
|
21
|
+
if (this.isFinished) return;
|
|
22
|
+
for (const status of newStatuses) {
|
|
23
|
+
const index = this.statuses.findIndex(
|
|
24
|
+
(s) => s.dictionaryKey === status.dictionaryKey
|
|
25
|
+
);
|
|
26
|
+
if (index >= 0) {
|
|
27
|
+
this.statuses[index] = status;
|
|
28
|
+
} else {
|
|
29
|
+
this.statuses.push(status);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
this.startSpinner();
|
|
33
|
+
this.render();
|
|
34
|
+
}
|
|
35
|
+
finish() {
|
|
36
|
+
this.isFinished = true;
|
|
37
|
+
this.stopSpinner();
|
|
38
|
+
this.render();
|
|
39
|
+
}
|
|
40
|
+
startSpinner() {
|
|
41
|
+
if (this.spinnerTimer || this.isFinished) return;
|
|
42
|
+
this.spinnerTimer = setInterval(() => {
|
|
43
|
+
this.spinnerIndex = (this.spinnerIndex + 1) % this.spinnerFrames.length;
|
|
44
|
+
this.render();
|
|
45
|
+
}, 100);
|
|
46
|
+
}
|
|
47
|
+
stopSpinner() {
|
|
48
|
+
if (!this.spinnerTimer) return;
|
|
49
|
+
clearInterval(this.spinnerTimer);
|
|
50
|
+
this.spinnerTimer = null;
|
|
51
|
+
}
|
|
52
|
+
render() {
|
|
53
|
+
const { total, done, pushed, modified, errors } = this.computeProgress();
|
|
54
|
+
const frame = this.spinnerFrames[this.spinnerIndex];
|
|
55
|
+
const lines = [];
|
|
56
|
+
const isDone = done === total;
|
|
57
|
+
const progressLabel = `dictionaries: ${done}/${total}`;
|
|
58
|
+
const details = [];
|
|
59
|
+
if (pushed > 0) details.push(`new: ${pushed}`);
|
|
60
|
+
if (modified > 0) details.push(`modified: ${modified}`);
|
|
61
|
+
if (errors > 0) details.push(colorize(`errors: ${errors}`, ANSIColors.RED));
|
|
62
|
+
const suffix = details.length > 0 ? ` (${details.join(", ")})` : "";
|
|
63
|
+
if (isDone) {
|
|
64
|
+
lines.push(
|
|
65
|
+
`${this.prefix} ${colorize("\u2714", ANSIColors.GREEN)} pushed ${progressLabel}${suffix}`
|
|
66
|
+
);
|
|
67
|
+
} else {
|
|
68
|
+
lines.push(
|
|
69
|
+
`${this.prefix} ${colorize(frame, ANSIColors.BLUE)} pushing ${progressLabel}${suffix}`
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
const currentState = lines.join("\n");
|
|
73
|
+
if (currentState === this.lastRenderedState) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
this.lastRenderedState = currentState;
|
|
77
|
+
if (this.renderedLines > 0) {
|
|
78
|
+
process.stdout.write(`\x1B[${this.renderedLines}F`);
|
|
79
|
+
}
|
|
80
|
+
const totalLinesToClear = Math.max(this.renderedLines, lines.length);
|
|
81
|
+
for (let i = 0; i < totalLinesToClear; i++) {
|
|
82
|
+
process.stdout.write("\x1B[2K");
|
|
83
|
+
const line = lines[i];
|
|
84
|
+
if (line !== void 0) {
|
|
85
|
+
process.stdout.write(line);
|
|
86
|
+
}
|
|
87
|
+
process.stdout.write("\n");
|
|
88
|
+
}
|
|
89
|
+
this.renderedLines = lines.length;
|
|
90
|
+
}
|
|
91
|
+
computeProgress() {
|
|
92
|
+
const keys = new Set(this.statuses.map((s) => s.dictionaryKey));
|
|
93
|
+
const pushed = this.statuses.filter((s) => s.status === "pushed").length;
|
|
94
|
+
const modified = this.statuses.filter(
|
|
95
|
+
(s) => s.status === "modified"
|
|
96
|
+
).length;
|
|
97
|
+
const errors = this.statuses.filter((s) => s.status === "error").length;
|
|
98
|
+
const done = pushed + modified + errors;
|
|
99
|
+
return {
|
|
100
|
+
total: keys.size,
|
|
101
|
+
done,
|
|
102
|
+
pushed,
|
|
103
|
+
modified,
|
|
104
|
+
errors
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
export {
|
|
109
|
+
PushLogger
|
|
110
|
+
};
|
|
111
|
+
//# sourceMappingURL=pushLog.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/pushLog.ts"],"sourcesContent":["import {\n ANSIColors,\n colorize,\n getConfiguration,\n spinnerFrames,\n} from '@intlayer/config';\n\nexport type PushStatus = {\n dictionaryKey: string;\n status: 'pending' | 'pushing' | 'pushed' | 'modified' | 'error';\n errorMessage?: string;\n};\n\nexport class PushLogger {\n private statuses: PushStatus[] = [];\n private spinnerTimer: NodeJS.Timeout | null = null;\n private spinnerIndex = 0;\n private renderedLines = 0;\n private readonly spinnerFrames = spinnerFrames;\n private isFinished = false;\n private readonly prefix: string;\n private lastRenderedState: string = '';\n\n constructor() {\n const configuration = getConfiguration();\n this.prefix = configuration.log.prefix;\n }\n\n update(newStatuses: PushStatus[]) {\n if (this.isFinished) return;\n for (const status of newStatuses) {\n const index = this.statuses.findIndex(\n (s) => s.dictionaryKey === status.dictionaryKey\n );\n if (index >= 0) {\n this.statuses[index] = status;\n } else {\n this.statuses.push(status);\n }\n }\n\n this.startSpinner();\n this.render();\n }\n\n finish() {\n this.isFinished = true;\n this.stopSpinner();\n this.render();\n }\n\n private startSpinner() {\n if (this.spinnerTimer || this.isFinished) return;\n this.spinnerTimer = setInterval(() => {\n this.spinnerIndex = (this.spinnerIndex + 1) % this.spinnerFrames.length;\n this.render();\n }, 100);\n }\n\n private stopSpinner() {\n if (!this.spinnerTimer) return;\n clearInterval(this.spinnerTimer);\n this.spinnerTimer = null;\n }\n\n private render() {\n const { total, done, pushed, modified, errors } = this.computeProgress();\n\n const frame = this.spinnerFrames[this.spinnerIndex];\n const lines: string[] = [];\n\n const isDone = done === total;\n\n const progressLabel = `dictionaries: ${done}/${total}`;\n const details: string[] = [];\n if (pushed > 0) details.push(`new: ${pushed}`);\n if (modified > 0) details.push(`modified: ${modified}`);\n if (errors > 0) details.push(colorize(`errors: ${errors}`, ANSIColors.RED));\n\n const suffix = details.length > 0 ? ` (${details.join(', ')})` : '';\n\n if (isDone) {\n lines.push(\n `${this.prefix} ${colorize('✔', ANSIColors.GREEN)} pushed ${progressLabel}${suffix}`\n );\n } else {\n lines.push(\n `${this.prefix} ${colorize(frame, ANSIColors.BLUE)} pushing ${progressLabel}${suffix}`\n );\n }\n\n const currentState = lines.join('\\n');\n if (currentState === this.lastRenderedState) {\n return;\n }\n this.lastRenderedState = currentState;\n\n if (this.renderedLines > 0) {\n process.stdout.write(`\\x1b[${this.renderedLines}F`);\n }\n\n const totalLinesToClear = Math.max(this.renderedLines, lines.length);\n for (let i = 0; i < totalLinesToClear; i++) {\n process.stdout.write('\\x1b[2K');\n const line = lines[i];\n if (line !== undefined) {\n process.stdout.write(line);\n }\n process.stdout.write('\\n');\n }\n\n this.renderedLines = lines.length;\n }\n\n private computeProgress() {\n const keys = new Set(this.statuses.map((s) => s.dictionaryKey));\n\n const pushed = this.statuses.filter((s) => s.status === 'pushed').length;\n const modified = this.statuses.filter(\n (s) => s.status === 'modified'\n ).length;\n const errors = this.statuses.filter((s) => s.status === 'error').length;\n const done = pushed + modified + errors;\n\n return {\n total: keys.size,\n done,\n pushed,\n modified,\n errors,\n } as const;\n }\n}\n"],"mappings":"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","names":[]}
|