@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.
- package/README.md +27 -371
- package/bin/api.js +3 -15
- package/bin/api.js.map +1 -1
- package/bin/config.js +5 -3
- package/bin/config.js.map +1 -1
- package/bin/ditto.js +0 -0
- package/bin/http/fetchComponentFolders.js +3 -3
- package/bin/http/fetchComponentFolders.js.map +1 -1
- package/bin/http/fetchComponents.js +13 -5
- package/bin/http/fetchComponents.js.map +1 -1
- package/bin/http/fetchVariants.js +3 -3
- package/bin/http/fetchVariants.js.map +1 -1
- package/bin/init/project.js +3 -3
- package/bin/init/project.js.map +1 -1
- package/bin/pull.js +82 -49
- package/bin/pull.js.map +1 -1
- package/bin/pull.test.js +26 -24
- package/bin/pull.test.js.map +1 -1
- package/bin/types.js +2 -2
- package/bin/types.js.map +1 -1
- package/bin/utils/determineModuleType.js +80 -0
- package/bin/utils/determineModuleType.js.map +1 -0
- package/bin/utils/generateIOSBundles.js +147 -0
- package/bin/utils/generateIOSBundles.js.map +1 -0
- package/bin/utils/generateJsDriver.js +117 -58
- package/bin/utils/generateJsDriver.js.map +1 -1
- package/bin/utils/generateJsDriverTypeFile.js +105 -0
- package/bin/utils/generateJsDriverTypeFile.js.map +1 -0
- package/bin/utils/generateSwiftDriver.js +93 -0
- package/bin/utils/generateSwiftDriver.js.map +1 -0
- package/lib/api.ts +1 -17
- package/lib/config.ts +4 -0
- package/lib/http/fetchComponentFolders.ts +1 -1
- package/lib/http/fetchComponents.ts +14 -9
- package/lib/http/fetchVariants.ts +1 -1
- package/lib/init/project.ts +1 -1
- package/lib/pull.test.ts +24 -22
- package/lib/pull.ts +127 -90
- package/lib/types.ts +4 -0
- package/lib/utils/determineModuleType.ts +57 -0
- package/lib/utils/generateIOSBundles.ts +122 -0
- package/lib/utils/generateJsDriver.ts +156 -51
- package/lib/utils/generateJsDriverTypeFile.ts +75 -0
- package/lib/utils/generateSwiftDriver.ts +48 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,411 +1,67 @@
|
|
|
1
1
|
# Ditto CLI
|
|
2
2
|
|
|
3
|
-
The Ditto CLI
|
|
3
|
+
The Ditto CLI enables developers to access the Ditto API directly from the command line.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
[](https://badge.fury.io/js/@dittowords%2Fcli)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Documentation
|
|
8
8
|
|
|
9
|
-
|
|
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
|
-
|
|
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
|
-
|
|
35
|
-
We'll save the key to: /Users/{username}/.config/ditto
|
|
36
|
-
```
|
|
17
|
+
## Installation
|
|
37
18
|
|
|
38
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
33
|
+
By default, the CLI operates against a `ditto/` folder relative to the current working directory.
|
|
115
34
|
|
|
116
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
60
|
+
See our demo projects for examples of how to integrate the Ditto CLI in different environments:
|
|
407
61
|
|
|
408
|
-
- [
|
|
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]="
|
|
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
|
-
|
|
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=
|
|
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
|
|
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]="
|
|
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=
|
|
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]="
|
|
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=
|
|
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":"
|
|
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]="
|
|
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(
|
|
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(
|
|
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(
|
|
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=
|
|
78
|
+
//# debugId=d39c596f-987e-58e0-99f5-8f5f27ee9f5a
|