@dittowords/cli 2.7.1 → 3.0.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 +150 -137
- package/bin/add-project.js +5 -7
- package/bin/add-project.js.map +1 -1
- package/bin/api.js +0 -5
- package/bin/api.js.map +1 -1
- package/bin/config.js +38 -11
- package/bin/config.js.map +1 -1
- package/bin/ditto.js +66 -57
- package/bin/ditto.js.map +1 -1
- package/bin/http/fetchVariants.js +26 -0
- package/bin/http/fetchVariants.js.map +1 -0
- package/bin/init/init.js +17 -6
- package/bin/init/init.js.map +1 -1
- package/bin/init/project.js +38 -45
- package/bin/init/project.js.map +1 -1
- package/bin/init/token.js +22 -20
- package/bin/init/token.js.map +1 -1
- package/bin/pull.js +142 -193
- package/bin/pull.js.map +1 -1
- package/bin/remove-project.js +2 -7
- package/bin/remove-project.js.map +1 -1
- package/bin/utils/cleanFileName.js +11 -0
- package/bin/utils/cleanFileName.js.map +1 -0
- package/bin/utils/generateJsDriver.js +56 -0
- package/bin/utils/generateJsDriver.js.map +1 -0
- package/bin/utils/getSelectedProjects.js +3 -18
- package/bin/utils/getSelectedProjects.js.map +1 -1
- package/bin/utils/projectsToText.js +10 -1
- package/bin/utils/projectsToText.js.map +1 -1
- package/bin/utils/promptForProject.js +2 -3
- package/bin/utils/promptForProject.js.map +1 -1
- package/bin/utils/quit.js +10 -0
- package/bin/utils/quit.js.map +1 -0
- package/lib/add-project.ts +6 -9
- package/lib/api.ts +0 -5
- package/lib/config.ts +57 -19
- package/lib/ditto.ts +74 -58
- package/lib/http/fetchVariants.ts +30 -0
- package/lib/init/init.ts +38 -6
- package/lib/init/project.test.ts +3 -3
- package/lib/init/project.ts +47 -58
- package/lib/init/token.ts +17 -16
- package/lib/pull.ts +205 -261
- package/lib/remove-project.ts +2 -8
- package/lib/types.ts +24 -3
- package/lib/utils/cleanFileName.ts +6 -0
- package/lib/utils/generateJsDriver.ts +68 -0
- package/lib/utils/getSelectedProjects.ts +5 -24
- package/lib/utils/projectsToText.ts +11 -1
- package/lib/utils/promptForProject.ts +2 -3
- package/lib/utils/quit.ts +5 -0
- package/package.json +1 -1
- package/tsconfig.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"promptForProject.js","sourceRoot":"","sources":["../../lib/utils/promptForProject.ts"],"names":[],"mappings":";;;;;AAAA,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAE7C,uDAA+B;
|
|
1
|
+
{"version":3,"file":"promptForProject.js","sourceRoot":"","sources":["../../lib/utils/promptForProject.ts"],"names":[],"mappings":";;;;;AAAA,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAE7C,uDAA+B;AAE/B,qDAAgD;AAEhD,SAAS,mBAAmB,CAAC,OAAgB;IAC3C,OAAO,CACL,OAAO,CAAC,IAAI,GAAG,GAAG,GAAG,gBAAM,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,IAAA,6BAAY,EAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAC5E,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,QAAgB;IACrC,IAAI,CAAC,QAAQ,EAAE;QACb,OAAO,IAAI,CAAC;KACb;IAED,MAAM,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAEjE,IAAI,EAAE,KAAK,KAAK,EAAE;QAChB,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,yBAAyB,EAAE,CAAC;KAChD;IAED,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;AACtB,CAAC;AAQD,MAAM,gBAAgB,GAAG,KAAK,EAAE,EAC9B,OAAO,EACP,QAAQ,EACR,KAAK,GAAG,EAAE,GACU,EAAE,EAAE;IACxB,gBAAM,CAAC,EAAE,EAAE,CAAC;IAEZ,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC;QAC9B,IAAI,EAAE,SAAS;QACf,OAAO;QACP,KAAK;QACL,OAAO;KACR,CAAC,CAAC;IAEH,IAAI,QAAQ,CAAC;IAEb,IAAI;QACF,QAAQ,GAAG,MAAM,MAAM,CAAC,GAAG,EAAE,CAAC;KAC/B;IAAC,OAAO,CAAC,EAAE;QACV,oDAAoD;QACpD,4CAA4C;QAC5C,QAAQ,GAAG,IAAI,CAAC;KACjB;IAED,OAAO,aAAa,CAAC,QAAQ,CAAC,CAAC;AACjC,CAAC,CAAC;AAEF,kBAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.quit = void 0;
|
|
4
|
+
function quit(message, exitCode = 2) {
|
|
5
|
+
console.log(`\n${message}\n`);
|
|
6
|
+
process.exitCode = exitCode;
|
|
7
|
+
process.exit();
|
|
8
|
+
}
|
|
9
|
+
exports.quit = quit;
|
|
10
|
+
//# sourceMappingURL=quit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quit.js","sourceRoot":"","sources":["../../lib/utils/quit.ts"],"names":[],"mappings":";;;AAAA,SAAgB,IAAI,CAAC,OAAe,EAAE,QAAQ,GAAG,CAAC;IAChD,OAAO,CAAC,GAAG,CAAC,KAAK,OAAO,IAAI,CAAC,CAAC;IAC9B,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC5B,OAAO,CAAC,IAAI,EAAE,CAAC;AACjB,CAAC;AAJD,oBAIC"}
|
package/lib/add-project.ts
CHANGED
|
@@ -1,16 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { collectAndSaveSource } from "./init/project";
|
|
2
2
|
import projectsToText from "./utils/projectsToText";
|
|
3
3
|
import {
|
|
4
4
|
getSelectedProjects,
|
|
5
5
|
getIsUsingComponents,
|
|
6
6
|
} from "./utils/getSelectedProjects";
|
|
7
7
|
import output from "./output";
|
|
8
|
-
|
|
9
|
-
function quit(exitCode = 2) {
|
|
10
|
-
console.log("Project selection was not updated.");
|
|
11
|
-
process.exitCode = exitCode;
|
|
12
|
-
process.exit();
|
|
13
|
-
}
|
|
8
|
+
import { quit } from "./utils/quit";
|
|
14
9
|
|
|
15
10
|
const addProject = async () => {
|
|
16
11
|
const projects = getSelectedProjects();
|
|
@@ -38,13 +33,15 @@ const addProject = async () => {
|
|
|
38
33
|
)}`
|
|
39
34
|
);
|
|
40
35
|
}
|
|
41
|
-
await
|
|
36
|
+
await collectAndSaveSource({
|
|
37
|
+
components: false,
|
|
38
|
+
});
|
|
42
39
|
} catch (error) {
|
|
43
40
|
console.log(
|
|
44
41
|
`\nSorry, there was an error adding a project to your workspace: `,
|
|
45
42
|
error
|
|
46
43
|
);
|
|
47
|
-
quit();
|
|
44
|
+
quit("Project selection was not updated.");
|
|
48
45
|
}
|
|
49
46
|
};
|
|
50
47
|
|
package/lib/api.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import axios from "axios";
|
|
2
|
-
import https from "https";
|
|
3
2
|
|
|
4
3
|
import config from "./config";
|
|
5
4
|
import consts from "./consts";
|
|
@@ -10,10 +9,6 @@ export const create = (token?: string) => {
|
|
|
10
9
|
headers: {
|
|
11
10
|
Authorization: `token ${token}`,
|
|
12
11
|
},
|
|
13
|
-
httpsAgent: new https.Agent({
|
|
14
|
-
requestCert: true,
|
|
15
|
-
rejectUnauthorized: false,
|
|
16
|
-
}),
|
|
17
12
|
});
|
|
18
13
|
};
|
|
19
14
|
|
package/lib/config.ts
CHANGED
|
@@ -3,16 +3,30 @@ import path from "path";
|
|
|
3
3
|
import url from "url";
|
|
4
4
|
import yaml from "js-yaml";
|
|
5
5
|
|
|
6
|
+
import output from "./output";
|
|
6
7
|
import consts from "./consts";
|
|
7
8
|
import { Project, ConfigYAML } from "./types";
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
export const DEFAULT_CONFIG_JSON: ConfigYAML = {
|
|
11
|
+
sources: {
|
|
12
|
+
components: { enabled: true },
|
|
13
|
+
},
|
|
14
|
+
variants: true,
|
|
15
|
+
format: "flat",
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const DEFAULT_CONFIG = yaml.dump(DEFAULT_CONFIG_JSON);
|
|
19
|
+
|
|
20
|
+
function createFileIfMissing(filename: string, defaultContents?: any) {
|
|
10
21
|
const dir = path.dirname(filename);
|
|
11
22
|
|
|
23
|
+
// create the directory if it doesn't already exist
|
|
12
24
|
if (!fs.existsSync(dir)) fs.mkdirSync(dir);
|
|
13
25
|
|
|
26
|
+
// create the file if it doesn't already exist
|
|
14
27
|
if (!fs.existsSync(filename)) {
|
|
15
|
-
|
|
28
|
+
// create the file, writing the `defaultContents` if provided
|
|
29
|
+
fs.writeFileSync(filename, defaultContents || "", "utf-8");
|
|
16
30
|
}
|
|
17
31
|
}
|
|
18
32
|
|
|
@@ -26,11 +40,13 @@ function jsonIsGlobalYAML(
|
|
|
26
40
|
return (
|
|
27
41
|
!!json &&
|
|
28
42
|
typeof json === "object" &&
|
|
29
|
-
Object.values(json).every(
|
|
30
|
-
arr
|
|
31
|
-
(
|
|
32
|
-
|
|
33
|
-
|
|
43
|
+
Object.values(json).every(
|
|
44
|
+
(arr) =>
|
|
45
|
+
(arr as any).every &&
|
|
46
|
+
arr.every(
|
|
47
|
+
(val: any) =>
|
|
48
|
+
typeof val === "object" && Object.keys(val).includes("token")
|
|
49
|
+
)
|
|
34
50
|
)
|
|
35
51
|
);
|
|
36
52
|
}
|
|
@@ -45,7 +61,7 @@ function readProjectConfigData(
|
|
|
45
61
|
file = consts.PROJECT_CONFIG_FILE,
|
|
46
62
|
defaultData = {}
|
|
47
63
|
): ConfigYAML {
|
|
48
|
-
createFileIfMissing(file);
|
|
64
|
+
createFileIfMissing(file, DEFAULT_CONFIG);
|
|
49
65
|
const fileContents = fs.readFileSync(file, "utf8");
|
|
50
66
|
const yamlData = yaml.load(fileContents);
|
|
51
67
|
if (jsonIsConfigYAML(yamlData)) {
|
|
@@ -73,10 +89,20 @@ function readGlobalConfigData(
|
|
|
73
89
|
return defaultData;
|
|
74
90
|
}
|
|
75
91
|
|
|
76
|
-
function writeProjectConfigData(file: string, data:
|
|
77
|
-
createFileIfMissing(file);
|
|
92
|
+
function writeProjectConfigData(file: string, data: Partial<ConfigYAML>) {
|
|
93
|
+
createFileIfMissing(file, DEFAULT_CONFIG);
|
|
78
94
|
const existingData = readProjectConfigData(file);
|
|
79
|
-
|
|
95
|
+
|
|
96
|
+
const configData: ConfigYAML = {
|
|
97
|
+
...existingData,
|
|
98
|
+
...data,
|
|
99
|
+
sources: {
|
|
100
|
+
...existingData.sources,
|
|
101
|
+
...data.sources,
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const yamlStr = yaml.dump(configData);
|
|
80
106
|
fs.writeFileSync(file, yamlStr, "utf8");
|
|
81
107
|
}
|
|
82
108
|
|
|
@@ -160,14 +186,22 @@ function dedupeProjectName(projectNames: Set<string>, projectName: string) {
|
|
|
160
186
|
* - an array of valid, deduped projects
|
|
161
187
|
* - the `variants` and `format` config options
|
|
162
188
|
*/
|
|
163
|
-
function parseSourceInformation() {
|
|
164
|
-
const {
|
|
165
|
-
|
|
189
|
+
function parseSourceInformation(file?: string) {
|
|
190
|
+
const {
|
|
191
|
+
sources,
|
|
192
|
+
variants,
|
|
193
|
+
format,
|
|
194
|
+
status,
|
|
195
|
+
richText,
|
|
196
|
+
projects: projectsRoot,
|
|
197
|
+
components: componentsRoot,
|
|
198
|
+
} = readProjectConfigData(file);
|
|
199
|
+
|
|
200
|
+
const projects = sources?.projects || [];
|
|
166
201
|
|
|
167
202
|
const projectNames = new Set<string>();
|
|
168
203
|
const validProjects: Project[] = [];
|
|
169
|
-
|
|
170
|
-
let componentLibraryInProjects = false;
|
|
204
|
+
let hasComponentLibraryInProjects = false;
|
|
171
205
|
|
|
172
206
|
(projects || []).forEach((project) => {
|
|
173
207
|
const isValid = project.id && project.name;
|
|
@@ -176,7 +210,7 @@ function parseSourceInformation() {
|
|
|
176
210
|
}
|
|
177
211
|
|
|
178
212
|
if (project.id === "ditto_component_library") {
|
|
179
|
-
|
|
213
|
+
hasComponentLibraryInProjects = true;
|
|
180
214
|
return;
|
|
181
215
|
}
|
|
182
216
|
|
|
@@ -186,8 +220,7 @@ function parseSourceInformation() {
|
|
|
186
220
|
validProjects.push(project);
|
|
187
221
|
});
|
|
188
222
|
|
|
189
|
-
const shouldFetchComponentLibrary =
|
|
190
|
-
!!components || componentLibraryInProjects;
|
|
223
|
+
const shouldFetchComponentLibrary = Boolean(sources?.components?.enabled);
|
|
191
224
|
|
|
192
225
|
const hasSourceData = !!validProjects.length || shouldFetchComponentLibrary;
|
|
193
226
|
|
|
@@ -198,6 +231,11 @@ function parseSourceInformation() {
|
|
|
198
231
|
variants: variants || false,
|
|
199
232
|
format,
|
|
200
233
|
status,
|
|
234
|
+
richText,
|
|
235
|
+
hasTopLevelProjectsField: !!projectsRoot,
|
|
236
|
+
hasTopLevelComponentsField: !!componentsRoot,
|
|
237
|
+
hasComponentLibraryInProjects,
|
|
238
|
+
componentFolders: sources?.components?.folders || null,
|
|
201
239
|
};
|
|
202
240
|
}
|
|
203
241
|
|
package/lib/ditto.ts
CHANGED
|
@@ -4,93 +4,109 @@ import { program } from "commander";
|
|
|
4
4
|
// to use V8's code cache to speed up instantiation time
|
|
5
5
|
import "v8-compile-cache";
|
|
6
6
|
|
|
7
|
-
import { init,
|
|
7
|
+
import { init, needsTokenOrSource } from "./init/init";
|
|
8
8
|
import { pull } from "./pull";
|
|
9
|
-
|
|
9
|
+
import { quit } from "./utils/quit";
|
|
10
10
|
import addProject from "./add-project";
|
|
11
11
|
import removeProject from "./remove-project";
|
|
12
|
+
|
|
12
13
|
import processMetaOption from "./utils/processMetaOption";
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
15
|
+
type Command = "pull" | "project" | "project add" | "project remove";
|
|
16
|
+
|
|
17
|
+
const COMMANDS = [
|
|
18
|
+
{
|
|
19
|
+
name: "pull",
|
|
20
|
+
description: "Sync copy from Ditto into the current working directory",
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: "project",
|
|
24
|
+
description: "Add a Ditto project to sync copy from",
|
|
25
|
+
commands: [
|
|
26
|
+
{
|
|
27
|
+
name: "add",
|
|
28
|
+
description: "Add a Ditto project to sync copy from",
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: "remove",
|
|
32
|
+
description: "Stop syncing copy from a Ditto project",
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
] as const;
|
|
24
37
|
|
|
25
38
|
const setupCommands = () => {
|
|
26
39
|
program.name("ditto-cli");
|
|
27
|
-
program
|
|
28
|
-
.command("pull")
|
|
29
|
-
.description("Sync copy from Ditto into working directory")
|
|
30
|
-
.action(() => checkInit("pull"));
|
|
31
|
-
|
|
32
|
-
const projectDescription = "Add a Ditto project to sync copy from";
|
|
33
|
-
const projectCommand = program
|
|
34
|
-
.command("project")
|
|
35
|
-
.description(projectDescription)
|
|
36
|
-
.action(() => checkInit("project"));
|
|
37
40
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
COMMANDS.forEach((config) => {
|
|
42
|
+
const cmd = program
|
|
43
|
+
.command(config.name)
|
|
44
|
+
.description(config.description)
|
|
45
|
+
.action(() => executeCommand(config.name));
|
|
42
46
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
+
if ("commands" in config) {
|
|
48
|
+
config.commands.forEach((nestedCommand) => {
|
|
49
|
+
cmd
|
|
50
|
+
.command(nestedCommand.name)
|
|
51
|
+
.description(nestedCommand.description)
|
|
52
|
+
.action(() => executeCommand(`${config.name} ${nestedCommand.name}`));
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
});
|
|
47
56
|
};
|
|
48
57
|
|
|
49
58
|
const setupOptions = () => {
|
|
50
59
|
program.option(
|
|
51
60
|
"-m, --meta <data...>",
|
|
52
|
-
"
|
|
61
|
+
"Include arbitrary data in requests to the Ditto API. Ex: -m githubActionRequest:true trigger:manual"
|
|
53
62
|
);
|
|
54
63
|
};
|
|
55
64
|
|
|
56
|
-
const
|
|
57
|
-
|
|
65
|
+
const executeCommand = async (command: Command | "none"): Promise<void> => {
|
|
66
|
+
const needsInitialization = needsTokenOrSource();
|
|
67
|
+
if (needsInitialization) {
|
|
58
68
|
try {
|
|
59
69
|
await init();
|
|
60
|
-
if (command === "pull") main(); // re-run to actually pull text now that init is finished
|
|
61
70
|
} catch (error) {
|
|
62
|
-
quit();
|
|
71
|
+
quit("Exiting Ditto CLI...");
|
|
72
|
+
return;
|
|
63
73
|
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const { meta } = program.opts();
|
|
77
|
+
switch (command) {
|
|
78
|
+
case "none":
|
|
79
|
+
case "pull": {
|
|
80
|
+
return pull({ meta: processMetaOption(meta) });
|
|
81
|
+
}
|
|
82
|
+
case "project":
|
|
83
|
+
case "project add": {
|
|
84
|
+
// initialization already includes the selection of a source,
|
|
85
|
+
// so if `project add` is called during initialization, don't
|
|
86
|
+
// prompt the user to select a source again
|
|
87
|
+
if (needsInitialization) return;
|
|
88
|
+
|
|
89
|
+
return addProject();
|
|
90
|
+
}
|
|
91
|
+
case "project remove": {
|
|
92
|
+
return removeProject();
|
|
93
|
+
}
|
|
94
|
+
default: {
|
|
95
|
+
quit("Exiting Ditto CLI...");
|
|
96
|
+
return;
|
|
83
97
|
}
|
|
84
98
|
}
|
|
85
99
|
};
|
|
86
100
|
|
|
87
101
|
const main = async () => {
|
|
102
|
+
setupCommands();
|
|
103
|
+
setupOptions();
|
|
104
|
+
|
|
88
105
|
if (process.argv.length <= 2 && process.argv[1].includes("ditto-cli")) {
|
|
89
|
-
await
|
|
90
|
-
|
|
91
|
-
setupCommands();
|
|
92
|
-
setupOptions();
|
|
106
|
+
await executeCommand("none");
|
|
107
|
+
return;
|
|
93
108
|
}
|
|
109
|
+
|
|
94
110
|
program.parse(process.argv);
|
|
95
111
|
};
|
|
96
112
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { AxiosRequestConfig } from "axios";
|
|
2
|
+
import api from "../api";
|
|
3
|
+
import { PullOptions } from "../pull";
|
|
4
|
+
import { SourceInformation } from "../types";
|
|
5
|
+
|
|
6
|
+
export async function fetchVariants(
|
|
7
|
+
source: SourceInformation,
|
|
8
|
+
options: PullOptions = {}
|
|
9
|
+
) {
|
|
10
|
+
if (!source.variants) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const { shouldFetchComponentLibrary, validProjects } = source;
|
|
15
|
+
|
|
16
|
+
const config: AxiosRequestConfig = {
|
|
17
|
+
params: { ...options?.meta },
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// if we're not syncing from the component library, then we pass the project ids
|
|
21
|
+
// to limit the list of returned variants to only those that are relevant for the
|
|
22
|
+
// specified projects
|
|
23
|
+
if (validProjects.length && !shouldFetchComponentLibrary) {
|
|
24
|
+
config.params.projectIds = validProjects.map(({ id }) => id);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const { data } = await api.get<{ apiID: string }[]>("/variants", config);
|
|
28
|
+
|
|
29
|
+
return data;
|
|
30
|
+
}
|
package/lib/init/init.ts
CHANGED
|
@@ -4,13 +4,15 @@ import boxen from "boxen";
|
|
|
4
4
|
import chalk from "chalk";
|
|
5
5
|
import projectsToText from "../utils/projectsToText";
|
|
6
6
|
|
|
7
|
-
import { needsSource,
|
|
7
|
+
import { needsSource, collectAndSaveSource } from "./project";
|
|
8
8
|
import { needsToken, collectAndSaveToken } from "./token";
|
|
9
9
|
|
|
10
10
|
import config from "../config";
|
|
11
|
+
import output from "../output";
|
|
11
12
|
import sourcesToText from "../utils/sourcesToText";
|
|
13
|
+
import { quit } from "../utils/quit";
|
|
12
14
|
|
|
13
|
-
export const
|
|
15
|
+
export const needsTokenOrSource = () => needsToken() || needsSource();
|
|
14
16
|
|
|
15
17
|
function welcome() {
|
|
16
18
|
const msg = chalk.white(`${chalk.bold(
|
|
@@ -29,11 +31,41 @@ export const init = async () => {
|
|
|
29
31
|
await collectAndSaveToken();
|
|
30
32
|
}
|
|
31
33
|
|
|
32
|
-
const {
|
|
33
|
-
|
|
34
|
+
const {
|
|
35
|
+
hasSourceData,
|
|
36
|
+
validProjects,
|
|
37
|
+
shouldFetchComponentLibrary,
|
|
38
|
+
hasTopLevelComponentsField,
|
|
39
|
+
hasTopLevelProjectsField,
|
|
40
|
+
} = config.parseSourceInformation();
|
|
41
|
+
|
|
42
|
+
if (hasTopLevelProjectsField) {
|
|
43
|
+
return quit(`${output.errorText(
|
|
44
|
+
`Support for ${output.warnText(
|
|
45
|
+
"projects"
|
|
46
|
+
)} as a top-level field has been removed; please configure ${output.warnText(
|
|
47
|
+
"sources.projects"
|
|
48
|
+
)} instead.`
|
|
49
|
+
)}
|
|
50
|
+
See ${output.url("https://github.com/dittowords/cli")} for more information.`);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (hasTopLevelComponentsField) {
|
|
54
|
+
return quit(
|
|
55
|
+
`${output.errorText(
|
|
56
|
+
"Support for `components` as a top-level field has been removed; please configure `sources.components` instead."
|
|
57
|
+
)}
|
|
58
|
+
See ${output.url("https://github.com/dittowords/cli")} for more information.`
|
|
59
|
+
);
|
|
60
|
+
}
|
|
34
61
|
|
|
35
62
|
if (!hasSourceData) {
|
|
36
|
-
|
|
63
|
+
console.log(
|
|
64
|
+
`Looks like there are no Ditto sources selected for your current directory: ${output.info(
|
|
65
|
+
process.cwd()
|
|
66
|
+
)}.`
|
|
67
|
+
);
|
|
68
|
+
await collectAndSaveSource({ initialize: true, components: true });
|
|
37
69
|
return;
|
|
38
70
|
}
|
|
39
71
|
|
|
@@ -44,4 +76,4 @@ export const init = async () => {
|
|
|
44
76
|
console.log(message);
|
|
45
77
|
};
|
|
46
78
|
|
|
47
|
-
export default {
|
|
79
|
+
export default { init };
|
package/lib/init/project.test.ts
CHANGED
|
@@ -42,8 +42,8 @@ describe("saveProject", () => {
|
|
|
42
42
|
it("creates a config file with config data", () => {
|
|
43
43
|
const fileContents = fs.readFileSync(configFile, "utf8");
|
|
44
44
|
const data = yaml.load(fileContents);
|
|
45
|
-
expect(data.projects).toBeDefined();
|
|
46
|
-
expect(data.projects[0].name).toEqual(projectName);
|
|
47
|
-
expect(data.projects[0].id).toEqual(projectId);
|
|
45
|
+
expect(data.sources.projects).toBeDefined();
|
|
46
|
+
expect(data.sources.projects[0].name).toEqual(projectName);
|
|
47
|
+
expect(data.sources.projects[0].id).toEqual(projectId);
|
|
48
48
|
});
|
|
49
49
|
});
|
package/lib/init/project.ts
CHANGED
|
@@ -12,25 +12,18 @@ import {
|
|
|
12
12
|
import promptForProject from "../utils/promptForProject";
|
|
13
13
|
import { AxiosResponse } from "axios";
|
|
14
14
|
import { Project, Token } from "../types";
|
|
15
|
-
|
|
16
|
-
function quit(exitCode = 2) {
|
|
17
|
-
console.log("\nExiting Ditto CLI...\n");
|
|
18
|
-
process.exitCode = exitCode;
|
|
19
|
-
process.exit();
|
|
20
|
-
}
|
|
15
|
+
import { quit } from "../utils/quit";
|
|
21
16
|
|
|
22
17
|
function saveProject(file: string, name: string, id: string) {
|
|
23
|
-
// old functionality included "ditto_component_library" in the `projects`
|
|
24
|
-
// array, but we want to always treat the component library as a separate
|
|
25
|
-
// entity and use the new notation of a top-level `components` key
|
|
26
18
|
if (id === "components") {
|
|
27
|
-
config.writeProjectConfigData(file, {
|
|
19
|
+
config.writeProjectConfigData(file, {
|
|
20
|
+
sources: { components: { enabled: true } },
|
|
21
|
+
});
|
|
28
22
|
return;
|
|
29
23
|
}
|
|
30
24
|
|
|
31
|
-
const projects = [...getSelectedProjects(), { name, id }];
|
|
32
|
-
|
|
33
|
-
config.writeProjectConfigData(file, { projects });
|
|
25
|
+
const projects = [...getSelectedProjects(file), { name, id }];
|
|
26
|
+
config.writeProjectConfigData(file, { sources: { projects } });
|
|
34
27
|
}
|
|
35
28
|
|
|
36
29
|
export const needsSource = () => {
|
|
@@ -44,12 +37,8 @@ async function askForAnotherToken() {
|
|
|
44
37
|
await collectAndSaveToken(message);
|
|
45
38
|
}
|
|
46
39
|
|
|
47
|
-
async function listProjects(
|
|
48
|
-
|
|
49
|
-
projectsAlreadySelected: Project[],
|
|
50
|
-
componentsSelected: boolean
|
|
51
|
-
) {
|
|
52
|
-
const spinner = ora("Fetching projects in your workspace...");
|
|
40
|
+
async function listProjects(token: Token, projectsAlreadySelected: Project[]) {
|
|
41
|
+
const spinner = ora("Fetching sources in your workspace...");
|
|
53
42
|
spinner.start();
|
|
54
43
|
|
|
55
44
|
let response: AxiosResponse<{ id: string; name: string }[]>;
|
|
@@ -64,35 +53,37 @@ async function listProjects(
|
|
|
64
53
|
throw e;
|
|
65
54
|
}
|
|
66
55
|
|
|
56
|
+
const projectsAlreadySelectedSet = projectsAlreadySelected.reduce(
|
|
57
|
+
(set, project) => set.add(project.id.toString()),
|
|
58
|
+
new Set<string>()
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
const result = response.data.filter(
|
|
62
|
+
({ id }) =>
|
|
63
|
+
// covers an edge case where v0 of the API includes the component library
|
|
64
|
+
// in the response from the `/project-names` endpoint
|
|
65
|
+
id !== "ditto_component_library" &&
|
|
66
|
+
!projectsAlreadySelectedSet.has(id.toString())
|
|
67
|
+
);
|
|
68
|
+
|
|
67
69
|
spinner.stop();
|
|
68
|
-
return response.data.filter(({ id }: Project) => {
|
|
69
|
-
if (id === "ditto_component_library") {
|
|
70
|
-
return !componentsSelected;
|
|
71
|
-
} else {
|
|
72
|
-
return !projectsAlreadySelected.some((project) => project.id === id);
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
70
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
if (initialize) {
|
|
80
|
-
console.log(
|
|
81
|
-
`Looks like there are no Ditto projects selected for your current directory: ${output.info(
|
|
82
|
-
path
|
|
83
|
-
)}.`
|
|
84
|
-
);
|
|
85
|
-
}
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
86
73
|
|
|
74
|
+
async function collectSource(token: Token, includeComponents: boolean) {
|
|
87
75
|
const projectsAlreadySelected = getSelectedProjects();
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
76
|
+
const componentSourceSelected = getIsUsingComponents();
|
|
77
|
+
|
|
78
|
+
let sources = await listProjects(token, projectsAlreadySelected);
|
|
79
|
+
if (includeComponents && !componentSourceSelected) {
|
|
80
|
+
sources = [
|
|
81
|
+
{ id: "ditto_component_library", name: "Ditto Component Library" },
|
|
82
|
+
...sources,
|
|
83
|
+
];
|
|
84
|
+
}
|
|
94
85
|
|
|
95
|
-
if (!
|
|
86
|
+
if (!sources?.length) {
|
|
96
87
|
console.log("You're currently syncing all projects in your workspace.");
|
|
97
88
|
console.log(
|
|
98
89
|
output.warnText(
|
|
@@ -102,24 +93,22 @@ async function collectProject(token: Token, initialize: boolean) {
|
|
|
102
93
|
return null;
|
|
103
94
|
}
|
|
104
95
|
|
|
105
|
-
const nonInitPrompt = usingComponents
|
|
106
|
-
? "Add a project"
|
|
107
|
-
: "Add a project or library";
|
|
108
|
-
|
|
109
96
|
return promptForProject({
|
|
110
|
-
projects,
|
|
111
|
-
message:
|
|
112
|
-
? "Choose the project or library you'd like to sync text from"
|
|
113
|
-
: nonInitPrompt,
|
|
97
|
+
projects: sources,
|
|
98
|
+
message: "Choose the source you'd like to sync text from",
|
|
114
99
|
});
|
|
115
100
|
}
|
|
116
101
|
|
|
117
|
-
export const
|
|
102
|
+
export const collectAndSaveSource = async (
|
|
103
|
+
{ components = false }: { initialize?: boolean; components?: boolean } = {
|
|
104
|
+
components: false,
|
|
105
|
+
}
|
|
106
|
+
) => {
|
|
118
107
|
try {
|
|
119
108
|
const token = config.getToken(consts.CONFIG_FILE, consts.API_HOST);
|
|
120
|
-
const project = await
|
|
109
|
+
const project = await collectSource(token, components);
|
|
121
110
|
if (!project) {
|
|
122
|
-
quit(0);
|
|
111
|
+
quit("", 0);
|
|
123
112
|
return;
|
|
124
113
|
}
|
|
125
114
|
|
|
@@ -127,7 +116,7 @@ export const collectAndSaveProject = async (initialize = false) => {
|
|
|
127
116
|
"\n" +
|
|
128
117
|
`Thanks for adding ${output.info(
|
|
129
118
|
project.name
|
|
130
|
-
)} to your selected
|
|
119
|
+
)} to your selected sources.\n` +
|
|
131
120
|
`We saved your updated configuration to: ${output.info(
|
|
132
121
|
consts.PROJECT_CONFIG_FILE
|
|
133
122
|
)}\n`
|
|
@@ -138,13 +127,13 @@ export const collectAndSaveProject = async (initialize = false) => {
|
|
|
138
127
|
console.log(e);
|
|
139
128
|
if (e.response && e.response.status === 404) {
|
|
140
129
|
await askForAnotherToken();
|
|
141
|
-
await
|
|
130
|
+
await collectAndSaveSource({ components });
|
|
142
131
|
} else {
|
|
143
|
-
quit();
|
|
132
|
+
quit("", 2);
|
|
144
133
|
}
|
|
145
134
|
}
|
|
146
135
|
};
|
|
147
136
|
|
|
148
137
|
export const _testing = { saveProject, needsSource };
|
|
149
138
|
|
|
150
|
-
export default { needsSource,
|
|
139
|
+
export default { needsSource, collectAndSaveSource };
|