@dittowords/cli 2.0.0-beta.0 → 2.1.2
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 +85 -9
- package/lib/config.js +77 -2
- package/lib/init/init.js +19 -11
- package/lib/init/project.js +12 -5
- package/lib/pull.js +31 -66
- package/lib/utils/projectsToText.js +1 -1
- package/lib/utils/sourcesToText.js +24 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,9 +16,39 @@ npm install --global @dittowords/cli
|
|
|
16
16
|
|
|
17
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) (with or without installation) like `npx @dittowords/cli`.
|
|
18
18
|
|
|
19
|
-
The first time you run the CLI, you'll be asked to provide an API key (found at [https://beta.dittowords.com/account/user](https://beta.dittowords.com/account/user) under **API Keys**)
|
|
19
|
+
The first time you run the CLI, you'll be asked to provide an API key (found at [https://beta.dittowords.com/account/user](https://beta.dittowords.com/account/user) under **API Keys**):
|
|
20
20
|
|
|
21
|
-
|
|
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
|
+
└──────────────────────────────────┘
|
|
31
|
+
|
|
32
|
+
What is your API key? > xxx-xxx-xxx
|
|
33
|
+
|
|
34
|
+
Thanks for authenticating.
|
|
35
|
+
We'll save the key to: /Users/{username}/.config/ditto
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Once you've successfully authenticated, you'll be asked to configure the CLI with an initial project from your workspace:
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
Looks like there are no Ditto projects selected for your current directory.
|
|
42
|
+
|
|
43
|
+
? Choose the project you'd like to sync text from:
|
|
44
|
+
- Ditto Component Library https://beta.dittowords.com/components/all
|
|
45
|
+
- NUX Onboarding Flow https://beta.dittowords.com/doc/609e9981c313f8018d0c346a
|
|
46
|
+
...
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
After selecting a project, 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 [documentation on config.yml](#files) further down in this README 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! You can set up the CLI in multiple directories by running `ditto-cli` and choosing an initial project to sync from.
|
|
22
52
|
|
|
23
53
|
## Commands
|
|
24
54
|
|
|
@@ -52,7 +82,7 @@ This folder houses the configuration file (`ditto/config.yml`) used by the CLI a
|
|
|
52
82
|
|
|
53
83
|
If you run the CLI in a directory that does not contain a `ditto/` folder, the folder and a `config.yml` file will be automatically created.
|
|
54
84
|
|
|
55
|
-
- ####
|
|
85
|
+
- #### config.yml
|
|
56
86
|
|
|
57
87
|
This 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 and in what format the text should be stored.
|
|
58
88
|
|
|
@@ -60,16 +90,62 @@ If you run the CLI in a directory that does not contain a `ditto/` folder, the f
|
|
|
60
90
|
|
|
61
91
|
**Supported properties**
|
|
62
92
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
93
|
+
##### `projects`
|
|
94
|
+
|
|
95
|
+
A list of project names and ids to pull text from. R
|
|
96
|
+
|
|
97
|
+
equired if `components: true` is not specified.
|
|
98
|
+
|
|
99
|
+
**Note**: the `name` property is used for display purposes when referencing a project in the CLI, but does not have to be an
|
|
100
|
+
exact match with the project name in Ditto.
|
|
101
|
+
|
|
102
|
+
```yml
|
|
103
|
+
projects:
|
|
104
|
+
- name: Landing Page Copy
|
|
105
|
+
id: 61b8d26105f8f400e97fdd14
|
|
106
|
+
- name: User Settings
|
|
107
|
+
id: 606cb89ac55041013d552f8b
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
##### `components`
|
|
111
|
+
|
|
112
|
+
If included with a value of `true`, data from the component library will be fetched and included in the CLI's output.
|
|
66
113
|
|
|
67
|
-
|
|
114
|
+
Required if `projects` is not specified with a valid list of projects.
|
|
115
|
+
|
|
116
|
+
```yml
|
|
117
|
+
components: true
|
|
118
|
+
```
|
|
68
119
|
|
|
120
|
+
##### `variants`
|
|
121
|
+
|
|
122
|
+
If included with a value of `true`, variant data will be pulled for the specified projects and/or the component library.
|
|
123
|
+
|
|
124
|
+
Defaults to `false`.
|
|
125
|
+
|
|
126
|
+
```yml
|
|
127
|
+
variants: true
|
|
69
128
|
```
|
|
129
|
+
|
|
130
|
+
##### `format`
|
|
131
|
+
|
|
132
|
+
The format the specified projects should be stored in. Acceptable values are `structured` or `flat`.
|
|
133
|
+
|
|
134
|
+
If not specified, the default format containing block and frame data will be used.
|
|
135
|
+
|
|
136
|
+
```yml
|
|
137
|
+
format: flat
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**Full Example**
|
|
141
|
+
|
|
142
|
+
```yml
|
|
70
143
|
projects:
|
|
71
|
-
- name:
|
|
72
|
-
id:
|
|
144
|
+
- name: Landing Page Copy
|
|
145
|
+
id: 61b8d26105f8f400e97fdd14
|
|
146
|
+
- name: User Settings
|
|
147
|
+
id: 606cb89ac55041013d552f8b
|
|
148
|
+
components: true
|
|
73
149
|
variants: true
|
|
74
150
|
format: flat
|
|
75
151
|
```
|
package/lib/config.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
const fs = require("fs");
|
|
2
2
|
const path = require("path");
|
|
3
3
|
const url = require("url");
|
|
4
|
-
|
|
5
4
|
const yaml = require("js-yaml");
|
|
6
5
|
|
|
6
|
+
const consts = require("./consts");
|
|
7
|
+
|
|
7
8
|
function createFileIfMissing(filename) {
|
|
8
9
|
const dir = path.dirname(filename);
|
|
9
10
|
|
|
@@ -14,7 +15,13 @@ function createFileIfMissing(filename) {
|
|
|
14
15
|
}
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Read data from a file
|
|
20
|
+
* @param {string} file defaults to `PROJECT_CONFIG_FILE` defined in `constants.js`
|
|
21
|
+
* @param {*} defaultData defaults to `{}`
|
|
22
|
+
* @returns
|
|
23
|
+
*/
|
|
24
|
+
function readData(file = consts.PROJECT_CONFIG_FILE, defaultData = {}) {
|
|
18
25
|
createFileIfMissing(file);
|
|
19
26
|
const fileContents = fs.readFileSync(file, "utf8");
|
|
20
27
|
return yaml.safeLoad(fileContents) || defaultData;
|
|
@@ -72,6 +79,73 @@ function save(file, key, value) {
|
|
|
72
79
|
writeData(file, data);
|
|
73
80
|
}
|
|
74
81
|
|
|
82
|
+
const IS_DUPLICATE = /-(\d+$)/;
|
|
83
|
+
function dedupeProjectName(projectNames, projectName) {
|
|
84
|
+
let dedupedName = projectName;
|
|
85
|
+
|
|
86
|
+
if (projectNames.has(dedupedName)) {
|
|
87
|
+
while (projectNames.has(dedupedName)) {
|
|
88
|
+
const [_, numberStr] = dedupedName.match(IS_DUPLICATE) || [];
|
|
89
|
+
if (numberStr && !isNaN(parseInt(numberStr))) {
|
|
90
|
+
dedupedName = `${dedupedName.replace(IS_DUPLICATE, "")}-${
|
|
91
|
+
parseInt(numberStr) + 1
|
|
92
|
+
}`;
|
|
93
|
+
} else {
|
|
94
|
+
dedupedName = `${dedupedName}-1`;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return dedupedName;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Reads from the config file, filters out
|
|
104
|
+
* invalid projects, dedupes those remaining, and returns:
|
|
105
|
+
* - whether or not the data required to `pull` is present
|
|
106
|
+
* - whether or not the component library should be fetched
|
|
107
|
+
* - an array of valid, deduped projects
|
|
108
|
+
* - the `variants` and `format` config options
|
|
109
|
+
*/
|
|
110
|
+
function parseSourceInformation() {
|
|
111
|
+
const { projects, components, variants, format } = readData();
|
|
112
|
+
|
|
113
|
+
const projectNames = new Set();
|
|
114
|
+
const validProjects = [];
|
|
115
|
+
|
|
116
|
+
let componentLibraryInProjects = false;
|
|
117
|
+
|
|
118
|
+
(projects || []).forEach((project) => {
|
|
119
|
+
const isValid = project.id && project.name;
|
|
120
|
+
if (!isValid) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (project.id === "ditto_component_library") {
|
|
125
|
+
componentLibraryInProjects = true;
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
project.fileName = dedupeProjectName(projectNames, project.name);
|
|
130
|
+
projectNames.add(project.fileName);
|
|
131
|
+
|
|
132
|
+
validProjects.push(project);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
const shouldFetchComponentLibrary =
|
|
136
|
+
!!components || componentLibraryInProjects;
|
|
137
|
+
|
|
138
|
+
const hasSourceData = validProjects.length || shouldFetchComponentLibrary;
|
|
139
|
+
|
|
140
|
+
return {
|
|
141
|
+
hasSourceData,
|
|
142
|
+
validProjects,
|
|
143
|
+
shouldFetchComponentLibrary,
|
|
144
|
+
variants,
|
|
145
|
+
format,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
75
149
|
module.exports = {
|
|
76
150
|
createFileIfMissing,
|
|
77
151
|
readData,
|
|
@@ -81,4 +155,5 @@ module.exports = {
|
|
|
81
155
|
deleteToken,
|
|
82
156
|
getToken,
|
|
83
157
|
save,
|
|
158
|
+
parseSourceInformation,
|
|
84
159
|
};
|
package/lib/init/init.js
CHANGED
|
@@ -2,13 +2,16 @@
|
|
|
2
2
|
// expected to be run once per project.
|
|
3
3
|
const boxen = require("boxen");
|
|
4
4
|
const chalk = require("chalk");
|
|
5
|
-
const getSelectedProjects = require("../utils/getSelectedProjects");
|
|
6
5
|
const projectsToText = require("../utils/projectsToText");
|
|
7
6
|
|
|
8
|
-
const {
|
|
7
|
+
const { needsSource, collectAndSaveProject } = require("./project");
|
|
9
8
|
const { needsToken, collectAndSaveToken } = require("./token");
|
|
10
9
|
|
|
11
|
-
const
|
|
10
|
+
const config = require("../config");
|
|
11
|
+
const output = require("../output");
|
|
12
|
+
const sourcesToText = require("../utils/sourcesToText");
|
|
13
|
+
|
|
14
|
+
const needsInit = () => needsToken() || needsSource();
|
|
12
15
|
|
|
13
16
|
function welcome() {
|
|
14
17
|
const msg = chalk.white(`${chalk.bold(
|
|
@@ -22,19 +25,24 @@ We're glad to have you here.`);
|
|
|
22
25
|
|
|
23
26
|
async function init() {
|
|
24
27
|
welcome();
|
|
28
|
+
|
|
25
29
|
if (needsToken()) {
|
|
26
30
|
await collectAndSaveToken();
|
|
27
31
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
)}\n`
|
|
34
|
-
);
|
|
35
|
-
} else {
|
|
32
|
+
|
|
33
|
+
const { hasSourceData, validProjects, shouldFetchComponentLibrary } =
|
|
34
|
+
config.parseSourceInformation();
|
|
35
|
+
|
|
36
|
+
if (!hasSourceData) {
|
|
36
37
|
await collectAndSaveProject(true);
|
|
38
|
+
return;
|
|
37
39
|
}
|
|
40
|
+
|
|
41
|
+
const message =
|
|
42
|
+
"You're currently set up to sync text from " +
|
|
43
|
+
sourcesToText(validProjects, shouldFetchComponentLibrary);
|
|
44
|
+
|
|
45
|
+
console.log(message);
|
|
38
46
|
}
|
|
39
47
|
|
|
40
48
|
module.exports = { needsInit, init };
|
package/lib/init/project.js
CHANGED
|
@@ -15,14 +15,21 @@ function quit(exitCode = 2) {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
function saveProject(file, name, id) {
|
|
18
|
+
// old functionality included "ditto_component_library" in the `projects`
|
|
19
|
+
// array, but we want to always treat the component library as a separate
|
|
20
|
+
// entity and use the new notation of a top-level `components` key
|
|
21
|
+
if (id === "ditto_component_library") {
|
|
22
|
+
config.writeData(file, { components: true });
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
18
26
|
const projects = [...getSelectedProjects(), { name, id }];
|
|
19
27
|
|
|
20
28
|
config.writeData(file, { projects });
|
|
21
29
|
}
|
|
22
30
|
|
|
23
|
-
function
|
|
24
|
-
|
|
25
|
-
return !(projects && projects.length);
|
|
31
|
+
function needsSource() {
|
|
32
|
+
return !config.parseSourceInformation().hasSourceData;
|
|
26
33
|
}
|
|
27
34
|
|
|
28
35
|
async function askForAnotherToken() {
|
|
@@ -60,7 +67,7 @@ async function collectProject(token, initialize) {
|
|
|
60
67
|
const path = process.cwd();
|
|
61
68
|
if (initialize) {
|
|
62
69
|
console.log(
|
|
63
|
-
`Looks like are no Ditto projects selected for your current directory: ${output.info(
|
|
70
|
+
`Looks like there are no Ditto projects selected for your current directory: ${output.info(
|
|
64
71
|
path
|
|
65
72
|
)}.`
|
|
66
73
|
);
|
|
@@ -113,4 +120,4 @@ async function collectAndSaveProject(initialize = false) {
|
|
|
113
120
|
}
|
|
114
121
|
}
|
|
115
122
|
|
|
116
|
-
module.exports = {
|
|
123
|
+
module.exports = { needsSource, collectAndSaveProject };
|
package/lib/pull.js
CHANGED
|
@@ -9,6 +9,7 @@ const consts = require("./consts");
|
|
|
9
9
|
const output = require("./output");
|
|
10
10
|
const { collectAndSaveToken } = require("./init/token");
|
|
11
11
|
const projectsToText = require("./utils/projectsToText");
|
|
12
|
+
const sourcesToText = require("./utils/sourcesToText");
|
|
12
13
|
|
|
13
14
|
const NON_DEFAULT_FORMATS = ["flat", "structured"];
|
|
14
15
|
|
|
@@ -30,54 +31,6 @@ async function askForAnotherToken() {
|
|
|
30
31
|
await collectAndSaveToken(message);
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
function cleanProjectName(projectName) {
|
|
34
|
-
return (
|
|
35
|
-
projectName
|
|
36
|
-
.replace(/\s/g, "-")
|
|
37
|
-
// replace double underscore since this is what we use
|
|
38
|
-
// to separate project names and API IDs
|
|
39
|
-
.replace(/__/g, "_")
|
|
40
|
-
.toLowerCase()
|
|
41
|
-
.trim()
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Return the passed array of projects with `project.name` modified
|
|
47
|
-
* to be `${project.name}-${duplicate_number}` for each project
|
|
48
|
-
* that has the same name as another project in the original array.
|
|
49
|
-
*/
|
|
50
|
-
const IS_DUPLICATE = /-(\d+$)/;
|
|
51
|
-
function getProjectsWithDedupedNames(projects) {
|
|
52
|
-
const projectsWithDedupedNames = [];
|
|
53
|
-
const projectNames = {};
|
|
54
|
-
|
|
55
|
-
projects.forEach(({ id, name }) => {
|
|
56
|
-
let dedupedName = name;
|
|
57
|
-
|
|
58
|
-
if (projectNames[dedupedName]) {
|
|
59
|
-
while (projectNames[dedupedName]) {
|
|
60
|
-
const [_, numberStr] = dedupedName.match(IS_DUPLICATE) || [];
|
|
61
|
-
if (numberStr && !isNaN(parseInt(numberStr))) {
|
|
62
|
-
dedupedName = `${dedupedName.replace(IS_DUPLICATE, "")}-${
|
|
63
|
-
parseInt(numberStr) + 1
|
|
64
|
-
}`;
|
|
65
|
-
} else {
|
|
66
|
-
dedupedName = `${dedupedName}-1`;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
projectNames[dedupedName] = true;
|
|
72
|
-
projectsWithDedupedNames.push({
|
|
73
|
-
id,
|
|
74
|
-
name: cleanProjectName(dedupedName),
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
return projectsWithDedupedNames;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
34
|
/**
|
|
82
35
|
* For a given variant:
|
|
83
36
|
* - if format is unspecified, fetch data for all projects from `/projects` and
|
|
@@ -93,7 +46,7 @@ async function downloadAndSaveVariant(variantApiId, projects, format, token) {
|
|
|
93
46
|
|
|
94
47
|
if (NON_DEFAULT_FORMATS.includes(format)) {
|
|
95
48
|
const savedMessages = await Promise.all(
|
|
96
|
-
projects.map(async ({ id,
|
|
49
|
+
projects.map(async ({ id, fileName }) => {
|
|
97
50
|
const { data } = await api.get(`/projects/${id}`, {
|
|
98
51
|
params,
|
|
99
52
|
headers: { Authorization: `token ${token}` },
|
|
@@ -103,7 +56,7 @@ async function downloadAndSaveVariant(variantApiId, projects, format, token) {
|
|
|
103
56
|
return "";
|
|
104
57
|
}
|
|
105
58
|
|
|
106
|
-
const filename =
|
|
59
|
+
const filename = fileName + ("__" + (variantApiId || "base")) + ".json";
|
|
107
60
|
const filepath = path.join(consts.TEXT_DIR, filename);
|
|
108
61
|
|
|
109
62
|
const dataString = JSON.stringify(data, null, 2);
|
|
@@ -162,13 +115,13 @@ async function downloadAndSaveBase(projects, format, token) {
|
|
|
162
115
|
|
|
163
116
|
if (NON_DEFAULT_FORMATS.includes(format)) {
|
|
164
117
|
const savedMessages = await Promise.all(
|
|
165
|
-
projects.map(async ({ id,
|
|
118
|
+
projects.map(async ({ id, fileName }) => {
|
|
166
119
|
const { data } = await api.get(`/projects/${id}`, {
|
|
167
120
|
params,
|
|
168
121
|
headers: { Authorization: `token ${token}` },
|
|
169
122
|
});
|
|
170
123
|
|
|
171
|
-
const filename = `${
|
|
124
|
+
const filename = `${fileName}.json`;
|
|
172
125
|
const filepath = path.join(consts.TEXT_DIR, filename);
|
|
173
126
|
|
|
174
127
|
const dataString = JSON.stringify(data, null, 2);
|
|
@@ -195,7 +148,7 @@ async function downloadAndSaveBase(projects, format, token) {
|
|
|
195
148
|
}
|
|
196
149
|
|
|
197
150
|
function getSavedMessage(file) {
|
|
198
|
-
return `Successfully saved to ${output.info(file)}
|
|
151
|
+
return `Successfully saved to ${output.info(file)}\n`;
|
|
199
152
|
}
|
|
200
153
|
|
|
201
154
|
function cleanOutputFiles() {
|
|
@@ -235,7 +188,7 @@ function generateJsDriver(projects, variants, format) {
|
|
|
235
188
|
.filter((fileName) => /\.json$/.test(fileName));
|
|
236
189
|
|
|
237
190
|
const projectIdsByName = projects.reduce(
|
|
238
|
-
(agg, project) => ({ ...agg, [project.
|
|
191
|
+
(agg, project) => ({ ...agg, [project.fileName]: project.id }),
|
|
239
192
|
{}
|
|
240
193
|
);
|
|
241
194
|
|
|
@@ -305,28 +258,40 @@ function generateJsDriver(projects, variants, format) {
|
|
|
305
258
|
const filePath = path.resolve(consts.TEXT_DIR, "index.js");
|
|
306
259
|
fs.writeFileSync(filePath, dataString, { encoding: "utf8" });
|
|
307
260
|
|
|
308
|
-
return `Generated .js SDK driver at ${output.info(filePath)}
|
|
261
|
+
return `Generated .js SDK driver at ${output.info(filePath)}`;
|
|
309
262
|
}
|
|
310
263
|
|
|
311
|
-
async function downloadAndSave(
|
|
312
|
-
const {
|
|
313
|
-
|
|
264
|
+
async function downloadAndSave(sourceInformation, token) {
|
|
265
|
+
const { validProjects, variants, format, shouldFetchComponentLibrary } =
|
|
266
|
+
sourceInformation;
|
|
314
267
|
|
|
315
|
-
let msg = `\nFetching the latest text from
|
|
316
|
-
|
|
268
|
+
let msg = `\nFetching the latest text from ${sourcesToText(
|
|
269
|
+
validProjects,
|
|
270
|
+
shouldFetchComponentLibrary
|
|
317
271
|
)}\n`;
|
|
318
272
|
|
|
319
273
|
const spinner = ora(msg);
|
|
320
274
|
spinner.start();
|
|
321
275
|
|
|
276
|
+
// We'll need to move away from this solution if at some
|
|
277
|
+
// point down the road we stop allowing the component
|
|
278
|
+
// library to be returned from the /projects endpoint
|
|
279
|
+
if (shouldFetchComponentLibrary) {
|
|
280
|
+
validProjects.push({
|
|
281
|
+
id: "ditto_component_library",
|
|
282
|
+
name: "Ditto Component Library",
|
|
283
|
+
fileName: "ditto-component-library",
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
|
|
322
287
|
try {
|
|
323
288
|
msg += cleanOutputFiles();
|
|
324
289
|
|
|
325
290
|
msg += variants
|
|
326
|
-
? await downloadAndSaveVariants(
|
|
327
|
-
: await downloadAndSaveBase(
|
|
291
|
+
? await downloadAndSaveVariants(validProjects, format, token)
|
|
292
|
+
: await downloadAndSaveBase(validProjects, format, token);
|
|
328
293
|
|
|
329
|
-
msg += generateJsDriver(
|
|
294
|
+
msg += generateJsDriver(validProjects, variants, format);
|
|
330
295
|
|
|
331
296
|
msg += `\n${output.success("Done")}!`;
|
|
332
297
|
|
|
@@ -371,15 +336,15 @@ async function downloadAndSave(projectConfig, token) {
|
|
|
371
336
|
|
|
372
337
|
function pull() {
|
|
373
338
|
const token = config.getToken(consts.CONFIG_FILE, consts.API_HOST);
|
|
374
|
-
const
|
|
375
|
-
|
|
339
|
+
const sourceInformation = config.parseSourceInformation();
|
|
340
|
+
|
|
341
|
+
return downloadAndSave(sourceInformation, token);
|
|
376
342
|
}
|
|
377
343
|
|
|
378
344
|
module.exports = {
|
|
379
345
|
pull,
|
|
380
346
|
_testing: {
|
|
381
347
|
cleanOutputFiles,
|
|
382
|
-
getProjectsWithDedupedNames,
|
|
383
348
|
downloadAndSaveVariant,
|
|
384
349
|
downloadAndSaveVariants,
|
|
385
350
|
downloadAndSaveBase,
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const output = require("../output");
|
|
2
|
+
const projectsToText = require("./projectsToText");
|
|
3
|
+
|
|
4
|
+
function sourcesToText(projects, componentLibrary) {
|
|
5
|
+
let message = "";
|
|
6
|
+
|
|
7
|
+
if (componentLibrary) {
|
|
8
|
+
message += `the ${output.info("Ditto Component Library")}`;
|
|
9
|
+
|
|
10
|
+
if ((projects || []).length) {
|
|
11
|
+
message += " and ";
|
|
12
|
+
} else {
|
|
13
|
+
message += "..";
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if ((projects || []).length) {
|
|
18
|
+
message += `the following projects: ${projectsToText(projects)}\n`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return message;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = sourcesToText;
|