gt 2.22.4 → 2.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/dist/auth/errors.d.ts +1 -0
- package/dist/auth/errors.js +12 -2
- package/dist/auth/errors.js.map +1 -1
- package/dist/auth/interactiveLogin.d.ts +2 -0
- package/dist/auth/interactiveLogin.js +22 -0
- package/dist/auth/interactiveLogin.js.map +1 -0
- package/dist/auth/oauth.js +2 -2
- package/dist/auth/oauth.js.map +1 -1
- package/dist/cli/base.d.ts +22 -4
- package/dist/cli/base.js +328 -223
- package/dist/cli/base.js.map +1 -1
- package/dist/cli/commands/api.js +15 -16
- package/dist/cli/commands/api.js.map +1 -1
- package/dist/cli/node.js +1 -1
- package/dist/cli/node.js.map +1 -1
- package/dist/cli/react.js +1 -1
- package/dist/cli/react.js.map +1 -1
- package/dist/cli/vue.js +2 -2
- package/dist/cli/vue.js.map +1 -1
- package/dist/config/generateSettings.d.ts +2 -0
- package/dist/config/generateSettings.js +13 -6
- package/dist/config/generateSettings.js.map +1 -1
- package/dist/config/resolveConfig.js +0 -4
- package/dist/config/resolveConfig.js.map +1 -1
- package/dist/config/validateSettings.js +5 -4
- package/dist/config/validateSettings.js.map +1 -1
- package/dist/console/{inkLocaleData.d.ts → localeOptions.d.ts} +7 -2
- package/dist/console/{inkLocaleData.js → localeOptions.js} +3 -8
- package/dist/console/localeOptions.js.map +1 -0
- package/dist/console/logger.d.ts +7 -0
- package/dist/console/logger.js +48 -85
- package/dist/console/logger.js.map +1 -1
- package/dist/console/logging.d.ts +11 -1
- package/dist/console/logging.js +88 -100
- package/dist/console/logging.js.map +1 -1
- package/dist/formats/files/aggregateFiles.js +1 -1
- package/dist/formats/files/supportedFiles.d.ts +3 -0
- package/dist/formats/files/supportedFiles.js +10 -1
- package/dist/formats/files/supportedFiles.js.map +1 -1
- package/dist/formats/yaml/mergeYaml.js +1 -1
- package/dist/fs/config/loadConfig.d.ts +2 -0
- package/dist/fs/config/loadConfig.js +5 -1
- package/dist/fs/config/loadConfig.js.map +1 -1
- package/dist/fs/config/setupConfig.d.ts +18 -9
- package/dist/fs/config/setupConfig.js +51 -31
- package/dist/fs/config/setupConfig.js.map +1 -1
- package/dist/fs/createLoadTranslationsFile.d.ts +22 -1
- package/dist/fs/createLoadTranslationsFile.js +43 -20
- package/dist/fs/createLoadTranslationsFile.js.map +1 -1
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/generated/version.js.map +1 -1
- package/dist/hooks/postProcess.d.ts +1 -2
- package/dist/hooks/postProcess.js +1 -1
- package/dist/hooks/postProcess.js.map +1 -1
- package/dist/locadex/setupFlow.d.ts +4 -1
- package/dist/locadex/setupFlow.js +5 -3
- package/dist/locadex/setupFlow.js.map +1 -1
- package/dist/react/jsx/utils/jsxParsing/addGTIdentifierToSyntaxTree.js +1 -1
- package/dist/react/jsx/utils/jsxParsing/parseJsx.js +1 -1
- package/dist/react/jsx/utils/parseString.js +1 -1
- package/dist/react/jsx/utils/stringParsing/derivation/index.js +1 -1
- package/dist/setup/buildTools/index.d.ts +44 -0
- package/dist/setup/buildTools/index.js +10 -0
- package/dist/setup/buildTools/index.js.map +1 -0
- package/dist/setup/buildTools/vite.d.ts +2 -0
- package/dist/setup/buildTools/vite.js +61 -0
- package/dist/setup/buildTools/vite.js.map +1 -0
- package/dist/setup/developmentCredentials.d.ts +40 -5
- package/dist/setup/developmentCredentials.js +119 -37
- package/dist/setup/developmentCredentials.js.map +1 -1
- package/dist/setup/instructions/base.md +1 -1
- package/dist/setup/onboarding.d.ts +131 -0
- package/dist/setup/onboarding.js +289 -0
- package/dist/setup/onboarding.js.map +1 -0
- package/dist/setup/setupTarget.d.ts +1 -0
- package/dist/setup/setupTarget.js +52 -0
- package/dist/setup/setupTarget.js.map +1 -0
- package/dist/setup/setupViteSPA.d.ts +32 -1
- package/dist/setup/setupViteSPA.js +110 -20
- package/dist/setup/setupViteSPA.js.map +1 -1
- package/dist/setup/userInput.d.ts +12 -3
- package/dist/setup/userInput.js +27 -11
- package/dist/setup/userInput.js.map +1 -1
- package/dist/setup/wizard.d.ts +19 -3
- package/dist/setup/wizard.js +119 -105
- package/dist/setup/wizard.js.map +1 -1
- package/dist/types/index.d.ts +2 -1
- package/dist/types/index.js +13 -1
- package/dist/types/index.js.map +1 -0
- package/dist/utils/credentials.d.ts +9 -6
- package/dist/utils/credentials.js +36 -22
- package/dist/utils/credentials.js.map +1 -1
- package/dist/utils/monorepoVersionCheck.d.ts +1 -1
- package/dist/utils/monorepoVersionCheck.js +5 -5
- package/dist/utils/monorepoVersionCheck.js.map +1 -1
- package/dist/utils/packageManager.js +13 -14
- package/dist/utils/packageManager.js.map +1 -1
- package/package.json +5 -9
- package/dist/console/inkFields.d.ts +0 -23
- package/dist/console/inkFields.js +0 -88
- package/dist/console/inkFields.js.map +0 -1
- package/dist/console/inkLayout.d.ts +0 -7
- package/dist/console/inkLayout.js +0 -140
- package/dist/console/inkLayout.js.map +0 -1
- package/dist/console/inkLocaleData.js.map +0 -1
- package/dist/console/inkPrompts.d.ts +0 -8
- package/dist/console/inkPrompts.js +0 -499
- package/dist/console/inkPrompts.js.map +0 -1
- package/dist/console/inkSession.d.ts +0 -3
- package/dist/console/inkSession.js +0 -42
- package/dist/console/inkSession.js.map +0 -1
- package/dist/console/inkTerminal.d.ts +0 -4
- package/dist/console/inkTerminal.js +0 -15
- package/dist/console/inkTerminal.js.map +0 -1
- package/dist/console/inkTheme.d.ts +0 -1
- package/dist/console/inkTheme.js +0 -6
- package/dist/console/inkTheme.js.map +0 -1
- package/dist/console/inkTypes.d.ts +0 -69
- package/dist/console/inkTypes.js +0 -1
- package/dist/console/inkUtils.d.ts +0 -24
- package/dist/console/inkUtils.js +0 -87
- package/dist/console/inkUtils.js.map +0 -1
- package/dist/console/terminalSession.d.ts +0 -5
- package/dist/console/terminalSession.js +0 -38
- package/dist/console/terminalSession.js.map +0 -1
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import type { Option } from '@clack/prompts';
|
|
1
2
|
import type { CustomMapping, FileToUpload } from 'generaltranslation/types';
|
|
2
3
|
import { type InlineLibrary } from '../types/libraries.js';
|
|
3
4
|
/**
|
|
4
5
|
* Strip ANSI escape codes from a string (e.g., chalk color codes)
|
|
5
6
|
*/
|
|
6
7
|
export declare function stripAnsi(str: string): string;
|
|
8
|
+
/** The message of the last logErrorAndExit call, for exit-time reporting. */
|
|
9
|
+
export declare function getLastExitError(): string | undefined;
|
|
7
10
|
export declare function logErrorAndExit(message: string): never;
|
|
8
11
|
export declare function exitSync(code: number): never;
|
|
9
12
|
export declare function displayHeader(introString?: string): void;
|
|
@@ -17,6 +20,12 @@ export declare function promptText({ message, defaultValue, validate, }: {
|
|
|
17
20
|
defaultValue?: string;
|
|
18
21
|
validate?: (value: string) => boolean | string;
|
|
19
22
|
}): Promise<string>;
|
|
23
|
+
/**
|
|
24
|
+
* Searchable locale options: supported locales ranked by the query, the
|
|
25
|
+
* configured customMapping aliases, and any other valid locale typed or
|
|
26
|
+
* already selected, so aliases and custom tags stay selectable.
|
|
27
|
+
*/
|
|
28
|
+
export declare function getLocalePromptOptions(query: string, selected?: string[], customMapping?: CustomMapping): Option<string>[];
|
|
20
29
|
export declare function promptLocale({ message, defaultValue, customMapping, }: {
|
|
21
30
|
message: string;
|
|
22
31
|
defaultValue?: string;
|
|
@@ -28,10 +37,11 @@ export declare function promptLocaleList({ message, defaultValue, required, cust
|
|
|
28
37
|
required?: boolean;
|
|
29
38
|
customMapping?: CustomMapping;
|
|
30
39
|
}): Promise<string[]>;
|
|
31
|
-
export declare function promptGlobPatterns(
|
|
40
|
+
export declare function promptGlobPatterns(options: {
|
|
32
41
|
label: string;
|
|
33
42
|
message: string;
|
|
34
43
|
defaultValue?: string;
|
|
44
|
+
validate?: (value: string) => boolean | string;
|
|
35
45
|
}): Promise<string>;
|
|
36
46
|
export declare function promptSelect<T>({ message, options, defaultValue, }: {
|
|
37
47
|
message: string;
|
package/dist/console/logging.js
CHANGED
|
@@ -1,24 +1,19 @@
|
|
|
1
|
-
import { endTerminalSession, shouldUseInkPrompts } from "./terminalSession.js";
|
|
2
1
|
import { logger } from "./logger.js";
|
|
3
2
|
import { getCLIVersion } from "../utils/packageJson.js";
|
|
4
3
|
import "../utils/constants.js";
|
|
5
|
-
import {
|
|
4
|
+
import { parseTypedLocale } from "./promptParsing.js";
|
|
5
|
+
import { getFilteredLocaleOptions } from "./localeOptions.js";
|
|
6
6
|
import { getInlineElementsLabel } from "../types/libraries.js";
|
|
7
|
-
import { cancel, confirm, isCancel, multiselect, select, text } from "@clack/prompts";
|
|
7
|
+
import { autocomplete, autocompleteMultiselect, cancel, confirm, isCancel, multiselect, select, text } from "@clack/prompts";
|
|
8
8
|
import chalk from "chalk";
|
|
9
|
+
import { createDiagnosticMessage } from "generaltranslation/internal";
|
|
9
10
|
//#region src/console/logging.ts
|
|
10
|
-
function
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
return import("./inkPrompts.js");
|
|
17
|
-
}
|
|
18
|
-
async function runInkPrompt(prompt, cancelMessage = "Operation cancelled") {
|
|
19
|
-
const result = await prompt(await loadInkPrompts());
|
|
20
|
-
if (result.cancelled) return cancelPromptAndExit(cancelMessage);
|
|
21
|
-
return result.value;
|
|
11
|
+
function exitIfCancelled(result, message = "Operation cancelled") {
|
|
12
|
+
if (isCancel(result)) {
|
|
13
|
+
cancel(message);
|
|
14
|
+
return exitSync(0);
|
|
15
|
+
}
|
|
16
|
+
return result;
|
|
22
17
|
}
|
|
23
18
|
/**
|
|
24
19
|
* Strip ANSI escape codes from a string (e.g., chalk color codes)
|
|
@@ -26,7 +21,13 @@ async function runInkPrompt(prompt, cancelMessage = "Operation cancelled") {
|
|
|
26
21
|
function stripAnsi(str) {
|
|
27
22
|
return str.replace(/\x1B\[[0-9;]*m/g, "");
|
|
28
23
|
}
|
|
24
|
+
let lastExitError;
|
|
25
|
+
/** The message of the last logErrorAndExit call, for exit-time reporting. */
|
|
26
|
+
function getLastExitError() {
|
|
27
|
+
return lastExitError;
|
|
28
|
+
}
|
|
29
29
|
function logErrorAndExit(message) {
|
|
30
|
+
lastExitError = message;
|
|
30
31
|
logger.error(message);
|
|
31
32
|
return exitSync(1);
|
|
32
33
|
}
|
|
@@ -77,117 +78,104 @@ function displayUpdatedVersionsFile(versionFilepath) {
|
|
|
77
78
|
logger.success(`Updated versions file ${chalk.cyan(versionFilepath)}`);
|
|
78
79
|
}
|
|
79
80
|
async function promptText({ message, defaultValue, validate }) {
|
|
80
|
-
|
|
81
|
-
message,
|
|
82
|
-
defaultValue,
|
|
83
|
-
validate
|
|
84
|
-
})) ?? "";
|
|
85
|
-
const result = await text({
|
|
81
|
+
return exitIfCancelled(await text({
|
|
86
82
|
message,
|
|
87
83
|
placeholder: defaultValue,
|
|
84
|
+
defaultValue,
|
|
88
85
|
validate: validate ? (value) => {
|
|
89
|
-
const validation = validate(value || "");
|
|
86
|
+
const validation = validate(value || defaultValue || "");
|
|
90
87
|
return validation === true ? void 0 : validation.toString();
|
|
91
88
|
} : void 0
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
89
|
+
}));
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Clack keeps the focused option while it still matches a new search, so
|
|
93
|
+
* typing `fr` could leave `af` (Afrikaans) focused. Refocus the top-ranked
|
|
94
|
+
* option whenever the search changes.
|
|
95
|
+
*/
|
|
96
|
+
function searchableLocaleOptions(getOptions) {
|
|
97
|
+
let lastQuery = "";
|
|
98
|
+
return function() {
|
|
99
|
+
const query = this.userInput ?? "";
|
|
100
|
+
if (query !== lastQuery) {
|
|
101
|
+
lastQuery = query;
|
|
102
|
+
this.focusedValue = void 0;
|
|
103
|
+
}
|
|
104
|
+
return getOptions(query, this.selectedValues ?? []);
|
|
105
|
+
};
|
|
98
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* Searchable locale options: supported locales ranked by the query, the
|
|
109
|
+
* configured customMapping aliases, and any other valid locale typed or
|
|
110
|
+
* already selected, so aliases and custom tags stay selectable.
|
|
111
|
+
*/
|
|
112
|
+
function getLocalePromptOptions(query, selected = [], customMapping) {
|
|
113
|
+
const normalizedQuery = query.trim().toLowerCase();
|
|
114
|
+
const supported = getFilteredLocaleOptions(query).map((option) => ({
|
|
115
|
+
value: option.code,
|
|
116
|
+
label: option.label
|
|
117
|
+
}));
|
|
118
|
+
const known = new Set(supported.map((option) => option.value));
|
|
119
|
+
const aliases = Object.keys(customMapping ?? {}).filter((alias) => alias.toLowerCase().includes(normalizedQuery)).map((alias) => ({
|
|
120
|
+
value: alias,
|
|
121
|
+
label: alias,
|
|
122
|
+
hint: "custom mapping"
|
|
123
|
+
}));
|
|
124
|
+
const typed = parseTypedLocale(query, customMapping);
|
|
125
|
+
const extras = [...selected, ...typed ? [typed] : []].filter((locale) => !known.has(locale) && !aliases.some((alias) => alias.value === locale)).map((locale) => ({
|
|
126
|
+
value: locale,
|
|
127
|
+
label: locale
|
|
128
|
+
}));
|
|
129
|
+
return [...new Map([
|
|
130
|
+
...aliases,
|
|
131
|
+
...extras,
|
|
132
|
+
...supported
|
|
133
|
+
].map((option) => [option.value, option])).values()].sort((a, b) => Number(b.value.toLowerCase() === normalizedQuery) - Number(a.value.toLowerCase() === normalizedQuery));
|
|
134
|
+
}
|
|
135
|
+
const noLocaleSelectedError = createDiagnosticMessage({
|
|
136
|
+
whatHappened: "No locale matches the search",
|
|
137
|
+
fix: "Change the search and select a locale from the list"
|
|
138
|
+
});
|
|
99
139
|
async function promptLocale({ message, defaultValue, customMapping }) {
|
|
100
|
-
|
|
101
|
-
message,
|
|
102
|
-
defaultValue,
|
|
103
|
-
customMapping
|
|
104
|
-
})) ?? "";
|
|
105
|
-
return promptText({
|
|
140
|
+
return exitIfCancelled(await autocomplete({
|
|
106
141
|
message,
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
142
|
+
placeholder: "Type to search locales",
|
|
143
|
+
initialValue: defaultValue,
|
|
144
|
+
options: searchableLocaleOptions((query) => getLocalePromptOptions(query, [], customMapping)),
|
|
145
|
+
validate: (value) => value ? void 0 : noLocaleSelectedError
|
|
146
|
+
}));
|
|
110
147
|
}
|
|
111
148
|
async function promptLocaleList({ message, defaultValue, required = true, customMapping }) {
|
|
112
|
-
|
|
149
|
+
return exitIfCancelled(await autocompleteMultiselect({
|
|
113
150
|
message,
|
|
114
|
-
|
|
151
|
+
placeholder: "Type to search, Tab or Space to select",
|
|
152
|
+
initialValues: defaultValue,
|
|
115
153
|
required,
|
|
116
|
-
customMapping
|
|
117
|
-
}))
|
|
118
|
-
return promptText({
|
|
119
|
-
message,
|
|
120
|
-
defaultValue: defaultValue?.join(" "),
|
|
121
|
-
validate: (value) => validateLocaleList(value, customMapping)
|
|
122
|
-
}).then(parseLocaleList);
|
|
154
|
+
options: searchableLocaleOptions((query, selected) => getLocalePromptOptions(query, [...defaultValue ?? [], ...selected], customMapping))
|
|
155
|
+
}));
|
|
123
156
|
}
|
|
124
|
-
async function promptGlobPatterns(
|
|
125
|
-
|
|
126
|
-
label,
|
|
127
|
-
message,
|
|
128
|
-
defaultValue
|
|
129
|
-
})) ?? "";
|
|
130
|
-
return promptText({
|
|
131
|
-
message,
|
|
132
|
-
defaultValue
|
|
133
|
-
});
|
|
157
|
+
async function promptGlobPatterns(options) {
|
|
158
|
+
return promptText(options);
|
|
134
159
|
}
|
|
135
160
|
async function promptSelect({ message, options, defaultValue }) {
|
|
136
|
-
|
|
161
|
+
return exitIfCancelled(await select({
|
|
137
162
|
message,
|
|
138
163
|
options,
|
|
139
|
-
defaultValue
|
|
140
|
-
}));
|
|
141
|
-
const result = await select({
|
|
142
|
-
message,
|
|
143
|
-
options: options.map((opt) => ({
|
|
144
|
-
value: opt.value,
|
|
145
|
-
label: opt.label,
|
|
146
|
-
hint: opt.hint
|
|
147
|
-
})),
|
|
148
164
|
initialValue: defaultValue
|
|
149
|
-
});
|
|
150
|
-
if (isCancel(result)) {
|
|
151
|
-
cancel("Operation cancelled");
|
|
152
|
-
return exitSync(0);
|
|
153
|
-
}
|
|
154
|
-
return result;
|
|
165
|
+
}));
|
|
155
166
|
}
|
|
156
167
|
async function promptMultiSelect({ message, options, required = true }) {
|
|
157
|
-
|
|
168
|
+
return exitIfCancelled(await multiselect({
|
|
158
169
|
message,
|
|
159
170
|
options,
|
|
160
171
|
required
|
|
161
|
-
}))
|
|
162
|
-
const result = await multiselect({
|
|
163
|
-
message,
|
|
164
|
-
options: options.map((opt) => ({
|
|
165
|
-
value: opt.value,
|
|
166
|
-
label: opt.label,
|
|
167
|
-
hint: opt.hint
|
|
168
|
-
})),
|
|
169
|
-
required
|
|
170
|
-
});
|
|
171
|
-
if (isCancel(result)) {
|
|
172
|
-
cancel("Operation cancelled");
|
|
173
|
-
return exitSync(0);
|
|
174
|
-
}
|
|
175
|
-
return result;
|
|
172
|
+
}));
|
|
176
173
|
}
|
|
177
174
|
async function promptConfirm({ message, defaultValue = true, cancelMessage = "Operation cancelled" }) {
|
|
178
|
-
|
|
179
|
-
message,
|
|
180
|
-
defaultValue
|
|
181
|
-
}), cancelMessage) ?? defaultValue;
|
|
182
|
-
const result = await confirm({
|
|
175
|
+
return exitIfCancelled(await confirm({
|
|
183
176
|
message,
|
|
184
177
|
initialValue: defaultValue
|
|
185
|
-
});
|
|
186
|
-
if (isCancel(result)) {
|
|
187
|
-
cancel(cancelMessage);
|
|
188
|
-
return exitSync(0);
|
|
189
|
-
}
|
|
190
|
-
return result;
|
|
178
|
+
}), cancelMessage);
|
|
191
179
|
}
|
|
192
180
|
function warnApiKeyInConfig(optionsFilepath) {
|
|
193
181
|
logger.warn(`Found ${chalk.cyan("apiKey")} in "${chalk.green(optionsFilepath)}". ` + chalk.white("Your API key is exposed! Remove it from the file and include it as an environment variable."));
|
|
@@ -221,6 +209,6 @@ function logCollectedFiles(files, inlineComponents, inlineLibrary) {
|
|
|
221
209
|
}).join("\n"));
|
|
222
210
|
}
|
|
223
211
|
//#endregion
|
|
224
|
-
export { displayCreatedConfigFile, displayHeader, displayProjectId, displayResolvedPaths, displayUpdatedConfigFile, displayUpdatedVersionsFile, exitSync, logCollectedFiles, logErrorAndExit, promptConfirm, promptGlobPatterns, promptLocale, promptLocaleList, promptMultiSelect, promptSelect, promptText, stripAnsi, warnApiKeyInConfig, warnDeprecatedField, warnHasUnwrappedExpression, warnNoId, warnTemplateLiteral, warnTernary, warnVariableProp };
|
|
212
|
+
export { displayCreatedConfigFile, displayHeader, displayProjectId, displayResolvedPaths, displayUpdatedConfigFile, displayUpdatedVersionsFile, exitSync, getLastExitError, getLocalePromptOptions, logCollectedFiles, logErrorAndExit, promptConfirm, promptGlobPatterns, promptLocale, promptLocaleList, promptMultiSelect, promptSelect, promptText, stripAnsi, warnApiKeyInConfig, warnDeprecatedField, warnHasUnwrappedExpression, warnNoId, warnTemplateLiteral, warnTernary, warnVariableProp };
|
|
225
213
|
|
|
226
214
|
//# sourceMappingURL=logging.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logging.js","names":[],"sources":["../../src/console/logging.ts"],"sourcesContent":["import {\n text,\n select,\n confirm,\n isCancel,\n cancel,\n multiselect,\n} from '@clack/prompts';\nimport type { Option } from '@clack/prompts';\nimport chalk from 'chalk';\nimport { getCLIVersion } from '../utils/packageJson.js';\nimport { logger } from './logger.js';\nimport { TEMPLATE_FILE_NAME } from '../utils/constants.js';\nimport type { CustomMapping, FileToUpload } from 'generaltranslation/types';\nimport { endTerminalSession, shouldUseInkPrompts } from './terminalSession.js';\nimport {\n parseLocaleList,\n validateLocale,\n validateLocaleList,\n} from './promptParsing.js';\nimport {\n getInlineElementsLabel,\n type InlineLibrary,\n} from '../types/libraries.js';\n\nfunction cancelPromptAndExit(message: string): never {\n endTerminalSession();\n cancel(message);\n return exitSync(0);\n}\n\nasync function loadInkPrompts() {\n return import('./inkPrompts.js');\n}\n\nasync function runInkPrompt<T>(\n prompt: (prompts: Awaited<ReturnType<typeof loadInkPrompts>>) => Promise<{\n value?: T;\n cancelled: boolean;\n }>,\n cancelMessage = 'Operation cancelled'\n) {\n const result = await prompt(await loadInkPrompts());\n if (result.cancelled) {\n return cancelPromptAndExit(cancelMessage);\n }\n return result.value;\n}\n\n/**\n * Strip ANSI escape codes from a string (e.g., chalk color codes)\n */\nexport function stripAnsi(str: string): string {\n // eslint-disable-next-line no-control-regex, no-useless-escape\n return str.replace(/\\x1B\\[[0-9;]*m/g, '');\n}\n\nexport function logErrorAndExit(message: string): never {\n logger.error(message);\n return exitSync(1);\n}\n\nexport function exitSync(code: number): never {\n // Flush logs before exit\n logger.flush();\n process.exit(code);\n}\n\n// GT specific logging\nexport function displayHeader(introString?: string) {\n // The ASCII banner is pure chatter and writes to console directly, bypassing\n // the logger, so gate it here to honor --quiet. startCommand stays outside\n // the gate: it is quiet-aware itself and must still run so the file log\n // gets its [START] marker.\n if (!logger.isQuiet()) {\n displayAsciiTitle();\n displayInitializingText();\n }\n\n if (introString) {\n logger.startCommand(introString);\n }\n}\n\nfunction displayAsciiTitle() {\n // eslint-disable-next-line no-console\n console.log(\n chalk.cyan(\n `\\n @@@@@@@@@@@@@@@@@@@@@@\n @@ @@@@@@@@@@@@ @@@@@@@\n @@ @@@ @ @\n@@ @@ @ @\n@@ @ @@@@@ @ @\n@@ @@ @@@ @ @ @\n @@ @@ @ @ @ @\n @@ @@@@@@@ @ @ @\n @@@@@@@@@ @ @`\n )\n );\n}\n\nfunction displayInitializingText() {\n const version = getCLIVersion();\n // eslint-disable-next-line no-console\n console.log(\n `\\n${chalk.bold.blue('General Translation, Inc.')}\n${chalk.dim('https://generaltranslation.com/docs')}\n${chalk.dim(`CLI Version: ${version}\\n`)}`\n );\n}\n\nexport function displayProjectId(projectId: string) {\n logger.message(\n chalk.dim(`Project ID: ${chalk.bold(projectId)}`),\n chalk.cyan('~')\n );\n}\n\nexport function displayResolvedPaths(resolvedPaths: [string, string][]) {\n const paths = resolvedPaths.map(([key, resolvedPath]) => {\n return chalk.dim(`'${chalk.white(key)}' → '${chalk.green(resolvedPath)}'`);\n });\n logger.step(`Resolved path aliases:\\n${paths.join('\\n')}`);\n}\n\nexport function displayCreatedConfigFile(configFilepath: string) {\n logger.step(`Created config file ${chalk.cyan(configFilepath)}`);\n}\n\nexport function displayUpdatedConfigFile(configFilepath: string) {\n logger.success(`Updated config file ${chalk.cyan(configFilepath)}`);\n}\n\nexport function displayUpdatedVersionsFile(versionFilepath: string) {\n logger.success(`Updated versions file ${chalk.cyan(versionFilepath)}`);\n}\n\n// Input prompts\nexport async function promptText({\n message,\n defaultValue,\n validate,\n}: {\n message: string;\n defaultValue?: string;\n validate?: (value: string) => boolean | string;\n}) {\n if (shouldUseInkPrompts()) {\n return (\n (await runInkPrompt<string>((prompts) =>\n prompts.inkPromptText({ message, defaultValue, validate })\n )) ?? ''\n );\n }\n\n const result = await text({\n message,\n placeholder: defaultValue,\n validate: validate\n ? (value) => {\n const validation = validate(value || '');\n return validation === true ? undefined : validation.toString();\n }\n : undefined,\n });\n\n if (isCancel(result)) {\n cancel('Operation cancelled');\n return exitSync(0);\n }\n\n return result;\n}\n\nexport async function promptLocale({\n message,\n defaultValue,\n customMapping,\n}: {\n message: string;\n defaultValue?: string;\n customMapping?: CustomMapping;\n}) {\n if (shouldUseInkPrompts()) {\n return (\n (await runInkPrompt<string>((prompts) =>\n prompts.inkPromptLocale({ message, defaultValue, customMapping })\n )) ?? ''\n );\n }\n\n return promptText({\n message,\n defaultValue,\n validate: (value) => validateLocale(value, customMapping),\n });\n}\n\nexport async function promptLocaleList({\n message,\n defaultValue,\n required = true,\n customMapping,\n}: {\n message: string;\n defaultValue?: string[];\n required?: boolean;\n customMapping?: CustomMapping;\n}) {\n if (shouldUseInkPrompts()) {\n return (\n (await runInkPrompt<string[]>((prompts) =>\n prompts.inkPromptLocaleMulti({\n message,\n defaultValue,\n required,\n customMapping,\n })\n )) ?? []\n );\n }\n\n return promptText({\n message,\n defaultValue: defaultValue?.join(' '),\n validate: (value) => validateLocaleList(value, customMapping),\n }).then(parseLocaleList);\n}\n\nexport async function promptGlobPatterns({\n label,\n message,\n defaultValue,\n}: {\n label: string;\n message: string;\n defaultValue?: string;\n}) {\n if (shouldUseInkPrompts()) {\n return (\n (await runInkPrompt<string>((prompts) =>\n prompts.inkPromptGlob({ label, message, defaultValue })\n )) ?? ''\n );\n }\n\n return promptText({\n message,\n defaultValue,\n });\n}\n\nexport async function promptSelect<T>({\n message,\n options,\n defaultValue,\n}: {\n message: string;\n options: Array<{ value: T; label: string; hint?: string }>;\n defaultValue?: T;\n}) {\n if (shouldUseInkPrompts()) {\n return (await runInkPrompt<T>((prompts) =>\n prompts.inkPromptSelect({ message, options, defaultValue })\n )) as T;\n }\n\n // Convert options to the format expected by clack\n const clackOptions = options.map((opt) => ({\n value: opt.value,\n label: opt.label,\n hint: opt.hint,\n })) as Option<T>[];\n\n const result = await select({\n message,\n options: clackOptions,\n initialValue: defaultValue,\n });\n\n if (isCancel(result)) {\n cancel('Operation cancelled');\n return exitSync(0);\n }\n\n return result as T;\n}\n\nexport async function promptMultiSelect<T extends string>({\n message,\n options,\n required = true,\n}: {\n message: string;\n options: Array<{ value: T; label: string; hint?: string }>;\n required?: boolean;\n}) {\n if (shouldUseInkPrompts()) {\n return (\n (await runInkPrompt<Array<T>>((prompts) =>\n prompts.inkPromptMultiSelect({\n message,\n options,\n required,\n })\n )) ?? []\n );\n }\n\n // Convert options to the format expected by clack\n const clackOptions = options.map((opt) => ({\n value: opt.value,\n label: opt.label,\n hint: opt.hint,\n })) as Option<T>[];\n\n const result = await multiselect({\n message,\n options: clackOptions,\n required,\n });\n\n if (isCancel(result)) {\n cancel('Operation cancelled');\n return exitSync(0);\n }\n\n return result as Array<T>;\n}\n\nexport async function promptConfirm({\n message,\n defaultValue = true,\n cancelMessage = 'Operation cancelled',\n}: {\n message: string;\n defaultValue?: boolean;\n cancelMessage?: string;\n}) {\n if (shouldUseInkPrompts()) {\n return (\n (await runInkPrompt<boolean>(\n (prompts) => prompts.inkPromptConfirm({ message, defaultValue }),\n cancelMessage\n )) ?? defaultValue\n );\n }\n\n const result = await confirm({\n message,\n initialValue: defaultValue,\n });\n\n if (isCancel(result)) {\n cancel(cancelMessage);\n return exitSync(0);\n }\n\n return result;\n}\n\n// Warning display functions\nexport function warnApiKeyInConfig(optionsFilepath: string) {\n logger.warn(\n `Found ${chalk.cyan('apiKey')} in \"${chalk.green(optionsFilepath)}\". ` +\n chalk.white(\n 'Your API key is exposed! Remove it from the file and include it as an environment variable.'\n )\n );\n}\n\nexport function warnVariableProp(\n file: string,\n attrName: string,\n value: string\n) {\n logger.warn(\n `Found ${chalk.green('<T>')} component in ${chalk.cyan(file)} with variable ${attrName}: \"${chalk.white(value)}\". ` +\n `Change \"${attrName}\" to ensure this content is translated.`\n );\n}\n\nexport function warnNoId(file: string) {\n logger.warn(\n `Found ${chalk.green('<T>')} component in ${chalk.cyan(file)} with no id. ` +\n chalk.white('Add an id to ensure the content is translated.')\n );\n}\n\nexport function warnHasUnwrappedExpression(\n file: string,\n id: string,\n unwrappedExpressions: string[]\n) {\n logger.warn(\n `${chalk.green('<T>')} with id \"${id}\" in ${chalk.cyan(file)} has children: ${unwrappedExpressions.join(', ')} that could change at runtime. ` +\n chalk.white('Use a variable component like ') +\n chalk.green('<Var>') +\n chalk.white(' (') +\n chalk.blue('https://generaltranslation.com/docs') +\n chalk.white(') to translate this properly.')\n );\n}\n\nexport function warnTemplateLiteral(file: string, value: string) {\n logger.warn(\n `Found template literal with quasis (${value}) in ${chalk.cyan(file)}. ` +\n chalk.white(\n 'Change the template literal to a string to ensure this content is translated.'\n )\n );\n}\n\nexport function warnTernary(file: string) {\n logger.warn(\n `Found ternary expression in ${chalk.cyan(file)}. ` +\n chalk.white('A Branch component may be more appropriate here.')\n );\n}\n\nexport function warnDeprecatedField(\n deprecatedField: string,\n replacement: string\n) {\n logger.warn(\n `${chalk.green(deprecatedField)} is deprecated. ` +\n chalk.white(`Use ${chalk.green(replacement)} instead.`)\n );\n}\n\n/**\n * Helper: Log all collected files\n */\nexport function logCollectedFiles(\n files: Pick<FileToUpload, 'fileName'>[],\n inlineComponents?: number,\n inlineLibrary?: InlineLibrary\n): void {\n const elementLabel = getInlineElementsLabel(inlineLibrary);\n logger.message(\n chalk.cyan('Files found in project:') +\n '\\n' +\n files\n .map((file) => {\n if (file.fileName === TEMPLATE_FILE_NAME) {\n return `- <${elementLabel}>${inlineComponents ? ` (${inlineComponents})` : ''}`;\n }\n return `- ${file.fileName}`;\n })\n .join('\\n')\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"logging.js","names":[],"sources":["../../src/console/logging.ts"],"sourcesContent":["import {\n text,\n select,\n confirm,\n isCancel,\n cancel,\n multiselect,\n autocomplete,\n autocompleteMultiselect,\n} from '@clack/prompts';\nimport type { Option } from '@clack/prompts';\nimport chalk from 'chalk';\nimport { createDiagnosticMessage } from 'generaltranslation/internal';\nimport { getCLIVersion } from '../utils/packageJson.js';\nimport { logger } from './logger.js';\nimport { TEMPLATE_FILE_NAME } from '../utils/constants.js';\nimport type { CustomMapping, FileToUpload } from 'generaltranslation/types';\nimport { parseTypedLocale } from './promptParsing.js';\nimport { getFilteredLocaleOptions } from './localeOptions.js';\nimport {\n getInlineElementsLabel,\n type InlineLibrary,\n} from '../types/libraries.js';\n\nfunction exitIfCancelled<T>(\n result: T | symbol,\n message = 'Operation cancelled'\n): T {\n if (isCancel(result)) {\n cancel(message);\n return exitSync(0);\n }\n return result as T;\n}\n\n/**\n * Strip ANSI escape codes from a string (e.g., chalk color codes)\n */\nexport function stripAnsi(str: string): string {\n // eslint-disable-next-line no-control-regex, no-useless-escape\n return str.replace(/\\x1B\\[[0-9;]*m/g, '');\n}\n\nlet lastExitError: string | undefined;\n\n/** The message of the last logErrorAndExit call, for exit-time reporting. */\nexport function getLastExitError(): string | undefined {\n return lastExitError;\n}\n\nexport function logErrorAndExit(message: string): never {\n lastExitError = message;\n logger.error(message);\n return exitSync(1);\n}\n\nexport function exitSync(code: number): never {\n // Flush logs before exit\n logger.flush();\n process.exit(code);\n}\n\n// GT specific logging\nexport function displayHeader(introString?: string) {\n // The ASCII banner is pure chatter and writes to console directly, bypassing\n // the logger, so gate it here to honor --quiet. startCommand stays outside\n // the gate: it is quiet-aware itself and must still run so the file log\n // gets its [START] marker.\n if (!logger.isQuiet()) {\n displayAsciiTitle();\n displayInitializingText();\n }\n\n if (introString) {\n logger.startCommand(introString);\n }\n}\n\nfunction displayAsciiTitle() {\n // eslint-disable-next-line no-console\n console.log(\n chalk.cyan(\n `\\n @@@@@@@@@@@@@@@@@@@@@@\n @@ @@@@@@@@@@@@ @@@@@@@\n @@ @@@ @ @\n@@ @@ @ @\n@@ @ @@@@@ @ @\n@@ @@ @@@ @ @ @\n @@ @@ @ @ @ @\n @@ @@@@@@@ @ @ @\n @@@@@@@@@ @ @`\n )\n );\n}\n\nfunction displayInitializingText() {\n const version = getCLIVersion();\n // eslint-disable-next-line no-console\n console.log(\n `\\n${chalk.bold.blue('General Translation, Inc.')}\n${chalk.dim('https://generaltranslation.com/docs')}\n${chalk.dim(`CLI Version: ${version}\\n`)}`\n );\n}\n\nexport function displayProjectId(projectId: string) {\n logger.message(\n chalk.dim(`Project ID: ${chalk.bold(projectId)}`),\n chalk.cyan('~')\n );\n}\n\nexport function displayResolvedPaths(resolvedPaths: [string, string][]) {\n const paths = resolvedPaths.map(([key, resolvedPath]) => {\n return chalk.dim(`'${chalk.white(key)}' → '${chalk.green(resolvedPath)}'`);\n });\n logger.step(`Resolved path aliases:\\n${paths.join('\\n')}`);\n}\n\nexport function displayCreatedConfigFile(configFilepath: string) {\n logger.step(`Created config file ${chalk.cyan(configFilepath)}`);\n}\n\nexport function displayUpdatedConfigFile(configFilepath: string) {\n logger.success(`Updated config file ${chalk.cyan(configFilepath)}`);\n}\n\nexport function displayUpdatedVersionsFile(versionFilepath: string) {\n logger.success(`Updated versions file ${chalk.cyan(versionFilepath)}`);\n}\n\n// Input prompts\nexport async function promptText({\n message,\n defaultValue,\n validate,\n}: {\n message: string;\n defaultValue?: string;\n validate?: (value: string) => boolean | string;\n}) {\n const result = await text({\n message,\n placeholder: defaultValue,\n defaultValue,\n validate: validate\n ? (value) => {\n // Clack applies defaultValue after validation; check what Enter returns.\n const validation = validate(value || defaultValue || '');\n return validation === true ? undefined : validation.toString();\n }\n : undefined,\n });\n return exitIfCancelled(result);\n}\n\ntype LocalePromptContext = {\n userInput: string;\n selectedValues: string[];\n focusedValue?: string;\n};\n\n/**\n * Clack keeps the focused option while it still matches a new search, so\n * typing `fr` could leave `af` (Afrikaans) focused. Refocus the top-ranked\n * option whenever the search changes.\n */\nfunction searchableLocaleOptions(\n getOptions: (query: string, selected: string[]) => Option<string>[]\n) {\n let lastQuery = '';\n return function (this: LocalePromptContext) {\n const query = this.userInput ?? '';\n if (query !== lastQuery) {\n lastQuery = query;\n this.focusedValue = undefined;\n }\n return getOptions(query, this.selectedValues ?? []);\n };\n}\n\n/**\n * Searchable locale options: supported locales ranked by the query, the\n * configured customMapping aliases, and any other valid locale typed or\n * already selected, so aliases and custom tags stay selectable.\n */\nexport function getLocalePromptOptions(\n query: string,\n selected: string[] = [],\n customMapping?: CustomMapping\n): Option<string>[] {\n const normalizedQuery = query.trim().toLowerCase();\n const supported = getFilteredLocaleOptions(query).map((option) => ({\n value: option.code,\n label: option.label,\n }));\n const known = new Set(supported.map((option) => option.value));\n const aliases = Object.keys(customMapping ?? {})\n .filter((alias) => alias.toLowerCase().includes(normalizedQuery))\n .map((alias) => ({ value: alias, label: alias, hint: 'custom mapping' }));\n const typed = parseTypedLocale(query, customMapping);\n const extras = [...selected, ...(typed ? [typed] : [])]\n .filter(\n (locale) =>\n !known.has(locale) && !aliases.some((alias) => alias.value === locale)\n )\n .map((locale) => ({ value: locale, label: locale }));\n return [\n ...new Map(\n [...aliases, ...extras, ...supported].map((option) => [\n option.value,\n option,\n ])\n ).values(),\n ].sort(\n (a, b) =>\n Number(b.value.toLowerCase() === normalizedQuery) -\n Number(a.value.toLowerCase() === normalizedQuery)\n );\n}\n\n// Body-only: Clack shows it inline under the prompt.\nconst noLocaleSelectedError = createDiagnosticMessage({\n whatHappened: 'No locale matches the search',\n fix: 'Change the search and select a locale from the list',\n});\n\nexport async function promptLocale({\n message,\n defaultValue,\n customMapping,\n}: {\n message: string;\n defaultValue?: string;\n customMapping?: CustomMapping;\n}) {\n const result = await autocomplete<string>({\n message,\n placeholder: 'Type to search locales',\n initialValue: defaultValue,\n options: searchableLocaleOptions((query) =>\n getLocalePromptOptions(query, [], customMapping)\n ),\n // Enter with no matching option submits nothing; keep asking.\n validate: (value) => (value ? undefined : noLocaleSelectedError),\n });\n return exitIfCancelled(result);\n}\n\nexport async function promptLocaleList({\n message,\n defaultValue,\n required = true,\n customMapping,\n}: {\n message: string;\n defaultValue?: string[];\n required?: boolean;\n customMapping?: CustomMapping;\n}) {\n const result = await autocompleteMultiselect<string>({\n message,\n placeholder: 'Type to search, Tab or Space to select',\n initialValues: defaultValue,\n required,\n // Clack only preselects defaults present in the first options list, so\n // keep custom default tags listed even before they are selected.\n options: searchableLocaleOptions((query, selected) =>\n getLocalePromptOptions(\n query,\n [...(defaultValue ?? []), ...selected],\n customMapping\n )\n ),\n });\n return exitIfCancelled(result);\n}\n\nexport async function promptGlobPatterns(options: {\n label: string;\n message: string;\n defaultValue?: string;\n validate?: (value: string) => boolean | string;\n}) {\n return promptText(options);\n}\n\nexport async function promptSelect<T>({\n message,\n options,\n defaultValue,\n}: {\n message: string;\n options: Array<{ value: T; label: string; hint?: string }>;\n defaultValue?: T;\n}) {\n const result = await select({\n message,\n options: options as Option<T>[],\n initialValue: defaultValue,\n });\n return exitIfCancelled(result);\n}\n\nexport async function promptMultiSelect<T extends string>({\n message,\n options,\n required = true,\n}: {\n message: string;\n options: Array<{ value: T; label: string; hint?: string }>;\n required?: boolean;\n}) {\n const result = await multiselect({\n message,\n options: options as Option<T>[],\n required,\n });\n return exitIfCancelled(result);\n}\n\nexport async function promptConfirm({\n message,\n defaultValue = true,\n cancelMessage = 'Operation cancelled',\n}: {\n message: string;\n defaultValue?: boolean;\n cancelMessage?: string;\n}) {\n const result = await confirm({\n message,\n initialValue: defaultValue,\n });\n return exitIfCancelled(result, cancelMessage);\n}\n\n// Warning display functions\nexport function warnApiKeyInConfig(optionsFilepath: string) {\n logger.warn(\n `Found ${chalk.cyan('apiKey')} in \"${chalk.green(optionsFilepath)}\". ` +\n chalk.white(\n 'Your API key is exposed! Remove it from the file and include it as an environment variable.'\n )\n );\n}\n\nexport function warnVariableProp(\n file: string,\n attrName: string,\n value: string\n) {\n logger.warn(\n `Found ${chalk.green('<T>')} component in ${chalk.cyan(file)} with variable ${attrName}: \"${chalk.white(value)}\". ` +\n `Change \"${attrName}\" to ensure this content is translated.`\n );\n}\n\nexport function warnNoId(file: string) {\n logger.warn(\n `Found ${chalk.green('<T>')} component in ${chalk.cyan(file)} with no id. ` +\n chalk.white('Add an id to ensure the content is translated.')\n );\n}\n\nexport function warnHasUnwrappedExpression(\n file: string,\n id: string,\n unwrappedExpressions: string[]\n) {\n logger.warn(\n `${chalk.green('<T>')} with id \"${id}\" in ${chalk.cyan(file)} has children: ${unwrappedExpressions.join(', ')} that could change at runtime. ` +\n chalk.white('Use a variable component like ') +\n chalk.green('<Var>') +\n chalk.white(' (') +\n chalk.blue('https://generaltranslation.com/docs') +\n chalk.white(') to translate this properly.')\n );\n}\n\nexport function warnTemplateLiteral(file: string, value: string) {\n logger.warn(\n `Found template literal with quasis (${value}) in ${chalk.cyan(file)}. ` +\n chalk.white(\n 'Change the template literal to a string to ensure this content is translated.'\n )\n );\n}\n\nexport function warnTernary(file: string) {\n logger.warn(\n `Found ternary expression in ${chalk.cyan(file)}. ` +\n chalk.white('A Branch component may be more appropriate here.')\n );\n}\n\nexport function warnDeprecatedField(\n deprecatedField: string,\n replacement: string\n) {\n logger.warn(\n `${chalk.green(deprecatedField)} is deprecated. ` +\n chalk.white(`Use ${chalk.green(replacement)} instead.`)\n );\n}\n\n/**\n * Helper: Log all collected files\n */\nexport function logCollectedFiles(\n files: Pick<FileToUpload, 'fileName'>[],\n inlineComponents?: number,\n inlineLibrary?: InlineLibrary\n): void {\n const elementLabel = getInlineElementsLabel(inlineLibrary);\n logger.message(\n chalk.cyan('Files found in project:') +\n '\\n' +\n files\n .map((file) => {\n if (file.fileName === TEMPLATE_FILE_NAME) {\n return `- <${elementLabel}>${inlineComponents ? ` (${inlineComponents})` : ''}`;\n }\n return `- ${file.fileName}`;\n })\n .join('\\n')\n );\n}\n"],"mappings":"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"}
|
|
@@ -6,7 +6,6 @@ import { fileEncodingSkipReason, lottieExpressionsError, xcstringsSourceLanguage
|
|
|
6
6
|
import { SUPPORTED_FILE_EXTENSIONS } from "./supportedFiles.js";
|
|
7
7
|
import { CONFIG_FILE_TYPE_TO_FILE_FORMAT, getTransformFormatProperty } from "./transformFormat.js";
|
|
8
8
|
import { api } from "../../utils/api.js";
|
|
9
|
-
import { determineLibrary } from "../../fs/determineFramework/index.js";
|
|
10
9
|
import { readFileContent } from "../../fs/fileContent.js";
|
|
11
10
|
import { flattenJson } from "../json/flattenJson.js";
|
|
12
11
|
import { recordWarning } from "../../state/translateWarnings.js";
|
|
@@ -18,6 +17,7 @@ import { resolveMintlifyRefs, shouldResolveRefs } from "../../utils/resolveMintl
|
|
|
18
17
|
import { storeRefMap } from "../../state/mintlifyRefMap.js";
|
|
19
18
|
import { validateYamlSchema } from "../yaml/utils.js";
|
|
20
19
|
import parseYaml from "../yaml/parseYaml.js";
|
|
20
|
+
import { determineLibrary } from "../../fs/determineFramework/index.js";
|
|
21
21
|
import { preprocessContent } from "./preprocessContent.js";
|
|
22
22
|
import { parseKeyedMetadata } from "../parseKeyedMetadata.js";
|
|
23
23
|
import YAML from "yaml";
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export declare const SUPPORTED_FILE_EXTENSIONS: readonly ["json", "pot", "mdx", "md", "ts", "js", "yaml", "html", "txt", "twilioContentJson", "lottie", "dotStrings", "dotStringsdict", "androidStrings", "xcstrings", "srt"];
|
|
2
|
+
/** The formats setup offers: an intentional subset of the supported ones. */
|
|
3
|
+
export declare const SETUP_FILE_FORMATS: readonly ["json", "md", "mdx", "ts", "js", "yaml"];
|
|
4
|
+
export type SetupFileFormat = (typeof SETUP_FILE_FORMATS)[number];
|
|
2
5
|
export declare const FILE_EXT_TO_EXT_LABEL: {
|
|
3
6
|
json: string;
|
|
4
7
|
pot: string;
|
|
@@ -17,6 +17,15 @@ const SUPPORTED_FILE_EXTENSIONS = [
|
|
|
17
17
|
"xcstrings",
|
|
18
18
|
"srt"
|
|
19
19
|
];
|
|
20
|
+
/** The formats setup offers: an intentional subset of the supported ones. */
|
|
21
|
+
const SETUP_FILE_FORMATS = [
|
|
22
|
+
"json",
|
|
23
|
+
"md",
|
|
24
|
+
"mdx",
|
|
25
|
+
"ts",
|
|
26
|
+
"js",
|
|
27
|
+
"yaml"
|
|
28
|
+
];
|
|
20
29
|
const FILE_EXT_TO_EXT_LABEL = {
|
|
21
30
|
json: "JSON",
|
|
22
31
|
pot: "POT",
|
|
@@ -36,6 +45,6 @@ const FILE_EXT_TO_EXT_LABEL = {
|
|
|
36
45
|
srt: "SubRip subtitles (.srt)"
|
|
37
46
|
};
|
|
38
47
|
//#endregion
|
|
39
|
-
export { FILE_EXT_TO_EXT_LABEL, SUPPORTED_FILE_EXTENSIONS };
|
|
48
|
+
export { FILE_EXT_TO_EXT_LABEL, SETUP_FILE_FORMATS, SUPPORTED_FILE_EXTENSIONS };
|
|
40
49
|
|
|
41
50
|
//# sourceMappingURL=supportedFiles.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"supportedFiles.js","names":[],"sources":["../../../src/formats/files/supportedFiles.ts"],"sourcesContent":["export const SUPPORTED_FILE_EXTENSIONS = [\n 'json',\n 'pot',\n 'mdx',\n 'md',\n 'ts',\n 'js',\n 'yaml',\n 'html',\n 'txt',\n 'twilioContentJson',\n 'lottie',\n 'dotStrings',\n 'dotStringsdict',\n 'androidStrings',\n 'xcstrings',\n 'srt',\n] as const;\n\nexport const FILE_EXT_TO_EXT_LABEL = {\n json: 'JSON',\n pot: 'POT',\n mdx: 'MDX',\n md: 'Markdown',\n ts: 'TypeScript',\n js: 'JavaScript',\n yaml: 'YAML',\n html: 'HTML',\n txt: 'Text',\n twilioContentJson: 'Twilio Content JSON',\n lottie: 'Lottie',\n dotStrings: '.strings',\n dotStringsdict: '.stringsdict',\n androidStrings: 'Android strings.xml',\n xcstrings: '.xcstrings',\n srt: 'SubRip subtitles (.srt)',\n};\n"],"mappings":";AAAA,MAAa,4BAA4B;CACvC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;
|
|
1
|
+
{"version":3,"file":"supportedFiles.js","names":[],"sources":["../../../src/formats/files/supportedFiles.ts"],"sourcesContent":["export const SUPPORTED_FILE_EXTENSIONS = [\n 'json',\n 'pot',\n 'mdx',\n 'md',\n 'ts',\n 'js',\n 'yaml',\n 'html',\n 'txt',\n 'twilioContentJson',\n 'lottie',\n 'dotStrings',\n 'dotStringsdict',\n 'androidStrings',\n 'xcstrings',\n 'srt',\n] as const;\n\n/** The formats setup offers: an intentional subset of the supported ones. */\nexport const SETUP_FILE_FORMATS = [\n 'json',\n 'md',\n 'mdx',\n 'ts',\n 'js',\n 'yaml',\n] as const satisfies readonly (typeof SUPPORTED_FILE_EXTENSIONS)[number][];\nexport type SetupFileFormat = (typeof SETUP_FILE_FORMATS)[number];\n\nexport const FILE_EXT_TO_EXT_LABEL = {\n json: 'JSON',\n pot: 'POT',\n mdx: 'MDX',\n md: 'Markdown',\n ts: 'TypeScript',\n js: 'JavaScript',\n yaml: 'YAML',\n html: 'HTML',\n txt: 'Text',\n twilioContentJson: 'Twilio Content JSON',\n lottie: 'Lottie',\n dotStrings: '.strings',\n dotStringsdict: '.stringsdict',\n androidStrings: 'Android strings.xml',\n xcstrings: '.xcstrings',\n srt: 'SubRip subtitles (.srt)',\n};\n"],"mappings":";AAAA,MAAa,4BAA4B;CACvC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;;AAGD,MAAa,qBAAqB;CAChC;CACA;CACA;CACA;CACA;CACA;CACD;AAGD,MAAa,wBAAwB;CACnC,MAAM;CACN,KAAK;CACL,KAAK;CACL,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,MAAM;CACN,MAAM;CACN,KAAK;CACL,mBAAmB;CACnB,QAAQ;CACR,YAAY;CACZ,gBAAgB;CAChB,gBAAgB;CAChB,WAAW;CACX,KAAK;CACN"}
|
|
@@ -2,8 +2,8 @@ import { logger } from "../../console/logger.js";
|
|
|
2
2
|
import { exitSync } from "../../console/logging.js";
|
|
3
3
|
import { validateYamlSchema } from "./utils.js";
|
|
4
4
|
import { applyTransformations } from "../json/mergeJson.js";
|
|
5
|
-
import JSONPointer from "jsonpointer";
|
|
6
5
|
import YAML from "yaml";
|
|
6
|
+
import JSONPointer from "jsonpointer";
|
|
7
7
|
//#region src/formats/yaml/mergeYaml.ts
|
|
8
8
|
function mergeYaml(originalContent, inputPath, options, targets, defaultLocale) {
|
|
9
9
|
const yamlSchema = validateYamlSchema(options, inputPath);
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
//#region src/fs/config/loadConfig.ts
|
|
3
|
+
/** `--config` accepts a path with or without its `.json` extension. */
|
|
4
|
+
function withJsonExtension(configPath) {
|
|
5
|
+
return configPath.endsWith(".json") ? configPath : `${configPath}.json`;
|
|
6
|
+
}
|
|
3
7
|
function loadConfig(filepath) {
|
|
4
8
|
try {
|
|
5
9
|
return JSON.parse(fs.readFileSync(filepath, "utf-8"));
|
|
@@ -8,6 +12,6 @@ function loadConfig(filepath) {
|
|
|
8
12
|
}
|
|
9
13
|
}
|
|
10
14
|
//#endregion
|
|
11
|
-
export { loadConfig };
|
|
15
|
+
export { loadConfig, withJsonExtension };
|
|
12
16
|
|
|
13
17
|
//# sourceMappingURL=loadConfig.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadConfig.js","names":[],"sources":["../../../src/fs/config/loadConfig.ts"],"sourcesContent":["import fs from 'node:fs';\n\nexport function loadConfig(filepath: string): Record<string, unknown> {\n try {\n return JSON.parse(fs.readFileSync(filepath, 'utf-8')) as Record<\n string,\n unknown\n >;\n } catch {\n return {};\n }\n}\n"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"loadConfig.js","names":[],"sources":["../../../src/fs/config/loadConfig.ts"],"sourcesContent":["import fs from 'node:fs';\n\n/** `--config` accepts a path with or without its `.json` extension. */\nexport function withJsonExtension(configPath: string): string {\n return configPath.endsWith('.json') ? configPath : `${configPath}.json`;\n}\n\nexport function loadConfig(filepath: string): Record<string, unknown> {\n try {\n return JSON.parse(fs.readFileSync(filepath, 'utf-8')) as Record<\n string,\n unknown\n >;\n } catch {\n return {};\n }\n}\n"],"mappings":";;;AAGA,SAAgB,kBAAkB,YAA4B;AAC5D,QAAO,WAAW,SAAS,QAAQ,GAAG,aAAa,GAAG,WAAW;;AAGnE,SAAgB,WAAW,UAA2C;AACpE,KAAI;AACF,SAAO,KAAK,MAAM,GAAG,aAAa,UAAU,QAAQ,CAAC;SAI/C;AACN,SAAO,EAAE"}
|
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
import { FilesOptions, SupportedFrameworks } from '../../types/index.js';
|
|
2
|
-
|
|
3
|
-
* Checks if the config file exists.
|
|
4
|
-
* If yes, make sure make sure projectId is correct
|
|
5
|
-
* If not, creates a new JSON file at the given filepath and writes the provided config object to it.
|
|
6
|
-
* @param {string} configFilepath - The path to the config file.
|
|
7
|
-
* @param {Record<string, any>} configObject - The config object to write if the file does not exist.
|
|
8
|
-
*/
|
|
9
|
-
export declare function createOrUpdateConfig(configFilepath: string, options: {
|
|
2
|
+
export type SetupConfigUpdate = {
|
|
10
3
|
projectId?: string;
|
|
11
4
|
defaultLocale?: string;
|
|
12
5
|
locales?: string[];
|
|
@@ -17,4 +10,20 @@ export declare function createOrUpdateConfig(configFilepath: string, options: {
|
|
|
17
10
|
publish?: boolean;
|
|
18
11
|
/** Removes stale global CDN intent when the selected runtime forbids it. */
|
|
19
12
|
clearPublish?: boolean;
|
|
20
|
-
|
|
13
|
+
/** File format entries deselected by an explicit format list. */
|
|
14
|
+
removeFiles?: string[];
|
|
15
|
+
/** Drops files.gt.output after an explicit switch to CDN storage. */
|
|
16
|
+
clearGtOutput?: boolean;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* The config setup writes: the existing content with the update applied.
|
|
20
|
+
* Unrelated fields and per-format options are kept; locales are replaced.
|
|
21
|
+
*/
|
|
22
|
+
export declare function mergeSetupConfig(oldContent: Record<string, unknown>, options: SetupConfigUpdate): Record<string, unknown>;
|
|
23
|
+
/**
|
|
24
|
+
* Creates the config file, or applies the update to the existing one.
|
|
25
|
+
* @param {string} configFilepath - The path to the config file.
|
|
26
|
+
* @param {SetupConfigUpdate} options - The values setup resolved.
|
|
27
|
+
* @throws When the existing file is not valid JSON or cannot be written.
|
|
28
|
+
*/
|
|
29
|
+
export declare function createOrUpdateConfig(configFilepath: string, options: SetupConfigUpdate): Promise<string>;
|
|
@@ -1,59 +1,79 @@
|
|
|
1
|
-
import { logger } from "../../console/logger.js";
|
|
2
1
|
import { GT_CONFIG_SCHEMA_URL } from "../../utils/constants.js";
|
|
3
2
|
import { displayCreatedConfigFile } from "../../console/logging.js";
|
|
3
|
+
import { createDiagnosticMessage, formatDiagnosticErrorDetails } from "generaltranslation/internal";
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
//#region src/fs/config/setupConfig.ts
|
|
6
|
+
function asObject(value) {
|
|
7
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
8
|
+
}
|
|
6
9
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* If not, creates a new JSON file at the given filepath and writes the provided config object to it.
|
|
10
|
-
* @param {string} configFilepath - The path to the config file.
|
|
11
|
-
* @param {Record<string, any>} configObject - The config object to write if the file does not exist.
|
|
10
|
+
* The config setup writes: the existing content with the update applied.
|
|
11
|
+
* Unrelated fields and per-format options are kept; locales are replaced.
|
|
12
12
|
*/
|
|
13
|
-
|
|
13
|
+
function mergeSetupConfig(oldContent, options) {
|
|
14
14
|
const newContent = {
|
|
15
15
|
...options.projectId && { projectId: options.projectId },
|
|
16
16
|
...options.defaultLocale && { defaultLocale: options.defaultLocale },
|
|
17
17
|
...options.src && { src: options.src },
|
|
18
|
-
...options.files && { files: options.files },
|
|
19
18
|
...options.framework && { framework: options.framework },
|
|
20
19
|
...options.baseUrl && { baseUrl: options.baseUrl },
|
|
21
20
|
...options.publish && { publish: options.publish }
|
|
22
21
|
};
|
|
22
|
+
const mergedContent = {
|
|
23
|
+
$schema: GT_CONFIG_SCHEMA_URL,
|
|
24
|
+
...oldContent,
|
|
25
|
+
...newContent
|
|
26
|
+
};
|
|
27
|
+
if (options.clearPublish) delete mergedContent.publish;
|
|
28
|
+
if (options.files || options.removeFiles?.length || options.clearGtOutput) {
|
|
29
|
+
const oldFiles = asObject(oldContent.files);
|
|
30
|
+
const files = {
|
|
31
|
+
...oldFiles,
|
|
32
|
+
...options.files
|
|
33
|
+
};
|
|
34
|
+
const gt = {
|
|
35
|
+
...asObject(oldFiles.gt),
|
|
36
|
+
...options.files?.gt
|
|
37
|
+
};
|
|
38
|
+
if (options.clearGtOutput) delete gt.output;
|
|
39
|
+
if (Object.keys(gt).length > 0) files.gt = gt;
|
|
40
|
+
else delete files.gt;
|
|
41
|
+
for (const format of options.removeFiles ?? []) delete files[format];
|
|
42
|
+
if (Object.keys(files).length > 0) mergedContent.files = files;
|
|
43
|
+
else delete mergedContent.files;
|
|
44
|
+
}
|
|
45
|
+
if (options.locales) mergedContent.locales = options.locales;
|
|
46
|
+
return mergedContent;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Creates the config file, or applies the update to the existing one.
|
|
50
|
+
* @param {string} configFilepath - The path to the config file.
|
|
51
|
+
* @param {SetupConfigUpdate} options - The values setup resolved.
|
|
52
|
+
* @throws When the existing file is not valid JSON or cannot be written.
|
|
53
|
+
*/
|
|
54
|
+
async function createOrUpdateConfig(configFilepath, options) {
|
|
23
55
|
try {
|
|
24
56
|
let oldContent = {};
|
|
25
57
|
if (fs.existsSync(configFilepath)) {
|
|
26
58
|
const parsed = JSON.parse(await fs.promises.readFile(configFilepath, "utf-8"));
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const mergedContent = {
|
|
30
|
-
$schema: GT_CONFIG_SCHEMA_URL,
|
|
31
|
-
...oldContent,
|
|
32
|
-
...newContent
|
|
33
|
-
};
|
|
34
|
-
if (options.clearPublish) delete mergedContent.publish;
|
|
35
|
-
if (options.files) {
|
|
36
|
-
const oldFiles = oldContent.files && typeof oldContent.files === "object" ? oldContent.files : {};
|
|
37
|
-
const oldGt = oldFiles.gt && typeof oldFiles.gt === "object" ? oldFiles.gt : {};
|
|
38
|
-
mergedContent.files = {
|
|
39
|
-
...oldFiles,
|
|
40
|
-
...options.files,
|
|
41
|
-
...options.files.gt && { gt: {
|
|
42
|
-
...oldGt,
|
|
43
|
-
...options.files.gt
|
|
44
|
-
} }
|
|
45
|
-
};
|
|
59
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) throw new Error("the file does not contain a JSON object");
|
|
60
|
+
oldContent = parsed;
|
|
46
61
|
}
|
|
47
|
-
|
|
48
|
-
const mergedJsonContent = JSON.stringify(mergedContent, null, 2);
|
|
62
|
+
const mergedJsonContent = JSON.stringify(mergeSetupConfig(oldContent, options), null, 2);
|
|
49
63
|
await fs.promises.writeFile(configFilepath, mergedJsonContent, "utf-8");
|
|
50
64
|
displayCreatedConfigFile(configFilepath);
|
|
51
65
|
} catch (error) {
|
|
52
|
-
|
|
66
|
+
throw new Error(createDiagnosticMessage({
|
|
67
|
+
source: "gt",
|
|
68
|
+
severity: "Error",
|
|
69
|
+
whatHappened: `Could not update ${configFilepath}`,
|
|
70
|
+
details: formatDiagnosticErrorDetails(error),
|
|
71
|
+
fix: "Fix or remove the file, then rerun the command"
|
|
72
|
+
}));
|
|
53
73
|
}
|
|
54
74
|
return configFilepath;
|
|
55
75
|
}
|
|
56
76
|
//#endregion
|
|
57
|
-
export { createOrUpdateConfig };
|
|
77
|
+
export { createOrUpdateConfig, mergeSetupConfig };
|
|
58
78
|
|
|
59
79
|
//# sourceMappingURL=setupConfig.js.map
|