@dittowords/cli 4.3.0 → 4.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/.github/actions/install-node-dependencies/action.yml +24 -0
  2. package/.github/workflows/required-checks.yml +24 -0
  3. package/.sentryclirc +3 -0
  4. package/__mocks__/fs.js +2 -0
  5. package/bin/__mocks__/api.js +48 -0
  6. package/bin/__mocks__/api.js.map +1 -0
  7. package/bin/config.test.js +4 -3
  8. package/bin/config.test.js.map +1 -1
  9. package/bin/consts.js +19 -29
  10. package/bin/consts.js.map +1 -1
  11. package/bin/ditto.js +12 -4
  12. package/bin/ditto.js.map +1 -1
  13. package/bin/generate-suggestions.js +68 -58
  14. package/bin/generate-suggestions.js.map +1 -1
  15. package/bin/generate-suggestions.test.js +24 -13
  16. package/bin/generate-suggestions.test.js.map +1 -1
  17. package/bin/http/__mocks__/fetchComponentFolders.js +71 -0
  18. package/bin/http/__mocks__/fetchComponentFolders.js.map +1 -0
  19. package/bin/http/__mocks__/fetchComponents.js +73 -0
  20. package/bin/http/__mocks__/fetchComponents.js.map +1 -0
  21. package/bin/http/__mocks__/fetchVariants.js +71 -0
  22. package/bin/http/__mocks__/fetchVariants.js.map +1 -0
  23. package/bin/http/fetchComponentFolders.js +4 -4
  24. package/bin/http/fetchComponentFolders.js.map +1 -1
  25. package/bin/http/fetchComponents.js +4 -4
  26. package/bin/http/fetchComponents.js.map +1 -1
  27. package/bin/http/fetchVariants.js +6 -3
  28. package/bin/http/fetchVariants.js.map +1 -1
  29. package/bin/http/http.test.js +159 -0
  30. package/bin/http/http.test.js.map +1 -0
  31. package/bin/http/importComponents.js +9 -2
  32. package/bin/http/importComponents.js.map +1 -1
  33. package/bin/init/project.test.js +5 -28
  34. package/bin/init/project.test.js.map +1 -1
  35. package/bin/init/token.js +72 -27
  36. package/bin/init/token.js.map +1 -1
  37. package/bin/init/token.test.js +87 -9
  38. package/bin/init/token.test.js.map +1 -1
  39. package/bin/pull-lib.test.js +379 -0
  40. package/bin/pull-lib.test.js.map +1 -0
  41. package/bin/pull.js +15 -4
  42. package/bin/pull.js.map +1 -1
  43. package/bin/pull.test.js +73 -290
  44. package/bin/pull.test.js.map +1 -1
  45. package/bin/replace.js +22 -6
  46. package/bin/replace.js.map +1 -1
  47. package/bin/replace.test.js +53 -11
  48. package/bin/replace.test.js.map +1 -1
  49. package/bin/utils/determineModuleType.js +6 -7
  50. package/bin/utils/determineModuleType.js.map +1 -1
  51. package/bin/utils/determineModuleType.test.js +60 -0
  52. package/bin/utils/determineModuleType.test.js.map +1 -0
  53. package/bin/utils/getSelectedProjects.js +5 -5
  54. package/bin/utils/getSelectedProjects.js.map +1 -1
  55. package/bin/utils/quit.js +3 -3
  56. package/bin/utils/quit.js.map +1 -1
  57. package/jest.config.ts +16 -0
  58. package/lib/__mocks__/api.ts +12 -0
  59. package/lib/config.test.ts +3 -1
  60. package/lib/consts.ts +19 -17
  61. package/lib/ditto.ts +9 -1
  62. package/lib/generate-suggestions.test.ts +23 -11
  63. package/lib/generate-suggestions.ts +89 -79
  64. package/lib/http/__mocks__/fetchComponentFolders.ts +23 -0
  65. package/lib/http/__mocks__/fetchComponents.ts +24 -0
  66. package/lib/http/__mocks__/fetchVariants.ts +21 -0
  67. package/lib/http/fetchComponentFolders.ts +6 -4
  68. package/lib/http/fetchComponents.ts +5 -3
  69. package/lib/http/fetchVariants.ts +15 -4
  70. package/lib/http/http.test.ts +122 -0
  71. package/lib/http/importComponents.ts +8 -0
  72. package/lib/init/project.test.ts +4 -27
  73. package/lib/init/token.test.ts +55 -7
  74. package/lib/init/token.ts +76 -27
  75. package/lib/pull-lib.test.ts +367 -0
  76. package/lib/pull.test.ts +63 -316
  77. package/lib/pull.ts +13 -2
  78. package/lib/replace.test.ts +46 -10
  79. package/lib/replace.ts +20 -3
  80. package/lib/utils/determineModuleType.test.ts +48 -0
  81. package/lib/utils/determineModuleType.ts +4 -6
  82. package/lib/utils/getSelectedProjects.ts +3 -3
  83. package/lib/utils/quit.ts +1 -1
  84. package/package.json +4 -3
  85. package/jest.config.js +0 -6
@@ -1,41 +1,18 @@
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]="303bce00-0890-56b5-beeb-9b739774442f")}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]="4aaa4928-24d6-5124-b02e-08fd3c766537")}catch(e){}}();
3
3
 
4
4
  var import_project = require("./project");
5
5
  const fs = require("fs");
6
- const path = require("path");
7
6
  const yaml = require("js-yaml");
8
- const { createFileIfMissing } = require("../config");
9
- const fakeProjectDir = path.join(__dirname, "../../testing/tmp");
10
- const badYaml = path.join(__dirname, "../../testing/fixtures/bad-yaml.yml");
11
- const configEmptyProjects = path.join(
12
- __dirname,
13
- "../../testing/fixtures/bad-yaml.yml"
14
- );
15
- const configMissingName = path.join(
16
- __dirname,
17
- "../../testing/fixtures/project-config-no-name.yml"
18
- );
19
- const configMissingId = path.join(
20
- __dirname,
21
- "../../testing/fixtures/project-config-no-id.yml"
22
- );
23
- const configLegit = path.join(
24
- __dirname,
25
- "../../testing/fixtures/project-config-working.yml"
26
- );
7
+ const fakeProjectDir = "/";
8
+ jest.mock("fs");
27
9
  describe("saveProject", () => {
28
- const configFile = path.join(fakeProjectDir, "ditto/config.yml");
10
+ const configFile = "/ditto/config.yml";
29
11
  const projectName = "My Amazing Project";
30
12
  const projectId = "5f284259ce1d451b2eb2e23c";
31
13
  beforeEach(() => {
32
- if (!fs.existsSync(fakeProjectDir))
33
- fs.mkdirSync(fakeProjectDir);
34
14
  import_project._testing.saveProject(configFile, projectName, projectId);
35
15
  });
36
- afterEach(() => {
37
- fs.rmdirSync(fakeProjectDir, { recursive: true });
38
- });
39
16
  it("creates a config file with config data", () => {
40
17
  const fileContents = fs.readFileSync(configFile, "utf8");
41
18
  const data = yaml.load(fileContents);
@@ -46,4 +23,4 @@ describe("saveProject", () => {
46
23
  });
47
24
  //# sourceMappingURL=project.test.js.map
48
25
 
49
- //# debugId=303bce00-0890-56b5-beeb-9b739774442f
26
+ //# debugId=4aaa4928-24d6-5124-b02e-08fd3c766537
@@ -1 +1 @@
1
- {"version":3,"sources":["../../lib/init/project.test.ts"],"sourcesContent":["const fs = require(\"fs\");\nconst path = require(\"path\");\n\nconst yaml = require(\"js-yaml\");\nconst { createFileIfMissing } = require(\"../config\");\n\nimport { _testing } from \"./project\";\n\nconst fakeProjectDir = path.join(__dirname, \"../../testing/tmp\");\nconst badYaml = path.join(__dirname, \"../../testing/fixtures/bad-yaml.yml\");\nconst configEmptyProjects = path.join(\n __dirname,\n \"../../testing/fixtures/bad-yaml.yml\"\n);\nconst configMissingName = path.join(\n __dirname,\n \"../../testing/fixtures/project-config-no-name.yml\"\n);\nconst configMissingId = path.join(\n __dirname,\n \"../../testing/fixtures/project-config-no-id.yml\"\n);\nconst configLegit = path.join(\n __dirname,\n \"../../testing/fixtures/project-config-working.yml\"\n);\n\ndescribe(\"saveProject\", () => {\n const configFile = path.join(fakeProjectDir, \"ditto/config.yml\");\n const projectName = \"My Amazing Project\";\n const projectId = \"5f284259ce1d451b2eb2e23c\";\n\n beforeEach(() => {\n if (!fs.existsSync(fakeProjectDir)) fs.mkdirSync(fakeProjectDir);\n _testing.saveProject(configFile, projectName, projectId);\n });\n\n afterEach(() => {\n fs.rmdirSync(fakeProjectDir, { recursive: true });\n });\n\n it(\"creates a config file with config data\", () => {\n const fileContents = fs.readFileSync(configFile, \"utf8\");\n const data = yaml.load(fileContents);\n expect(data.sources.projects).toBeDefined();\n expect(data.sources.projects[0].name).toEqual(projectName);\n expect(data.sources.projects[0].id).toEqual(projectId);\n });\n});\n"],"names":[],"mappings":";;;AAMA,qBAAyB;AANzB,MAAM,KAAK,QAAQ,IAAI;AACvB,MAAM,OAAO,QAAQ,MAAM;AAE3B,MAAM,OAAO,QAAQ,SAAS;AAC9B,MAAM,EAAE,oBAAoB,IAAI,QAAQ,WAAW;AAInD,MAAM,iBAAiB,KAAK,KAAK,WAAW,mBAAmB;AAC/D,MAAM,UAAU,KAAK,KAAK,WAAW,qCAAqC;AAC1E,MAAM,sBAAsB,KAAK;AAAA,EAC/B;AAAA,EACA;AACF;AACA,MAAM,oBAAoB,KAAK;AAAA,EAC7B;AAAA,EACA;AACF;AACA,MAAM,kBAAkB,KAAK;AAAA,EAC3B;AAAA,EACA;AACF;AACA,MAAM,cAAc,KAAK;AAAA,EACvB;AAAA,EACA;AACF;AAEA,SAAS,eAAe,MAAM;AAC5B,QAAM,aAAa,KAAK,KAAK,gBAAgB,kBAAkB;AAC/D,QAAM,cAAc;AACpB,QAAM,YAAY;AAElB,aAAW,MAAM;AACf,QAAI,CAAC,GAAG,WAAW,cAAc;AAAG,SAAG,UAAU,cAAc;AAC/D,4BAAS,YAAY,YAAY,aAAa,SAAS;AAAA,EACzD,CAAC;AAED,YAAU,MAAM;AACd,OAAG,UAAU,gBAAgB,EAAE,WAAW,KAAK,CAAC;AAAA,EAClD,CAAC;AAED,KAAG,0CAA0C,MAAM;AACjD,UAAM,eAAe,GAAG,aAAa,YAAY,MAAM;AACvD,UAAM,OAAO,KAAK,KAAK,YAAY;AACnC,WAAO,KAAK,QAAQ,QAAQ,EAAE,YAAY;AAC1C,WAAO,KAAK,QAAQ,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,WAAW;AACzD,WAAO,KAAK,QAAQ,SAAS,CAAC,EAAE,EAAE,EAAE,QAAQ,SAAS;AAAA,EACvD,CAAC;AACH,CAAC","debug_id":"303bce00-0890-56b5-beeb-9b739774442f"}
1
+ {"version":3,"sources":["../../lib/init/project.test.ts"],"sourcesContent":["const fs = require(\"fs\");\nconst yaml = require(\"js-yaml\");\n\nimport { _testing } from \"./project\";\n\nconst fakeProjectDir = \"/\";\n\njest.mock(\"fs\");\n\ndescribe(\"saveProject\", () => {\n const configFile = \"/ditto/config.yml\";\n const projectName = \"My Amazing Project\";\n const projectId = \"5f284259ce1d451b2eb2e23c\";\n\n beforeEach(() => {\n _testing.saveProject(configFile, projectName, projectId);\n });\n\n it(\"creates a config file with config data\", () => {\n const fileContents = fs.readFileSync(configFile, \"utf8\");\n const data = yaml.load(fileContents);\n expect(data.sources.projects).toBeDefined();\n expect(data.sources.projects[0].name).toEqual(projectName);\n expect(data.sources.projects[0].id).toEqual(projectId);\n });\n});\n"],"names":[],"mappings":";;;AAGA,qBAAyB;AAHzB,MAAM,KAAK,QAAQ,IAAI;AACvB,MAAM,OAAO,QAAQ,SAAS;AAI9B,MAAM,iBAAiB;AAEvB,KAAK,KAAK,IAAI;AAEd,SAAS,eAAe,MAAM;AAC5B,QAAM,aAAa;AACnB,QAAM,cAAc;AACpB,QAAM,YAAY;AAElB,aAAW,MAAM;AACf,4BAAS,YAAY,YAAY,aAAa,SAAS;AAAA,EACzD,CAAC;AAED,KAAG,0CAA0C,MAAM;AACjD,UAAM,eAAe,GAAG,aAAa,YAAY,MAAM;AACvD,UAAM,OAAO,KAAK,KAAK,YAAY;AACnC,WAAO,KAAK,QAAQ,QAAQ,EAAE,YAAY;AAC1C,WAAO,KAAK,QAAQ,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,WAAW;AACzD,WAAO,KAAK,QAAQ,SAAS,CAAC,EAAE,EAAE,EAAE,QAAQ,SAAS;AAAA,EACvD,CAAC;AACH,CAAC","debug_id":"4aaa4928-24d6-5124-b02e-08fd3c766537"}
package/bin/init/token.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]="8ea35454-3a68-5e02-b127-d1129433ec18")}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]="269cb038-6f18-5abe-8383-a29108298035")}catch(e){}}();
3
3
 
4
4
  var __create = Object.create;
5
5
  var __defProp = Object.defineProperty;
@@ -50,12 +50,14 @@ var __async = (__this, __arguments, generator) => {
50
50
  };
51
51
  var token_exports = {};
52
52
  __export(token_exports, {
53
+ _test: () => _test,
53
54
  collectAndSaveToken: () => collectAndSaveToken,
54
55
  default: () => token_default,
55
56
  needsToken: () => needsToken
56
57
  });
57
58
  module.exports = __toCommonJS(token_exports);
58
59
  var import_fs = __toESM(require("fs"));
60
+ var Sentry = __toESM(require("@sentry/node"));
59
61
  var import_chalk = __toESM(require("chalk"));
60
62
  var import_enquirer = require("enquirer");
61
63
  var import_api = require("../api");
@@ -63,6 +65,7 @@ var import_consts = __toESM(require("../consts"));
63
65
  var import_output = __toESM(require("../output"));
64
66
  var import_config = __toESM(require("../config"));
65
67
  var import_quit = require("../utils/quit");
68
+ var import_axios = require("axios");
66
69
  const needsToken = (configFile, host = import_consts.default.API_HOST) => {
67
70
  if (import_config.default.getTokenFromEnv()) {
68
71
  return false;
@@ -75,46 +78,74 @@ const needsToken = (configFile, host = import_consts.default.API_HOST) => {
75
78
  return true;
76
79
  return false;
77
80
  };
78
- function checkToken(token) {
81
+ function verifyTokenUsingTokenCheck(token) {
79
82
  return __async(this, null, function* () {
83
+ var _a, _b;
80
84
  const axios = (0, import_api.createApiClient)(token);
81
85
  const endpoint = "/token-check";
82
86
  let resOrError;
83
87
  try {
84
- resOrError = yield axios.get(endpoint).catch((error) => {
85
- if (error.code === "ENOTFOUND") {
86
- return import_output.default.errorText(
87
- `Can't connect to API: ${import_output.default.url(error.hostname)}`
88
- );
89
- }
90
- if (error.response.status === 401 || error.response.status === 404) {
91
- return import_output.default.errorText(
92
- "This API key isn't valid. Please try another."
93
- );
94
- }
95
- return import_output.default.warnText("We're having trouble reaching the Ditto API.");
96
- });
88
+ resOrError = yield axios.get(endpoint);
97
89
  } catch (e) {
98
- import_output.default.errorText(e);
99
- import_output.default.errorText("Sorry! We're having trouble reaching the Ditto API.");
90
+ if (!(e instanceof import_axios.AxiosError)) {
91
+ return {
92
+ success: false,
93
+ output: [
94
+ import_output.default.warnText(
95
+ "Sorry! We're having trouble reaching the Ditto API."
96
+ )
97
+ ]
98
+ };
99
+ }
100
+ if (e.code === "ENOTFOUND") {
101
+ return {
102
+ success: false,
103
+ output: [
104
+ import_output.default.errorText(
105
+ `Can't connect to API: ${import_output.default.url(import_consts.default.API_HOST)}`
106
+ )
107
+ ]
108
+ };
109
+ }
110
+ if (((_a = e.response) == null ? void 0 : _a.status) === 401 || ((_b = e.response) == null ? void 0 : _b.status) === 404) {
111
+ return {
112
+ success: false,
113
+ output: [
114
+ import_output.default.errorText("This API key isn't valid. Please try another.")
115
+ ]
116
+ };
117
+ }
100
118
  }
101
119
  if (typeof resOrError === "string") {
102
- return resOrError;
120
+ return {
121
+ success: false,
122
+ output: [resOrError]
123
+ };
103
124
  }
104
125
  if ((resOrError == null ? void 0 : resOrError.status) === 200) {
105
- return true;
126
+ return { success: true };
127
+ }
128
+ return {
129
+ success: false,
130
+ output: [import_output.default.errorText("This API key isn't valid. Please try another.")]
131
+ };
132
+ });
133
+ }
134
+ function checkToken(token) {
135
+ return __async(this, null, function* () {
136
+ const result = yield verifyTokenUsingTokenCheck(token);
137
+ if (!result.success) {
138
+ return result.output.join("\n");
106
139
  }
107
- return import_output.default.errorText("This API key isn't valid. Please try another.");
140
+ return true;
108
141
  });
109
142
  }
110
143
  function collectToken(message) {
111
144
  return __async(this, null, function* () {
112
145
  const blue = import_output.default.info;
113
- const apiUrl = import_output.default.url("https://app.dittowords.com/account/user");
114
- const breadcrumbs = `${blue("User")}`;
115
- const tokenDescription = message || `To get started, you'll need your Ditto API key. You can find this at: ${apiUrl} > ${breadcrumbs} under "${import_chalk.default.bold(
116
- "API Keys"
117
- )}".`;
146
+ const apiUrl = import_output.default.url("https://app.dittowords.com/account/devtools");
147
+ const breadcrumbs = `${import_chalk.default.bold(blue("API Keys"))}`;
148
+ const tokenDescription = message || `To get started, you'll need your Ditto API key. You can find this at: ${apiUrl} under "${breadcrumbs}".`;
118
149
  console.log(tokenDescription);
119
150
  const response = yield (0, import_enquirer.prompt)({
120
151
  type: "input",
@@ -137,15 +168,29 @@ const collectAndSaveToken = (message = null) => __async(void 0, null, function*
137
168
  import_config.default.saveToken(import_consts.default.CONFIG_FILE, import_consts.default.API_HOST, token);
138
169
  return token;
139
170
  } catch (error) {
140
- (0, import_quit.quit)("API token was not saved");
171
+ if (error === "") {
172
+ (0, import_quit.quit)("", 0);
173
+ return;
174
+ }
175
+ const eventId = Sentry.captureException(error);
176
+ const eventStr = `
177
+
178
+ Error ID: ${import_output.default.info(eventId)}`;
179
+ return (0, import_quit.quit)(
180
+ import_output.default.errorText(
181
+ "Something went wrong. Please contact support or try again later."
182
+ ) + eventStr
183
+ );
141
184
  }
142
185
  });
143
186
  var token_default = { needsToken, collectAndSaveToken };
187
+ const _test = { verifyTokenUsingTokenCheck };
144
188
  // Annotate the CommonJS export names for ESM import in node:
145
189
  0 && (module.exports = {
190
+ _test,
146
191
  collectAndSaveToken,
147
192
  needsToken
148
193
  });
149
194
  //# sourceMappingURL=token.js.map
150
195
 
151
- //# debugId=8ea35454-3a68-5e02-b127-d1129433ec18
196
+ //# debugId=269cb038-6f18-5abe-8383-a29108298035
@@ -1 +1 @@
1
- {"version":3,"sources":["../../lib/init/token.ts"],"sourcesContent":["import fs from \"fs\";\n\nimport chalk from \"chalk\";\n\nimport { prompt } from \"enquirer\";\n\nimport { createApiClient } from \"../api\";\nimport consts from \"../consts\";\nimport output from \"../output\";\nimport config from \"../config\";\nimport { quit } from \"../utils/quit\";\n\nexport const needsToken = (configFile?: string, host = consts.API_HOST) => {\n if (config.getTokenFromEnv()) {\n return false;\n }\n\n const file = configFile || consts.CONFIG_FILE;\n if (!fs.existsSync(file)) return true;\n const configData = config.readGlobalConfigData(file);\n if (\n !configData[config.justTheHost(host)] ||\n configData[config.justTheHost(host)][0].token === \"\"\n )\n return true;\n return false;\n};\n\n// Returns true if valid, otherwise an error message.\nasync function checkToken(token: string): Promise<any> {\n const axios = createApiClient(token);\n const endpoint = \"/token-check\";\n\n let resOrError;\n try {\n resOrError = await axios.get(endpoint).catch((error: any) => {\n if (error.code === \"ENOTFOUND\") {\n return output.errorText(\n `Can't connect to API: ${output.url(error.hostname)}`\n );\n }\n if (error.response.status === 401 || error.response.status === 404) {\n return output.errorText(\n \"This API key isn't valid. Please try another.\"\n );\n }\n return output.warnText(\"We're having trouble reaching the Ditto API.\");\n });\n } catch (e: unknown) {\n output.errorText(e as any);\n output.errorText(\"Sorry! We're having trouble reaching the Ditto API.\");\n }\n\n if (typeof resOrError === \"string\") {\n return resOrError;\n }\n\n if (resOrError?.status === 200) {\n return true;\n }\n\n return output.errorText(\"This API key isn't valid. Please try another.\");\n}\n\nasync function collectToken(message: string | null) {\n const blue = output.info;\n const apiUrl = output.url(\"https://app.dittowords.com/account/user\");\n const breadcrumbs = `${blue(\"User\")}`;\n const tokenDescription =\n message ||\n `To get started, you'll need your Ditto API key. You can find this at: ${apiUrl} > ${breadcrumbs} under \"${chalk.bold(\n \"API Keys\"\n )}\".`;\n console.log(tokenDescription);\n\n const response = await prompt<{ token: string }>({\n type: \"input\",\n name: \"token\",\n message: \"What is your API key?\",\n validate: (token) => checkToken(token),\n });\n return response.token;\n}\n\n/**\n *\n * @param {string | null} message\n * @returns\n */\nexport const collectAndSaveToken = async (message: string | null = null) => {\n try {\n const token = await collectToken(message);\n console.log(\n `Thanks for authenticating. We'll save the key to: ${output.info(\n consts.CONFIG_FILE\n )}`\n );\n output.nl();\n\n config.saveToken(consts.CONFIG_FILE, consts.API_HOST, token);\n return token;\n } catch (error) {\n quit(\"API token was not saved\");\n }\n};\n\nexport default { needsToken, collectAndSaveToken };\n"],"names":["consts","config","fs","output","chalk"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAAe;AAEf,mBAAkB;AAElB,sBAAuB;AAEvB,iBAAgC;AAChC,oBAAmB;AACnB,oBAAmB;AACnB,oBAAmB;AACnB,kBAAqB;AAEd,MAAM,aAAa,CAAC,YAAqB,OAAO,cAAAA,QAAO,aAAa;AACzE,MAAI,cAAAC,QAAO,gBAAgB,GAAG;AAC5B,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,cAAc,cAAAD,QAAO;AAClC,MAAI,CAAC,UAAAE,QAAG,WAAW,IAAI;AAAG,WAAO;AACjC,QAAM,aAAa,cAAAD,QAAO,qBAAqB,IAAI;AACnD,MACE,CAAC,WAAW,cAAAA,QAAO,YAAY,IAAI,CAAC,KACpC,WAAW,cAAAA,QAAO,YAAY,IAAI,CAAC,EAAE,CAAC,EAAE,UAAU;AAElD,WAAO;AACT,SAAO;AACT;AAGA,SAAe,WAAW,OAA6B;AAAA;AACrD,UAAM,YAAQ,4BAAgB,KAAK;AACnC,UAAM,WAAW;AAEjB,QAAI;AACJ,QAAI;AACF,mBAAa,MAAM,MAAM,IAAI,QAAQ,EAAE,MAAM,CAAC,UAAe;AAC3D,YAAI,MAAM,SAAS,aAAa;AAC9B,iBAAO,cAAAE,QAAO;AAAA,YACZ,yBAAyB,cAAAA,QAAO,IAAI,MAAM,QAAQ,CAAC;AAAA,UACrD;AAAA,QACF;AACA,YAAI,MAAM,SAAS,WAAW,OAAO,MAAM,SAAS,WAAW,KAAK;AAClE,iBAAO,cAAAA,QAAO;AAAA,YACZ;AAAA,UACF;AAAA,QACF;AACA,eAAO,cAAAA,QAAO,SAAS,8CAA8C;AAAA,MACvE,CAAC;AAAA,IACH,SAAS,GAAY;AACnB,oBAAAA,QAAO,UAAU,CAAQ;AACzB,oBAAAA,QAAO,UAAU,qDAAqD;AAAA,IACxE;AAEA,QAAI,OAAO,eAAe,UAAU;AAClC,aAAO;AAAA,IACT;AAEA,SAAI,yCAAY,YAAW,KAAK;AAC9B,aAAO;AAAA,IACT;AAEA,WAAO,cAAAA,QAAO,UAAU,+CAA+C;AAAA,EACzE;AAAA;AAEA,SAAe,aAAa,SAAwB;AAAA;AAClD,UAAM,OAAO,cAAAA,QAAO;AACpB,UAAM,SAAS,cAAAA,QAAO,IAAI,yCAAyC;AACnE,UAAM,cAAc,GAAG,KAAK,MAAM,CAAC;AACnC,UAAM,mBACJ,WACA,yEAAyE,MAAM,MAAM,WAAW,WAAW,aAAAC,QAAM;AAAA,MAC/G;AAAA,IACF,CAAC;AACH,YAAQ,IAAI,gBAAgB;AAE5B,UAAM,WAAW,UAAM,wBAA0B;AAAA,MAC/C,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,UAAU,CAAC,UAAU,WAAW,KAAK;AAAA,IACvC,CAAC;AACD,WAAO,SAAS;AAAA,EAClB;AAAA;AAOO,MAAM,sBAAsB,CAAO,UAAyB,SAAS;AAC1E,MAAI;AACF,UAAM,QAAQ,MAAM,aAAa,OAAO;AACxC,YAAQ;AAAA,MACN,sDAAsD,cAAAD,QAAO;AAAA,QAC3D,cAAAH,QAAO;AAAA,MACT,CAAC;AAAA,IACH;AACA,kBAAAG,QAAO,GAAG;AAEV,kBAAAF,QAAO,UAAU,cAAAD,QAAO,aAAa,cAAAA,QAAO,UAAU,KAAK;AAC3D,WAAO;AAAA,EACT,SAAS,OAAO;AACd,0BAAK,yBAAyB;AAAA,EAChC;AACF;AAEA,IAAO,gBAAQ,EAAE,YAAY,oBAAoB","debug_id":"8ea35454-3a68-5e02-b127-d1129433ec18"}
1
+ {"version":3,"sources":["../../lib/init/token.ts"],"sourcesContent":["import fs from \"fs\";\nimport * as Sentry from \"@sentry/node\";\n\nimport chalk from \"chalk\";\n\nimport { prompt } from \"enquirer\";\n\nimport { createApiClient } from \"../api\";\nimport consts from \"../consts\";\nimport output from \"../output\";\nimport config from \"../config\";\nimport { quit } from \"../utils/quit\";\nimport { AxiosError, AxiosResponse } from \"axios\";\n\nexport const needsToken = (configFile?: string, host = consts.API_HOST) => {\n if (config.getTokenFromEnv()) {\n return false;\n }\n\n const file = configFile || consts.CONFIG_FILE;\n if (!fs.existsSync(file)) return true;\n const configData = config.readGlobalConfigData(file);\n if (\n !configData[config.justTheHost(host)] ||\n configData[config.justTheHost(host)][0].token === \"\"\n )\n return true;\n return false;\n};\n\nasync function verifyTokenUsingTokenCheck(\n token: string\n): Promise<{ success: true } | { success: false; output: string[] }> {\n const axios = createApiClient(token);\n const endpoint = \"/token-check\";\n\n let resOrError: AxiosResponse<any> | undefined;\n try {\n resOrError = await axios.get(endpoint);\n } catch (e: unknown) {\n if (!(e instanceof AxiosError)) {\n return {\n success: false,\n output: [\n output.warnText(\n \"Sorry! We're having trouble reaching the Ditto API.\"\n ),\n ],\n };\n }\n\n if (e.code === \"ENOTFOUND\") {\n return {\n success: false,\n output: [\n output.errorText(\n `Can't connect to API: ${output.url(consts.API_HOST)}`\n ),\n ],\n };\n }\n\n if (e.response?.status === 401 || e.response?.status === 404) {\n return {\n success: false,\n output: [\n output.errorText(\"This API key isn't valid. Please try another.\"),\n ],\n };\n }\n }\n\n if (typeof resOrError === \"string\") {\n return {\n success: false,\n output: [resOrError],\n };\n }\n\n if (resOrError?.status === 200) {\n return { success: true };\n }\n\n return {\n success: false,\n output: [output.errorText(\"This API key isn't valid. Please try another.\")],\n };\n}\n\n// Returns true if valid, otherwise an error message.\nasync function checkToken(token: string): Promise<any> {\n const result = await verifyTokenUsingTokenCheck(token);\n if (!result.success) {\n return result.output.join(\"\\n\");\n }\n\n return true;\n}\n\nasync function collectToken(message: string | null) {\n const blue = output.info;\n const apiUrl = output.url(\"https://app.dittowords.com/account/devtools\");\n const breadcrumbs = `${chalk.bold(blue(\"API Keys\"))}`;\n const tokenDescription =\n message ||\n `To get started, you'll need your Ditto API key. You can find this at: ${apiUrl} under \"${breadcrumbs}\".`;\n console.log(tokenDescription);\n\n const response = await prompt<{ token: string }>({\n type: \"input\",\n name: \"token\",\n message: \"What is your API key?\",\n validate: (token) => checkToken(token),\n });\n return response.token;\n}\n\n/**\n *\n * @param {string | null} message\n * @returns\n */\nexport const collectAndSaveToken = async (message: string | null = null) => {\n try {\n const token = await collectToken(message);\n console.log(\n `Thanks for authenticating. We'll save the key to: ${output.info(\n consts.CONFIG_FILE\n )}`\n );\n output.nl();\n\n config.saveToken(consts.CONFIG_FILE, consts.API_HOST, token);\n return token;\n } catch (error) {\n // https://github.com/enquirer/enquirer/issues/225#issue-516043136\n // Empty string corresponds to the user hitting Ctrl + C\n if (error === \"\") {\n quit(\"\", 0);\n return;\n }\n\n const eventId = Sentry.captureException(error);\n const eventStr = `\\n\\nError ID: ${output.info(eventId)}`;\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 { needsToken, collectAndSaveToken };\n\nexport const _test = { verifyTokenUsingTokenCheck };\n"],"names":["consts","config","fs","output","chalk"],"mappings":"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","debug_id":"269cb038-6f18-5abe-8383-a29108298035"}
@@ -1,12 +1,26 @@
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]="e92edc0a-e477-5f6e-9ea3-7caaa5dbec80")}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]="1ef8b4a1-dcf4-58eb-9243-783ea548d73c")}catch(e){}}();
3
3
 
4
4
  var __create = Object.create;
5
5
  var __defProp = Object.defineProperty;
6
6
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
7
  var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
8
9
  var __getProtoOf = Object.getPrototypeOf;
9
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
+ };
10
24
  var __copyProps = (to, from, except, desc) => {
11
25
  if (from && typeof from === "object" || typeof from === "function") {
12
26
  for (let key of __getOwnPropNames(from))
@@ -23,20 +37,66 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
37
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
24
38
  mod
25
39
  ));
26
- var import_tempy = __toESM(require("tempy"));
40
+ var __async = (__this, __arguments, generator) => {
41
+ return new Promise((resolve, reject) => {
42
+ var fulfilled = (value) => {
43
+ try {
44
+ step(generator.next(value));
45
+ } catch (e) {
46
+ reject(e);
47
+ }
48
+ };
49
+ var rejected = (value) => {
50
+ try {
51
+ step(generator.throw(value));
52
+ } catch (e) {
53
+ reject(e);
54
+ }
55
+ };
56
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
57
+ step((generator = generator.apply(__this, __arguments)).next());
58
+ });
59
+ };
60
+ var import_fs = __toESM(require("fs"));
27
61
  var import_config = __toESM(require("../config"));
62
+ var import_crypto = require("crypto");
28
63
  var import_token = require("./token");
29
- describe("needsToken()", () => {
64
+ var import_token2 = require("./token");
65
+ var import_memfs = require("memfs");
66
+ var import_globals = require("@jest/globals");
67
+ var import_axios = __toESM(require("axios"));
68
+ import_globals.jest.mock("fs");
69
+ import_globals.jest.mock("../api");
70
+ const axiosMocked = import_globals.jest.mocked(import_axios.default);
71
+ const defaultEnv = __spreadValues({}, process.env);
72
+ beforeEach(() => {
73
+ import_memfs.vol.reset();
74
+ process.env = __spreadValues({}, defaultEnv);
75
+ });
76
+ describe("needsToken", () => {
30
77
  it("is true if there is no config file", () => {
31
- expect((0, import_token.needsToken)(import_tempy.default.file())).toBeTruthy();
78
+ expect((0, import_token.needsToken)((0, import_crypto.randomUUID)())).toBeTruthy();
79
+ });
80
+ it("is false if there is a token in the environment", () => {
81
+ process.env.DITTO_API_KEY = "xxx-xxx-xxx";
82
+ expect((0, import_token.needsToken)((0, import_crypto.randomUUID)())).toBe(false);
32
83
  });
33
84
  describe("with a config file", () => {
34
85
  let configFile = "";
35
- beforeEach(() => {
36
- configFile = import_tempy.default.writeSync("");
37
- });
86
+ beforeEach(() => __async(exports, null, function* () {
87
+ configFile = `/${(0, import_crypto.randomUUID)()}`;
88
+ yield new Promise(
89
+ (resolve, reject) => import_fs.default.writeFile(configFile, "", (err) => {
90
+ if (err)
91
+ reject(err);
92
+ else {
93
+ resolve(null);
94
+ }
95
+ })
96
+ );
97
+ }));
38
98
  it("returns true if empty", () => {
39
- expect((0, import_token.needsToken)(configFile, "testing.dittowrods.com")).toBeTruthy();
99
+ expect((0, import_token.needsToken)(configFile, "testing.dittowords.com")).toBeTruthy();
40
100
  });
41
101
  describe("with some data", () => {
42
102
  beforeEach(() => {
@@ -64,6 +124,24 @@ describe("needsToken()", () => {
64
124
  });
65
125
  });
66
126
  });
127
+ const { verifyTokenUsingTokenCheck } = import_token2._test;
128
+ describe("verifyTokenUsingTokenCheck", () => {
129
+ it("returns success: true for api success response", () => __async(exports, null, function* () {
130
+ axiosMocked.get.mockResolvedValueOnce({ status: 200 });
131
+ const result = yield verifyTokenUsingTokenCheck("xxx-xxx");
132
+ expect(result.success).toBe(true);
133
+ }));
134
+ it("returns success: false for api unauthorized response", () => __async(exports, null, function* () {
135
+ axiosMocked.get.mockResolvedValueOnce({ status: 401 });
136
+ const result = yield verifyTokenUsingTokenCheck("xxx-xxx");
137
+ expect(result.success).toBe(false);
138
+ }));
139
+ it("returns success: false for api invalid response", () => __async(exports, null, function* () {
140
+ axiosMocked.get.mockResolvedValueOnce("error");
141
+ const result = yield verifyTokenUsingTokenCheck("xxx-xxx");
142
+ expect(result.success).toBe(false);
143
+ }));
144
+ });
67
145
  //# sourceMappingURL=token.test.js.map
68
146
 
69
- //# debugId=e92edc0a-e477-5f6e-9ea3-7caaa5dbec80
147
+ //# debugId=1ef8b4a1-dcf4-58eb-9243-783ea548d73c
@@ -1 +1 @@
1
- {"version":3,"sources":["../../lib/init/token.test.ts"],"sourcesContent":["import tempy from \"tempy\";\n\nimport config from \"../config\";\nimport { needsToken } from \"./token\";\n\ndescribe(\"needsToken()\", () => {\n it(\"is true if there is no config file\", () => {\n expect(needsToken(tempy.file())).toBeTruthy();\n });\n\n describe(\"with a config file\", () => {\n let configFile = \"\";\n\n beforeEach(() => {\n configFile = tempy.writeSync(\"\");\n });\n\n it(\"returns true if empty\", () => {\n expect(needsToken(configFile, \"testing.dittowrods.com\")).toBeTruthy();\n });\n\n describe(\"with some data\", () => {\n beforeEach(() => {\n config.saveToken(configFile, \"badtesting.dittowords.com\", \"faketoken\");\n });\n\n it(\"is true if there is no entries for our API host\", () => {\n expect(needsToken(configFile, \"testing.dittowords.com\")).toBeTruthy();\n });\n\n it(\"is false if we have a token listed\", () => {\n config.saveToken(configFile, \"testing.dittowords.com\", \"faketoken\");\n expect(needsToken(configFile, \"testing.dittowords.com\")).toBeFalsy();\n });\n });\n\n it(\"is true if there is no token listed\", () => {\n const configNoToken = \"../../testing/fixtures/ditto-config-no-token\";\n expect(needsToken(configNoToken, \"testing.dittowords.com\")).toBeTruthy();\n });\n\n it(\"is strips the protocol when writing an entry\", () => {\n config.saveToken(\n configFile,\n \"https://testing.dittowords.com\",\n \"faketoken\"\n );\n expect(needsToken(configFile, \"testing.dittowords.com\")).toBeFalsy();\n });\n });\n});\n"],"names":["tempy","config"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,mBAAkB;AAElB,oBAAmB;AACnB,mBAA2B;AAE3B,SAAS,gBAAgB,MAAM;AAC7B,KAAG,sCAAsC,MAAM;AAC7C,eAAO,yBAAW,aAAAA,QAAM,KAAK,CAAC,CAAC,EAAE,WAAW;AAAA,EAC9C,CAAC;AAED,WAAS,sBAAsB,MAAM;AACnC,QAAI,aAAa;AAEjB,eAAW,MAAM;AACf,mBAAa,aAAAA,QAAM,UAAU,EAAE;AAAA,IACjC,CAAC;AAED,OAAG,yBAAyB,MAAM;AAChC,iBAAO,yBAAW,YAAY,wBAAwB,CAAC,EAAE,WAAW;AAAA,IACtE,CAAC;AAED,aAAS,kBAAkB,MAAM;AAC/B,iBAAW,MAAM;AACf,sBAAAC,QAAO,UAAU,YAAY,6BAA6B,WAAW;AAAA,MACvE,CAAC;AAED,SAAG,mDAAmD,MAAM;AAC1D,mBAAO,yBAAW,YAAY,wBAAwB,CAAC,EAAE,WAAW;AAAA,MACtE,CAAC;AAED,SAAG,sCAAsC,MAAM;AAC7C,sBAAAA,QAAO,UAAU,YAAY,0BAA0B,WAAW;AAClE,mBAAO,yBAAW,YAAY,wBAAwB,CAAC,EAAE,UAAU;AAAA,MACrE,CAAC;AAAA,IACH,CAAC;AAED,OAAG,uCAAuC,MAAM;AAC9C,YAAM,gBAAgB;AACtB,iBAAO,yBAAW,eAAe,wBAAwB,CAAC,EAAE,WAAW;AAAA,IACzE,CAAC;AAED,OAAG,gDAAgD,MAAM;AACvD,oBAAAA,QAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,iBAAO,yBAAW,YAAY,wBAAwB,CAAC,EAAE,UAAU;AAAA,IACrE,CAAC;AAAA,EACH,CAAC;AACH,CAAC","debug_id":"e92edc0a-e477-5f6e-9ea3-7caaa5dbec80"}
1
+ {"version":3,"sources":["../../lib/init/token.test.ts"],"sourcesContent":["import fs from \"fs\";\nimport config from \"../config\";\nimport { randomUUID } from \"crypto\";\nimport { needsToken } from \"./token\";\nimport { _test } from \"./token\";\nimport { vol } from \"memfs\";\nimport { jest } from \"@jest/globals\";\nimport axios from \"axios\";\n\njest.mock(\"fs\");\njest.mock(\"../api\");\n\nconst axiosMocked = jest.mocked(axios);\n\nconst defaultEnv = { ...process.env };\n\nbeforeEach(() => {\n vol.reset();\n process.env = { ...defaultEnv };\n});\n\ndescribe(\"needsToken\", () => {\n it(\"is true if there is no config file\", () => {\n expect(needsToken(randomUUID())).toBeTruthy();\n });\n\n it(\"is false if there is a token in the environment\", () => {\n process.env.DITTO_API_KEY = \"xxx-xxx-xxx\";\n expect(needsToken(randomUUID())).toBe(false);\n });\n\n describe(\"with a config file\", () => {\n let configFile = \"\";\n\n beforeEach(async () => {\n configFile = `/${randomUUID()}`;\n await new Promise((resolve, reject) =>\n fs.writeFile(configFile, \"\", (err) => {\n if (err) reject(err);\n else {\n resolve(null);\n }\n })\n );\n });\n\n it(\"returns true if empty\", () => {\n expect(needsToken(configFile, \"testing.dittowords.com\")).toBeTruthy();\n });\n\n describe(\"with some data\", () => {\n beforeEach(() => {\n config.saveToken(configFile, \"badtesting.dittowords.com\", \"faketoken\");\n });\n\n it(\"is true if there is no entries for our API host\", () => {\n expect(needsToken(configFile, \"testing.dittowords.com\")).toBeTruthy();\n });\n\n it(\"is false if we have a token listed\", () => {\n config.saveToken(configFile, \"testing.dittowords.com\", \"faketoken\");\n expect(needsToken(configFile, \"testing.dittowords.com\")).toBeFalsy();\n });\n });\n\n it(\"is true if there is no token listed\", () => {\n const configNoToken = \"../../testing/fixtures/ditto-config-no-token\";\n expect(needsToken(configNoToken, \"testing.dittowords.com\")).toBeTruthy();\n });\n\n it(\"is strips the protocol when writing an entry\", () => {\n config.saveToken(\n configFile,\n \"https://testing.dittowords.com\",\n \"faketoken\"\n );\n expect(needsToken(configFile, \"testing.dittowords.com\")).toBeFalsy();\n });\n });\n});\n\nconst { verifyTokenUsingTokenCheck } = _test;\ndescribe(\"verifyTokenUsingTokenCheck\", () => {\n it(\"returns success: true for api success response\", async () => {\n axiosMocked.get.mockResolvedValueOnce({ status: 200 });\n const result = await verifyTokenUsingTokenCheck(\"xxx-xxx\");\n expect(result.success).toBe(true);\n });\n it(\"returns success: false for api unauthorized response\", async () => {\n axiosMocked.get.mockResolvedValueOnce({ status: 401 });\n const result = await verifyTokenUsingTokenCheck(\"xxx-xxx\");\n expect(result.success).toBe(false);\n });\n it(\"returns success: false for api invalid response\", async () => {\n axiosMocked.get.mockResolvedValueOnce(\"error\");\n const result = await verifyTokenUsingTokenCheck(\"xxx-xxx\");\n expect(result.success).toBe(false);\n });\n});\n"],"names":["import_token","axios","fs","config"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,gBAAe;AACf,oBAAmB;AACnB,oBAA2B;AAC3B,mBAA2B;AAC3B,IAAAA,gBAAsB;AACtB,mBAAoB;AACpB,qBAAqB;AACrB,mBAAkB;AAElB,oBAAK,KAAK,IAAI;AACd,oBAAK,KAAK,QAAQ;AAElB,MAAM,cAAc,oBAAK,OAAO,aAAAC,OAAK;AAErC,MAAM,aAAa,mBAAK,QAAQ;AAEhC,WAAW,MAAM;AACf,mBAAI,MAAM;AACV,UAAQ,MAAM,mBAAK;AACrB,CAAC;AAED,SAAS,cAAc,MAAM;AAC3B,KAAG,sCAAsC,MAAM;AAC7C,eAAO,6BAAW,0BAAW,CAAC,CAAC,EAAE,WAAW;AAAA,EAC9C,CAAC;AAED,KAAG,mDAAmD,MAAM;AAC1D,YAAQ,IAAI,gBAAgB;AAC5B,eAAO,6BAAW,0BAAW,CAAC,CAAC,EAAE,KAAK,KAAK;AAAA,EAC7C,CAAC;AAED,WAAS,sBAAsB,MAAM;AACnC,QAAI,aAAa;AAEjB,eAAW,MAAY;AACrB,mBAAa,QAAI,0BAAW,CAAC;AAC7B,YAAM,IAAI;AAAA,QAAQ,CAAC,SAAS,WAC1B,UAAAC,QAAG,UAAU,YAAY,IAAI,CAAC,QAAQ;AACpC,cAAI;AAAK,mBAAO,GAAG;AAAA,eACd;AACH,oBAAQ,IAAI;AAAA,UACd;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF,EAAC;AAED,OAAG,yBAAyB,MAAM;AAChC,iBAAO,yBAAW,YAAY,wBAAwB,CAAC,EAAE,WAAW;AAAA,IACtE,CAAC;AAED,aAAS,kBAAkB,MAAM;AAC/B,iBAAW,MAAM;AACf,sBAAAC,QAAO,UAAU,YAAY,6BAA6B,WAAW;AAAA,MACvE,CAAC;AAED,SAAG,mDAAmD,MAAM;AAC1D,mBAAO,yBAAW,YAAY,wBAAwB,CAAC,EAAE,WAAW;AAAA,MACtE,CAAC;AAED,SAAG,sCAAsC,MAAM;AAC7C,sBAAAA,QAAO,UAAU,YAAY,0BAA0B,WAAW;AAClE,mBAAO,yBAAW,YAAY,wBAAwB,CAAC,EAAE,UAAU;AAAA,MACrE,CAAC;AAAA,IACH,CAAC;AAED,OAAG,uCAAuC,MAAM;AAC9C,YAAM,gBAAgB;AACtB,iBAAO,yBAAW,eAAe,wBAAwB,CAAC,EAAE,WAAW;AAAA,IACzE,CAAC;AAED,OAAG,gDAAgD,MAAM;AACvD,oBAAAA,QAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,iBAAO,yBAAW,YAAY,wBAAwB,CAAC,EAAE,UAAU;AAAA,IACrE,CAAC;AAAA,EACH,CAAC;AACH,CAAC;AAED,MAAM,EAAE,2BAA2B,IAAI;AACvC,SAAS,8BAA8B,MAAM;AAC3C,KAAG,kDAAkD,MAAY;AAC/D,gBAAY,IAAI,sBAAsB,EAAE,QAAQ,IAAI,CAAC;AACrD,UAAM,SAAS,MAAM,2BAA2B,SAAS;AACzD,WAAO,OAAO,OAAO,EAAE,KAAK,IAAI;AAAA,EAClC,EAAC;AACD,KAAG,wDAAwD,MAAY;AACrE,gBAAY,IAAI,sBAAsB,EAAE,QAAQ,IAAI,CAAC;AACrD,UAAM,SAAS,MAAM,2BAA2B,SAAS;AACzD,WAAO,OAAO,OAAO,EAAE,KAAK,KAAK;AAAA,EACnC,EAAC;AACD,KAAG,mDAAmD,MAAY;AAChE,gBAAY,IAAI,sBAAsB,OAAO;AAC7C,UAAM,SAAS,MAAM,2BAA2B,SAAS;AACzD,WAAO,OAAO,OAAO,EAAE,KAAK,KAAK;AAAA,EACnC,EAAC;AACH,CAAC","debug_id":"1ef8b4a1-dcf4-58eb-9243-783ea548d73c"}