@dittowords/cli 4.5.2 → 5.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -5
- package/bin/ditto.js +110 -285
- package/package.json +16 -10
- package/.github/actions/install-node-dependencies/action.yml +0 -24
- package/.github/workflows/required-checks.yml +0 -24
- package/.husky/pre-commit +0 -4
- package/.prettierignore +0 -0
- package/.prettierrc.json +0 -1
- package/__mocks__/fs.js +0 -2
- package/babel.config.js +0 -6
- package/bin/__mocks__/api.js +0 -48
- package/bin/__mocks__/api.js.map +0 -1
- package/bin/add-project.js +0 -104
- package/bin/add-project.js.map +0 -1
- package/bin/api.js +0 -54
- package/bin/api.js.map +0 -1
- package/bin/component-folders.js +0 -59
- package/bin/component-folders.js.map +0 -1
- package/bin/config.js +0 -242
- package/bin/config.js.map +0 -1
- package/bin/config.test.js +0 -93
- package/bin/config.test.js.map +0 -1
- package/bin/consts.js +0 -57
- package/bin/consts.js.map +0 -1
- package/bin/ditto.js.map +0 -1
- package/bin/generate-suggestions.js +0 -183
- package/bin/generate-suggestions.js.map +0 -1
- package/bin/generate-suggestions.test.js +0 -200
- package/bin/generate-suggestions.test.js.map +0 -1
- package/bin/http/__mocks__/fetchComponentFolders.js +0 -71
- package/bin/http/__mocks__/fetchComponentFolders.js.map +0 -1
- package/bin/http/__mocks__/fetchComponents.js +0 -73
- package/bin/http/__mocks__/fetchComponents.js.map +0 -1
- package/bin/http/__mocks__/fetchVariants.js +0 -71
- package/bin/http/__mocks__/fetchVariants.js.map +0 -1
- package/bin/http/fetchComponentFolders.js +0 -64
- package/bin/http/fetchComponentFolders.js.map +0 -1
- package/bin/http/fetchComponents.js +0 -78
- package/bin/http/fetchComponents.js.map +0 -1
- package/bin/http/fetchVariants.js +0 -87
- package/bin/http/fetchVariants.js.map +0 -1
- package/bin/http/http.test.js +0 -159
- package/bin/http/http.test.js.map +0 -1
- package/bin/http/importComponents.js +0 -114
- package/bin/http/importComponents.js.map +0 -1
- package/bin/importComponents.js +0 -65
- package/bin/importComponents.js.map +0 -1
- package/bin/init/init.js +0 -126
- package/bin/init/init.js.map +0 -1
- package/bin/init/project.js +0 -182
- package/bin/init/project.js.map +0 -1
- package/bin/init/project.test.js +0 -26
- package/bin/init/project.test.js.map +0 -1
- package/bin/init/token.js +0 -196
- package/bin/init/token.js.map +0 -1
- package/bin/init/token.test.js +0 -147
- package/bin/init/token.test.js.map +0 -1
- package/bin/output.js +0 -76
- package/bin/output.js.map +0 -1
- package/bin/pull-lib.test.js +0 -379
- package/bin/pull-lib.test.js.map +0 -1
- package/bin/pull.js +0 -562
- package/bin/pull.js.map +0 -1
- package/bin/pull.test.js +0 -151
- package/bin/pull.test.js.map +0 -1
- package/bin/remove-project.js +0 -99
- package/bin/remove-project.js.map +0 -1
- package/bin/replace.js +0 -171
- package/bin/replace.js.map +0 -1
- package/bin/replace.test.js +0 -197
- package/bin/replace.test.js.map +0 -1
- package/bin/types.js +0 -21
- package/bin/types.js.map +0 -1
- package/bin/utils/cleanFileName.js +0 -40
- package/bin/utils/cleanFileName.js.map +0 -1
- package/bin/utils/cleanFileName.test.js +0 -15
- package/bin/utils/cleanFileName.test.js.map +0 -1
- package/bin/utils/createSentryContext.js +0 -43
- package/bin/utils/createSentryContext.js.map +0 -1
- package/bin/utils/determineModuleType.js +0 -79
- package/bin/utils/determineModuleType.js.map +0 -1
- package/bin/utils/determineModuleType.test.js +0 -60
- package/bin/utils/determineModuleType.test.js.map +0 -1
- package/bin/utils/generateIOSBundles.js +0 -147
- package/bin/utils/generateIOSBundles.js.map +0 -1
- package/bin/utils/generateJsDriver.js +0 -178
- package/bin/utils/generateJsDriver.js.map +0 -1
- package/bin/utils/generateJsDriverTypeFile.js +0 -105
- package/bin/utils/generateJsDriverTypeFile.js.map +0 -1
- package/bin/utils/generateSwiftDriver.js +0 -93
- package/bin/utils/generateSwiftDriver.js.map +0 -1
- package/bin/utils/getSelectedProjects.js +0 -67
- package/bin/utils/getSelectedProjects.js.map +0 -1
- package/bin/utils/processMetaOption.js +0 -40
- package/bin/utils/processMetaOption.js.map +0 -1
- package/bin/utils/processMetaOption.test.js +0 -45
- package/bin/utils/processMetaOption.test.js.map +0 -1
- package/bin/utils/projectsToText.js +0 -58
- package/bin/utils/projectsToText.js.map +0 -1
- package/bin/utils/promptForProject.js +0 -96
- package/bin/utils/promptForProject.js.map +0 -1
- package/bin/utils/quit.js +0 -73
- package/bin/utils/quit.js.map +0 -1
- package/bin/utils/sourcesToText.js +0 -57
- package/bin/utils/sourcesToText.js.map +0 -1
- package/etsc.config.js +0 -13
- package/jest.config.ts +0 -16
- package/jsconfig.json +0 -5
- package/lib/__mocks__/api.ts +0 -12
- package/lib/add-project.ts +0 -48
- package/lib/api.ts +0 -16
- package/lib/component-folders.ts +0 -9
- package/lib/config.test.ts +0 -79
- package/lib/config.ts +0 -279
- package/lib/consts.ts +0 -22
- package/lib/ditto.ts +0 -285
- package/lib/generate-suggestions.test.ts +0 -169
- package/lib/generate-suggestions.ts +0 -166
- package/lib/http/__mocks__/fetchComponentFolders.ts +0 -23
- package/lib/http/__mocks__/fetchComponents.ts +0 -24
- package/lib/http/__mocks__/fetchVariants.ts +0 -21
- package/lib/http/fetchComponentFolders.ts +0 -23
- package/lib/http/fetchComponents.ts +0 -43
- package/lib/http/fetchVariants.ts +0 -42
- package/lib/http/http.test.ts +0 -122
- package/lib/http/importComponents.ts +0 -79
- package/lib/importComponents.ts +0 -24
- package/lib/init/init.ts +0 -79
- package/lib/init/project.test.ts +0 -26
- package/lib/init/project.ts +0 -136
- package/lib/init/token.test.ts +0 -99
- package/lib/init/token.ts +0 -156
- package/lib/output.ts +0 -21
- package/lib/pull-lib.test.ts +0 -367
- package/lib/pull.test.ts +0 -117
- package/lib/pull.ts +0 -629
- package/lib/remove-project.ts +0 -44
- package/lib/replace.test.ts +0 -157
- package/lib/replace.ts +0 -140
- package/lib/types.ts +0 -83
- package/lib/utils/cleanFileName.test.ts +0 -11
- package/lib/utils/cleanFileName.ts +0 -8
- package/lib/utils/createSentryContext.ts +0 -20
- package/lib/utils/determineModuleType.test.ts +0 -48
- package/lib/utils/determineModuleType.ts +0 -55
- package/lib/utils/generateIOSBundles.ts +0 -122
- package/lib/utils/generateJsDriver.ts +0 -207
- package/lib/utils/generateJsDriverTypeFile.ts +0 -75
- package/lib/utils/generateSwiftDriver.ts +0 -48
- package/lib/utils/getSelectedProjects.ts +0 -36
- package/lib/utils/processMetaOption.test.ts +0 -18
- package/lib/utils/processMetaOption.ts +0 -16
- package/lib/utils/projectsToText.ts +0 -29
- package/lib/utils/promptForProject.ts +0 -61
- package/lib/utils/quit.ts +0 -7
- package/lib/utils/sourcesToText.ts +0 -25
- package/pull_request_template.md +0 -20
- package/testfiles/en.json +0 -5
- package/testfiles/es.json +0 -5
- package/testfiles/fr.json +0 -5
- package/testfiles/test1.jsx +0 -18
- package/testfiles/test2.jsx +0 -9
- package/testing/.gitkeep +0 -0
- package/testing/fixtures/bad-yaml.yml +0 -6
- package/testing/fixtures/ditto-config-no-token +0 -2
- package/testing/fixtures/project-config-empty-projects.yml +0 -1
- package/testing/fixtures/project-config-no-id.yml +0 -2
- package/testing/fixtures/project-config-no-name.yml +0 -2
- package/testing/fixtures/project-config-pull.yml +0 -0
- package/testing/fixtures/project-config-working.yml +0 -3
- package/tsconfig.json +0 -16
package/bin/pull.js
DELETED
|
@@ -1,562 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="e1fa8919-644e-53c0-9bd8-11223fd4f8f2")}catch(e){}}();
|
|
3
|
-
|
|
4
|
-
var __create = Object.create;
|
|
5
|
-
var __defProp = Object.defineProperty;
|
|
6
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
7
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
8
|
-
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
9
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
10
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
11
|
-
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
12
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
13
|
-
var __spreadValues = (a, b) => {
|
|
14
|
-
for (var prop in b || (b = {}))
|
|
15
|
-
if (__hasOwnProp.call(b, prop))
|
|
16
|
-
__defNormalProp(a, prop, b[prop]);
|
|
17
|
-
if (__getOwnPropSymbols)
|
|
18
|
-
for (var prop of __getOwnPropSymbols(b)) {
|
|
19
|
-
if (__propIsEnum.call(b, prop))
|
|
20
|
-
__defNormalProp(a, prop, b[prop]);
|
|
21
|
-
}
|
|
22
|
-
return a;
|
|
23
|
-
};
|
|
24
|
-
var __export = (target, all) => {
|
|
25
|
-
for (var name in all)
|
|
26
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
27
|
-
};
|
|
28
|
-
var __copyProps = (to, from, except, desc) => {
|
|
29
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
30
|
-
for (let key of __getOwnPropNames(from))
|
|
31
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
32
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
33
|
-
}
|
|
34
|
-
return to;
|
|
35
|
-
};
|
|
36
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
37
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
38
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
39
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
40
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
41
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
42
|
-
mod
|
|
43
|
-
));
|
|
44
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
45
|
-
var __async = (__this, __arguments, generator) => {
|
|
46
|
-
return new Promise((resolve, reject) => {
|
|
47
|
-
var fulfilled = (value) => {
|
|
48
|
-
try {
|
|
49
|
-
step(generator.next(value));
|
|
50
|
-
} catch (e) {
|
|
51
|
-
reject(e);
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
var rejected = (value) => {
|
|
55
|
-
try {
|
|
56
|
-
step(generator.throw(value));
|
|
57
|
-
} catch (e) {
|
|
58
|
-
reject(e);
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
62
|
-
step((generator = generator.apply(__this, __arguments)).next());
|
|
63
|
-
});
|
|
64
|
-
};
|
|
65
|
-
var pull_exports = {};
|
|
66
|
-
__export(pull_exports, {
|
|
67
|
-
_test: () => _test,
|
|
68
|
-
default: () => pull_default,
|
|
69
|
-
getFormatDataIsValid: () => getFormatDataIsValid,
|
|
70
|
-
pull: () => pull,
|
|
71
|
-
writeFile: () => writeFile
|
|
72
|
-
});
|
|
73
|
-
module.exports = __toCommonJS(pull_exports);
|
|
74
|
-
var import_fs = __toESM(require("fs"));
|
|
75
|
-
var import_path = __toESM(require("path"));
|
|
76
|
-
var import_ora = __toESM(require("ora"));
|
|
77
|
-
var Sentry = __toESM(require("@sentry/node"));
|
|
78
|
-
var import_api = require("./api");
|
|
79
|
-
var import_config = __toESM(require("./config"));
|
|
80
|
-
var import_consts = __toESM(require("./consts"));
|
|
81
|
-
var import_output = __toESM(require("./output"));
|
|
82
|
-
var import_token = require("./init/token");
|
|
83
|
-
var import_sourcesToText = __toESM(require("./utils/sourcesToText"));
|
|
84
|
-
var import_generateJsDriver = require("./utils/generateJsDriver");
|
|
85
|
-
var import_cleanFileName = require("./utils/cleanFileName");
|
|
86
|
-
var import_fetchVariants = require("./http/fetchVariants");
|
|
87
|
-
var import_quit = require("./utils/quit");
|
|
88
|
-
var import_axios = require("axios");
|
|
89
|
-
var import_fetchComponentFolders = require("./http/fetchComponentFolders");
|
|
90
|
-
var import_generateSwiftDriver = require("./utils/generateSwiftDriver");
|
|
91
|
-
var import_generateIOSBundles = require("./utils/generateIOSBundles");
|
|
92
|
-
const ensureEndsWithNewLine = (str) => str + (/[\r\n]$/.test(str) ? "" : "\n");
|
|
93
|
-
const writeFile = (path2, data) => new Promise((r) => import_fs.default.writeFile(path2, ensureEndsWithNewLine(data), r));
|
|
94
|
-
const SUPPORTED_FORMATS = [
|
|
95
|
-
"flat",
|
|
96
|
-
"nested",
|
|
97
|
-
"structured",
|
|
98
|
-
"android",
|
|
99
|
-
"ios-strings",
|
|
100
|
-
"ios-stringsdict",
|
|
101
|
-
"icu"
|
|
102
|
-
];
|
|
103
|
-
const IOS_FORMATS = ["ios-strings", "ios-stringsdict"];
|
|
104
|
-
const JSON_FORMATS = ["flat", "nested", "structured", "icu"];
|
|
105
|
-
const getJsonFormat = (formats) => {
|
|
106
|
-
const jsonFormats = formats.filter(
|
|
107
|
-
(f) => JSON_FORMATS.includes(f)
|
|
108
|
-
);
|
|
109
|
-
return jsonFormats[jsonFormats.length - 1] || "flat";
|
|
110
|
-
};
|
|
111
|
-
const FORMAT_EXTENSIONS = {
|
|
112
|
-
flat: ".json",
|
|
113
|
-
nested: ".json",
|
|
114
|
-
structured: ".json",
|
|
115
|
-
android: ".xml",
|
|
116
|
-
"ios-strings": ".strings",
|
|
117
|
-
"ios-stringsdict": ".stringsdict",
|
|
118
|
-
icu: ".json"
|
|
119
|
-
};
|
|
120
|
-
const getJsonFormatIsValid = (data) => {
|
|
121
|
-
try {
|
|
122
|
-
return Object.keys(JSON.parse(data)).some(
|
|
123
|
-
(k) => !k.startsWith("__variant")
|
|
124
|
-
);
|
|
125
|
-
} catch (e) {
|
|
126
|
-
return false;
|
|
127
|
-
}
|
|
128
|
-
};
|
|
129
|
-
const getFormatDataIsValid = {
|
|
130
|
-
flat: getJsonFormatIsValid,
|
|
131
|
-
nested: getJsonFormatIsValid,
|
|
132
|
-
structured: getJsonFormatIsValid,
|
|
133
|
-
icu: getJsonFormatIsValid,
|
|
134
|
-
android: (data) => data.includes("<string"),
|
|
135
|
-
"ios-strings": (data) => data.includes(`" = "`),
|
|
136
|
-
"ios-stringsdict": (data) => data.includes("<key>")
|
|
137
|
-
};
|
|
138
|
-
const getFormat = (formatFromSource) => {
|
|
139
|
-
const formats = (Array.isArray(formatFromSource) ? formatFromSource : [formatFromSource]).filter(
|
|
140
|
-
(format) => SUPPORTED_FORMATS.includes(format)
|
|
141
|
-
);
|
|
142
|
-
if (formats.length) {
|
|
143
|
-
return formats;
|
|
144
|
-
}
|
|
145
|
-
return ["flat"];
|
|
146
|
-
};
|
|
147
|
-
const getFormatExtension = (format) => {
|
|
148
|
-
return FORMAT_EXTENSIONS[format];
|
|
149
|
-
};
|
|
150
|
-
const DEFAULT_FORMAT_KEYS = ["projects", "exported_at"];
|
|
151
|
-
const hasVariantData = (data) => {
|
|
152
|
-
const hasTopLevelKeys = Object.keys(data).filter((key) => !DEFAULT_FORMAT_KEYS.includes(key)).length > 0;
|
|
153
|
-
const hasProjectKeys = data.projects && Object.keys(data.projects).length > 0;
|
|
154
|
-
return hasTopLevelKeys || hasProjectKeys;
|
|
155
|
-
};
|
|
156
|
-
function askForAnotherToken() {
|
|
157
|
-
return __async(this, null, function* () {
|
|
158
|
-
import_config.default.deleteToken(import_consts.default.CONFIG_FILE, import_consts.default.API_HOST);
|
|
159
|
-
const message = "Looks like the API key you have saved no longer works. Please enter another one.";
|
|
160
|
-
yield (0, import_token.collectAndSaveToken)(message);
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
function downloadAndSaveVariant(variantApiId, requestOptions) {
|
|
164
|
-
return __async(this, null, function* () {
|
|
165
|
-
const { projects, format, status, richText, token } = requestOptions;
|
|
166
|
-
const api = (0, import_api.createApiClient)();
|
|
167
|
-
const params = { variant: variantApiId };
|
|
168
|
-
if (format)
|
|
169
|
-
params.format = format;
|
|
170
|
-
if (richText)
|
|
171
|
-
params.includeRichText = richText.toString();
|
|
172
|
-
if (status)
|
|
173
|
-
params.status = status;
|
|
174
|
-
const savedMessages = yield Promise.all(
|
|
175
|
-
projects.map((project) => __async(this, null, function* () {
|
|
176
|
-
const projectParams = __spreadValues({}, params);
|
|
177
|
-
if (project.status)
|
|
178
|
-
projectParams.status = project.status;
|
|
179
|
-
if (project.exclude_components)
|
|
180
|
-
projectParams.exclude_components = String(project.exclude_components);
|
|
181
|
-
const { data } = yield api.get(`/v1/projects/${project.id}`, {
|
|
182
|
-
params: projectParams,
|
|
183
|
-
headers: { Authorization: `token ${token}` }
|
|
184
|
-
});
|
|
185
|
-
if (!hasVariantData(data)) {
|
|
186
|
-
return "";
|
|
187
|
-
}
|
|
188
|
-
const extension = getFormatExtension(format);
|
|
189
|
-
const filename = (0, import_cleanFileName.cleanFileName)(
|
|
190
|
-
project.fileName + ("__" + (variantApiId || "base")) + extension
|
|
191
|
-
);
|
|
192
|
-
const filepath = import_path.default.join(import_consts.default.TEXT_DIR, filename);
|
|
193
|
-
let dataString = data;
|
|
194
|
-
if (extension === ".json") {
|
|
195
|
-
dataString = JSON.stringify(data, null, 2);
|
|
196
|
-
}
|
|
197
|
-
const dataIsValid = getFormatDataIsValid[format];
|
|
198
|
-
if (!dataIsValid(dataString)) {
|
|
199
|
-
return "";
|
|
200
|
-
}
|
|
201
|
-
yield writeFile(filepath, dataString);
|
|
202
|
-
return getSavedMessage(filename);
|
|
203
|
-
}))
|
|
204
|
-
);
|
|
205
|
-
return savedMessages.join("");
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
function downloadAndSaveVariants(requestOptions) {
|
|
209
|
-
return __async(this, null, function* () {
|
|
210
|
-
const messages = yield Promise.all([
|
|
211
|
-
downloadAndSaveVariant(null, requestOptions),
|
|
212
|
-
...requestOptions.variants.map(
|
|
213
|
-
({ apiID }) => downloadAndSaveVariant(apiID, requestOptions)
|
|
214
|
-
)
|
|
215
|
-
]);
|
|
216
|
-
return messages.join("");
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
function downloadAndSaveBase(requestOptions) {
|
|
220
|
-
return __async(this, null, function* () {
|
|
221
|
-
const { projects, format, status, richText, token, options } = requestOptions;
|
|
222
|
-
const api = (0, import_api.createApiClient)();
|
|
223
|
-
const params = __spreadValues({}, options == null ? void 0 : options.meta);
|
|
224
|
-
if (format)
|
|
225
|
-
params.format = format;
|
|
226
|
-
if (richText)
|
|
227
|
-
params.includeRichText = richText.toString();
|
|
228
|
-
if (status)
|
|
229
|
-
params.status = status;
|
|
230
|
-
const savedMessages = yield Promise.all(
|
|
231
|
-
projects.map((project) => __async(this, null, function* () {
|
|
232
|
-
const projectParams = __spreadValues({}, params);
|
|
233
|
-
if (project.status)
|
|
234
|
-
projectParams.status = project.status;
|
|
235
|
-
if (project.exclude_components)
|
|
236
|
-
projectParams.exclude_components = String(project.exclude_components);
|
|
237
|
-
const { data } = yield api.get(`/v1/projects/${project.id}`, {
|
|
238
|
-
params: projectParams,
|
|
239
|
-
headers: { Authorization: `token ${token}` }
|
|
240
|
-
});
|
|
241
|
-
const extension = getFormatExtension(format);
|
|
242
|
-
const filename = (0, import_cleanFileName.cleanFileName)(`${project.fileName}__base${extension}`);
|
|
243
|
-
const filepath = import_path.default.join(import_consts.default.TEXT_DIR, filename);
|
|
244
|
-
let dataString = data;
|
|
245
|
-
if (extension === ".json") {
|
|
246
|
-
dataString = JSON.stringify(data, null, 2);
|
|
247
|
-
}
|
|
248
|
-
const dataIsValid = getFormatDataIsValid[format];
|
|
249
|
-
if (!dataIsValid(dataString)) {
|
|
250
|
-
return "";
|
|
251
|
-
}
|
|
252
|
-
yield writeFile(filepath, dataString);
|
|
253
|
-
return getSavedMessage(filename);
|
|
254
|
-
}))
|
|
255
|
-
);
|
|
256
|
-
return savedMessages.join("");
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
function getSavedMessage(file) {
|
|
260
|
-
return `Successfully saved to ${import_output.default.info(file)}
|
|
261
|
-
`;
|
|
262
|
-
}
|
|
263
|
-
function cleanOutputFiles() {
|
|
264
|
-
if (!import_fs.default.existsSync(import_consts.default.TEXT_DIR)) {
|
|
265
|
-
import_fs.default.mkdirSync(import_consts.default.TEXT_DIR);
|
|
266
|
-
}
|
|
267
|
-
const directoryContents = import_fs.default.readdirSync(import_consts.default.TEXT_DIR, {
|
|
268
|
-
withFileTypes: true
|
|
269
|
-
});
|
|
270
|
-
directoryContents.forEach((item) => {
|
|
271
|
-
if (item.isDirectory() && /\.lproj$/.test(item.name)) {
|
|
272
|
-
return import_fs.default.rmSync(import_path.default.resolve(import_consts.default.TEXT_DIR, item.name), {
|
|
273
|
-
recursive: true,
|
|
274
|
-
force: true
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
|
-
if (item.isFile() && /\.js(on)?|\.ts|\.xml|\.strings(dict)?$|\.swift$/.test(item.name)) {
|
|
278
|
-
return import_fs.default.unlinkSync(import_path.default.resolve(import_consts.default.TEXT_DIR, item.name));
|
|
279
|
-
}
|
|
280
|
-
});
|
|
281
|
-
return "Cleaning old output files..\n";
|
|
282
|
-
}
|
|
283
|
-
function downloadAndSave(source, token, options) {
|
|
284
|
-
return __async(this, null, function* () {
|
|
285
|
-
const api = (0, import_api.createApiClient)();
|
|
286
|
-
const {
|
|
287
|
-
validProjects,
|
|
288
|
-
format: formatFromSource,
|
|
289
|
-
shouldFetchComponentLibrary,
|
|
290
|
-
status,
|
|
291
|
-
richText,
|
|
292
|
-
componentFolders: specifiedComponentFolders,
|
|
293
|
-
componentRoot,
|
|
294
|
-
localeByVariantApiId,
|
|
295
|
-
disableJsDriver
|
|
296
|
-
} = source;
|
|
297
|
-
const formats = getFormat(formatFromSource);
|
|
298
|
-
const hasJSONFormat = formats.some(
|
|
299
|
-
(f) => JSON_FORMATS.includes(f)
|
|
300
|
-
);
|
|
301
|
-
const hasIOSFormat = formats.some((f) => IOS_FORMATS.includes(f));
|
|
302
|
-
const shouldGenerateIOSBundles = hasIOSFormat && localeByVariantApiId;
|
|
303
|
-
const shouldLogOutputFiles = !shouldGenerateIOSBundles;
|
|
304
|
-
let msg = "";
|
|
305
|
-
const spinner = (0, import_ora.default)(msg);
|
|
306
|
-
spinner.start();
|
|
307
|
-
const [variants, allComponentFoldersResponse] = yield Promise.all([
|
|
308
|
-
(0, import_fetchVariants.fetchVariants)(source, options),
|
|
309
|
-
(0, import_fetchComponentFolders.fetchComponentFolders)({})
|
|
310
|
-
]);
|
|
311
|
-
const allComponentFolders = Object.entries(
|
|
312
|
-
allComponentFoldersResponse
|
|
313
|
-
).reduce(
|
|
314
|
-
(acc, [id, name]) => acc.concat([{ id, name }]),
|
|
315
|
-
[]
|
|
316
|
-
);
|
|
317
|
-
try {
|
|
318
|
-
msg += cleanOutputFiles();
|
|
319
|
-
msg += `
|
|
320
|
-
Fetching the latest text from ${(0, import_sourcesToText.default)(
|
|
321
|
-
validProjects,
|
|
322
|
-
shouldFetchComponentLibrary
|
|
323
|
-
)}
|
|
324
|
-
`;
|
|
325
|
-
const meta = options ? options.meta : {};
|
|
326
|
-
const rootRequest = {
|
|
327
|
-
id: "__root__",
|
|
328
|
-
name: "Root",
|
|
329
|
-
// componentRoot can be a boolean or an object
|
|
330
|
-
status: typeof source.componentRoot === "object" ? source.componentRoot.status : void 0
|
|
331
|
-
};
|
|
332
|
-
let componentFolderRequests = [];
|
|
333
|
-
if (specifiedComponentFolders) {
|
|
334
|
-
switch (componentRoot) {
|
|
335
|
-
case void 0:
|
|
336
|
-
case false:
|
|
337
|
-
componentFolderRequests.push(...specifiedComponentFolders);
|
|
338
|
-
break;
|
|
339
|
-
default:
|
|
340
|
-
componentFolderRequests.push(...specifiedComponentFolders);
|
|
341
|
-
componentFolderRequests.push(rootRequest);
|
|
342
|
-
break;
|
|
343
|
-
}
|
|
344
|
-
} else {
|
|
345
|
-
switch (componentRoot) {
|
|
346
|
-
case void 0:
|
|
347
|
-
componentFolderRequests.push(...allComponentFolders);
|
|
348
|
-
componentFolderRequests.push(rootRequest);
|
|
349
|
-
break;
|
|
350
|
-
case false:
|
|
351
|
-
componentFolderRequests.push(...allComponentFolders);
|
|
352
|
-
break;
|
|
353
|
-
default:
|
|
354
|
-
componentFolderRequests.push(rootRequest);
|
|
355
|
-
break;
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
const componentSources = [];
|
|
359
|
-
function fetchComponentLibrary(format) {
|
|
360
|
-
return __async(this, null, function* () {
|
|
361
|
-
const componentVariants = [{ apiID: void 0 }, ...variants || []];
|
|
362
|
-
const params = new URLSearchParams();
|
|
363
|
-
if (options == null ? void 0 : options.meta)
|
|
364
|
-
Object.entries(options.meta).forEach(([k, v]) => params.append(k, v));
|
|
365
|
-
if (format)
|
|
366
|
-
params.append("format", format);
|
|
367
|
-
if (richText)
|
|
368
|
-
params.append("includeRichText", richText.toString());
|
|
369
|
-
if (status)
|
|
370
|
-
params.append("status", status);
|
|
371
|
-
const messagePromises = [];
|
|
372
|
-
componentVariants.forEach(({ apiID: variantApiId }) => {
|
|
373
|
-
messagePromises.push(
|
|
374
|
-
...componentFolderRequests.map((componentFolder) => __async(this, null, function* () {
|
|
375
|
-
const componentFolderParams = new URLSearchParams(params);
|
|
376
|
-
if (variantApiId)
|
|
377
|
-
componentFolderParams.append("variant", variantApiId);
|
|
378
|
-
if (componentFolder.status)
|
|
379
|
-
componentFolderParams.append("status", componentFolder.status);
|
|
380
|
-
const url = componentFolder.id === "__root__" ? "/v1/components?root_only=true" : `/v1/component-folders/${componentFolder.id}/components`;
|
|
381
|
-
const { data } = yield api.get(url, {
|
|
382
|
-
params: componentFolderParams
|
|
383
|
-
});
|
|
384
|
-
const nameExt = getFormatExtension(format);
|
|
385
|
-
const nameBase = "components";
|
|
386
|
-
const nameFolder = `__${(0, import_cleanFileName.cleanFileName)(componentFolder.name)}`;
|
|
387
|
-
const namePostfix = `__${variantApiId || "base"}`;
|
|
388
|
-
const fileName = (0, import_cleanFileName.cleanFileName)(
|
|
389
|
-
`${nameBase}${nameFolder}${namePostfix}${nameExt}`
|
|
390
|
-
);
|
|
391
|
-
const filePath = import_path.default.join(import_consts.default.TEXT_DIR, fileName);
|
|
392
|
-
let dataString = data;
|
|
393
|
-
if (nameExt === ".json") {
|
|
394
|
-
dataString = JSON.stringify(data, null, 2);
|
|
395
|
-
}
|
|
396
|
-
const dataIsValid = getFormatDataIsValid[format];
|
|
397
|
-
if (!dataIsValid(dataString)) {
|
|
398
|
-
return "";
|
|
399
|
-
}
|
|
400
|
-
yield writeFile(filePath, dataString);
|
|
401
|
-
componentSources.push({
|
|
402
|
-
type: "components",
|
|
403
|
-
id: "ditto_component_library",
|
|
404
|
-
name: "ditto_component_library",
|
|
405
|
-
fileName,
|
|
406
|
-
variant: variantApiId || "base"
|
|
407
|
-
});
|
|
408
|
-
return getSavedMessage(fileName);
|
|
409
|
-
}))
|
|
410
|
-
);
|
|
411
|
-
});
|
|
412
|
-
const messages = yield Promise.all(messagePromises);
|
|
413
|
-
if (shouldLogOutputFiles) {
|
|
414
|
-
msg += messages.join("");
|
|
415
|
-
}
|
|
416
|
-
});
|
|
417
|
-
}
|
|
418
|
-
if (shouldFetchComponentLibrary) {
|
|
419
|
-
for (const format of formats) {
|
|
420
|
-
yield fetchComponentLibrary(format);
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
function fetchProjects(format) {
|
|
424
|
-
return __async(this, null, function* () {
|
|
425
|
-
let result = "";
|
|
426
|
-
if (variants) {
|
|
427
|
-
result = yield downloadAndSaveVariants({
|
|
428
|
-
variants,
|
|
429
|
-
projects: validProjects,
|
|
430
|
-
format,
|
|
431
|
-
status,
|
|
432
|
-
richText,
|
|
433
|
-
token
|
|
434
|
-
});
|
|
435
|
-
} else {
|
|
436
|
-
result = yield downloadAndSaveBase({
|
|
437
|
-
projects: validProjects,
|
|
438
|
-
format,
|
|
439
|
-
status,
|
|
440
|
-
richText,
|
|
441
|
-
token,
|
|
442
|
-
options: {
|
|
443
|
-
meta
|
|
444
|
-
}
|
|
445
|
-
});
|
|
446
|
-
}
|
|
447
|
-
if (shouldLogOutputFiles) {
|
|
448
|
-
msg += result;
|
|
449
|
-
}
|
|
450
|
-
});
|
|
451
|
-
}
|
|
452
|
-
if (validProjects.length) {
|
|
453
|
-
for (const format of formats) {
|
|
454
|
-
yield fetchProjects(format);
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
const sources = [...validProjects, ...componentSources];
|
|
458
|
-
if (hasJSONFormat && !disableJsDriver)
|
|
459
|
-
msg += (0, import_generateJsDriver.generateJsDriver)(sources, getJsonFormat(formats));
|
|
460
|
-
if (shouldGenerateIOSBundles) {
|
|
461
|
-
msg += "iOS locale information detected, generating bundles..\n\n";
|
|
462
|
-
msg += yield (0, import_generateIOSBundles.generateIOSBundles)(localeByVariantApiId);
|
|
463
|
-
msg += yield (0, import_generateSwiftDriver.generateSwiftDriver)(source);
|
|
464
|
-
}
|
|
465
|
-
msg += `
|
|
466
|
-
|
|
467
|
-
${import_output.default.success("Done")}!`;
|
|
468
|
-
spinner.stop();
|
|
469
|
-
return console.log(msg);
|
|
470
|
-
} catch (e) {
|
|
471
|
-
console.error(e);
|
|
472
|
-
spinner.stop();
|
|
473
|
-
let error = e.message;
|
|
474
|
-
if (e.response && e.response.status === 404) {
|
|
475
|
-
yield askForAnotherToken();
|
|
476
|
-
pull();
|
|
477
|
-
return;
|
|
478
|
-
}
|
|
479
|
-
if (e.response && e.response.status === 401) {
|
|
480
|
-
error = "You don't have access to the selected projects";
|
|
481
|
-
msg = `${import_output.default.errorText(error)}.
|
|
482
|
-
Choose others using the ${import_output.default.info(
|
|
483
|
-
"project"
|
|
484
|
-
)} command, or update your API key.`;
|
|
485
|
-
return console.log(msg);
|
|
486
|
-
}
|
|
487
|
-
if (e.response && e.response.status === 403) {
|
|
488
|
-
error = "One or more of the requested projects don't have Developer Mode enabled";
|
|
489
|
-
msg = `${import_output.default.errorText(
|
|
490
|
-
error
|
|
491
|
-
)}.
|
|
492
|
-
Please choose different projects using the ${import_output.default.info(
|
|
493
|
-
"project"
|
|
494
|
-
)} command, or turn on Developer Mode for all selected projects. Learn more here: ${import_output.default.subtle(
|
|
495
|
-
"https://www.dittowords.com/docs/ditto-developer-mode"
|
|
496
|
-
)}.`;
|
|
497
|
-
return console.log(msg);
|
|
498
|
-
}
|
|
499
|
-
if (e.response && e.response.status === 400) {
|
|
500
|
-
error = "projects not found";
|
|
501
|
-
}
|
|
502
|
-
msg = `We hit an error fetching text from the projects: ${import_output.default.errorText(
|
|
503
|
-
error
|
|
504
|
-
)}.
|
|
505
|
-
Choose others using the ${import_output.default.info("project")} command.`;
|
|
506
|
-
return console.log(msg);
|
|
507
|
-
}
|
|
508
|
-
});
|
|
509
|
-
}
|
|
510
|
-
const pull = (options) => __async(void 0, null, function* () {
|
|
511
|
-
const meta = options ? options.meta : {};
|
|
512
|
-
const includeSampleData = (options == null ? void 0 : options.includeSampleData) || false;
|
|
513
|
-
const token = import_config.default.getToken(import_consts.default.CONFIG_FILE, import_consts.default.API_HOST);
|
|
514
|
-
const sourceInformation = import_config.default.parseSourceInformation();
|
|
515
|
-
try {
|
|
516
|
-
return yield downloadAndSave(sourceInformation, token, {
|
|
517
|
-
meta,
|
|
518
|
-
includeSampleData
|
|
519
|
-
});
|
|
520
|
-
} catch (e) {
|
|
521
|
-
const eventId = Sentry.captureException(e);
|
|
522
|
-
const eventStr = `
|
|
523
|
-
|
|
524
|
-
Error ID: ${import_output.default.info(eventId)}`;
|
|
525
|
-
if (e instanceof import_axios.AxiosError) {
|
|
526
|
-
return yield (0, import_quit.quit)(
|
|
527
|
-
import_output.default.errorText(
|
|
528
|
-
"Something went wrong connecting to Ditto servers. Please contact support or try again later."
|
|
529
|
-
) + eventStr
|
|
530
|
-
);
|
|
531
|
-
}
|
|
532
|
-
return yield (0, import_quit.quit)(
|
|
533
|
-
import_output.default.errorText(
|
|
534
|
-
"Something went wrong. Please contact support or try again later."
|
|
535
|
-
) + eventStr
|
|
536
|
-
);
|
|
537
|
-
}
|
|
538
|
-
});
|
|
539
|
-
var pull_default = {
|
|
540
|
-
pull,
|
|
541
|
-
_testing: {
|
|
542
|
-
cleanOutputFiles,
|
|
543
|
-
downloadAndSaveVariant,
|
|
544
|
-
downloadAndSaveVariants,
|
|
545
|
-
downloadAndSaveBase
|
|
546
|
-
}
|
|
547
|
-
};
|
|
548
|
-
const _test = {
|
|
549
|
-
getJsonFormat,
|
|
550
|
-
getJsonFormatIsValid,
|
|
551
|
-
ensureEndsWithNewLine
|
|
552
|
-
};
|
|
553
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
554
|
-
0 && (module.exports = {
|
|
555
|
-
_test,
|
|
556
|
-
getFormatDataIsValid,
|
|
557
|
-
pull,
|
|
558
|
-
writeFile
|
|
559
|
-
});
|
|
560
|
-
//# sourceMappingURL=pull.js.map
|
|
561
|
-
|
|
562
|
-
//# debugId=e1fa8919-644e-53c0-9bd8-11223fd4f8f2
|
package/bin/pull.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../lib/pull.ts"],"sourcesContent":["import fs from \"fs\";\nimport path from \"path\";\n\nimport ora from \"ora\";\nimport * as Sentry from \"@sentry/node\";\n\nimport { createApiClient } from \"./api\";\nimport config from \"./config\";\nimport consts from \"./consts\";\nimport output from \"./output\";\nimport { collectAndSaveToken } from \"./init/token\";\nimport sourcesToText from \"./utils/sourcesToText\";\nimport { generateJsDriver } from \"./utils/generateJsDriver\";\nimport { cleanFileName } from \"./utils/cleanFileName\";\nimport {\n SourceInformation,\n Token,\n Project,\n SupportedFormat,\n SupportedExtension,\n ComponentFolder,\n ComponentSource,\n Source,\n} from \"./types\";\nimport { fetchVariants } from \"./http/fetchVariants\";\nimport { quit } from \"./utils/quit\";\nimport { AxiosError } from \"axios\";\nimport { fetchComponentFolders } from \"./http/fetchComponentFolders\";\nimport { generateSwiftDriver } from \"./utils/generateSwiftDriver\";\nimport { generateIOSBundles } from \"./utils/generateIOSBundles\";\n\ninterface IRequestOptions {\n projects: Project[];\n format: SupportedFormat;\n status: string | undefined;\n richText?: boolean | undefined;\n token?: Token;\n options?: PullOptions;\n}\n\ninterface IRequestOptionsWithVariants extends IRequestOptions {\n variants: { apiID: string }[];\n}\n\nconst ensureEndsWithNewLine = (str: string) =>\n str + (/[\\r\\n]$/.test(str) ? \"\" : \"\\n\");\n\nexport const writeFile = (path: string, data: string) =>\n new Promise((r) => fs.writeFile(path, ensureEndsWithNewLine(data), r));\n\nconst SUPPORTED_FORMATS: SupportedFormat[] = [\n \"flat\",\n \"nested\",\n \"structured\",\n \"android\",\n \"ios-strings\",\n \"ios-stringsdict\",\n \"icu\",\n];\n\nexport type JSONFormat = \"flat\" | \"nested\" | \"structured\" | \"icu\";\n\nconst IOS_FORMATS: SupportedFormat[] = [\"ios-strings\", \"ios-stringsdict\"];\nconst JSON_FORMATS: JSONFormat[] = [\"flat\", \"nested\", \"structured\", \"icu\"];\n\nconst getJsonFormat = (formats: string[]): JSONFormat => {\n // edge case: multiple json formats specified\n // we should grab the last one\n const jsonFormats = formats.filter((f) =>\n JSON_FORMATS.includes(f as JSONFormat)\n ) as JSONFormat[];\n\n return jsonFormats[jsonFormats.length - 1] || \"flat\";\n};\n\nconst FORMAT_EXTENSIONS: Record<SupportedFormat, SupportedExtension> = {\n flat: \".json\",\n nested: \".json\",\n structured: \".json\",\n android: \".xml\",\n \"ios-strings\": \".strings\",\n \"ios-stringsdict\": \".stringsdict\",\n icu: \".json\",\n};\n\nconst getJsonFormatIsValid = (data: string) => {\n try {\n return Object.keys(JSON.parse(data)).some(\n (k) => !k.startsWith(\"__variant\")\n );\n } catch {\n return false;\n }\n};\n\n// exported for test usage only\nexport const getFormatDataIsValid = {\n flat: getJsonFormatIsValid,\n nested: getJsonFormatIsValid,\n structured: getJsonFormatIsValid,\n icu: getJsonFormatIsValid,\n android: (data: string) => data.includes(\"<string\"),\n \"ios-strings\": (data: string) => data.includes(`\" = \"`),\n \"ios-stringsdict\": (data: string) => data.includes(\"<key>\"),\n};\n\nconst getFormat = (\n formatFromSource: string | string[] | undefined\n): SupportedFormat[] => {\n const formats = (\n Array.isArray(formatFromSource) ? formatFromSource : [formatFromSource]\n ).filter((format) =>\n SUPPORTED_FORMATS.includes(format as SupportedFormat)\n ) as SupportedFormat[];\n\n if (formats.length) {\n return formats;\n }\n\n return [\"flat\"];\n};\n\nconst getFormatExtension = (format: SupportedFormat) => {\n return FORMAT_EXTENSIONS[format];\n};\n\nconst DEFAULT_FORMAT_KEYS = [\"projects\", \"exported_at\"];\nconst hasVariantData = (data: any) => {\n const hasTopLevelKeys =\n Object.keys(data).filter((key) => !DEFAULT_FORMAT_KEYS.includes(key))\n .length > 0;\n\n const hasProjectKeys = data.projects && Object.keys(data.projects).length > 0;\n\n return hasTopLevelKeys || hasProjectKeys;\n};\n\nasync function askForAnotherToken() {\n config.deleteToken(consts.CONFIG_FILE, consts.API_HOST);\n const message =\n \"Looks like the API key you have saved no longer works. Please enter another one.\";\n await collectAndSaveToken(message);\n}\n\n/**\n * For a given variant:\n * - if format is unspecified, fetch data for all projects from `/projects` and\n * save in `{variantApiId}.json`\n * - if format is `flat` or `structured`, fetch data for each project from `/project/:project_id` and\n * save in `{projectName}-${variantApiId}.json`\n */\nasync function downloadAndSaveVariant(\n variantApiId: string | null,\n requestOptions: IRequestOptions\n) {\n const { projects, format, status, richText, token } = requestOptions;\n const api = createApiClient();\n const params: Record<string, string | null> = { variant: variantApiId };\n if (format) params.format = format;\n if (richText) params.includeRichText = richText.toString();\n\n // Root-level status gets set as the default if specified\n if (status) params.status = status;\n\n const savedMessages = await Promise.all(\n projects.map(async (project) => {\n const projectParams = { ...params };\n // If project-level status is specified, overrides root-level status\n if (project.status) projectParams.status = project.status;\n if (project.exclude_components)\n projectParams.exclude_components = String(project.exclude_components);\n\n const { data } = await api.get(`/v1/projects/${project.id}`, {\n params: projectParams,\n headers: { Authorization: `token ${token}` },\n });\n\n if (!hasVariantData(data)) {\n return \"\";\n }\n\n const extension = getFormatExtension(format);\n\n const filename = cleanFileName(\n project.fileName + (\"__\" + (variantApiId || \"base\")) + extension\n );\n const filepath = path.join(consts.TEXT_DIR, filename);\n\n let dataString = data;\n if (extension === \".json\") {\n dataString = JSON.stringify(data, null, 2);\n }\n\n const dataIsValid = getFormatDataIsValid[format];\n if (!dataIsValid(dataString)) {\n return \"\";\n }\n\n await writeFile(filepath, dataString);\n return getSavedMessage(filename);\n })\n );\n\n return savedMessages.join(\"\");\n}\n\nasync function downloadAndSaveVariants(\n requestOptions: IRequestOptionsWithVariants\n) {\n const messages = await Promise.all([\n downloadAndSaveVariant(null, requestOptions),\n ...requestOptions.variants.map(({ apiID }: { apiID: string }) =>\n downloadAndSaveVariant(apiID, requestOptions)\n ),\n ]);\n\n return messages.join(\"\");\n}\n\nasync function downloadAndSaveBase(requestOptions: IRequestOptions) {\n const { projects, format, status, richText, token, options } = requestOptions;\n\n const api = createApiClient();\n const params = { ...options?.meta };\n if (format) params.format = format;\n if (richText) params.includeRichText = richText.toString();\n\n // Root-level status gets set as the default if specified\n if (status) params.status = status;\n\n const savedMessages = await Promise.all(\n projects.map(async (project) => {\n const projectParams = { ...params };\n // If project-level status is specified, overrides root-level status\n if (project.status) projectParams.status = project.status;\n if (project.exclude_components)\n projectParams.exclude_components = String(project.exclude_components);\n\n const { data } = await api.get(`/v1/projects/${project.id}`, {\n params: projectParams,\n headers: { Authorization: `token ${token}` },\n });\n\n const extension = getFormatExtension(format);\n const filename = cleanFileName(`${project.fileName}__base${extension}`);\n const filepath = path.join(consts.TEXT_DIR, filename);\n\n let dataString = data;\n if (extension === \".json\") {\n dataString = JSON.stringify(data, null, 2);\n }\n\n const dataIsValid = getFormatDataIsValid[format];\n if (!dataIsValid(dataString)) {\n return \"\";\n }\n\n await writeFile(filepath, dataString);\n return getSavedMessage(filename);\n })\n );\n\n return savedMessages.join(\"\");\n}\n\nfunction getSavedMessage(file: string) {\n return `Successfully saved to ${output.info(file)}\\n`;\n}\n\nfunction cleanOutputFiles() {\n if (!fs.existsSync(consts.TEXT_DIR)) {\n fs.mkdirSync(consts.TEXT_DIR);\n }\n\n const directoryContents = fs.readdirSync(consts.TEXT_DIR, {\n withFileTypes: true,\n });\n\n directoryContents.forEach((item) => {\n if (item.isDirectory() && /\\.lproj$/.test(item.name)) {\n return fs.rmSync(path.resolve(consts.TEXT_DIR, item.name), {\n recursive: true,\n force: true,\n });\n }\n\n if (\n item.isFile() &&\n /\\.js(on)?|\\.ts|\\.xml|\\.strings(dict)?$|\\.swift$/.test(item.name)\n ) {\n return fs.unlinkSync(path.resolve(consts.TEXT_DIR, item.name));\n }\n });\n\n return \"Cleaning old output files..\\n\";\n}\n\nasync function downloadAndSave(\n source: SourceInformation,\n token?: Token,\n options?: PullOptions\n) {\n const api = createApiClient();\n const {\n validProjects,\n format: formatFromSource,\n shouldFetchComponentLibrary,\n status,\n richText,\n componentFolders: specifiedComponentFolders,\n componentRoot,\n localeByVariantApiId,\n disableJsDriver,\n } = source;\n\n const formats = getFormat(formatFromSource);\n\n const hasJSONFormat = formats.some((f) =>\n JSON_FORMATS.includes(f as JSONFormat)\n );\n const hasIOSFormat = formats.some((f) => IOS_FORMATS.includes(f));\n const shouldGenerateIOSBundles = hasIOSFormat && localeByVariantApiId;\n\n const shouldLogOutputFiles = !shouldGenerateIOSBundles;\n\n let msg = \"\";\n const spinner = ora(msg);\n spinner.start();\n\n const [variants, allComponentFoldersResponse] = await Promise.all([\n fetchVariants(source, options),\n fetchComponentFolders({}),\n ]);\n\n const allComponentFolders = Object.entries(\n allComponentFoldersResponse\n ).reduce(\n (acc, [id, name]) => acc.concat([{ id, name }]),\n [] as ComponentFolder[]\n );\n\n try {\n msg += cleanOutputFiles();\n msg += `\\nFetching the latest text from ${sourcesToText(\n validProjects,\n shouldFetchComponentLibrary\n )}\\n`;\n\n const meta = options ? options.meta : {};\n\n const rootRequest = {\n id: \"__root__\",\n name: \"Root\",\n // componentRoot can be a boolean or an object\n status:\n typeof source.componentRoot === \"object\"\n ? source.componentRoot.status\n : undefined,\n };\n\n let componentFolderRequests: ComponentFolder[] = [];\n\n // there's a lot of complex logic here, and it's tempting to want to\n // simplify it. however, it's difficult to get rid of the complexity\n // without sacrificing specificity and expressiveness.\n //\n // if folders specified..\n if (specifiedComponentFolders) {\n switch (componentRoot) {\n // .. and no root specified, you only get components in the specified folders\n case undefined:\n case false:\n componentFolderRequests.push(...specifiedComponentFolders);\n break;\n // .. and root specified, you get components in folders and the root\n default:\n componentFolderRequests.push(...specifiedComponentFolders);\n componentFolderRequests.push(rootRequest);\n break;\n }\n }\n // if no folders specified..\n else {\n switch (componentRoot) {\n // .. and no root specified, you get all components including those in folders\n case undefined:\n componentFolderRequests.push(...allComponentFolders);\n componentFolderRequests.push(rootRequest);\n break;\n // .. and root specified as false, you only get components in folders\n case false:\n componentFolderRequests.push(...allComponentFolders);\n break;\n // .. and root specified as true or config object, you only get components in the root\n default:\n componentFolderRequests.push(rootRequest);\n break;\n }\n }\n\n // this array is populated while fetching from the component library and is used when\n // generating the index.js driver file\n const componentSources: ComponentSource[] = [];\n\n async function fetchComponentLibrary(format: SupportedFormat) {\n // Always include a variant with an apiID of undefined to ensure that we\n // fetch the base text for the component library.\n const componentVariants = [{ apiID: undefined }, ...(variants || [])];\n\n const params = new URLSearchParams();\n if (options?.meta)\n Object.entries(options.meta).forEach(([k, v]) => params.append(k, v));\n if (format) params.append(\"format\", format);\n if (richText) params.append(\"includeRichText\", richText.toString());\n\n // Root-level status gets set as the default if specified\n if (status) params.append(\"status\", status);\n\n const messagePromises: Promise<string>[] = [];\n\n componentVariants.forEach(({ apiID: variantApiId }) => {\n messagePromises.push(\n ...componentFolderRequests.map(async (componentFolder) => {\n const componentFolderParams = new URLSearchParams(params);\n\n if (variantApiId)\n componentFolderParams.append(\"variant\", variantApiId);\n\n // If folder-level status is specified, overrides root-level status\n if (componentFolder.status)\n componentFolderParams.append(\"status\", componentFolder.status);\n\n const url =\n componentFolder.id === \"__root__\"\n ? \"/v1/components?root_only=true\"\n : `/v1/component-folders/${componentFolder.id}/components`;\n\n const { data } = await api.get(url, {\n params: componentFolderParams,\n });\n\n const nameExt = getFormatExtension(format);\n const nameBase = \"components\";\n\n // we need to clean the folder name by itself first, otherwise we can\n // end up with \"empty\" words and weird hyphenation.\n const nameFolder = `__${cleanFileName(componentFolder.name)}`;\n const namePostfix = `__${variantApiId || \"base\"}`;\n\n const fileName = cleanFileName(\n `${nameBase}${nameFolder}${namePostfix}${nameExt}`\n );\n const filePath = path.join(consts.TEXT_DIR, fileName);\n\n let dataString = data;\n if (nameExt === \".json\") {\n dataString = JSON.stringify(data, null, 2);\n }\n\n const dataIsValid = getFormatDataIsValid[format];\n if (!dataIsValid(dataString)) {\n return \"\";\n }\n\n await writeFile(filePath, dataString);\n\n componentSources.push({\n type: \"components\",\n id: \"ditto_component_library\",\n name: \"ditto_component_library\",\n fileName,\n variant: variantApiId || \"base\",\n });\n\n return getSavedMessage(fileName);\n })\n );\n });\n\n const messages = await Promise.all(messagePromises);\n if (shouldLogOutputFiles) {\n msg += messages.join(\"\");\n }\n }\n\n if (shouldFetchComponentLibrary) {\n for (const format of formats) {\n await fetchComponentLibrary(format);\n }\n }\n\n async function fetchProjects(format: SupportedFormat) {\n let result = \"\";\n if (variants) {\n result = await downloadAndSaveVariants({\n variants,\n projects: validProjects,\n format,\n status,\n richText,\n token,\n });\n } else {\n result = await downloadAndSaveBase({\n projects: validProjects,\n format,\n status,\n richText,\n token,\n options: {\n meta,\n },\n });\n }\n\n if (shouldLogOutputFiles) {\n msg += result;\n }\n }\n\n if (validProjects.length) {\n for (const format of formats) {\n await fetchProjects(format);\n }\n }\n\n const sources: Source[] = [...validProjects, ...componentSources];\n\n if (hasJSONFormat && !disableJsDriver)\n msg += generateJsDriver(sources, getJsonFormat(formats));\n\n if (shouldGenerateIOSBundles) {\n msg += \"iOS locale information detected, generating bundles..\\n\\n\";\n msg += await generateIOSBundles(localeByVariantApiId);\n msg += await generateSwiftDriver(source);\n }\n\n msg += `\\n\\n${output.success(\"Done\")}!`;\n\n spinner.stop();\n return console.log(msg);\n } catch (e: any) {\n console.error(e);\n\n spinner.stop();\n let error = e.message;\n if (e.response && e.response.status === 404) {\n await askForAnotherToken();\n pull();\n return;\n }\n if (e.response && e.response.status === 401) {\n error = \"You don't have access to the selected projects\";\n msg = `${output.errorText(error)}.\\nChoose others using the ${output.info(\n \"project\"\n )} command, or update your API key.`;\n return console.log(msg);\n }\n if (e.response && e.response.status === 403) {\n error =\n \"One or more of the requested projects don't have Developer Mode enabled\";\n msg = `${output.errorText(\n error\n )}.\\nPlease choose different projects using the ${output.info(\n \"project\"\n )} command, or turn on Developer Mode for all selected projects. Learn more here: ${output.subtle(\n \"https://www.dittowords.com/docs/ditto-developer-mode\"\n )}.`;\n return console.log(msg);\n }\n if (e.response && e.response.status === 400) {\n error = \"projects not found\";\n }\n msg = `We hit an error fetching text from the projects: ${output.errorText(\n error\n )}.\\nChoose others using the ${output.info(\"project\")} command.`;\n return console.log(msg);\n }\n}\n\nexport interface PullOptions {\n meta?: Record<string, string>;\n includeSampleData?: boolean;\n}\n\nexport const pull = async (options?: PullOptions) => {\n const meta = options ? options.meta : {};\n const includeSampleData = options?.includeSampleData || false;\n const token = config.getToken(consts.CONFIG_FILE, consts.API_HOST);\n const sourceInformation = config.parseSourceInformation();\n try {\n return await downloadAndSave(sourceInformation, token, {\n meta,\n includeSampleData,\n });\n } catch (e) {\n const eventId = Sentry.captureException(e);\n const eventStr = `\\n\\nError ID: ${output.info(eventId)}`;\n if (e instanceof AxiosError) {\n return await quit(\n output.errorText(\n \"Something went wrong connecting to Ditto servers. Please contact support or try again later.\"\n ) + eventStr\n );\n }\n\n return await quit(\n output.errorText(\n \"Something went wrong. Please contact support or try again later.\"\n ) + eventStr\n );\n }\n};\n\nexport default {\n pull,\n _testing: {\n cleanOutputFiles,\n downloadAndSaveVariant,\n downloadAndSaveVariants,\n downloadAndSaveBase,\n },\n};\n\nexport const _test = {\n getJsonFormat,\n getJsonFormatIsValid,\n ensureEndsWithNewLine,\n};\n"],"names":["path","fs","config","consts","output","ora","sourcesToText"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAAe;AACf,kBAAiB;AAEjB,iBAAgB;AAChB,aAAwB;AAExB,iBAAgC;AAChC,oBAAmB;AACnB,oBAAmB;AACnB,oBAAmB;AACnB,mBAAoC;AACpC,2BAA0B;AAC1B,8BAAiC;AACjC,2BAA8B;AAW9B,2BAA8B;AAC9B,kBAAqB;AACrB,mBAA2B;AAC3B,mCAAsC;AACtC,iCAAoC;AACpC,gCAAmC;AAenC,MAAM,wBAAwB,CAAC,QAC7B,OAAO,UAAU,KAAK,GAAG,IAAI,KAAK;AAE7B,MAAM,YAAY,CAACA,OAAc,SACtC,IAAI,QAAQ,CAAC,MAAM,UAAAC,QAAG,UAAUD,OAAM,sBAAsB,IAAI,GAAG,CAAC,CAAC;AAEvE,MAAM,oBAAuC;AAAA,EAC3C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAIA,MAAM,cAAiC,CAAC,eAAe,iBAAiB;AACxE,MAAM,eAA6B,CAAC,QAAQ,UAAU,cAAc,KAAK;AAEzE,MAAM,gBAAgB,CAAC,YAAkC;AAGvD,QAAM,cAAc,QAAQ;AAAA,IAAO,CAAC,MAClC,aAAa,SAAS,CAAe;AAAA,EACvC;AAEA,SAAO,YAAY,YAAY,SAAS,CAAC,KAAK;AAChD;AAEA,MAAM,oBAAiE;AAAA,EACrE,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,KAAK;AACP;AAEA,MAAM,uBAAuB,CAAC,SAAiB;AAC7C,MAAI;AACF,WAAO,OAAO,KAAK,KAAK,MAAM,IAAI,CAAC,EAAE;AAAA,MACnC,CAAC,MAAM,CAAC,EAAE,WAAW,WAAW;AAAA,IAClC;AAAA,EACF,SAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,MAAM,uBAAuB;AAAA,EAClC,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,KAAK;AAAA,EACL,SAAS,CAAC,SAAiB,KAAK,SAAS,SAAS;AAAA,EAClD,eAAe,CAAC,SAAiB,KAAK,SAAS,OAAO;AAAA,EACtD,mBAAmB,CAAC,SAAiB,KAAK,SAAS,OAAO;AAC5D;AAEA,MAAM,YAAY,CAChB,qBACsB;AACtB,QAAM,WACJ,MAAM,QAAQ,gBAAgB,IAAI,mBAAmB,CAAC,gBAAgB,GACtE;AAAA,IAAO,CAAC,WACR,kBAAkB,SAAS,MAAyB;AAAA,EACtD;AAEA,MAAI,QAAQ,QAAQ;AAClB,WAAO;AAAA,EACT;AAEA,SAAO,CAAC,MAAM;AAChB;AAEA,MAAM,qBAAqB,CAAC,WAA4B;AACtD,SAAO,kBAAkB,MAAM;AACjC;AAEA,MAAM,sBAAsB,CAAC,YAAY,aAAa;AACtD,MAAM,iBAAiB,CAAC,SAAc;AACpC,QAAM,kBACJ,OAAO,KAAK,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,oBAAoB,SAAS,GAAG,CAAC,EACjE,SAAS;AAEd,QAAM,iBAAiB,KAAK,YAAY,OAAO,KAAK,KAAK,QAAQ,EAAE,SAAS;AAE5E,SAAO,mBAAmB;AAC5B;AAEA,SAAe,qBAAqB;AAAA;AAClC,kBAAAE,QAAO,YAAY,cAAAC,QAAO,aAAa,cAAAA,QAAO,QAAQ;AACtD,UAAM,UACJ;AACF,cAAM,kCAAoB,OAAO;AAAA,EACnC;AAAA;AASA,SAAe,uBACb,cACA,gBACA;AAAA;AACA,UAAM,EAAE,UAAU,QAAQ,QAAQ,UAAU,MAAM,IAAI;AACtD,UAAM,UAAM,4BAAgB;AAC5B,UAAM,SAAwC,EAAE,SAAS,aAAa;AACtE,QAAI;AAAQ,aAAO,SAAS;AAC5B,QAAI;AAAU,aAAO,kBAAkB,SAAS,SAAS;AAGzD,QAAI;AAAQ,aAAO,SAAS;AAE5B,UAAM,gBAAgB,MAAM,QAAQ;AAAA,MAClC,SAAS,IAAI,CAAO,YAAY;AAC9B,cAAM,gBAAgB,mBAAK;AAE3B,YAAI,QAAQ;AAAQ,wBAAc,SAAS,QAAQ;AACnD,YAAI,QAAQ;AACV,wBAAc,qBAAqB,OAAO,QAAQ,kBAAkB;AAEtE,cAAM,EAAE,KAAK,IAAI,MAAM,IAAI,IAAI,gBAAgB,QAAQ,EAAE,IAAI;AAAA,UAC3D,QAAQ;AAAA,UACR,SAAS,EAAE,eAAe,SAAS,KAAK,GAAG;AAAA,QAC7C,CAAC;AAED,YAAI,CAAC,eAAe,IAAI,GAAG;AACzB,iBAAO;AAAA,QACT;AAEA,cAAM,YAAY,mBAAmB,MAAM;AAE3C,cAAM,eAAW;AAAA,UACf,QAAQ,YAAY,QAAQ,gBAAgB,WAAW;AAAA,QACzD;AACA,cAAM,WAAW,YAAAH,QAAK,KAAK,cAAAG,QAAO,UAAU,QAAQ;AAEpD,YAAI,aAAa;AACjB,YAAI,cAAc,SAAS;AACzB,uBAAa,KAAK,UAAU,MAAM,MAAM,CAAC;AAAA,QAC3C;AAEA,cAAM,cAAc,qBAAqB,MAAM;AAC/C,YAAI,CAAC,YAAY,UAAU,GAAG;AAC5B,iBAAO;AAAA,QACT;AAEA,cAAM,UAAU,UAAU,UAAU;AACpC,eAAO,gBAAgB,QAAQ;AAAA,MACjC,EAAC;AAAA,IACH;AAEA,WAAO,cAAc,KAAK,EAAE;AAAA,EAC9B;AAAA;AAEA,SAAe,wBACb,gBACA;AAAA;AACA,UAAM,WAAW,MAAM,QAAQ,IAAI;AAAA,MACjC,uBAAuB,MAAM,cAAc;AAAA,MAC3C,GAAG,eAAe,SAAS;AAAA,QAAI,CAAC,EAAE,MAAM,MACtC,uBAAuB,OAAO,cAAc;AAAA,MAC9C;AAAA,IACF,CAAC;AAED,WAAO,SAAS,KAAK,EAAE;AAAA,EACzB;AAAA;AAEA,SAAe,oBAAoB,gBAAiC;AAAA;AAClE,UAAM,EAAE,UAAU,QAAQ,QAAQ,UAAU,OAAO,QAAQ,IAAI;AAE/D,UAAM,UAAM,4BAAgB;AAC5B,UAAM,SAAS,mBAAK,mCAAS;AAC7B,QAAI;AAAQ,aAAO,SAAS;AAC5B,QAAI;AAAU,aAAO,kBAAkB,SAAS,SAAS;AAGzD,QAAI;AAAQ,aAAO,SAAS;AAE5B,UAAM,gBAAgB,MAAM,QAAQ;AAAA,MAClC,SAAS,IAAI,CAAO,YAAY;AAC9B,cAAM,gBAAgB,mBAAK;AAE3B,YAAI,QAAQ;AAAQ,wBAAc,SAAS,QAAQ;AACnD,YAAI,QAAQ;AACV,wBAAc,qBAAqB,OAAO,QAAQ,kBAAkB;AAEtE,cAAM,EAAE,KAAK,IAAI,MAAM,IAAI,IAAI,gBAAgB,QAAQ,EAAE,IAAI;AAAA,UAC3D,QAAQ;AAAA,UACR,SAAS,EAAE,eAAe,SAAS,KAAK,GAAG;AAAA,QAC7C,CAAC;AAED,cAAM,YAAY,mBAAmB,MAAM;AAC3C,cAAM,eAAW,oCAAc,GAAG,QAAQ,QAAQ,SAAS,SAAS,EAAE;AACtE,cAAM,WAAW,YAAAH,QAAK,KAAK,cAAAG,QAAO,UAAU,QAAQ;AAEpD,YAAI,aAAa;AACjB,YAAI,cAAc,SAAS;AACzB,uBAAa,KAAK,UAAU,MAAM,MAAM,CAAC;AAAA,QAC3C;AAEA,cAAM,cAAc,qBAAqB,MAAM;AAC/C,YAAI,CAAC,YAAY,UAAU,GAAG;AAC5B,iBAAO;AAAA,QACT;AAEA,cAAM,UAAU,UAAU,UAAU;AACpC,eAAO,gBAAgB,QAAQ;AAAA,MACjC,EAAC;AAAA,IACH;AAEA,WAAO,cAAc,KAAK,EAAE;AAAA,EAC9B;AAAA;AAEA,SAAS,gBAAgB,MAAc;AACrC,SAAO,yBAAyB,cAAAC,QAAO,KAAK,IAAI,CAAC;AAAA;AACnD;AAEA,SAAS,mBAAmB;AAC1B,MAAI,CAAC,UAAAH,QAAG,WAAW,cAAAE,QAAO,QAAQ,GAAG;AACnC,cAAAF,QAAG,UAAU,cAAAE,QAAO,QAAQ;AAAA,EAC9B;AAEA,QAAM,oBAAoB,UAAAF,QAAG,YAAY,cAAAE,QAAO,UAAU;AAAA,IACxD,eAAe;AAAA,EACjB,CAAC;AAED,oBAAkB,QAAQ,CAAC,SAAS;AAClC,QAAI,KAAK,YAAY,KAAK,WAAW,KAAK,KAAK,IAAI,GAAG;AACpD,aAAO,UAAAF,QAAG,OAAO,YAAAD,QAAK,QAAQ,cAAAG,QAAO,UAAU,KAAK,IAAI,GAAG;AAAA,QACzD,WAAW;AAAA,QACX,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAEA,QACE,KAAK,OAAO,KACZ,kDAAkD,KAAK,KAAK,IAAI,GAChE;AACA,aAAO,UAAAF,QAAG,WAAW,YAAAD,QAAK,QAAQ,cAAAG,QAAO,UAAU,KAAK,IAAI,CAAC;AAAA,IAC/D;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAEA,SAAe,gBACb,QACA,OACA,SACA;AAAA;AACA,UAAM,UAAM,4BAAgB;AAC5B,UAAM;AAAA,MACJ;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA,kBAAkB;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,IACF,IAAI;AAEJ,UAAM,UAAU,UAAU,gBAAgB;AAE1C,UAAM,gBAAgB,QAAQ;AAAA,MAAK,CAAC,MAClC,aAAa,SAAS,CAAe;AAAA,IACvC;AACA,UAAM,eAAe,QAAQ,KAAK,CAAC,MAAM,YAAY,SAAS,CAAC,CAAC;AAChE,UAAM,2BAA2B,gBAAgB;AAEjD,UAAM,uBAAuB,CAAC;AAE9B,QAAI,MAAM;AACV,UAAM,cAAU,WAAAE,SAAI,GAAG;AACvB,YAAQ,MAAM;AAEd,UAAM,CAAC,UAAU,2BAA2B,IAAI,MAAM,QAAQ,IAAI;AAAA,UAChE,oCAAc,QAAQ,OAAO;AAAA,UAC7B,oDAAsB,CAAC,CAAC;AAAA,IAC1B,CAAC;AAED,UAAM,sBAAsB,OAAO;AAAA,MACjC;AAAA,IACF,EAAE;AAAA,MACA,CAAC,KAAK,CAAC,IAAI,IAAI,MAAM,IAAI,OAAO,CAAC,EAAE,IAAI,KAAK,CAAC,CAAC;AAAA,MAC9C,CAAC;AAAA,IACH;AAEA,QAAI;AACF,aAAO,iBAAiB;AACxB,aAAO;AAAA,oCAAmC,qBAAAC;AAAA,QACxC;AAAA,QACA;AAAA,MACF,CAAC;AAAA;AAED,YAAM,OAAO,UAAU,QAAQ,OAAO,CAAC;AAEvC,YAAM,cAAc;AAAA,QAClB,IAAI;AAAA,QACJ,MAAM;AAAA;AAAA,QAEN,QACE,OAAO,OAAO,kBAAkB,WAC5B,OAAO,cAAc,SACrB;AAAA,MACR;AAEA,UAAI,0BAA6C,CAAC;AAOlD,UAAI,2BAA2B;AAC7B,gBAAQ,eAAe;AAAA,UAErB,KAAK;AAAA,UACL,KAAK;AACH,oCAAwB,KAAK,GAAG,yBAAyB;AACzD;AAAA,UAEF;AACE,oCAAwB,KAAK,GAAG,yBAAyB;AACzD,oCAAwB,KAAK,WAAW;AACxC;AAAA,QACJ;AAAA,MACF,OAEK;AACH,gBAAQ,eAAe;AAAA,UAErB,KAAK;AACH,oCAAwB,KAAK,GAAG,mBAAmB;AACnD,oCAAwB,KAAK,WAAW;AACxC;AAAA,UAEF,KAAK;AACH,oCAAwB,KAAK,GAAG,mBAAmB;AACnD;AAAA,UAEF;AACE,oCAAwB,KAAK,WAAW;AACxC;AAAA,QACJ;AAAA,MACF;AAIA,YAAM,mBAAsC,CAAC;AAE7C,eAAe,sBAAsB,QAAyB;AAAA;AAG5D,gBAAM,oBAAoB,CAAC,EAAE,OAAO,OAAU,GAAG,GAAI,YAAY,CAAC,CAAE;AAEpE,gBAAM,SAAS,IAAI,gBAAgB;AACnC,cAAI,mCAAS;AACX,mBAAO,QAAQ,QAAQ,IAAI,EAAE,QAAQ,CAAC,CAAC,GAAG,CAAC,MAAM,OAAO,OAAO,GAAG,CAAC,CAAC;AACtE,cAAI;AAAQ,mBAAO,OAAO,UAAU,MAAM;AAC1C,cAAI;AAAU,mBAAO,OAAO,mBAAmB,SAAS,SAAS,CAAC;AAGlE,cAAI;AAAQ,mBAAO,OAAO,UAAU,MAAM;AAE1C,gBAAM,kBAAqC,CAAC;AAE5C,4BAAkB,QAAQ,CAAC,EAAE,OAAO,aAAa,MAAM;AACrD,4BAAgB;AAAA,cACd,GAAG,wBAAwB,IAAI,CAAO,oBAAoB;AACxD,sBAAM,wBAAwB,IAAI,gBAAgB,MAAM;AAExD,oBAAI;AACF,wCAAsB,OAAO,WAAW,YAAY;AAGtD,oBAAI,gBAAgB;AAClB,wCAAsB,OAAO,UAAU,gBAAgB,MAAM;AAE/D,sBAAM,MACJ,gBAAgB,OAAO,aACnB,kCACA,yBAAyB,gBAAgB,EAAE;AAEjD,sBAAM,EAAE,KAAK,IAAI,MAAM,IAAI,IAAI,KAAK;AAAA,kBAClC,QAAQ;AAAA,gBACV,CAAC;AAED,sBAAM,UAAU,mBAAmB,MAAM;AACzC,sBAAM,WAAW;AAIjB,sBAAM,aAAa,SAAK,oCAAc,gBAAgB,IAAI,CAAC;AAC3D,sBAAM,cAAc,KAAK,gBAAgB,MAAM;AAE/C,sBAAM,eAAW;AAAA,kBACf,GAAG,QAAQ,GAAG,UAAU,GAAG,WAAW,GAAG,OAAO;AAAA,gBAClD;AACA,sBAAM,WAAW,YAAAN,QAAK,KAAK,cAAAG,QAAO,UAAU,QAAQ;AAEpD,oBAAI,aAAa;AACjB,oBAAI,YAAY,SAAS;AACvB,+BAAa,KAAK,UAAU,MAAM,MAAM,CAAC;AAAA,gBAC3C;AAEA,sBAAM,cAAc,qBAAqB,MAAM;AAC/C,oBAAI,CAAC,YAAY,UAAU,GAAG;AAC5B,yBAAO;AAAA,gBACT;AAEA,sBAAM,UAAU,UAAU,UAAU;AAEpC,iCAAiB,KAAK;AAAA,kBACpB,MAAM;AAAA,kBACN,IAAI;AAAA,kBACJ,MAAM;AAAA,kBACN;AAAA,kBACA,SAAS,gBAAgB;AAAA,gBAC3B,CAAC;AAED,uBAAO,gBAAgB,QAAQ;AAAA,cACjC,EAAC;AAAA,YACH;AAAA,UACF,CAAC;AAED,gBAAM,WAAW,MAAM,QAAQ,IAAI,eAAe;AAClD,cAAI,sBAAsB;AACxB,mBAAO,SAAS,KAAK,EAAE;AAAA,UACzB;AAAA,QACF;AAAA;AAEA,UAAI,6BAA6B;AAC/B,mBAAW,UAAU,SAAS;AAC5B,gBAAM,sBAAsB,MAAM;AAAA,QACpC;AAAA,MACF;AAEA,eAAe,cAAc,QAAyB;AAAA;AACpD,cAAI,SAAS;AACb,cAAI,UAAU;AACZ,qBAAS,MAAM,wBAAwB;AAAA,cACrC;AAAA,cACA,UAAU;AAAA,cACV;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YACF,CAAC;AAAA,UACH,OAAO;AACL,qBAAS,MAAM,oBAAoB;AAAA,cACjC,UAAU;AAAA,cACV;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA,SAAS;AAAA,gBACP;AAAA,cACF;AAAA,YACF,CAAC;AAAA,UACH;AAEA,cAAI,sBAAsB;AACxB,mBAAO;AAAA,UACT;AAAA,QACF;AAAA;AAEA,UAAI,cAAc,QAAQ;AACxB,mBAAW,UAAU,SAAS;AAC5B,gBAAM,cAAc,MAAM;AAAA,QAC5B;AAAA,MACF;AAEA,YAAM,UAAoB,CAAC,GAAG,eAAe,GAAG,gBAAgB;AAEhE,UAAI,iBAAiB,CAAC;AACpB,mBAAO,0CAAiB,SAAS,cAAc,OAAO,CAAC;AAEzD,UAAI,0BAA0B;AAC5B,eAAO;AACP,eAAO,UAAM,8CAAmB,oBAAoB;AACpD,eAAO,UAAM,gDAAoB,MAAM;AAAA,MACzC;AAEA,aAAO;AAAA;AAAA,EAAO,cAAAC,QAAO,QAAQ,MAAM,CAAC;AAEpC,cAAQ,KAAK;AACb,aAAO,QAAQ,IAAI,GAAG;AAAA,IACxB,SAAS,GAAQ;AACf,cAAQ,MAAM,CAAC;AAEf,cAAQ,KAAK;AACb,UAAI,QAAQ,EAAE;AACd,UAAI,EAAE,YAAY,EAAE,SAAS,WAAW,KAAK;AAC3C,cAAM,mBAAmB;AACzB,aAAK;AACL;AAAA,MACF;AACA,UAAI,EAAE,YAAY,EAAE,SAAS,WAAW,KAAK;AAC3C,gBAAQ;AACR,cAAM,GAAG,cAAAA,QAAO,UAAU,KAAK,CAAC;AAAA,0BAA8B,cAAAA,QAAO;AAAA,UACnE;AAAA,QACF,CAAC;AACD,eAAO,QAAQ,IAAI,GAAG;AAAA,MACxB;AACA,UAAI,EAAE,YAAY,EAAE,SAAS,WAAW,KAAK;AAC3C,gBACE;AACF,cAAM,GAAG,cAAAA,QAAO;AAAA,UACd;AAAA,QACF,CAAC;AAAA,6CAAiD,cAAAA,QAAO;AAAA,UACvD;AAAA,QACF,CAAC,mFAAmF,cAAAA,QAAO;AAAA,UACzF;AAAA,QACF,CAAC;AACD,eAAO,QAAQ,IAAI,GAAG;AAAA,MACxB;AACA,UAAI,EAAE,YAAY,EAAE,SAAS,WAAW,KAAK;AAC3C,gBAAQ;AAAA,MACV;AACA,YAAM,oDAAoD,cAAAA,QAAO;AAAA,QAC/D;AAAA,MACF,CAAC;AAAA,0BAA8B,cAAAA,QAAO,KAAK,SAAS,CAAC;AACrD,aAAO,QAAQ,IAAI,GAAG;AAAA,IACxB;AAAA,EACF;AAAA;AAOO,MAAM,OAAO,CAAO,YAA0B;AACnD,QAAM,OAAO,UAAU,QAAQ,OAAO,CAAC;AACvC,QAAM,qBAAoB,mCAAS,sBAAqB;AACxD,QAAM,QAAQ,cAAAF,QAAO,SAAS,cAAAC,QAAO,aAAa,cAAAA,QAAO,QAAQ;AACjE,QAAM,oBAAoB,cAAAD,QAAO,uBAAuB;AACxD,MAAI;AACF,WAAO,MAAM,gBAAgB,mBAAmB,OAAO;AAAA,MACrD;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH,SAAS,GAAG;AACV,UAAM,UAAU,OAAO,iBAAiB,CAAC;AACzC,UAAM,WAAW;AAAA;AAAA,YAAiB,cAAAE,QAAO,KAAK,OAAO,CAAC;AACtD,QAAI,aAAa,yBAAY;AAC3B,aAAO,UAAM;AAAA,QACX,cAAAA,QAAO;AAAA,UACL;AAAA,QACF,IAAI;AAAA,MACN;AAAA,IACF;AAEA,WAAO,UAAM;AAAA,MACX,cAAAA,QAAO;AAAA,QACL;AAAA,MACF,IAAI;AAAA,IACN;AAAA,EACF;AACF;AAEA,IAAO,eAAQ;AAAA,EACb;AAAA,EACA,UAAU;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,MAAM,QAAQ;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AACF","debug_id":"e1fa8919-644e-53c0-9bd8-11223fd4f8f2"}
|