@dittowords/cli 3.10.1 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/README.md +125 -36
  2. package/bin/add-project.js +101 -33
  3. package/bin/add-project.js.map +1 -1
  4. package/bin/api.js +49 -15
  5. package/bin/api.js.map +1 -1
  6. package/bin/component-folders.js +56 -7
  7. package/bin/component-folders.js.map +1 -1
  8. package/bin/config.js +206 -170
  9. package/bin/config.js.map +1 -1
  10. package/bin/config.test.js +92 -0
  11. package/bin/config.test.js.map +1 -0
  12. package/bin/consts.js +64 -18
  13. package/bin/consts.js.map +1 -1
  14. package/bin/ditto.js +250 -200
  15. package/bin/ditto.js.map +1 -1
  16. package/bin/generate-suggestions.js +155 -78
  17. package/bin/generate-suggestions.js.map +1 -1
  18. package/bin/generate-suggestions.test.js +189 -0
  19. package/bin/generate-suggestions.test.js.map +1 -0
  20. package/bin/http/fetchComponentFolders.js +60 -8
  21. package/bin/http/fetchComponentFolders.js.map +1 -1
  22. package/bin/http/fetchComponents.js +65 -18
  23. package/bin/http/fetchComponents.js.map +1 -1
  24. package/bin/http/fetchVariants.js +74 -14
  25. package/bin/http/fetchVariants.js.map +1 -1
  26. package/bin/http/importComponents.js +100 -49
  27. package/bin/http/importComponents.js.map +1 -1
  28. package/bin/importComponents.js +61 -10
  29. package/bin/importComponents.js.map +1 -1
  30. package/bin/init/init.js +120 -44
  31. package/bin/init/init.js.map +1 -1
  32. package/bin/init/project.js +160 -83
  33. package/bin/init/project.js.map +1 -1
  34. package/bin/init/project.test.js +49 -0
  35. package/bin/init/project.test.js.map +1 -0
  36. package/bin/init/token.js +134 -74
  37. package/bin/init/token.js.map +1 -1
  38. package/bin/init/token.test.js +69 -0
  39. package/bin/init/token.test.js.map +1 -0
  40. package/bin/output.js +72 -30
  41. package/bin/output.js.map +1 -1
  42. package/bin/pull.js +424 -213
  43. package/bin/pull.js.map +1 -1
  44. package/bin/pull.test.js +410 -0
  45. package/bin/pull.test.js.map +1 -0
  46. package/bin/remove-project.js +91 -27
  47. package/bin/remove-project.js.map +1 -1
  48. package/bin/replace.js +140 -100
  49. package/bin/replace.js.map +1 -1
  50. package/bin/replace.test.js +155 -0
  51. package/bin/replace.test.js.map +1 -0
  52. package/bin/sentry-test.js.map +1 -0
  53. package/bin/types.js +20 -2
  54. package/bin/types.js.map +1 -1
  55. package/bin/utils/cleanFileName.js +32 -8
  56. package/bin/utils/cleanFileName.js.map +1 -1
  57. package/bin/utils/createSentryContext.js +43 -0
  58. package/bin/utils/createSentryContext.js.map +1 -0
  59. package/bin/utils/generateJsDriver.js +114 -51
  60. package/bin/utils/generateJsDriver.js.map +1 -1
  61. package/bin/utils/getSelectedProjects.js +58 -52
  62. package/bin/utils/getSelectedProjects.js.map +1 -1
  63. package/bin/utils/processMetaOption.js +36 -11
  64. package/bin/utils/processMetaOption.js.map +1 -1
  65. package/bin/utils/processMetaOption.test.js +45 -0
  66. package/bin/utils/processMetaOption.test.js.map +1 -0
  67. package/bin/utils/projectsToText.js +52 -19
  68. package/bin/utils/projectsToText.js.map +1 -1
  69. package/bin/utils/promptForProject.js +89 -36
  70. package/bin/utils/promptForProject.js.map +1 -1
  71. package/bin/utils/quit.js +36 -7
  72. package/bin/utils/quit.js.map +1 -1
  73. package/bin/utils/sourcesToText.js +51 -19
  74. package/bin/utils/sourcesToText.js.map +1 -1
  75. package/etsc.config.js +13 -0
  76. package/lib/config.ts +27 -8
  77. package/lib/ditto.ts +6 -0
  78. package/lib/init/project.ts +3 -3
  79. package/lib/pull.ts +190 -52
  80. package/lib/types.ts +24 -7
  81. package/lib/utils/createSentryContext.ts +20 -0
  82. package/lib/utils/generateJsDriver.ts +40 -6
  83. package/lib/utils/quit.ts +2 -3
  84. package/package.json +10 -6
  85. package/tsconfig.json +4 -1
  86. package/bin/lib/add-project.js +0 -36
  87. package/bin/lib/add-project.js.map +0 -1
  88. package/bin/lib/api.js +0 -20
  89. package/bin/lib/api.js.map +0 -1
  90. package/bin/lib/config.js +0 -202
  91. package/bin/lib/config.js.map +0 -1
  92. package/bin/lib/consts.js +0 -21
  93. package/bin/lib/consts.js.map +0 -1
  94. package/bin/lib/ditto.js +0 -121
  95. package/bin/lib/ditto.js.map +0 -1
  96. package/bin/lib/generate-suggestions.js +0 -71
  97. package/bin/lib/generate-suggestions.js.map +0 -1
  98. package/bin/lib/http/fetchComponents.js +0 -13
  99. package/bin/lib/http/fetchComponents.js.map +0 -1
  100. package/bin/lib/http/fetchVariants.js +0 -26
  101. package/bin/lib/http/fetchVariants.js.map +0 -1
  102. package/bin/lib/init/init.js +0 -50
  103. package/bin/lib/init/init.js.map +0 -1
  104. package/bin/lib/init/project.js +0 -108
  105. package/bin/lib/init/project.js.map +0 -1
  106. package/bin/lib/init/token.js +0 -91
  107. package/bin/lib/init/token.js.map +0 -1
  108. package/bin/lib/output.js +0 -34
  109. package/bin/lib/output.js.map +0 -1
  110. package/bin/lib/pull.js +0 -264
  111. package/bin/lib/pull.js.map +0 -1
  112. package/bin/lib/remove-project.js +0 -35
  113. package/bin/lib/remove-project.js.map +0 -1
  114. package/bin/lib/replace.js +0 -107
  115. package/bin/lib/replace.js.map +0 -1
  116. package/bin/lib/types.js +0 -3
  117. package/bin/lib/types.js.map +0 -1
  118. package/bin/lib/utils/cleanFileName.js +0 -11
  119. package/bin/lib/utils/cleanFileName.js.map +0 -1
  120. package/bin/lib/utils/generateJsDriver.js +0 -56
  121. package/bin/lib/utils/generateJsDriver.js.map +0 -1
  122. package/bin/lib/utils/getSelectedProjects.js +0 -61
  123. package/bin/lib/utils/getSelectedProjects.js.map +0 -1
  124. package/bin/lib/utils/processMetaOption.js +0 -15
  125. package/bin/lib/utils/processMetaOption.js.map +0 -1
  126. package/bin/lib/utils/projectsToText.js +0 -25
  127. package/bin/lib/utils/projectsToText.js.map +0 -1
  128. package/bin/lib/utils/promptForProject.js +0 -43
  129. package/bin/lib/utils/promptForProject.js.map +0 -1
  130. package/bin/lib/utils/quit.js +0 -10
  131. package/bin/lib/utils/quit.js.map +0 -1
  132. package/bin/lib/utils/sourcesToText.js +0 -25
  133. package/bin/lib/utils/sourcesToText.js.map +0 -1
  134. package/bin/package.json +0 -76
package/bin/pull.js CHANGED
@@ -1,292 +1,503 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
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]="8e8abce7-7d1b-5b40-96a6-09318358142e")}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;
4
35
  };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.pull = void 0;
7
- const fs_1 = __importDefault(require("fs"));
8
- const path_1 = __importDefault(require("path"));
9
- const ora_1 = __importDefault(require("ora"));
10
- const api_1 = require("./api");
11
- const config_1 = __importDefault(require("./config"));
12
- const consts_1 = __importDefault(require("./consts"));
13
- const output_1 = __importDefault(require("./output"));
14
- const token_1 = require("./init/token");
15
- const sourcesToText_1 = __importDefault(require("./utils/sourcesToText"));
16
- const generateJsDriver_1 = require("./utils/generateJsDriver");
17
- const cleanFileName_1 = require("./utils/cleanFileName");
18
- const fetchVariants_1 = require("./http/fetchVariants");
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
+ default: () => pull_default,
68
+ getFormatDataIsValid: () => getFormatDataIsValid,
69
+ pull: () => pull
70
+ });
71
+ module.exports = __toCommonJS(pull_exports);
72
+ var import_fs = __toESM(require("fs"));
73
+ var import_path = __toESM(require("path"));
74
+ var import_ora = __toESM(require("ora"));
75
+ var Sentry = __toESM(require("@sentry/node"));
76
+ var import_api = require("./api");
77
+ var import_config = __toESM(require("./config"));
78
+ var import_consts = __toESM(require("./consts"));
79
+ var import_output = __toESM(require("./output"));
80
+ var import_token = require("./init/token");
81
+ var import_sourcesToText = __toESM(require("./utils/sourcesToText"));
82
+ var import_generateJsDriver = require("./utils/generateJsDriver");
83
+ var import_cleanFileName = require("./utils/cleanFileName");
84
+ var import_fetchVariants = require("./http/fetchVariants");
85
+ var import_quit = require("./utils/quit");
86
+ var import_axios = require("axios");
87
+ var import_fetchComponentFolders = require("./http/fetchComponentFolders");
88
+ const ensureEndsWithNewLine = (str) => str + (/[\r\n]$/.test(str) ? "" : "\n");
89
+ const writeFile = (path2, data) => new Promise((r) => import_fs.default.writeFile(path2, ensureEndsWithNewLine(data), r));
19
90
  const SUPPORTED_FORMATS = [
20
- "flat",
21
- "structured",
22
- "android",
23
- "ios-strings",
24
- "ios-stringsdict",
25
- "icu",
91
+ "flat",
92
+ "structured",
93
+ "android",
94
+ "ios-strings",
95
+ "ios-stringsdict",
96
+ "icu"
26
97
  ];
27
98
  const JSON_FORMATS = ["flat", "structured", "icu"];
28
99
  const FORMAT_EXTENSIONS = {
29
- flat: ".json",
30
- structured: ".json",
31
- android: ".xml",
32
- "ios-strings": ".strings",
33
- "ios-stringsdict": ".stringsdict",
34
- icu: ".json",
100
+ flat: ".json",
101
+ structured: ".json",
102
+ android: ".xml",
103
+ "ios-strings": ".strings",
104
+ "ios-stringsdict": ".stringsdict",
105
+ icu: ".json"
35
106
  };
36
107
  const getJsonFormatIsValid = (data) => {
37
- try {
38
- return (Object.keys(JSON.parse(data)).filter((k) => !k.startsWith("__variant"))
39
- .length > 0);
40
- }
41
- catch {
42
- return false;
43
- }
108
+ try {
109
+ return Object.keys(JSON.parse(data)).some(
110
+ (k) => !k.startsWith("__variant")
111
+ );
112
+ } catch (e) {
113
+ return false;
114
+ }
44
115
  };
45
116
  const getFormatDataIsValid = {
46
- flat: getJsonFormatIsValid,
47
- structured: getJsonFormatIsValid,
48
- icu: getJsonFormatIsValid,
49
- android: (data) => data.includes("<string"),
50
- "ios-strings": (data) => data.includes(`" = "`),
51
- "ios-stringsdict": (data) => data.includes("<key>"),
117
+ flat: getJsonFormatIsValid,
118
+ structured: getJsonFormatIsValid,
119
+ icu: getJsonFormatIsValid,
120
+ android: (data) => data.includes("<string"),
121
+ "ios-strings": (data) => data.includes(`" = "`),
122
+ "ios-stringsdict": (data) => data.includes("<key>")
52
123
  };
53
124
  const getFormat = (formatFromSource) => {
54
- const formats = (Array.isArray(formatFromSource) ? formatFromSource : [formatFromSource]).filter((format) => SUPPORTED_FORMATS.includes(format));
55
- if (formats.length) {
56
- return formats;
57
- }
58
- return ["flat"];
125
+ const formats = (Array.isArray(formatFromSource) ? formatFromSource : [formatFromSource]).filter(
126
+ (format) => SUPPORTED_FORMATS.includes(format)
127
+ );
128
+ if (formats.length) {
129
+ return formats;
130
+ }
131
+ return ["flat"];
59
132
  };
60
133
  const getFormatExtension = (format) => {
61
- return FORMAT_EXTENSIONS[format];
134
+ return FORMAT_EXTENSIONS[format];
62
135
  };
63
136
  const DEFAULT_FORMAT_KEYS = ["projects", "exported_at"];
64
137
  const hasVariantData = (data) => {
65
- const hasTopLevelKeys = Object.keys(data).filter((key) => !DEFAULT_FORMAT_KEYS.includes(key))
66
- .length > 0;
67
- const hasProjectKeys = data.projects && Object.keys(data.projects).length > 0;
68
- return hasTopLevelKeys || hasProjectKeys;
138
+ const hasTopLevelKeys = Object.keys(data).filter((key) => !DEFAULT_FORMAT_KEYS.includes(key)).length > 0;
139
+ const hasProjectKeys = data.projects && Object.keys(data.projects).length > 0;
140
+ return hasTopLevelKeys || hasProjectKeys;
69
141
  };
70
- async function askForAnotherToken() {
71
- config_1.default.deleteToken(consts_1.default.CONFIG_FILE, consts_1.default.API_HOST);
142
+ function askForAnotherToken() {
143
+ return __async(this, null, function* () {
144
+ import_config.default.deleteToken(import_consts.default.CONFIG_FILE, import_consts.default.API_HOST);
72
145
  const message = "Looks like the API key you have saved no longer works. Please enter another one.";
73
- await (0, token_1.collectAndSaveToken)(message);
146
+ yield (0, import_token.collectAndSaveToken)(message);
147
+ });
74
148
  }
75
- /**
76
- * For a given variant:
77
- * - if format is unspecified, fetch data for all projects from `/projects` and
78
- * save in `{variantApiId}.json`
79
- * - if format is `flat` or `structured`, fetch data for each project from `/project/:project_id` and
80
- * save in `{projectName}-${variantApiId}.json`
81
- */
82
- async function downloadAndSaveVariant(variantApiId, projects, format, status, richText, token) {
83
- const api = (0, api_1.createApiClient)();
149
+ function downloadAndSaveVariant(variantApiId, projects, format, status, richText, token) {
150
+ return __async(this, null, function* () {
151
+ const api = (0, import_api.createApiClient)();
84
152
  const params = { variant: variantApiId };
85
153
  if (format)
86
- params.format = format;
87
- if (status)
88
- params.status = status;
154
+ params.format = format;
89
155
  if (richText)
90
- params.includeRichText = richText.toString();
91
- const savedMessages = await Promise.all(projects.map(async ({ id, fileName }) => {
92
- const { data } = await api.get(`/projects/${id}`, {
93
- params,
94
- headers: { Authorization: `token ${token}` },
156
+ params.includeRichText = richText.toString();
157
+ if (status)
158
+ params.status = status;
159
+ const savedMessages = yield Promise.all(
160
+ projects.map((project) => __async(this, null, function* () {
161
+ const projectParams = __spreadValues({}, params);
162
+ if (project.status)
163
+ projectParams.status = project.status;
164
+ if (project.exclude_components)
165
+ projectParams.exclude_components = String(project.exclude_components);
166
+ const { data } = yield api.get(`/projects/${project.id}`, {
167
+ params: projectParams,
168
+ headers: { Authorization: `token ${token}` }
95
169
  });
96
170
  if (!hasVariantData(data)) {
97
- return "";
171
+ return "";
98
172
  }
99
173
  const extension = getFormatExtension(format);
100
- const filename = (0, cleanFileName_1.cleanFileName)(fileName + ("__" + (variantApiId || "base")) + extension);
101
- const filepath = path_1.default.join(consts_1.default.TEXT_DIR, filename);
174
+ const filename = (0, import_cleanFileName.cleanFileName)(
175
+ project.fileName + ("__" + (variantApiId || "base")) + extension
176
+ );
177
+ const filepath = import_path.default.join(import_consts.default.TEXT_DIR, filename);
102
178
  let dataString = data;
103
179
  if (extension === ".json") {
104
- dataString = JSON.stringify(data, null, 2);
180
+ dataString = JSON.stringify(data, null, 2);
105
181
  }
106
182
  const dataIsValid = getFormatDataIsValid[format];
107
183
  if (!dataIsValid(dataString)) {
108
- return "";
184
+ return "";
109
185
  }
110
- fs_1.default.writeFileSync(filepath, dataString);
186
+ yield writeFile(filepath, dataString);
111
187
  return getSavedMessage(filename);
112
- }));
188
+ }))
189
+ );
113
190
  return savedMessages.join("");
191
+ });
114
192
  }
115
- async function downloadAndSaveVariants(variants, projects, format, status, richText, token) {
116
- const messages = await Promise.all([
117
- downloadAndSaveVariant(null, projects, format, status, richText, token),
118
- ...variants.map(({ apiID }) => downloadAndSaveVariant(apiID, projects, format, status, richText, token)),
193
+ function downloadAndSaveVariants(variants, projects, format, status, richText, token) {
194
+ return __async(this, null, function* () {
195
+ const messages = yield Promise.all([
196
+ downloadAndSaveVariant(null, projects, format, status, richText, token),
197
+ ...variants.map(
198
+ ({ apiID }) => downloadAndSaveVariant(apiID, projects, format, status, richText, token)
199
+ )
119
200
  ]);
120
201
  return messages.join("");
202
+ });
121
203
  }
122
- async function downloadAndSaveBase(projects, format, status, richText, token, options) {
123
- const api = (0, api_1.createApiClient)();
124
- const params = { ...options?.meta };
204
+ function downloadAndSaveBase(projects, format, status, richText, token, options) {
205
+ return __async(this, null, function* () {
206
+ const api = (0, import_api.createApiClient)();
207
+ const params = __spreadValues({}, options == null ? void 0 : options.meta);
125
208
  if (format)
126
- params.format = format;
127
- if (status)
128
- params.status = status;
209
+ params.format = format;
129
210
  if (richText)
130
- params.includeRichText = richText.toString();
131
- const savedMessages = await Promise.all(projects.map(async ({ id, fileName }) => {
132
- const { data } = await api.get(`/projects/${id}`, {
133
- params,
134
- headers: { Authorization: `token ${token}` },
211
+ params.includeRichText = richText.toString();
212
+ if (status)
213
+ params.status = status;
214
+ const savedMessages = yield Promise.all(
215
+ projects.map((project) => __async(this, null, function* () {
216
+ const projectParams = __spreadValues({}, params);
217
+ if (project.status)
218
+ projectParams.status = project.status;
219
+ if (project.exclude_components)
220
+ projectParams.exclude_components = String(project.exclude_components);
221
+ const { data } = yield api.get(`/projects/${project.id}`, {
222
+ params: projectParams,
223
+ headers: { Authorization: `token ${token}` }
135
224
  });
136
225
  const extension = getFormatExtension(format);
137
- const filename = (0, cleanFileName_1.cleanFileName)(`${fileName}__base${extension}`);
138
- const filepath = path_1.default.join(consts_1.default.TEXT_DIR, filename);
226
+ const filename = (0, import_cleanFileName.cleanFileName)(`${project.fileName}__base${extension}`);
227
+ const filepath = import_path.default.join(import_consts.default.TEXT_DIR, filename);
139
228
  let dataString = data;
140
229
  if (extension === ".json") {
141
- dataString = JSON.stringify(data, null, 2);
230
+ dataString = JSON.stringify(data, null, 2);
142
231
  }
143
232
  const dataIsValid = getFormatDataIsValid[format];
144
233
  if (!dataIsValid(dataString)) {
145
- return "";
234
+ return "";
146
235
  }
147
- fs_1.default.writeFileSync(filepath, dataString);
236
+ yield writeFile(filepath, dataString);
148
237
  return getSavedMessage(filename);
149
- }));
238
+ }))
239
+ );
150
240
  return savedMessages.join("");
241
+ });
151
242
  }
152
243
  function getSavedMessage(file) {
153
- return `Successfully saved to ${output_1.default.info(file)}\n`;
244
+ return `Successfully saved to ${import_output.default.info(file)}
245
+ `;
154
246
  }
155
247
  function cleanOutputFiles() {
156
- if (!fs_1.default.existsSync(consts_1.default.TEXT_DIR)) {
157
- fs_1.default.mkdirSync(consts_1.default.TEXT_DIR);
248
+ if (!import_fs.default.existsSync(import_consts.default.TEXT_DIR)) {
249
+ import_fs.default.mkdirSync(import_consts.default.TEXT_DIR);
250
+ }
251
+ const fileNames = import_fs.default.readdirSync(import_consts.default.TEXT_DIR);
252
+ fileNames.forEach((fileName) => {
253
+ if (/\.js(on)?|\.xml|\.strings(dict)?$/.test(fileName)) {
254
+ import_fs.default.unlinkSync(import_path.default.resolve(import_consts.default.TEXT_DIR, fileName));
158
255
  }
159
- const fileNames = fs_1.default.readdirSync(consts_1.default.TEXT_DIR);
160
- fileNames.forEach((fileName) => {
161
- if (/\.js(on)?|\.xml|\.strings(dict)?$/.test(fileName)) {
162
- fs_1.default.unlinkSync(path_1.default.resolve(consts_1.default.TEXT_DIR, fileName));
163
- }
164
- });
165
- return "Cleaning old output files..\n";
256
+ });
257
+ return "Cleaning old output files..\n";
166
258
  }
167
- async function downloadAndSave(source, token, options) {
168
- const api = (0, api_1.createApiClient)();
169
- const { validProjects, format: formatFromSource, shouldFetchComponentLibrary, status, richText, componentFolders, } = source;
259
+ function downloadAndSave(source, token, options) {
260
+ return __async(this, null, function* () {
261
+ const api = (0, import_api.createApiClient)();
262
+ const {
263
+ validProjects,
264
+ format: formatFromSource,
265
+ shouldFetchComponentLibrary,
266
+ status,
267
+ richText,
268
+ componentFolders: specifiedComponentFolders,
269
+ componentRoot
270
+ } = source;
170
271
  const formats = getFormat(formatFromSource);
171
272
  let msg = "";
172
- const spinner = (0, ora_1.default)(msg);
273
+ const spinner = (0, import_ora.default)(msg);
173
274
  spinner.start();
174
- const variants = await (0, fetchVariants_1.fetchVariants)(source);
275
+ const [variants, allComponentFoldersResponse] = yield Promise.all([
276
+ (0, import_fetchVariants.fetchVariants)(source),
277
+ (0, import_fetchComponentFolders.fetchComponentFolders)()
278
+ ]);
279
+ const allComponentFolders = Object.entries(
280
+ allComponentFoldersResponse
281
+ ).reduce(
282
+ (acc, [id, name]) => acc.concat([{ id, name }]),
283
+ []
284
+ );
175
285
  try {
176
- msg += cleanOutputFiles();
177
- msg += `\nFetching the latest text from ${(0, sourcesToText_1.default)(validProjects, shouldFetchComponentLibrary)}\n`;
178
- const meta = options ? options.meta : {};
179
- async function fetchComponentLibrary(format) {
180
- // Always include a variant with an apiID of undefined to ensure that we
181
- // fetch the base text for the component library.
182
- const componentVariants = [{ apiID: undefined }, ...(variants || [])];
183
- const params = new URLSearchParams();
184
- if (options?.meta)
185
- Object.entries(options.meta).forEach(([k, v]) => params.append(k, v));
186
- if (format)
187
- params.append("format", format);
188
- if (status)
189
- params.append("status", status);
190
- if (richText)
191
- params.append("includeRichText", richText.toString());
192
- if (componentFolders) {
193
- componentFolders.forEach(({ id }) => params.append("folder_id[]", id));
194
- }
195
- const messages = await Promise.all(componentVariants.map(async ({ apiID: variantApiId }) => {
196
- const p = new URLSearchParams(params);
286
+ msg += cleanOutputFiles();
287
+ msg += `
288
+ Fetching the latest text from ${(0, import_sourcesToText.default)(
289
+ validProjects,
290
+ shouldFetchComponentLibrary
291
+ )}
292
+ `;
293
+ const meta = options ? options.meta : {};
294
+ const rootRequest = {
295
+ id: "__root__",
296
+ name: "Root",
297
+ // componentRoot can be a boolean or an object
298
+ status: typeof source.componentRoot === "object" ? source.componentRoot.status : void 0
299
+ };
300
+ let componentFolderRequests = [];
301
+ if (specifiedComponentFolders) {
302
+ switch (componentRoot) {
303
+ case void 0:
304
+ case false:
305
+ componentFolderRequests.push(...specifiedComponentFolders);
306
+ break;
307
+ default:
308
+ componentFolderRequests.push(...specifiedComponentFolders);
309
+ componentFolderRequests.push(rootRequest);
310
+ break;
311
+ }
312
+ } else {
313
+ switch (componentRoot) {
314
+ case void 0:
315
+ componentFolderRequests.push(...allComponentFolders);
316
+ componentFolderRequests.push(rootRequest);
317
+ break;
318
+ case false:
319
+ componentFolderRequests.push(...allComponentFolders);
320
+ break;
321
+ default:
322
+ componentFolderRequests.push(rootRequest);
323
+ break;
324
+ }
325
+ }
326
+ const componentSources = [];
327
+ function fetchComponentLibrary(format) {
328
+ return __async(this, null, function* () {
329
+ const componentVariants = [{ apiID: void 0 }, ...variants || []];
330
+ const params = new URLSearchParams();
331
+ if (options == null ? void 0 : options.meta)
332
+ Object.entries(options.meta).forEach(([k, v]) => params.append(k, v));
333
+ if (format)
334
+ params.append("format", format);
335
+ if (richText)
336
+ params.append("includeRichText", richText.toString());
337
+ if (status)
338
+ params.append("status", status);
339
+ const messagePromises = [];
340
+ componentVariants.forEach(({ apiID: variantApiId }) => {
341
+ messagePromises.push(
342
+ ...componentFolderRequests.map((componentFolder) => __async(this, null, function* () {
343
+ const componentFolderParams = new URLSearchParams(params);
197
344
  if (variantApiId)
198
- p.append("variant", variantApiId);
199
- const { data } = await api.get(`/components`, { params: p });
345
+ componentFolderParams.append("variant", variantApiId);
346
+ if (componentFolder.status)
347
+ componentFolderParams.append("status", componentFolder.status);
348
+ const url = componentFolder.id === "__root__" ? "/components?root_only=true" : `/component-folders/${componentFolder.id}/components`;
349
+ const { data } = yield api.get(url, {
350
+ params: componentFolderParams
351
+ });
200
352
  const nameExt = getFormatExtension(format);
201
- const nameBase = "ditto-component-library";
353
+ const nameBase = "components";
354
+ const nameFolder = `__${componentFolder.name}`;
202
355
  const namePostfix = `__${variantApiId || "base"}`;
203
- const fileName = (0, cleanFileName_1.cleanFileName)(`${nameBase}${namePostfix}${nameExt}`);
204
- const filePath = path_1.default.join(consts_1.default.TEXT_DIR, fileName);
356
+ const fileName = (0, import_cleanFileName.cleanFileName)(
357
+ `${nameBase}${nameFolder}${namePostfix}${nameExt}`
358
+ );
359
+ const filePath = import_path.default.join(import_consts.default.TEXT_DIR, fileName);
205
360
  let dataString = data;
206
361
  if (nameExt === ".json") {
207
- dataString = JSON.stringify(data, null, 2);
362
+ dataString = JSON.stringify(data, null, 2);
208
363
  }
209
364
  const dataIsValid = getFormatDataIsValid[format];
210
365
  if (!dataIsValid(dataString)) {
211
- return "";
366
+ return "";
212
367
  }
213
- await new Promise((r) => fs_1.default.writeFile(filePath, dataString, r));
214
- return getSavedMessage(fileName);
215
- }));
216
- msg += messages.join("");
217
- }
218
- if (shouldFetchComponentLibrary) {
219
- for (const format of formats) {
220
- await fetchComponentLibrary(format);
221
- }
222
- }
223
- async function fetchProjects(format) {
224
- msg += variants
225
- ? await downloadAndSaveVariants(variants, validProjects, format, status, richText, token)
226
- : await downloadAndSaveBase(validProjects, format, status, richText, token, {
227
- meta,
368
+ yield writeFile(filePath, dataString);
369
+ componentSources.push({
370
+ type: "components",
371
+ id: "ditto_component_library",
372
+ name: "ditto_component_library",
373
+ fileName,
374
+ variant: variantApiId || "base"
228
375
  });
376
+ return getSavedMessage(fileName);
377
+ }))
378
+ );
379
+ });
380
+ const messages = yield Promise.all(messagePromises);
381
+ msg += messages.join("");
382
+ });
383
+ }
384
+ if (shouldFetchComponentLibrary) {
385
+ for (const format of formats) {
386
+ yield fetchComponentLibrary(format);
229
387
  }
230
- if (validProjects.length) {
231
- for (const format of formats) {
232
- await fetchProjects(format);
388
+ }
389
+ function fetchProjects(format) {
390
+ return __async(this, null, function* () {
391
+ msg += variants ? yield downloadAndSaveVariants(
392
+ variants,
393
+ validProjects,
394
+ format,
395
+ status,
396
+ richText,
397
+ token
398
+ ) : yield downloadAndSaveBase(
399
+ validProjects,
400
+ format,
401
+ status,
402
+ richText,
403
+ token,
404
+ {
405
+ meta
233
406
  }
407
+ );
408
+ });
409
+ }
410
+ if (validProjects.length) {
411
+ for (const format of formats) {
412
+ yield fetchProjects(format);
234
413
  }
235
- const sources = [...validProjects];
236
- if (shouldFetchComponentLibrary) {
237
- sources.push({
238
- id: "ditto_component_library",
239
- name: "Ditto Component Library",
240
- fileName: "ditto-component-library",
241
- });
242
- }
243
- if (formats.some((f) => JSON_FORMATS.includes(f)))
244
- msg += (0, generateJsDriver_1.generateJsDriver)(sources);
245
- msg += `\n${output_1.default.success("Done")}!`;
246
- spinner.stop();
414
+ }
415
+ const sources = [...validProjects, ...componentSources];
416
+ if (formats.some((f) => JSON_FORMATS.includes(f)))
417
+ msg += (0, import_generateJsDriver.generateJsDriver)(sources);
418
+ msg += `
419
+ ${import_output.default.success("Done")}!`;
420
+ spinner.stop();
421
+ return console.log(msg);
422
+ } catch (e) {
423
+ console.error(e);
424
+ spinner.stop();
425
+ let error = e.message;
426
+ if (e.response && e.response.status === 404) {
427
+ yield askForAnotherToken();
428
+ pull();
429
+ return;
430
+ }
431
+ if (e.response && e.response.status === 401) {
432
+ error = "You don't have access to the selected projects";
433
+ msg = `${import_output.default.errorText(error)}.
434
+ Choose others using the ${import_output.default.info(
435
+ "project"
436
+ )} command, or update your API key.`;
247
437
  return console.log(msg);
248
- }
249
- catch (e) {
250
- console.error(e);
251
- spinner.stop();
252
- let error = e.message;
253
- if (e.response && e.response.status === 404) {
254
- await askForAnotherToken();
255
- (0, exports.pull)();
256
- return;
257
- }
258
- if (e.response && e.response.status === 401) {
259
- error = "You don't have access to the selected projects";
260
- msg = `${output_1.default.errorText(error)}.\nChoose others using the ${output_1.default.info("project")} command, or update your API key.`;
261
- return console.log(msg);
262
- }
263
- if (e.response && e.response.status === 403) {
264
- error =
265
- "One or more of the requested projects don't have Developer Mode enabled";
266
- msg = `${output_1.default.errorText(error)}.\nPlease choose different projects using the ${output_1.default.info("project")} command, or turn on Developer Mode for all selected projects. Learn more here: ${output_1.default.subtle("https://www.dittowords.com/docs/ditto-developer-mode")}.`;
267
- return console.log(msg);
268
- }
269
- if (e.response && e.response.status === 400) {
270
- error = "projects not found";
271
- }
272
- msg = `We hit an error fetching text from the projects: ${output_1.default.errorText(error)}.\nChoose others using the ${output_1.default.info("project")} command.`;
438
+ }
439
+ if (e.response && e.response.status === 403) {
440
+ error = "One or more of the requested projects don't have Developer Mode enabled";
441
+ msg = `${import_output.default.errorText(
442
+ error
443
+ )}.
444
+ Please choose different projects using the ${import_output.default.info(
445
+ "project"
446
+ )} command, or turn on Developer Mode for all selected projects. Learn more here: ${import_output.default.subtle(
447
+ "https://www.dittowords.com/docs/ditto-developer-mode"
448
+ )}.`;
273
449
  return console.log(msg);
450
+ }
451
+ if (e.response && e.response.status === 400) {
452
+ error = "projects not found";
453
+ }
454
+ msg = `We hit an error fetching text from the projects: ${import_output.default.errorText(
455
+ error
456
+ )}.
457
+ Choose others using the ${import_output.default.info("project")} command.`;
458
+ return console.log(msg);
274
459
  }
460
+ });
275
461
  }
276
- const pull = (options) => {
277
- const meta = options ? options.meta : {};
278
- const token = config_1.default.getToken(consts_1.default.CONFIG_FILE, consts_1.default.API_HOST);
279
- const sourceInformation = config_1.default.parseSourceInformation();
280
- return downloadAndSave(sourceInformation, token, { meta });
281
- };
282
- exports.pull = pull;
283
- exports.default = {
284
- pull: exports.pull,
285
- _testing: {
286
- cleanOutputFiles,
287
- downloadAndSaveVariant,
288
- downloadAndSaveVariants,
289
- downloadAndSaveBase,
290
- },
462
+ const pull = (options) => __async(void 0, null, function* () {
463
+ const meta = options ? options.meta : {};
464
+ const token = import_config.default.getToken(import_consts.default.CONFIG_FILE, import_consts.default.API_HOST);
465
+ const sourceInformation = import_config.default.parseSourceInformation();
466
+ try {
467
+ return yield downloadAndSave(sourceInformation, token, { meta });
468
+ } catch (e) {
469
+ const eventId = Sentry.captureException(e);
470
+ const eventStr = `
471
+
472
+ Error ID: ${import_output.default.info(eventId)}`;
473
+ if (e instanceof import_axios.AxiosError) {
474
+ return (0, import_quit.quit)(
475
+ import_output.default.errorText(
476
+ "Something went wrong connecting to Ditto servers. Please contact support or try again later."
477
+ ) + eventStr
478
+ );
479
+ }
480
+ return (0, import_quit.quit)(
481
+ import_output.default.errorText(
482
+ "Something went wrong. Please contact support or try again later."
483
+ ) + eventStr
484
+ );
485
+ }
486
+ });
487
+ var pull_default = {
488
+ pull,
489
+ _testing: {
490
+ cleanOutputFiles,
491
+ downloadAndSaveVariant,
492
+ downloadAndSaveVariants,
493
+ downloadAndSaveBase
494
+ }
291
495
  };
292
- //# sourceMappingURL=pull.js.map
496
+ // Annotate the CommonJS export names for ESM import in node:
497
+ 0 && (module.exports = {
498
+ getFormatDataIsValid,
499
+ pull
500
+ });
501
+ //# sourceMappingURL=pull.js.map
502
+
503
+ //# debugId=8e8abce7-7d1b-5b40-96a6-09318358142e