@dittowords/cli 4.0.0-alpha.0 → 4.0.1-alpha.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/bin/pull.js CHANGED
@@ -1,5 +1,5 @@
1
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]="c9f589e3-b75d-5846-b29d-266ca10a8560")}catch(e){}}();
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]="c9033e67-0b68-5118-944f-a91f2383e9dd")}catch(e){}}();
3
3
 
4
4
  var __create = Object.create;
5
5
  var __defProp = Object.defineProperty;
@@ -84,6 +84,9 @@ var import_cleanFileName = require("./utils/cleanFileName");
84
84
  var import_fetchVariants = require("./http/fetchVariants");
85
85
  var import_quit = require("./utils/quit");
86
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));
87
90
  const SUPPORTED_FORMATS = [
88
91
  "flat",
89
92
  "structured",
@@ -149,14 +152,19 @@ function downloadAndSaveVariant(variantApiId, projects, format, status, richText
149
152
  const params = { variant: variantApiId };
150
153
  if (format)
151
154
  params.format = format;
152
- if (status)
153
- params.status = status;
154
155
  if (richText)
155
156
  params.includeRichText = richText.toString();
157
+ if (status)
158
+ params.status = status;
156
159
  const savedMessages = yield Promise.all(
157
- projects.map((_0) => __async(this, [_0], function* ({ id, fileName }) {
158
- const { data } = yield api.get(`/projects/${id}`, {
159
- params,
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,
160
168
  headers: { Authorization: `token ${token}` }
161
169
  });
162
170
  if (!hasVariantData(data)) {
@@ -164,7 +172,7 @@ function downloadAndSaveVariant(variantApiId, projects, format, status, richText
164
172
  }
165
173
  const extension = getFormatExtension(format);
166
174
  const filename = (0, import_cleanFileName.cleanFileName)(
167
- fileName + ("__" + (variantApiId || "base")) + extension
175
+ project.fileName + ("__" + (variantApiId || "base")) + extension
168
176
  );
169
177
  const filepath = import_path.default.join(import_consts.default.TEXT_DIR, filename);
170
178
  let dataString = data;
@@ -175,7 +183,7 @@ function downloadAndSaveVariant(variantApiId, projects, format, status, richText
175
183
  if (!dataIsValid(dataString)) {
176
184
  return "";
177
185
  }
178
- import_fs.default.writeFileSync(filepath, dataString);
186
+ yield writeFile(filepath, dataString);
179
187
  return getSavedMessage(filename);
180
188
  }))
181
189
  );
@@ -199,18 +207,23 @@ function downloadAndSaveBase(projects, format, status, richText, token, options)
199
207
  const params = __spreadValues({}, options == null ? void 0 : options.meta);
200
208
  if (format)
201
209
  params.format = format;
202
- if (status)
203
- params.status = status;
204
210
  if (richText)
205
211
  params.includeRichText = richText.toString();
212
+ if (status)
213
+ params.status = status;
206
214
  const savedMessages = yield Promise.all(
207
- projects.map((_0) => __async(this, [_0], function* ({ id, fileName }) {
208
- const { data } = yield api.get(`/projects/${id}`, {
209
- params,
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,
210
223
  headers: { Authorization: `token ${token}` }
211
224
  });
212
225
  const extension = getFormatExtension(format);
213
- const filename = (0, import_cleanFileName.cleanFileName)(`${fileName}__base${extension}`);
226
+ const filename = (0, import_cleanFileName.cleanFileName)(`${project.fileName}__base${extension}`);
214
227
  const filepath = import_path.default.join(import_consts.default.TEXT_DIR, filename);
215
228
  let dataString = data;
216
229
  if (extension === ".json") {
@@ -220,7 +233,7 @@ function downloadAndSaveBase(projects, format, status, richText, token, options)
220
233
  if (!dataIsValid(dataString)) {
221
234
  return "";
222
235
  }
223
- import_fs.default.writeFileSync(filepath, dataString);
236
+ yield writeFile(filepath, dataString);
224
237
  return getSavedMessage(filename);
225
238
  }))
226
239
  );
@@ -246,19 +259,37 @@ function cleanOutputFiles() {
246
259
  function downloadAndSave(source, token, options) {
247
260
  return __async(this, null, function* () {
248
261
  const api = (0, import_api.createApiClient)();
262
+ if (process.env.DEBUG_CLI) {
263
+ try {
264
+ yield api.get("/health");
265
+ console.debug("Can connect to api.dittowords.com");
266
+ } catch (e) {
267
+ console.debug("CANNOT connect to api.dittowords.com");
268
+ }
269
+ }
249
270
  const {
250
271
  validProjects,
251
272
  format: formatFromSource,
252
273
  shouldFetchComponentLibrary,
253
274
  status,
254
275
  richText,
255
- componentFolders
276
+ componentFolders: specifiedComponentFolders,
277
+ componentRoot
256
278
  } = source;
257
279
  const formats = getFormat(formatFromSource);
258
280
  let msg = "";
259
281
  const spinner = (0, import_ora.default)(msg);
260
282
  spinner.start();
261
- const variants = yield (0, import_fetchVariants.fetchVariants)(source);
283
+ const [variants, allComponentFoldersResponse] = yield Promise.all([
284
+ (0, import_fetchVariants.fetchVariants)(source),
285
+ (0, import_fetchComponentFolders.fetchComponentFolders)()
286
+ ]);
287
+ const allComponentFolders = Object.entries(
288
+ allComponentFoldersResponse
289
+ ).reduce(
290
+ (acc, [id, name]) => acc.concat([{ id, name }]),
291
+ []
292
+ );
262
293
  try {
263
294
  msg += cleanOutputFiles();
264
295
  msg += `
@@ -268,6 +299,39 @@ Fetching the latest text from ${(0, import_sourcesToText.default)(
268
299
  )}
269
300
  `;
270
301
  const meta = options ? options.meta : {};
302
+ const rootRequest = {
303
+ id: "__root__",
304
+ name: "Root",
305
+ // componentRoot can be a boolean or an object
306
+ status: typeof source.componentRoot === "object" ? source.componentRoot.status : void 0
307
+ };
308
+ let componentFolderRequests = [];
309
+ if (specifiedComponentFolders) {
310
+ switch (componentRoot) {
311
+ case void 0:
312
+ case false:
313
+ componentFolderRequests.push(...specifiedComponentFolders);
314
+ break;
315
+ default:
316
+ componentFolderRequests.push(...specifiedComponentFolders);
317
+ componentFolderRequests.push(rootRequest);
318
+ break;
319
+ }
320
+ } else {
321
+ switch (componentRoot) {
322
+ case void 0:
323
+ componentFolderRequests.push(...allComponentFolders);
324
+ componentFolderRequests.push(rootRequest);
325
+ break;
326
+ case false:
327
+ componentFolderRequests.push(...allComponentFolders);
328
+ break;
329
+ default:
330
+ componentFolderRequests.push(rootRequest);
331
+ break;
332
+ }
333
+ }
334
+ const componentSources = [];
271
335
  function fetchComponentLibrary(format) {
272
336
  return __async(this, null, function* () {
273
337
  const componentVariants = [{ apiID: void 0 }, ...variants || []];
@@ -276,36 +340,52 @@ Fetching the latest text from ${(0, import_sourcesToText.default)(
276
340
  Object.entries(options.meta).forEach(([k, v]) => params.append(k, v));
277
341
  if (format)
278
342
  params.append("format", format);
279
- if (status)
280
- params.append("status", status);
281
343
  if (richText)
282
344
  params.append("includeRichText", richText.toString());
283
- if (componentFolders) {
284
- componentFolders.forEach(({ id }) => params.append("folder_id[]", id));
285
- }
286
- const messages = yield Promise.all(
287
- componentVariants.map((_0) => __async(this, [_0], function* ({ apiID: variantApiId }) {
288
- const p = new URLSearchParams(params);
289
- if (variantApiId)
290
- p.append("variant", variantApiId);
291
- const { data } = yield api.get(`/components`, { params: p });
292
- const nameExt = getFormatExtension(format);
293
- const nameBase = "ditto-component-library";
294
- const namePostfix = `__${variantApiId || "base"}`;
295
- const fileName = (0, import_cleanFileName.cleanFileName)(`${nameBase}${namePostfix}${nameExt}`);
296
- const filePath = import_path.default.join(import_consts.default.TEXT_DIR, fileName);
297
- let dataString = data;
298
- if (nameExt === ".json") {
299
- dataString = JSON.stringify(data, null, 2);
300
- }
301
- const dataIsValid = getFormatDataIsValid[format];
302
- if (!dataIsValid(dataString)) {
303
- return "";
304
- }
305
- yield new Promise((r) => import_fs.default.writeFile(filePath, dataString, r));
306
- return getSavedMessage(fileName);
307
- }))
308
- );
345
+ if (status)
346
+ params.append("status", status);
347
+ const messagePromises = [];
348
+ componentVariants.forEach(({ apiID: variantApiId }) => {
349
+ messagePromises.push(
350
+ ...componentFolderRequests.map((componentFolder) => __async(this, null, function* () {
351
+ const componentFolderParams = new URLSearchParams(params);
352
+ if (variantApiId)
353
+ componentFolderParams.append("variant", variantApiId);
354
+ if (componentFolder.status)
355
+ componentFolderParams.append("status", componentFolder.status);
356
+ const url = componentFolder.id === "__root__" ? "/components?root_only=true" : `/component-folders/${componentFolder.id}/components`;
357
+ const { data } = yield api.get(url, {
358
+ params: componentFolderParams
359
+ });
360
+ const nameExt = getFormatExtension(format);
361
+ const nameBase = "components";
362
+ const nameFolder = `__${componentFolder.name}`;
363
+ const namePostfix = `__${variantApiId || "base"}`;
364
+ const fileName = (0, import_cleanFileName.cleanFileName)(
365
+ `${nameBase}${nameFolder}${namePostfix}${nameExt}`
366
+ );
367
+ const filePath = import_path.default.join(import_consts.default.TEXT_DIR, fileName);
368
+ let dataString = data;
369
+ if (nameExt === ".json") {
370
+ dataString = JSON.stringify(data, null, 2);
371
+ }
372
+ const dataIsValid = getFormatDataIsValid[format];
373
+ if (!dataIsValid(dataString)) {
374
+ return "";
375
+ }
376
+ yield writeFile(filePath, dataString);
377
+ componentSources.push({
378
+ type: "components",
379
+ id: "ditto_component_library",
380
+ name: "ditto_component_library",
381
+ fileName,
382
+ variant: variantApiId || "base"
383
+ });
384
+ return getSavedMessage(fileName);
385
+ }))
386
+ );
387
+ });
388
+ const messages = yield Promise.all(messagePromises);
309
389
  msg += messages.join("");
310
390
  });
311
391
  }
@@ -340,14 +420,7 @@ Fetching the latest text from ${(0, import_sourcesToText.default)(
340
420
  yield fetchProjects(format);
341
421
  }
342
422
  }
343
- const sources = [...validProjects];
344
- if (shouldFetchComponentLibrary) {
345
- sources.push({
346
- id: "ditto_component_library",
347
- name: "Ditto Component Library",
348
- fileName: "ditto-component-library"
349
- });
350
- }
423
+ const sources = [...validProjects, ...componentSources];
351
424
  if (formats.some((f) => JSON_FORMATS.includes(f)))
352
425
  msg += (0, import_generateJsDriver.generateJsDriver)(sources);
353
426
  msg += `
@@ -398,19 +471,27 @@ const pull = (options) => __async(void 0, null, function* () {
398
471
  const meta = options ? options.meta : {};
399
472
  const token = import_config.default.getToken(import_consts.default.CONFIG_FILE, import_consts.default.API_HOST);
400
473
  const sourceInformation = import_config.default.parseSourceInformation();
474
+ if (process.env.DEBUG_CLI === "true") {
475
+ console.debug(`Token: ${token}`);
476
+ }
401
477
  try {
402
478
  return yield downloadAndSave(sourceInformation, token, { meta });
403
479
  } catch (e) {
404
- Sentry.captureException(e);
480
+ const eventId = Sentry.captureException(e);
481
+ const eventStr = `
482
+
483
+ Error ID: ${import_output.default.info(eventId)}`;
405
484
  if (e instanceof import_axios.AxiosError) {
406
485
  return (0, import_quit.quit)(
407
486
  import_output.default.errorText(
408
487
  "Something went wrong connecting to Ditto servers. Please contact support or try again later."
409
- )
488
+ ) + eventStr
410
489
  );
411
490
  }
412
491
  return (0, import_quit.quit)(
413
- import_output.default.errorText("Something went wrong. Please try again later.")
492
+ import_output.default.errorText(
493
+ "Something went wrong. Please contact support or try again later."
494
+ ) + eventStr
414
495
  );
415
496
  }
416
497
  });
@@ -430,4 +511,4 @@ var pull_default = {
430
511
  });
431
512
  //# sourceMappingURL=pull.js.map
432
513
 
433
- //# debugId=c9f589e3-b75d-5846-b29d-266ca10a8560
514
+ //# debugId=c9033e67-0b68-5118-944f-a91f2383e9dd
package/bin/pull.js.map CHANGED
@@ -1 +1 @@
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 { SourceInformation, Token, Project, SupportedFormat } from \"./types\";\nimport { fetchVariants } from \"./http/fetchVariants\";\nimport { kMaxLength } from \"buffer\";\nimport { quit } from \"./utils/quit\";\nimport { AxiosError } from \"axios\";\n\nconst SUPPORTED_FORMATS: SupportedFormat[] = [\n \"flat\",\n \"structured\",\n \"android\",\n \"ios-strings\",\n \"ios-stringsdict\",\n \"icu\",\n];\n\nconst JSON_FORMATS: SupportedFormat[] = [\"flat\", \"structured\", \"icu\"];\n\nconst FORMAT_EXTENSIONS = {\n flat: \".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 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 projects: Project[],\n format: SupportedFormat,\n status: string | undefined,\n richText: boolean | undefined,\n token?: Token\n) {\n const api = createApiClient();\n const params: Record<string, string | null> = { variant: variantApiId };\n if (format) params.format = format;\n if (status) params.status = status;\n if (richText) params.includeRichText = richText.toString();\n\n const savedMessages = await Promise.all(\n projects.map(async ({ id, fileName }: Project) => {\n const { data } = await api.get(`/projects/${id}`, {\n params,\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 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 fs.writeFileSync(filepath, dataString);\n return getSavedMessage(filename);\n })\n );\n\n return savedMessages.join(\"\");\n}\n\nasync function downloadAndSaveVariants(\n variants: { apiID: string }[],\n projects: Project[],\n format: SupportedFormat,\n status: string | undefined,\n richText: boolean | undefined,\n token?: Token\n) {\n const messages = await Promise.all([\n downloadAndSaveVariant(null, projects, format, status, richText, token),\n ...variants.map(({ apiID }: { apiID: string }) =>\n downloadAndSaveVariant(apiID, projects, format, status, richText, token)\n ),\n ]);\n\n return messages.join(\"\");\n}\n\nasync function downloadAndSaveBase(\n projects: Project[],\n format: SupportedFormat,\n status: string | undefined,\n richText?: boolean | undefined,\n token?: Token,\n options?: PullOptions\n) {\n const api = createApiClient();\n const params = { ...options?.meta };\n if (format) params.format = format;\n if (status) params.status = status;\n if (richText) params.includeRichText = richText.toString();\n\n const savedMessages = await Promise.all(\n projects.map(async ({ id, fileName }: Project) => {\n const { data } = await api.get(`/projects/${id}`, {\n params,\n headers: { Authorization: `token ${token}` },\n });\n\n const extension = getFormatExtension(format);\n const filename = cleanFileName(`${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 fs.writeFileSync(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 fileNames = fs.readdirSync(consts.TEXT_DIR);\n fileNames.forEach((fileName) => {\n if (/\\.js(on)?|\\.xml|\\.strings(dict)?$/.test(fileName)) {\n fs.unlinkSync(path.resolve(consts.TEXT_DIR, fileName));\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,\n } = source;\n\n const formats = getFormat(formatFromSource);\n\n let msg = \"\";\n const spinner = ora(msg);\n spinner.start();\n\n const variants = await fetchVariants(source);\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 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 (status) params.append(\"status\", status);\n if (richText) params.append(\"includeRichText\", richText.toString());\n if (componentFolders) {\n componentFolders.forEach(({ id }) => params.append(\"folder_id[]\", id));\n }\n\n const messages = await Promise.all(\n componentVariants.map(async ({ apiID: variantApiId }) => {\n const p = new URLSearchParams(params);\n if (variantApiId) p.append(\"variant\", variantApiId);\n\n const { data } = await api.get(`/components`, { params: p });\n\n const nameExt = getFormatExtension(format);\n const nameBase = \"ditto-component-library\";\n const namePostfix = `__${variantApiId || \"base\"}`;\n\n const fileName = cleanFileName(`${nameBase}${namePostfix}${nameExt}`);\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 new Promise((r) => fs.writeFile(filePath, dataString, r));\n return getSavedMessage(fileName);\n })\n );\n\n msg += messages.join(\"\");\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 msg += variants\n ? await downloadAndSaveVariants(\n variants,\n validProjects,\n format,\n status,\n richText,\n token\n )\n : await downloadAndSaveBase(\n validProjects,\n format,\n status,\n richText,\n token,\n {\n meta,\n }\n );\n }\n\n if (validProjects.length) {\n for (const format of formats) {\n await fetchProjects(format);\n }\n }\n\n const sources = [...validProjects];\n if (shouldFetchComponentLibrary) {\n sources.push({\n id: \"ditto_component_library\",\n name: \"Ditto Component Library\",\n fileName: \"ditto-component-library\",\n });\n }\n\n if (formats.some((f) => JSON_FORMATS.includes(f)))\n msg += generateJsDriver(sources);\n\n msg += `\\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}\n\nexport const pull = async (options?: PullOptions) => {\n const meta = options ? options.meta : {};\n const token = config.getToken(consts.CONFIG_FILE, consts.API_HOST);\n const sourceInformation = config.parseSourceInformation();\n\n try {\n return await downloadAndSave(sourceInformation, token, { meta });\n } catch (e) {\n Sentry.captureException(e);\n if (e instanceof AxiosError) {\n return quit(\n output.errorText(\n \"Something went wrong connecting to Ditto servers. Please contact support or try again later.\"\n )\n );\n }\n\n return quit(\n output.errorText(\"Something went wrong. Please try again later.\")\n );\n }\n};\n\nexport default {\n pull,\n _testing: {\n cleanOutputFiles,\n downloadAndSaveVariant,\n downloadAndSaveVariants,\n downloadAndSaveBase,\n },\n};\n"],"names":["config","consts","path","fs","output","ora","sourcesToText"],"mappings":"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","debug_id":"c9f589e3-b75d-5846-b29d-266ca10a8560"}
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 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\";\n\nconst ensureEndsWithNewLine = (str: string) =>\n str + (/[\\r\\n]$/.test(str) ? \"\" : \"\\n\");\n\nconst writeFile = (path: string, data: string) =>\n new Promise((r) => fs.writeFile(path, ensureEndsWithNewLine(data), r));\n\nconst SUPPORTED_FORMATS: SupportedFormat[] = [\n \"flat\",\n \"structured\",\n \"android\",\n \"ios-strings\",\n \"ios-stringsdict\",\n \"icu\",\n];\n\nconst JSON_FORMATS: SupportedFormat[] = [\"flat\", \"structured\", \"icu\"];\n\nconst FORMAT_EXTENSIONS = {\n flat: \".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 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 projects: Project[],\n format: SupportedFormat,\n status: string | undefined,\n richText: boolean | undefined,\n token?: Token,\n) {\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(`/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 variants: { apiID: string }[],\n projects: Project[],\n format: SupportedFormat,\n status: string | undefined,\n richText: boolean | undefined,\n token?: Token,\n) {\n const messages = await Promise.all([\n downloadAndSaveVariant(null, projects, format, status, richText, token),\n ...variants.map(({ apiID }: { apiID: string }) =>\n downloadAndSaveVariant(apiID, projects, format, status, richText, token),\n ),\n ]);\n\n return messages.join(\"\");\n}\n\nasync function downloadAndSaveBase(\n projects: Project[],\n format: SupportedFormat,\n status: string | undefined,\n richText?: boolean | undefined,\n token?: Token,\n options?: PullOptions,\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(`/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 fileNames = fs.readdirSync(consts.TEXT_DIR);\n fileNames.forEach((fileName) => {\n if (/\\.js(on)?|\\.xml|\\.strings(dict)?$/.test(fileName)) {\n fs.unlinkSync(path.resolve(consts.TEXT_DIR, fileName));\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\n if (process.env.DEBUG_CLI) {\n try {\n await api.get(\"/health\");\n console.debug(\"Can connect to api.dittowords.com\");\n } catch {\n console.debug(\"CANNOT connect to api.dittowords.com\");\n }\n }\n\n const {\n validProjects,\n format: formatFromSource,\n shouldFetchComponentLibrary,\n status,\n richText,\n componentFolders: specifiedComponentFolders,\n componentRoot,\n } = source;\n\n const formats = getFormat(formatFromSource);\n\n let msg = \"\";\n const spinner = ora(msg);\n spinner.start();\n\n const [variants, allComponentFoldersResponse] = await Promise.all([\n fetchVariants(source),\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 ? \"/components?root_only=true\"\n : `/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 const nameFolder = `__${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 msg += messages.join(\"\");\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 msg += variants\n ? await downloadAndSaveVariants(\n variants,\n validProjects,\n format,\n status,\n richText,\n token,\n )\n : await downloadAndSaveBase(\n validProjects,\n format,\n status,\n richText,\n token,\n {\n meta,\n },\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 (formats.some((f) => JSON_FORMATS.includes(f)))\n msg += generateJsDriver(sources);\n\n msg += `\\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}\n\nexport const pull = async (options?: PullOptions) => {\n const meta = options ? options.meta : {};\n const token = config.getToken(consts.CONFIG_FILE, consts.API_HOST);\n const sourceInformation = config.parseSourceInformation();\n\n if (process.env.DEBUG_CLI === \"true\") {\n console.debug(`Token: ${token}`);\n }\n\n try {\n return await downloadAndSave(sourceInformation, token, { meta });\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 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 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"],"names":["path","fs","config","consts","output","ora","sourcesToText"],"mappings":"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","debug_id":"c9033e67-0b68-5118-944f-a91f2383e9dd"}
package/bin/types.js CHANGED
@@ -1,5 +1,5 @@
1
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]="9778a30d-4eba-5c79-89d3-78e5ca9db6fc")}catch(e){}}();
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]="3a899a8b-8170-53ae-808a-dea1164e29fe")}catch(e){}}();
3
3
 
4
4
  var __defProp = Object.defineProperty;
5
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -18,4 +18,4 @@ var types_exports = {};
18
18
  module.exports = __toCommonJS(types_exports);
19
19
  //# sourceMappingURL=types.js.map
20
20
 
21
- //# debugId=9778a30d-4eba-5c79-89d3-78e5ca9db6fc
21
+ //# debugId=3a899a8b-8170-53ae-808a-dea1164e29fe
package/bin/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../lib/types.ts"],"sourcesContent":["export interface Project {\n name: string;\n id: string;\n url?: string;\n fileName?: string;\n}\n\nexport type Source = Project;\n\ninterface ComponentFolder {\n id: string;\n name: string;\n}\n\nexport type SupportedFormat =\n | \"flat\"\n | \"structured\"\n | \"android\"\n | \"ios-strings\"\n | \"ios-stringsdict\"\n | \"icu\";\n\nexport interface ConfigYAML {\n sources?: {\n components?: {\n enabled?: boolean;\n folders?: ComponentFolder[];\n };\n projects?: Project[];\n };\n format?: SupportedFormat;\n status?: string;\n variants?: boolean;\n richText?: boolean;\n\n // these are legacy fields - if they exist, we should output\n // a deprecation error, and suggest that they nest them under\n // a top-level `sources` property\n components?: boolean;\n projects?: Project[];\n}\n\nexport interface SourceInformation {\n hasSourceData: boolean;\n validProjects: Project[];\n shouldFetchComponentLibrary: boolean;\n variants: boolean;\n format: string | string[] | undefined;\n status: string | undefined;\n richText: boolean | undefined;\n componentFolders: ComponentFolder[] | null;\n}\n\nexport type Token = string | undefined;\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA;AAAA","debug_id":"9778a30d-4eba-5c79-89d3-78e5ca9db6fc"}
1
+ {"version":3,"sources":["../lib/types.ts"],"sourcesContent":["export interface Project {\n name: string;\n id: string;\n url?: string;\n fileName?: string;\n status?: string;\n exclude_components?: boolean;\n}\n\nexport type ComponentSource = ComponentFolder & {\n type: \"components\";\n fileName: string;\n variant: string;\n};\n\nexport type Source = (Project & { type?: undefined }) | ComponentSource;\n\nexport interface ComponentFolder {\n id: string;\n name: string;\n status?: string;\n}\n\nexport type SupportedFormat =\n | \"flat\"\n | \"structured\"\n | \"android\"\n | \"ios-strings\"\n | \"ios-stringsdict\"\n | \"icu\";\n\ntype ComponentsSourceBool = boolean;\ntype ComponentsSourceConfig = {\n root?: boolean | { status: string };\n folders?: ComponentFolder[];\n};\ntype ComponentsSource = ComponentsSourceBool | ComponentsSourceConfig;\n\nexport interface ConfigYAML {\n sources?: {\n components?: ComponentsSource;\n projects?: Project[];\n };\n format?: SupportedFormat;\n status?: string;\n variants?: boolean;\n richText?: boolean;\n\n // these are legacy fields - if they exist, we should output\n // a deprecation error, and suggest that they nest them under\n // a top-level `sources` property\n components?: boolean;\n projects?: Project[];\n}\n\nexport interface SourceInformation {\n hasSourceData: boolean;\n hasTopLevelProjectsField: boolean;\n hasTopLevelComponentsField: boolean;\n hasComponentLibraryInProjects: boolean;\n validProjects: Project[];\n shouldFetchComponentLibrary: boolean;\n variants: boolean;\n format: string | string[] | undefined;\n status: string | undefined;\n richText: boolean | undefined;\n componentRoot: boolean | { status: string } | undefined;\n componentFolders: ComponentFolder[] | undefined;\n}\n\nexport type Token = string | undefined;\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA;AAAA","debug_id":"3a899a8b-8170-53ae-808a-dea1164e29fe"}
@@ -1,5 +1,5 @@
1
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]="d33f7b20-9173-5593-839d-599b5b4b51ef")}catch(e){}}();
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]="38a5733b-13a9-57f6-843f-d2de84c4c1d0")}catch(e){}}();
3
3
 
4
4
  var __defProp = Object.defineProperty;
5
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -40,4 +40,4 @@ function createSentryContext(obj) {
40
40
  });
41
41
  //# sourceMappingURL=createSentryContext.js.map
42
42
 
43
- //# debugId=d33f7b20-9173-5593-839d-599b5b4b51ef
43
+ //# debugId=38a5733b-13a9-57f6-843f-d2de84c4c1d0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../lib/utils/createSentryContext.ts"],"sourcesContent":["type SentryContext = Record<\n string,\n string | number | boolean | null | undefined\n>;\n\n/**\n * Sentry context\n */\nexport function createSentryContext(obj: unknown) {\n if (typeof obj !== \"object\") return {};\n\n const ctx: SentryContext = {};\n for (const key in obj) {\n const k = key as keyof typeof obj;\n const r = obj[k];\n ctx[k] = typeof r === \"object\" || Array.isArray(r) ? JSON.stringify(r) : r;\n }\n\n return ctx;\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQO,SAAS,oBAAoB,KAAc;AAChD,MAAI,OAAO,QAAQ;AAAU,WAAO,CAAC;AAErC,QAAM,MAAqB,CAAC;AAC5B,aAAW,OAAO,KAAK;AACrB,UAAM,IAAI;AACV,UAAM,IAAI,IAAI,CAAC;AACf,QAAI,CAAC,IAAI,OAAO,MAAM,YAAY,MAAM,QAAQ,CAAC,IAAI,KAAK,UAAU,CAAC,IAAI;AAAA,EAC3E;AAEA,SAAO;AACT","debug_id":"d33f7b20-9173-5593-839d-599b5b4b51ef"}
1
+ {"version":3,"sources":["../../lib/utils/createSentryContext.ts"],"sourcesContent":["type SentryContext = Record<\n string,\n string | number | boolean | null | undefined\n>;\n\n/**\n * Sentry context only supports properties one layer deep\n */\nexport function createSentryContext(obj: unknown) {\n if (typeof obj !== \"object\") return {};\n\n const ctx: SentryContext = {};\n for (const key in obj) {\n const k = key as keyof typeof obj;\n const r = obj[k];\n ctx[k] = typeof r === \"object\" || Array.isArray(r) ? JSON.stringify(r) : r;\n }\n\n return ctx;\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQO,SAAS,oBAAoB,KAAc;AAChD,MAAI,OAAO,QAAQ;AAAU,WAAO,CAAC;AAErC,QAAM,MAAqB,CAAC;AAC5B,aAAW,OAAO,KAAK;AACrB,UAAM,IAAI;AACV,UAAM,IAAI,IAAI,CAAC;AACf,QAAI,CAAC,IAAI,OAAO,MAAM,YAAY,MAAM,QAAQ,CAAC,IAAI,KAAK,UAAU,CAAC,IAAI;AAAA,EAC3E;AAEA,SAAO;AACT","debug_id":"38a5733b-13a9-57f6-843f-d2de84c4c1d0"}
@@ -1,5 +1,5 @@
1
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]="e416d2b1-db35-5e4a-8bb1-6725adbec6e1")}catch(e){}}();
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]="abf6148b-b36f-5809-b765-ac588ff7207f")}catch(e){}}();
3
3
 
4
4
  var __create = Object.create;
5
5
  var __defProp = Object.defineProperty;
@@ -57,7 +57,6 @@ var import_output = __toESM(require("../output"));
57
57
  var import_cleanFileName = require("./cleanFileName");
58
58
  const stringifySourceId = (projectId) => projectId === "ditto_component_library" ? projectId : `project_${projectId}`;
59
59
  function generateJsDriver(sources) {
60
- const fileNames = import_fs.default.readdirSync(import_consts.default.TEXT_DIR).filter((fileName) => /\.json$/.test(fileName));
61
60
  const sourceIdsByName = sources.reduce(
62
61
  (agg, source) => {
63
62
  if (source.fileName) {
@@ -67,7 +66,10 @@ function generateJsDriver(sources) {
67
66
  },
68
67
  {}
69
68
  );
70
- const data = fileNames.reduce(
69
+ const projectFileNames = import_fs.default.readdirSync(import_consts.default.TEXT_DIR).filter(
70
+ (fileName) => /\.json$/.test(fileName) && !/^components__/.test(fileName)
71
+ );
72
+ const data = projectFileNames.reduce(
71
73
  (obj, fileName) => {
72
74
  const [sourceId, rest] = fileName.split("__");
73
75
  const [variantApiId] = rest.split(".");
@@ -81,7 +83,29 @@ function generateJsDriver(sources) {
81
83
  },
82
84
  {}
83
85
  );
84
- let dataString = `module.exports = ${JSON.stringify(data, null, 2)}`.replace(/"require\((.*)\)"/g, "require($1)");
86
+ const componentData = {};
87
+ sources.filter((s) => s.type === "components").forEach((componentSource) => {
88
+ var _a, _b;
89
+ if (componentSource.type !== "components")
90
+ return;
91
+ (_b = componentData[_a = componentSource.variant]) != null ? _b : componentData[_a] = [];
92
+ componentData[componentSource.variant].push(
93
+ `...require('./${componentSource.fileName}')`
94
+ );
95
+ });
96
+ Object.keys(componentData).forEach((key) => {
97
+ var _a;
98
+ (_a = data.ditto_component_library) != null ? _a : data.ditto_component_library = {};
99
+ let str = "{";
100
+ componentData[key].forEach((k, i) => {
101
+ str += k;
102
+ if (i < componentData[key].length - 1)
103
+ str += ", ";
104
+ });
105
+ str += "}";
106
+ data.ditto_component_library[key] = str;
107
+ });
108
+ let dataString = `module.exports = ${JSON.stringify(data, null, 2)}`.replace(/"require\((.*)\)"/g, "require($1)").replace(/"\{/g, "{").replace(/\}"/g, "}");
85
109
  const filePath = import_path.default.resolve(import_consts.default.TEXT_DIR, "index.js");
86
110
  import_fs.default.writeFileSync(filePath, dataString, { encoding: "utf8" });
87
111
  return `Generated .js SDK driver at ${import_output.default.info(filePath)}`;
@@ -92,4 +116,4 @@ function generateJsDriver(sources) {
92
116
  });
93
117
  //# sourceMappingURL=generateJsDriver.js.map
94
118
 
95
- //# debugId=e416d2b1-db35-5e4a-8bb1-6725adbec6e1
119
+ //# debugId=abf6148b-b36f-5809-b765-ac588ff7207f
@@ -1 +1 @@
1
- {"version":3,"sources":["../../lib/utils/generateJsDriver.ts"],"sourcesContent":["import fs from \"fs\";\nimport path from \"path\";\nimport consts from \"../consts\";\nimport output from \"../output\";\nimport { Source } from \"../types\";\nimport { cleanFileName } from \"./cleanFileName\";\n\n// compatability with legacy method of specifying project ids\n// that is still used by the default format\nconst stringifySourceId = (projectId: string) =>\n projectId === \"ditto_component_library\" ? projectId : `project_${projectId}`;\n\n/**\n * Generates an index.js file that can be consumed\n * by an SDK - this is a big DX improvement because\n * it provides a single entry point to get all data\n * (including variants) instead of having to import\n * each generated file individually.\n *\n * The generated file will have a unified format\n * independent of the CLI configuration used to fetch\n * data from Ditto.\n */\n\n// TODO: support ESM\nexport function generateJsDriver(sources: Source[]) {\n const fileNames = fs\n .readdirSync(consts.TEXT_DIR)\n .filter((fileName) => /\\.json$/.test(fileName));\n\n const sourceIdsByName: Record<string, string> = sources.reduce(\n (agg, source) => {\n if (source.fileName) {\n return { ...agg, [cleanFileName(source.fileName)]: source.id };\n }\n\n return agg;\n },\n {}\n );\n\n const data = fileNames.reduce(\n (obj: Record<string, Record<string, string>>, fileName) => {\n const [sourceId, rest] = fileName.split(\"__\");\n const [variantApiId] = rest.split(\".\");\n\n const projectId = sourceIdsByName[sourceId];\n const projectIdStr = stringifySourceId(projectId);\n\n if (!obj[projectIdStr]) {\n obj[projectIdStr] = {};\n }\n\n obj[projectIdStr][variantApiId] = `require('./${fileName}')`;\n return obj;\n },\n {}\n );\n\n let dataString = `module.exports = ${JSON.stringify(data, null, 2)}`\n // remove quotes around require statements\n .replace(/\"require\\((.*)\\)\"/g, \"require($1)\");\n\n const filePath = path.resolve(consts.TEXT_DIR, \"index.js\");\n fs.writeFileSync(filePath, dataString, { encoding: \"utf8\" });\n\n return `Generated .js SDK driver at ${output.info(filePath)}`;\n}\n"],"names":["fs","consts","path","output"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAAe;AACf,kBAAiB;AACjB,oBAAmB;AACnB,oBAAmB;AAEnB,2BAA8B;AAI9B,MAAM,oBAAoB,CAAC,cACzB,cAAc,4BAA4B,YAAY,WAAW,SAAS;AAerE,SAAS,iBAAiB,SAAmB;AAClD,QAAM,YAAY,UAAAA,QACf,YAAY,cAAAC,QAAO,QAAQ,EAC3B,OAAO,CAAC,aAAa,UAAU,KAAK,QAAQ,CAAC;AAEhD,QAAM,kBAA0C,QAAQ;AAAA,IACtD,CAAC,KAAK,WAAW;AACf,UAAI,OAAO,UAAU;AACnB,eAAO,iCAAK,MAAL,EAAU,KAAC,oCAAc,OAAO,QAAQ,CAAC,GAAG,OAAO,GAAG;AAAA,MAC/D;AAEA,aAAO;AAAA,IACT;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,OAAO,UAAU;AAAA,IACrB,CAAC,KAA6C,aAAa;AACzD,YAAM,CAAC,UAAU,IAAI,IAAI,SAAS,MAAM,IAAI;AAC5C,YAAM,CAAC,YAAY,IAAI,KAAK,MAAM,GAAG;AAErC,YAAM,YAAY,gBAAgB,QAAQ;AAC1C,YAAM,eAAe,kBAAkB,SAAS;AAEhD,UAAI,CAAC,IAAI,YAAY,GAAG;AACtB,YAAI,YAAY,IAAI,CAAC;AAAA,MACvB;AAEA,UAAI,YAAY,EAAE,YAAY,IAAI,cAAc,QAAQ;AACxD,aAAO;AAAA,IACT;AAAA,IACA,CAAC;AAAA,EACH;AAEA,MAAI,aAAa,oBAAoB,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC,GAE/D,QAAQ,sBAAsB,aAAa;AAE9C,QAAM,WAAW,YAAAC,QAAK,QAAQ,cAAAD,QAAO,UAAU,UAAU;AACzD,YAAAD,QAAG,cAAc,UAAU,YAAY,EAAE,UAAU,OAAO,CAAC;AAE3D,SAAO,+BAA+B,cAAAG,QAAO,KAAK,QAAQ,CAAC;AAC7D","debug_id":"e416d2b1-db35-5e4a-8bb1-6725adbec6e1"}
1
+ {"version":3,"sources":["../../lib/utils/generateJsDriver.ts"],"sourcesContent":["import fs from \"fs\";\nimport path from \"path\";\nimport consts from \"../consts\";\nimport output from \"../output\";\nimport { Source } from \"../types\";\nimport { cleanFileName } from \"./cleanFileName\";\n\n// compatability with legacy method of specifying project ids\n// that is still used by the default format\nconst stringifySourceId = (projectId: string) =>\n projectId === \"ditto_component_library\" ? projectId : `project_${projectId}`;\n\n/**\n * Generates an index.js file that can be consumed\n * by an SDK - this is a big DX improvement because\n * it provides a single entry point to get all data\n * (including variants) instead of having to import\n * each generated file individually.\n *\n * The generated file will have a unified format\n * independent of the CLI configuration used to fetch\n * data from Ditto.\n */\n\n// TODO: support ESM\nexport function generateJsDriver(sources: Source[]) {\n const sourceIdsByName: Record<string, string> = sources.reduce(\n (agg, source) => {\n if (source.fileName) {\n return { ...agg, [cleanFileName(source.fileName)]: source.id };\n }\n\n return agg;\n },\n {}\n );\n\n const projectFileNames = fs\n .readdirSync(consts.TEXT_DIR)\n .filter(\n (fileName) => /\\.json$/.test(fileName) && !/^components__/.test(fileName)\n );\n\n type DriverFile = Record<string, Record<string, string | object>>;\n const data: DriverFile = projectFileNames.reduce(\n (obj: Record<string, Record<string, string>>, fileName) => {\n const [sourceId, rest] = fileName.split(\"__\");\n const [variantApiId] = rest.split(\".\");\n\n const projectId = sourceIdsByName[sourceId];\n const projectIdStr = stringifySourceId(projectId);\n\n if (!obj[projectIdStr]) {\n obj[projectIdStr] = {};\n }\n\n obj[projectIdStr][variantApiId] = `require('./${fileName}')`;\n return obj;\n },\n {}\n );\n\n // Create arrays of stringified \"...require()\" statements,\n // each of which corresponds to one of the component files\n // (which are created on a per-component-folder basis)\n const componentData: Record<string, string[]> = {};\n sources\n .filter((s) => s.type === \"components\")\n .forEach((componentSource) => {\n if (componentSource.type !== \"components\") return;\n componentData[componentSource.variant] ??= [];\n componentData[componentSource.variant].push(\n `...require('./${componentSource.fileName}')`\n );\n });\n // Convert each array of stringified \"...require()\" statements\n // into a unified string, and set it on the final data object\n // that will be written to the driver file\n Object.keys(componentData).forEach((key) => {\n data.ditto_component_library ??= {};\n\n let str = \"{\";\n componentData[key].forEach((k, i) => {\n str += k;\n if (i < componentData[key].length - 1) str += \", \";\n });\n str += \"}\";\n data.ditto_component_library[key] = str;\n });\n\n let dataString = `module.exports = ${JSON.stringify(data, null, 2)}`\n // remove quotes around require statements\n .replace(/\"require\\((.*)\\)\"/g, \"require($1)\")\n // remove quotes around opening & closing curlies\n .replace(/\"\\{/g, \"{\")\n .replace(/\\}\"/g, \"}\");\n\n const filePath = path.resolve(consts.TEXT_DIR, \"index.js\");\n fs.writeFileSync(filePath, dataString, { encoding: \"utf8\" });\n\n return `Generated .js SDK driver at ${output.info(filePath)}`;\n}\n"],"names":["fs","consts","path","output"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAAe;AACf,kBAAiB;AACjB,oBAAmB;AACnB,oBAAmB;AAEnB,2BAA8B;AAI9B,MAAM,oBAAoB,CAAC,cACzB,cAAc,4BAA4B,YAAY,WAAW,SAAS;AAerE,SAAS,iBAAiB,SAAmB;AAClD,QAAM,kBAA0C,QAAQ;AAAA,IACtD,CAAC,KAAK,WAAW;AACf,UAAI,OAAO,UAAU;AACnB,eAAO,iCAAK,MAAL,EAAU,KAAC,oCAAc,OAAO,QAAQ,CAAC,GAAG,OAAO,GAAG;AAAA,MAC/D;AAEA,aAAO;AAAA,IACT;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,mBAAmB,UAAAA,QACtB,YAAY,cAAAC,QAAO,QAAQ,EAC3B;AAAA,IACC,CAAC,aAAa,UAAU,KAAK,QAAQ,KAAK,CAAC,gBAAgB,KAAK,QAAQ;AAAA,EAC1E;AAGF,QAAM,OAAmB,iBAAiB;AAAA,IACxC,CAAC,KAA6C,aAAa;AACzD,YAAM,CAAC,UAAU,IAAI,IAAI,SAAS,MAAM,IAAI;AAC5C,YAAM,CAAC,YAAY,IAAI,KAAK,MAAM,GAAG;AAErC,YAAM,YAAY,gBAAgB,QAAQ;AAC1C,YAAM,eAAe,kBAAkB,SAAS;AAEhD,UAAI,CAAC,IAAI,YAAY,GAAG;AACtB,YAAI,YAAY,IAAI,CAAC;AAAA,MACvB;AAEA,UAAI,YAAY,EAAE,YAAY,IAAI,cAAc,QAAQ;AACxD,aAAO;AAAA,IACT;AAAA,IACA,CAAC;AAAA,EACH;AAKA,QAAM,gBAA0C,CAAC;AACjD,UACG,OAAO,CAAC,MAAM,EAAE,SAAS,YAAY,EACrC,QAAQ,CAAC,oBAAoB;AApElC;AAqEM,QAAI,gBAAgB,SAAS;AAAc;AAC3C,6BAAc,gBAAgB,aAA9B,gCAA2C,CAAC;AAC5C,kBAAc,gBAAgB,OAAO,EAAE;AAAA,MACrC,iBAAiB,gBAAgB,QAAQ;AAAA,IAC3C;AAAA,EACF,CAAC;AAIH,SAAO,KAAK,aAAa,EAAE,QAAQ,CAAC,QAAQ;AA9E9C;AA+EI,eAAK,4BAAL,iBAAK,0BAA4B,CAAC;AAElC,QAAI,MAAM;AACV,kBAAc,GAAG,EAAE,QAAQ,CAAC,GAAG,MAAM;AACnC,aAAO;AACP,UAAI,IAAI,cAAc,GAAG,EAAE,SAAS;AAAG,eAAO;AAAA,IAChD,CAAC;AACD,WAAO;AACP,SAAK,wBAAwB,GAAG,IAAI;AAAA,EACtC,CAAC;AAED,MAAI,aAAa,oBAAoB,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC,GAE/D,QAAQ,sBAAsB,aAAa,EAE3C,QAAQ,QAAQ,GAAG,EACnB,QAAQ,QAAQ,GAAG;AAEtB,QAAM,WAAW,YAAAC,QAAK,QAAQ,cAAAD,QAAO,UAAU,UAAU;AACzD,YAAAD,QAAG,cAAc,UAAU,YAAY,EAAE,UAAU,OAAO,CAAC;AAE3D,SAAO,+BAA+B,cAAAG,QAAO,KAAK,QAAQ,CAAC;AAC7D","debug_id":"abf6148b-b36f-5809-b765-ac588ff7207f"}
package/lib/api.ts CHANGED
@@ -4,7 +4,7 @@ import config from "./config";
4
4
  import consts from "./consts";
5
5
 
6
6
  export function createApiClient(token?: string) {
7
- return axios.create({
7
+ const client = axios.create({
8
8
  baseURL: consts.API_HOST,
9
9
  headers: {
10
10
  Authorization: `token ${
@@ -12,4 +12,20 @@ export function createApiClient(token?: string) {
12
12
  }`,
13
13
  },
14
14
  });
15
+
16
+ if (process.env.DEBUG_CLI) {
17
+ console.debug(`Host: ${consts.API_HOST}`);
18
+
19
+ client.interceptors.request.use((request) => {
20
+ console.debug("Starting Request", request.url);
21
+ return request;
22
+ });
23
+
24
+ client.interceptors.response.use(response => {
25
+ console.debug('Response:', response);
26
+ return response;
27
+ });
28
+ }
29
+
30
+ return client;
15
31
  }