@dittowords/cli 4.0.1-alpha.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +27 -371
  2. package/bin/api.js +3 -15
  3. package/bin/api.js.map +1 -1
  4. package/bin/config.js +5 -3
  5. package/bin/config.js.map +1 -1
  6. package/bin/ditto.js +0 -0
  7. package/bin/http/fetchComponentFolders.js +3 -3
  8. package/bin/http/fetchComponentFolders.js.map +1 -1
  9. package/bin/http/fetchComponents.js +13 -5
  10. package/bin/http/fetchComponents.js.map +1 -1
  11. package/bin/http/fetchVariants.js +3 -3
  12. package/bin/http/fetchVariants.js.map +1 -1
  13. package/bin/init/project.js +3 -3
  14. package/bin/init/project.js.map +1 -1
  15. package/bin/pull.js +82 -49
  16. package/bin/pull.js.map +1 -1
  17. package/bin/pull.test.js +26 -24
  18. package/bin/pull.test.js.map +1 -1
  19. package/bin/types.js +2 -2
  20. package/bin/types.js.map +1 -1
  21. package/bin/utils/determineModuleType.js +80 -0
  22. package/bin/utils/determineModuleType.js.map +1 -0
  23. package/bin/utils/generateIOSBundles.js +147 -0
  24. package/bin/utils/generateIOSBundles.js.map +1 -0
  25. package/bin/utils/generateJsDriver.js +117 -58
  26. package/bin/utils/generateJsDriver.js.map +1 -1
  27. package/bin/utils/generateJsDriverTypeFile.js +105 -0
  28. package/bin/utils/generateJsDriverTypeFile.js.map +1 -0
  29. package/bin/utils/generateSwiftDriver.js +93 -0
  30. package/bin/utils/generateSwiftDriver.js.map +1 -0
  31. package/lib/api.ts +1 -17
  32. package/lib/config.ts +4 -0
  33. package/lib/http/fetchComponentFolders.ts +1 -1
  34. package/lib/http/fetchComponents.ts +14 -9
  35. package/lib/http/fetchVariants.ts +1 -1
  36. package/lib/init/project.ts +1 -1
  37. package/lib/pull.test.ts +24 -22
  38. package/lib/pull.ts +127 -90
  39. package/lib/types.ts +4 -0
  40. package/lib/utils/determineModuleType.ts +57 -0
  41. package/lib/utils/generateIOSBundles.ts +122 -0
  42. package/lib/utils/generateJsDriver.ts +156 -51
  43. package/lib/utils/generateJsDriverTypeFile.ts +75 -0
  44. package/lib/utils/generateSwiftDriver.ts +48 -0
  45. package/package.json +1 -1
package/README.md CHANGED
@@ -1,411 +1,67 @@
1
1
  # Ditto CLI
2
2
 
3
- The Ditto CLI helps teams integrate [Ditto](https://dittowords.com/) into their development workflows and build processes.
3
+ The Ditto CLI enables developers to access the Ditto API directly from the command line.
4
4
 
5
- ## Getting Started
5
+ [![NPM version](https://badge.fury.io/js/@dittowords%2Fcli.svg)](https://badge.fury.io/js/@dittowords%2Fcli)
6
6
 
7
- You can install the CLI from npm:
7
+ ## Documentation
8
8
 
9
- ```bash
10
- # as a dev dependency (**recommended**)
11
- npm install --save-dev @dittowords/cli
12
- ****
13
- # as a global package
14
- npm install --global @dittowords/cli
15
- ```
16
-
17
- The installed binary is named `ditto-cli`. You can execute it directly in `node_modules/.bin/ditto-cli` or using [npx](https://www.npmjs.com/package/npx) like `npx @dittowords/cli`.
18
-
19
- The first time you run the CLI, you'll be asked to provide an API key (found at [https://app.dittowords.com/account/user](https://app.dittowords.com/account/user) under **API Keys**):
9
+ The official documentation can be found [here](http://developer.dittowords.com/cli-reference/authentication).
20
10
 
21
- ```
22
- $ npx @dittowords/cli
23
-
24
- ┌──────────────────────────────────┐
25
- │ │
26
- │ Welcome to the Ditto CLI. │
27
- │ │
28
- │ We're glad to have you here. │
29
- │ │
30
- └──────────────────────────────────┘
11
+ ## Support
31
12
 
32
- What is your API key? > xxx-xxx-xxx
13
+ - [Bug Reports](https://github.com/dittowords/cli/issues/)
14
+ - [Support Chat](https://www.dittowords.com)
15
+ - [What is Ditto?](https://www.dittowords.com/docs/what-is-ditto)
33
16
 
34
- Thanks for authenticating.
35
- We'll save the key to: /Users/{username}/.config/ditto
36
- ```
17
+ ## Installation
37
18
 
38
- Once you've successfully authenticated, you'll be asked to choose a source (a project or your component library) to pull data from:
39
-
40
- ```
41
- Looks like there are no Ditto sources selected for your current directory: /Users/ditto
42
- ****
43
- ? Choose the source you'd like to sync text from:
44
- - Ditto Component Library https://app.dittowords.com/components
45
- - NUX Onboarding Flow https://app.dittowords.com/doc/609e9981c313f8018d0c346a
46
- ...
19
+ ```sh
20
+ npm install --save-dev @dittowords/cli
47
21
  ```
48
22
 
49
- After selecting a source, a configuration file will automatically be created at the path `./ditto/config.yml` relative to your current working directory. The CLI will attempt to read from this file every time a command is executed. See the [config.yml documentation](#files) for a full reference of how the CLI can be configured.
50
-
51
- Once you've successfully authenticated and a config file has been created, you’re ready to start fetching copy! If you need to use the CLI with multiple configurations, simply initialize it in multiple directories.
52
-
53
- ## API Keys
54
-
55
- The CLI will not prompt for an API key if a value is provided in the environment variable `DITTO_API_KEY`.
56
-
57
- If the `DITTO_API_KEY` environment variable is not set, the CLI will look for an API token in [your authentication file](#authentication). If this file does not exist or does not contain a valid API key, the CLI will prompt for one.
58
-
59
- We don't recommend editing the authentication file by hand; if you need to remove a saved API key or swap one key with another, it's better to fully delete the file and then re-run the CLI.
60
-
61
- ## Commands
62
-
63
- ### Pull
64
-
65
- **Usage:** `ditto-cli` (no commands), `ditto-cli pull`
66
-
67
- **Action:** Pulls data from Ditto according to configured sources.
23
+ It's recommended to install the CLI as a development dependency to ensure your whole team is on the same version.
68
24
 
69
- Generate files your local `ditto/` folder. File extension is determined by the `format` property specified in `config.yml`.
70
-
71
- If no format is specified, the `flat` format will be used by default. Each time text is pulled from Ditto, the existing files in the `ditto/` directory are removed before new files are created in their place.
72
-
73
- For more details on files generated by this command, see [Output Files](#output-files).
74
-
75
- ### Add project
76
-
77
- **Usage:** `ditto-cli project add`
78
-
79
- **Action:** Lists projects in your workspace that have developer mode enabled and permits selecting one to add to `config.yml` via an interactive prompt.
80
-
81
- ### Remove project
82
-
83
- **Usage:** `ditto-cli project remove`
84
-
85
- **Action:** Lists projects in `config.yml` and permits selecting one to remove from `config.yml` via an interactive prompt.
86
-
87
- ### Component folders
88
-
89
- **Usage:** `ditto-cli component-folders`
90
-
91
- **Action:** List component folders in your workspace.
92
-
93
- More information about component folders in Ditto can be found [here](https://www.dittowords.com/docs/component-folders).
94
-
95
- ### Import components
25
+ ## Authentication
96
26
 
97
- **Usage:** `ditto-cli import-components <file_path>`
27
+ The first time you run the CLI, you’ll be asked to provide an API key. You can generate an API key from your [developer integrations settings](https://app.dittowords.com/account/devtools).
98
28
 
99
- **Action:** Import components via a file. Please see https://www.dittowords.com/docs/importing-string-files for more information.
100
- When [importing CSV files](https://www.dittowords.com/docs/importing-csv-files), the follow parameters are applicable:
101
-
102
- ```
103
- -t, --text [value] Text column index (Required)
104
- -n, --component-name [value] Name column indexes (comma separated) (Required)
105
- -no, --notes [value] Notes column index
106
- -t, --tags [value] Tags column index
107
- -s, --status [value] Status column index
108
- -c, --component-id [value] Component ID column index
109
- -h, --help display help for command
110
- ```
29
+ See the [Authentication](http://developer.dittowords.com/api-reference/authentication) page for more information on API keys.
111
30
 
112
31
  ## Configuration
113
32
 
114
- The `config.yml` file is the source of truth for a given directory about how the CLI should fetch and store data from Ditto. It includes information about which Ditto projects the CLI should pull text from, whether or not the component library should be included, in what format(s) the text should be stored, and more.
33
+ By default, the CLI operates against a `ditto/` folder relative to the current working directory.
115
34
 
116
- This file is edited by the `project add` / `project remove` commands, but most options are currently only supported through manual edits.
35
+ The first time you run the CLI, a `ditto/` folder will be created if it doesn't already exist. The folder will also be populated with a default `config.yml` file, which is used to control the CLI's behavior.
117
36
 
118
- This is the default configuration file that is generated the first time that the CLI is run in a given directory:
119
-
120
- ```yml
121
- sources:
122
- components:
123
- enabled: true
124
- format: flat
125
- variants: true
126
- ```
127
-
128
- ### Supported Properties
129
-
130
- #### Sources
131
-
132
- A list of places the CLI should pull text data from. For the CLI to function, at least one source type (`projects` or `components`) is required.
133
-
134
- ##### `sources.projects`
135
-
136
- A list of projects to pull text from.
137
-
138
- ```yml
139
- sources:
140
- projects:
141
- - id: 61b8d26105f8f400e97fdd14
142
- name: Landing Page Copy
143
- - id: 606cb89ac55041013d552f8b
144
- name: User Settings
145
- ```
146
-
147
- The `name` property is used for display purposes when referencing a project in the CLI, but does not have to be an exact match with the project name in Ditto.
148
-
149
- An `exclude_components` property can be added on a per-project basis to indicate that text items should only be pulled which are not associated with a component:
150
-
151
- ```yml
152
- sources:
153
- projects:
154
- - id: 61b8d26105f8f400e97fdd14
155
- name: Landing Page Copy
156
- exclude_components: true
157
- ```
158
-
159
- ##### `sources.components`
160
-
161
- A boolean or configuration object indicating how component data should be pulled from your component library.
162
-
163
- The simplest configuration is a boolean, which indicates that all components in your component library should be fetched:
37
+ The default file looks like this:
164
38
 
165
39
  ```yml
166
40
  sources:
167
41
  components: true
168
- ```
169
-
170
- You can also pass an object that supports two complementary properties: `root` and `folders`.
171
-
172
- - `root` controls behavior for components that are NOT in folders (i.e. that are at the _root_ of the component library)
173
- - `folders` controls behavior for components that are ARE in folders
174
-
175
- If `root` is `true` and `folders` is unspecified, **only components not in folders** will be fetched:
176
-
177
- ```yml
178
- sources:
179
- components:
180
- root: true
181
- ```
182
-
183
- If `root` is `false` and `folders` is unspecified, **only components in any folder** will be fetched:
184
-
185
- ```yml
186
- sources:
187
- components:
188
- root: false
189
- ```
190
-
191
- If `root` is unspecified and `folders` contains a list of component folders, **only components in the specified folders** will be fetched:
192
-
193
- ```yml
194
- sources:
195
- components:
196
- folders:
197
- - id: folder-api-id-1
198
- name: Folder 1
199
- - id: folder-api-id-2
200
- name: Folder 2
201
- ```
202
-
203
- If `root` is `true` and `folders` contains a list of component folders, **non-folder components and components in the specified folders** will be fetched:
204
-
205
- ```yml
206
- sources:
207
- components:
208
- folders:
209
- - id: folder-api-id-1
210
- name: Folder 1
211
- - id: folder-api-id-2
212
- name: Folder 2
213
- ```
214
-
215
- `root` can also be specified as a configuration object with a `status` property to indicate that non-folder components should be fetched that have the indicated status:
216
-
217
- ```yml
218
- sources:
219
- components:
220
- root:
221
- status: WIP
222
- ```
223
-
224
- #### Variants
225
-
226
- Enables including variant information when pulling text data for configured sources.
227
-
228
- Defaults to `false` if not specified.
229
-
230
- ```yml
231
42
  variants: true
232
- ```
233
-
234
- #### Format
235
-
236
- The format that text data should be generated in. Accepted values:
237
-
238
- - `structured`
239
- - `flat`
240
- - `android`
241
- - `ios-strings`
242
- - `ios-stringsdict` (will only include text that has pluralization enabled in Ditto)
243
-
244
- Defaults to `flat` if not specified.
245
-
246
- ```yml
247
43
  format: flat
248
44
  ```
249
45
 
250
- Also accepts a list of values:
251
-
252
- ```yml
253
- format:
254
- - ios-strings
255
- - ios-stringsdict
256
- ```
257
-
258
- You should not specify multiple JSON formats in the same configuration, as they will overwrite one another when writing to disk.
259
-
260
- #### Status
261
-
262
- If specified, only source data with the indicated status will be fetched. Accepted values:
46
+ For more information on configuring the CLI, see [http://developer.dittowords.com/cli-reference/configuration](http://developer.dittowords.com/cli-reference/configuration).
263
47
 
264
- - `NONE`
265
- - `WIP`
266
- - `REVIEW`
267
- - `FINAL`
268
-
269
- If `status` is specified at the top level of the configuration, it will apply to all sources:
270
-
271
- ```yml
272
- status: FINAL
273
- sources:
274
- components: true
275
- projects:
276
- - id: project-1
277
- name: Project 1
278
- ```
279
-
280
- `status` can also be specified at the level of individual sources:
281
-
282
- ```yml
283
- sources:
284
- components:
285
- root:
286
- status: REVIEW
287
- folders:
288
- - id: folder-api-id-1
289
- name: Folder 1
290
- status: NONE
291
- projects:
292
- - id: project-1
293
- name: Project 1
294
- status: WIP
295
- ```
296
-
297
- If both are specified, a source-level `status` overrides a top-level `status`.
298
-
299
- More information about Ditto statuses can be found [here](https://www.dittowords.com/docs/tips-for-collaborating).
300
-
301
- #### Rich Text
302
-
303
- If defined with the `flat` format, output values will be HTML strings (rich text) for each piece of source data.
304
-
305
- If defined with the `structured` format, output data will include a `rich_text` property that is an HTML string (rich text) for each piece of source data.
306
-
307
- You can read more about Ditto's rich text feature [here](https://www.dittowords.com/docs/rich-text).
308
-
309
- ```yml
310
- richText: true
311
- ```
312
-
313
- ### Full Configuration Example
314
-
315
- ```yml
316
- sources:
317
- components:
318
- root: true
319
- folders:
320
- - id: 61b8d26105f8f400e97fdd14
321
- name: Onboarding
322
- - id: 61b8d26105f8f400e97fdd15
323
- name: Onboarding 2
324
- status: WIP
325
- projects:
326
- - name: Landing Page Copy
327
- id: 61b8d26105f8f400e97fdd14
328
- - name: User Settings
329
- id: 606cb89ac55041013d552f8b
330
- status: WIP
331
- variants: true
332
- format: structured
333
- status: FINAL
334
- richText: false
335
- ```
336
-
337
- ## CLI Files
338
-
339
- ### `ditto/` Directory
340
-
341
- This directory houses the configuration file (`ditto/config.yml`) used by the CLI and is also the default write destination for any output files the CLI writes to disk.
342
-
343
- If you run the CLI in a directory that does not contain a `ditto/` folder, the folder and a default `config.yml` file will be automatically created.
344
-
345
- #### Output Files
346
-
347
- The CLI outputs data from Ditto by writing files to disk. By default, these files are written to a `./ditto` folder relative to the current working directory, but the location of the output files can be customized by setting the environment variable `DITTO_TEXT_DIR`.
48
+ ## Usage
348
49
 
349
50
  ```bash
350
- export DITTO_TEXT_DIR=./src/some-custom-path
351
-
352
- # writes output files to ./src/some-custom-path
353
51
  npx @dittowords/cli
354
52
  ```
355
53
 
356
- The format and extension of such files will correspond to the `format` property of your configuration.
357
-
358
- | **Format** | **File Extension** | **Common Usage** |
359
- | :-------------: | :----------------: | :-----------------: |
360
- | flat | .json | Web apps |
361
- | structured | .json | Web apps |
362
- | icu | .json | Web apps |
363
- | android | .xml | Native Android apps |
364
- | ios-strings | .strings | Native iOS apps |
365
- | ios-stringsdict | .stringsdict | Native iOS apps |
366
-
367
- All files created will adhere to the following template:
368
-
369
- ```
370
- {source_name}__{variant_name}.{extension}
371
- ```
372
-
373
- - `source_name`: the name of the source a given file holds data for
374
- - for projects, this is `{project-name}`
375
- - for components, this is `components__{folder_name}`
376
- - `variant_name`: the API ID of a variant or `base` for files generated for non-variant text
377
- - `extension`: the file extension that corresponds to the configured format(s)
378
-
379
- To keep cross-platform behavior consistent, file names will be fully lowercase, have whitespace replaced with hyphens, and have non-word characters (with the exception of `-` and `_`) removed.
380
-
381
- If the configured format(s) result(s) in JSON files being generated, an `index.js` "driver file" is also created to simplify the process of integrating Ditto into web apps:
382
-
383
- ```js
384
- module.exports = {
385
- ditto_component_library: {
386
- base: require("./components__root__base.json"),
387
- spanish: require("./components__root__spanish.json"),
388
- },
389
- project_xxx: {
390
- base: require("./example-project__base.json"),
391
- spanish: require("./example-project__spanish.json"),
392
- },
393
- };
394
- ```
395
-
396
- The driver file is currently generated as a CommonJS module, but it's possible that ESM will be supported in the future.
397
-
398
- ## Authentication
399
-
400
- By default, your API key is saved to `$HOME/.config/ditto`; the default path can be overwritten by specifying a custom one via the environment variable `DITTO_CONFIG_FILE`.
54
+ Run the CLI to pull string data from Ditto and write it to disk.
401
55
 
402
- To change your API key, delete this file and you'll be prompted for a new key the next time that the CLI executes.
56
+ String files are written to the `ditto` folder in a format that corresponds to your configuration. After integrating these files into development, you can execute the CLI at any time to fetch the latest strings from Ditto and update them in your application.
403
57
 
404
- ## SDKs
58
+ For more information on how files written to disk, see [http://developer.dittowords.com/cli-reference/files](http://developer.dittowords.com/cli-reference/files).
405
59
 
406
- Our SDKs make it easy to integrate the copy pulled from the Ditto CLI into your applications.
60
+ See our demo projects for examples of how to integrate the Ditto CLI in different environments:
407
61
 
408
- - [Ditto React](https://www.npmjs.com/package/ditto-react) - easily integrate Ditto into your React project; includes support for localization using variants.
62
+ - [React web app](https://github.com/dittowords/ditto-react-demo)
63
+ - [iOS mobile app](https://github.com/dittowords/ditto-react-demo)
64
+ - [Android mobile app](https://github.com/dittowords/ditto-react-demo)
409
65
 
410
66
  ## Feedback
411
67
 
package/bin/api.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]="a5a0c25e-7b00-51b0-9bcc-d86d951d5190")}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]="60c0c8b2-1610-5e22-a814-c819798eb831")}catch(e){}}();
3
3
 
4
4
  var __create = Object.create;
5
5
  var __defProp = Object.defineProperty;
@@ -37,24 +37,12 @@ var import_axios = __toESM(require("axios"));
37
37
  var import_config = __toESM(require("./config"));
38
38
  var import_consts = __toESM(require("./consts"));
39
39
  function createApiClient(token) {
40
- const client = import_axios.default.create({
40
+ return import_axios.default.create({
41
41
  baseURL: import_consts.default.API_HOST,
42
42
  headers: {
43
43
  Authorization: `token ${token || import_config.default.getToken(import_consts.default.CONFIG_FILE, import_consts.default.API_HOST)}`
44
44
  }
45
45
  });
46
- if (process.env.DEBUG_CLI) {
47
- console.debug(`Host: ${import_consts.default.API_HOST}`);
48
- client.interceptors.request.use((request) => {
49
- console.debug("Starting Request", request.url);
50
- return request;
51
- });
52
- client.interceptors.response.use((response) => {
53
- console.debug("Response:", response);
54
- return response;
55
- });
56
- }
57
- return client;
58
46
  }
59
47
  // Annotate the CommonJS export names for ESM import in node:
60
48
  0 && (module.exports = {
@@ -62,4 +50,4 @@ function createApiClient(token) {
62
50
  });
63
51
  //# sourceMappingURL=api.js.map
64
52
 
65
- //# debugId=a5a0c25e-7b00-51b0-9bcc-d86d951d5190
53
+ //# debugId=60c0c8b2-1610-5e22-a814-c819798eb831
package/bin/api.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../lib/api.ts"],"sourcesContent":["import axios from \"axios\";\n\nimport config from \"./config\";\nimport consts from \"./consts\";\n\nexport function createApiClient(token?: string) {\n const client = axios.create({\n baseURL: consts.API_HOST,\n headers: {\n Authorization: `token ${\n token || config.getToken(consts.CONFIG_FILE, consts.API_HOST)\n }`,\n },\n });\n\n if (process.env.DEBUG_CLI) {\n console.debug(`Host: ${consts.API_HOST}`);\n\n client.interceptors.request.use((request) => {\n console.debug(\"Starting Request\", request.url);\n return request;\n });\n\n client.interceptors.response.use(response => {\n console.debug('Response:', response);\n return response;\n });\n }\n\n return client;\n}\n"],"names":["axios","consts","config"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAkB;AAElB,oBAAmB;AACnB,oBAAmB;AAEZ,SAAS,gBAAgB,OAAgB;AAC9C,QAAM,SAAS,aAAAA,QAAM,OAAO;AAAA,IAC1B,SAAS,cAAAC,QAAO;AAAA,IAChB,SAAS;AAAA,MACP,eAAe,SACb,SAAS,cAAAC,QAAO,SAAS,cAAAD,QAAO,aAAa,cAAAA,QAAO,QAAQ,CAC9D;AAAA,IACF;AAAA,EACF,CAAC;AAED,MAAI,QAAQ,IAAI,WAAW;AACzB,YAAQ,MAAM,SAAS,cAAAA,QAAO,QAAQ,EAAE;AAExC,WAAO,aAAa,QAAQ,IAAI,CAAC,YAAY;AAC3C,cAAQ,MAAM,oBAAoB,QAAQ,GAAG;AAC7C,aAAO;AAAA,IACT,CAAC;AAED,WAAO,aAAa,SAAS,IAAI,cAAY;AAC3C,cAAQ,MAAM,aAAa,QAAQ;AACnC,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,SAAO;AACT","debug_id":"a5a0c25e-7b00-51b0-9bcc-d86d951d5190"}
1
+ {"version":3,"sources":["../lib/api.ts"],"sourcesContent":["import axios from \"axios\";\n\nimport config from \"./config\";\nimport consts from \"./consts\";\n\nexport function createApiClient(token?: string) {\n return axios.create({\n baseURL: consts.API_HOST,\n headers: {\n Authorization: `token ${\n token || config.getToken(consts.CONFIG_FILE, consts.API_HOST)\n }`,\n },\n });\n}\n"],"names":["axios","consts","config"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAkB;AAElB,oBAAmB;AACnB,oBAAmB;AAEZ,SAAS,gBAAgB,OAAgB;AAC9C,SAAO,aAAAA,QAAM,OAAO;AAAA,IAClB,SAAS,cAAAC,QAAO;AAAA,IAChB,SAAS;AAAA,MACP,eAAe,SACb,SAAS,cAAAC,QAAO,SAAS,cAAAD,QAAO,aAAa,cAAAA,QAAO,QAAQ,CAC9D;AAAA,IACF;AAAA,EACF,CAAC;AACH","debug_id":"60c0c8b2-1610-5e22-a814-c819798eb831"}
package/bin/config.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]="3f451b9b-6016-532a-b399-58b8b273e73c")}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]="907226eb-d4b7-553b-a3ea-7aa63bccb645")}catch(e){}}();
3
3
 
4
4
  var __create = Object.create;
5
5
  var __defProp = Object.defineProperty;
@@ -174,6 +174,7 @@ function parseSourceInformation(file) {
174
174
  format,
175
175
  status,
176
176
  richText,
177
+ iosLocales,
177
178
  projects: projectsRoot,
178
179
  components: componentsRoot
179
180
  } = readProjectConfigData(file);
@@ -210,7 +211,8 @@ function parseSourceInformation(file) {
210
211
  hasTopLevelComponentsField: !!componentsRoot,
211
212
  hasComponentLibraryInProjects,
212
213
  componentRoot,
213
- componentFolders
214
+ componentFolders,
215
+ localeByVariantApiId: iosLocales ? iosLocales.reduce((acc, e) => __spreadValues(__spreadValues({}, acc), e), {}) : void 0
214
216
  };
215
217
  Sentry.setContext("config", (0, import_createSentryContext.createSentryContext)(result));
216
218
  return result;
@@ -235,4 +237,4 @@ var config_default = {
235
237
  });
236
238
  //# sourceMappingURL=config.js.map
237
239
 
238
- //# debugId=3f451b9b-6016-532a-b399-58b8b273e73c
240
+ //# debugId=907226eb-d4b7-553b-a3ea-7aa63bccb645
package/bin/config.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../lib/config.ts"],"sourcesContent":["import fs from \"fs\";\nimport path from \"path\";\nimport url from \"url\";\nimport yaml from \"js-yaml\";\nimport * as Sentry from \"@sentry/node\";\n\nimport consts from \"./consts\";\nimport { createSentryContext } from \"./utils/createSentryContext\";\nimport { Project, ConfigYAML, SourceInformation } from \"./types\";\n\nexport const DEFAULT_CONFIG_JSON: ConfigYAML = {\n sources: {\n components: true,\n },\n variants: true,\n format: \"flat\",\n};\n\nexport const DEFAULT_CONFIG = yaml.dump(DEFAULT_CONFIG_JSON);\n\nfunction createFileIfMissing(filename: string, defaultContents?: any) {\n const dir = path.dirname(filename);\n\n // create the directory if it doesn't already exist\n if (!fs.existsSync(dir)) fs.mkdirSync(dir);\n\n // create the file if it doesn't already exist\n if (!fs.existsSync(filename)) {\n // create the file, writing the `defaultContents` if provided\n fs.writeFileSync(filename, defaultContents || \"\", \"utf-8\");\n }\n}\n\nfunction jsonIsConfigYAML(json: unknown): json is ConfigYAML {\n return typeof json === \"object\";\n}\n\nfunction jsonIsGlobalYAML(\n json: unknown\n): json is Record<string, { token: string }[]> {\n return (\n !!json &&\n typeof json === \"object\" &&\n Object.values(json).every(\n (arr) =>\n (arr as any).every &&\n arr.every(\n (val: any) =>\n typeof val === \"object\" && Object.keys(val).includes(\"token\")\n )\n )\n );\n}\n\n/**\n * Read data from a project config file\n * @param {string} file defaults to `PROJECT_CONFIG_FILE` defined in `constants.js`\n * @param {*} defaultData defaults to `{}`\n * @returns { ConfigYAML }\n */\nfunction readProjectConfigData(\n file = consts.PROJECT_CONFIG_FILE,\n defaultData = {}\n): ConfigYAML {\n createFileIfMissing(file, DEFAULT_CONFIG);\n const fileContents = fs.readFileSync(file, \"utf8\");\n const yamlData = yaml.load(fileContents);\n if (jsonIsConfigYAML(yamlData)) {\n return yamlData;\n }\n return defaultData;\n}\n\n/**\n * Read data from a global config file\n * @param {string} file defaults to `CONFIG_FILE` defined in `constants.js`\n * @param {*} defaultData defaults to `{}`\n * @returns { Record<string, { token: string }[]> }\n */\nfunction readGlobalConfigData(\n file = consts.CONFIG_FILE,\n defaultData = {}\n): Record<string, { token: string }[]> {\n createFileIfMissing(file);\n const fileContents = fs.readFileSync(file, \"utf8\");\n const yamlData = yaml.load(fileContents);\n if (jsonIsGlobalYAML(yamlData)) {\n return yamlData;\n }\n return defaultData;\n}\n\nfunction writeProjectConfigData(file: string, data: Partial<ConfigYAML>) {\n createFileIfMissing(file, DEFAULT_CONFIG);\n const existingData = readProjectConfigData(file);\n\n const configData: ConfigYAML = {\n ...existingData,\n ...data,\n sources: {\n ...existingData.sources,\n ...data.sources,\n },\n };\n\n const yamlStr = yaml.dump(configData);\n fs.writeFileSync(file, yamlStr, \"utf8\");\n}\n\nfunction writeGlobalConfigData(file: string, data: object) {\n createFileIfMissing(file);\n const existingData = readGlobalConfigData(file);\n const yamlStr = yaml.dump({ ...existingData, ...data });\n fs.writeFileSync(file, yamlStr, \"utf8\");\n}\n\nfunction justTheHost(host: string) {\n if (!host.includes(\"://\")) return host;\n return url.parse(host).hostname || \"\";\n}\n\nfunction deleteToken(file: string, host: string) {\n const data = readGlobalConfigData(file);\n const hostParsed = justTheHost(host);\n data[hostParsed] = [];\n data[hostParsed][0] = { token: \"\" };\n writeGlobalConfigData(file, data);\n}\n\nfunction saveToken(file: string, host: string, token: string) {\n const data = readGlobalConfigData(file);\n const hostParsed = justTheHost(host);\n data[hostParsed] = []; // only allow one token per host\n data[hostParsed][0] = { token };\n writeGlobalConfigData(file, data);\n}\n\nfunction getTokenFromEnv() {\n return process.env.DITTO_API_KEY;\n}\n\n/**\n *\n * @param {string} file\n * @param {string} host\n * @returns {Token}\n */\nfunction getToken(file: string, host: string) {\n const tokenFromEnv = getTokenFromEnv();\n if (tokenFromEnv) {\n return tokenFromEnv;\n }\n\n const data = readGlobalConfigData(file);\n const hostEntry = data[justTheHost(host)];\n if (!hostEntry) return undefined;\n const { length } = hostEntry;\n\n return hostEntry[length - 1].token;\n}\n\nconst IS_DUPLICATE = /-(\\d+$)/;\n\nfunction dedupeProjectName(projectNames: Set<string>, projectName: string) {\n let dedupedName = projectName;\n\n if (projectNames.has(dedupedName)) {\n while (projectNames.has(dedupedName)) {\n const [_, numberStr] = dedupedName.match(IS_DUPLICATE) || [];\n if (numberStr && !isNaN(parseInt(numberStr))) {\n dedupedName = `${dedupedName.replace(IS_DUPLICATE, \"\")}-${\n parseInt(numberStr) + 1\n }`;\n } else {\n dedupedName = `${dedupedName}-1`;\n }\n }\n }\n\n return dedupedName;\n}\n\n/**\n * Reads from the config file, filters out\n * invalid projects, dedupes those remaining, and returns:\n * - whether or not the data required to `pull` is present\n * - whether or not the component library should be fetched\n * - an array of valid, deduped projects\n * - the `variants` and `format` config options\n */\nfunction parseSourceInformation(file?: string): SourceInformation {\n const {\n sources,\n variants,\n format,\n status,\n richText,\n projects: projectsRoot,\n components: componentsRoot,\n } = readProjectConfigData(file);\n\n const projects = sources?.projects || [];\n\n const projectNames = new Set<string>();\n const validProjects: Project[] = [];\n let hasComponentLibraryInProjects = false;\n\n (projects || []).forEach((project) => {\n const isValid = project.id && project.name;\n if (!isValid) {\n return;\n }\n\n if (project.id === \"ditto_component_library\") {\n hasComponentLibraryInProjects = true;\n return;\n }\n\n project.fileName = dedupeProjectName(projectNames, project.name);\n projectNames.add(project.fileName);\n\n validProjects.push(project);\n });\n\n const shouldFetchComponentLibrary = Boolean(sources?.components);\n const componentRoot =\n typeof sources?.components === \"object\"\n ? sources.components.root\n : undefined;\n const componentFolders =\n typeof sources?.components === \"object\"\n ? sources.components.folders\n : undefined;\n\n /**\n * If it's not specified to fetch projects or the component library, then there\n * is no source data to pull.\n */\n const hasSourceData = !!validProjects.length || shouldFetchComponentLibrary;\n\n const result = {\n hasSourceData,\n validProjects,\n shouldFetchComponentLibrary,\n variants: variants || false,\n format,\n status,\n richText,\n hasTopLevelProjectsField: !!projectsRoot,\n hasTopLevelComponentsField: !!componentsRoot,\n hasComponentLibraryInProjects,\n componentRoot,\n componentFolders,\n };\n\n Sentry.setContext(\"config\", createSentryContext(result));\n\n return result;\n}\n\nexport default {\n createFileIfMissing,\n readProjectConfigData,\n readGlobalConfigData,\n writeGlobalConfigData,\n writeProjectConfigData,\n justTheHost,\n saveToken,\n deleteToken,\n getToken,\n getTokenFromEnv,\n parseSourceInformation,\n};\n"],"names":["yaml","path","fs","consts","url"],"mappings":"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","debug_id":"3f451b9b-6016-532a-b399-58b8b273e73c"}
1
+ {"version":3,"sources":["../lib/config.ts"],"sourcesContent":["import fs from \"fs\";\nimport path from \"path\";\nimport url from \"url\";\nimport yaml from \"js-yaml\";\nimport * as Sentry from \"@sentry/node\";\n\nimport consts from \"./consts\";\nimport { createSentryContext } from \"./utils/createSentryContext\";\nimport { Project, ConfigYAML, SourceInformation } from \"./types\";\n\nexport const DEFAULT_CONFIG_JSON: ConfigYAML = {\n sources: {\n components: true,\n },\n variants: true,\n format: \"flat\",\n};\n\nexport const DEFAULT_CONFIG = yaml.dump(DEFAULT_CONFIG_JSON);\n\nfunction createFileIfMissing(filename: string, defaultContents?: any) {\n const dir = path.dirname(filename);\n\n // create the directory if it doesn't already exist\n if (!fs.existsSync(dir)) fs.mkdirSync(dir);\n\n // create the file if it doesn't already exist\n if (!fs.existsSync(filename)) {\n // create the file, writing the `defaultContents` if provided\n fs.writeFileSync(filename, defaultContents || \"\", \"utf-8\");\n }\n}\n\nfunction jsonIsConfigYAML(json: unknown): json is ConfigYAML {\n return typeof json === \"object\";\n}\n\nfunction jsonIsGlobalYAML(\n json: unknown\n): json is Record<string, { token: string }[]> {\n return (\n !!json &&\n typeof json === \"object\" &&\n Object.values(json).every(\n (arr) =>\n (arr as any).every &&\n arr.every(\n (val: any) =>\n typeof val === \"object\" && Object.keys(val).includes(\"token\")\n )\n )\n );\n}\n\n/**\n * Read data from a project config file\n * @param {string} file defaults to `PROJECT_CONFIG_FILE` defined in `constants.js`\n * @param {*} defaultData defaults to `{}`\n * @returns { ConfigYAML }\n */\nfunction readProjectConfigData(\n file = consts.PROJECT_CONFIG_FILE,\n defaultData = {}\n): ConfigYAML {\n createFileIfMissing(file, DEFAULT_CONFIG);\n const fileContents = fs.readFileSync(file, \"utf8\");\n const yamlData = yaml.load(fileContents);\n if (jsonIsConfigYAML(yamlData)) {\n return yamlData;\n }\n return defaultData;\n}\n\n/**\n * Read data from a global config file\n * @param {string} file defaults to `CONFIG_FILE` defined in `constants.js`\n * @param {*} defaultData defaults to `{}`\n * @returns { Record<string, { token: string }[]> }\n */\nfunction readGlobalConfigData(\n file = consts.CONFIG_FILE,\n defaultData = {}\n): Record<string, { token: string }[]> {\n createFileIfMissing(file);\n const fileContents = fs.readFileSync(file, \"utf8\");\n const yamlData = yaml.load(fileContents);\n if (jsonIsGlobalYAML(yamlData)) {\n return yamlData;\n }\n return defaultData;\n}\n\nfunction writeProjectConfigData(file: string, data: Partial<ConfigYAML>) {\n createFileIfMissing(file, DEFAULT_CONFIG);\n const existingData = readProjectConfigData(file);\n\n const configData: ConfigYAML = {\n ...existingData,\n ...data,\n sources: {\n ...existingData.sources,\n ...data.sources,\n },\n };\n\n const yamlStr = yaml.dump(configData);\n fs.writeFileSync(file, yamlStr, \"utf8\");\n}\n\nfunction writeGlobalConfigData(file: string, data: object) {\n createFileIfMissing(file);\n const existingData = readGlobalConfigData(file);\n const yamlStr = yaml.dump({ ...existingData, ...data });\n fs.writeFileSync(file, yamlStr, \"utf8\");\n}\n\nfunction justTheHost(host: string) {\n if (!host.includes(\"://\")) return host;\n return url.parse(host).hostname || \"\";\n}\n\nfunction deleteToken(file: string, host: string) {\n const data = readGlobalConfigData(file);\n const hostParsed = justTheHost(host);\n data[hostParsed] = [];\n data[hostParsed][0] = { token: \"\" };\n writeGlobalConfigData(file, data);\n}\n\nfunction saveToken(file: string, host: string, token: string) {\n const data = readGlobalConfigData(file);\n const hostParsed = justTheHost(host);\n data[hostParsed] = []; // only allow one token per host\n data[hostParsed][0] = { token };\n writeGlobalConfigData(file, data);\n}\n\nfunction getTokenFromEnv() {\n return process.env.DITTO_API_KEY;\n}\n\n/**\n *\n * @param {string} file\n * @param {string} host\n * @returns {Token}\n */\nfunction getToken(file: string, host: string) {\n const tokenFromEnv = getTokenFromEnv();\n if (tokenFromEnv) {\n return tokenFromEnv;\n }\n\n const data = readGlobalConfigData(file);\n const hostEntry = data[justTheHost(host)];\n if (!hostEntry) return undefined;\n const { length } = hostEntry;\n\n return hostEntry[length - 1].token;\n}\n\nconst IS_DUPLICATE = /-(\\d+$)/;\n\nfunction dedupeProjectName(projectNames: Set<string>, projectName: string) {\n let dedupedName = projectName;\n\n if (projectNames.has(dedupedName)) {\n while (projectNames.has(dedupedName)) {\n const [_, numberStr] = dedupedName.match(IS_DUPLICATE) || [];\n if (numberStr && !isNaN(parseInt(numberStr))) {\n dedupedName = `${dedupedName.replace(IS_DUPLICATE, \"\")}-${\n parseInt(numberStr) + 1\n }`;\n } else {\n dedupedName = `${dedupedName}-1`;\n }\n }\n }\n\n return dedupedName;\n}\n\n/**\n * Reads from the config file, filters out\n * invalid projects, dedupes those remaining, and returns:\n * - whether or not the data required to `pull` is present\n * - whether or not the component library should be fetched\n * - an array of valid, deduped projects\n * - the `variants` and `format` config options\n */\nfunction parseSourceInformation(file?: string): SourceInformation {\n const {\n sources,\n variants,\n format,\n status,\n richText,\n iosLocales,\n projects: projectsRoot,\n components: componentsRoot,\n } = readProjectConfigData(file);\n\n const projects = sources?.projects || [];\n\n const projectNames = new Set<string>();\n const validProjects: Project[] = [];\n let hasComponentLibraryInProjects = false;\n\n (projects || []).forEach((project) => {\n const isValid = project.id && project.name;\n if (!isValid) {\n return;\n }\n\n if (project.id === \"ditto_component_library\") {\n hasComponentLibraryInProjects = true;\n return;\n }\n\n project.fileName = dedupeProjectName(projectNames, project.name);\n projectNames.add(project.fileName);\n\n validProjects.push(project);\n });\n\n const shouldFetchComponentLibrary = Boolean(sources?.components);\n const componentRoot =\n typeof sources?.components === \"object\"\n ? sources.components.root\n : undefined;\n const componentFolders =\n typeof sources?.components === \"object\"\n ? sources.components.folders\n : undefined;\n\n /**\n * If it's not specified to fetch projects or the component library, then there\n * is no source data to pull.\n */\n const hasSourceData = !!validProjects.length || shouldFetchComponentLibrary;\n\n const result = {\n hasSourceData,\n validProjects,\n shouldFetchComponentLibrary,\n variants: variants || false,\n format,\n status,\n richText,\n hasTopLevelProjectsField: !!projectsRoot,\n hasTopLevelComponentsField: !!componentsRoot,\n hasComponentLibraryInProjects,\n componentRoot,\n componentFolders,\n localeByVariantApiId: iosLocales\n ? iosLocales.reduce((acc, e) => ({ ...acc, ...e }), {} as any)\n : undefined,\n };\n\n Sentry.setContext(\"config\", createSentryContext(result));\n\n return result;\n}\n\nexport default {\n createFileIfMissing,\n readProjectConfigData,\n readGlobalConfigData,\n writeGlobalConfigData,\n writeProjectConfigData,\n justTheHost,\n saveToken,\n deleteToken,\n getToken,\n getTokenFromEnv,\n parseSourceInformation,\n};\n"],"names":["yaml","path","fs","consts","url"],"mappings":"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","debug_id":"907226eb-d4b7-553b-a3ea-7aa63bccb645"}
package/bin/ditto.js CHANGED
File without changes
@@ -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]="9bc7c4e1-465b-5786-8656-d536f004e70b")}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]="1ef09b5a-43ab-5873-b98e-b7121710bc2b")}catch(e){}}();
3
3
 
4
4
  var __defProp = Object.defineProperty;
5
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -48,7 +48,7 @@ function fetchComponentFolders() {
48
48
  return __async(this, null, function* () {
49
49
  const api = (0, import_api.createApiClient)();
50
50
  const { data } = yield api.get(
51
- "/component-folders",
51
+ "/v1/component-folders",
52
52
  {}
53
53
  );
54
54
  return data;
@@ -60,4 +60,4 @@ function fetchComponentFolders() {
60
60
  });
61
61
  //# sourceMappingURL=fetchComponentFolders.js.map
62
62
 
63
- //# debugId=9bc7c4e1-465b-5786-8656-d536f004e70b
63
+ //# debugId=1ef09b5a-43ab-5873-b98e-b7121710bc2b
@@ -1 +1 @@
1
- {"version":3,"sources":["../../lib/http/fetchComponentFolders.ts"],"sourcesContent":["import { createApiClient } from \"../api\";\n\ninterface FetchComponentFoldersResponse {\n [id: string]: string;\n}\n\nexport async function fetchComponentFolders(): Promise<FetchComponentFoldersResponse> {\n const api = createApiClient();\n\n const { data } = await api.get<FetchComponentFoldersResponse>(\n \"/component-folders\",\n {}\n );\n\n return data;\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAAgC;AAMhC,SAAsB,wBAAgE;AAAA;AACpF,UAAM,UAAM,4BAAgB;AAE5B,UAAM,EAAE,KAAK,IAAI,MAAM,IAAI;AAAA,MACzB;AAAA,MACA,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAAA","debug_id":"9bc7c4e1-465b-5786-8656-d536f004e70b"}
1
+ {"version":3,"sources":["../../lib/http/fetchComponentFolders.ts"],"sourcesContent":["import { createApiClient } from \"../api\";\n\ninterface FetchComponentFoldersResponse {\n [id: string]: string;\n}\n\nexport async function fetchComponentFolders(): Promise<FetchComponentFoldersResponse> {\n const api = createApiClient();\n\n const { data } = await api.get<FetchComponentFoldersResponse>(\n \"/v1/component-folders\",\n {}\n );\n\n return data;\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAAgC;AAMhC,SAAsB,wBAAgE;AAAA;AACpF,UAAM,UAAM,4BAAgB;AAE5B,UAAM,EAAE,KAAK,IAAI,MAAM,IAAI;AAAA,MACzB;AAAA,MACA,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAAA","debug_id":"1ef09b5a-43ab-5873-b98e-b7121710bc2b"}
@@ -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]="7dd5234f-c640-5939-abb0-c3c9967f3844")}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]="d39c596f-987e-58e0-99f5-8f5f27ee9f5a")}catch(e){}}();
3
3
 
4
4
  var __defProp = Object.defineProperty;
5
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -49,14 +49,22 @@ function fetchComponents(options) {
49
49
  const api = (0, import_api.createApiClient)();
50
50
  if (options.componentFolder) {
51
51
  try {
52
- const { data } = yield api.get(`/component-folders/${options.componentFolder}/components`, {});
52
+ const { data } = yield api.get(
53
+ `/v1/component-folders/${options.componentFolder}/components`,
54
+ {}
55
+ );
53
56
  return data;
54
57
  } catch (e) {
55
- console.log(`Failed to get components for ${options.componentFolder}. Please verify the folder's API ID.`);
58
+ console.log(
59
+ `Failed to get components for ${options.componentFolder}. Please verify the folder's API ID.`
60
+ );
56
61
  return {};
57
62
  }
58
63
  } else {
59
- const { data } = yield api.get("/components", {});
64
+ const { data } = yield api.get(
65
+ "/v1/components",
66
+ {}
67
+ );
60
68
  return data;
61
69
  }
62
70
  });
@@ -67,4 +75,4 @@ function fetchComponents(options) {
67
75
  });
68
76
  //# sourceMappingURL=fetchComponents.js.map
69
77
 
70
- //# debugId=7dd5234f-c640-5939-abb0-c3c9967f3844
78
+ //# debugId=d39c596f-987e-58e0-99f5-8f5f27ee9f5a