@dittowords/cli 2.5.0 → 2.5.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 +14 -7
- package/babel.config.js +2 -8
- package/bin/add-project.js +38 -0
- package/bin/add-project.js.map +1 -0
- package/bin/api.js +20 -0
- package/bin/api.js.map +1 -0
- package/bin/config.js +174 -0
- package/bin/config.js.map +1 -0
- package/bin/consts.js +21 -0
- package/bin/consts.js.map +1 -0
- package/bin/ditto.js +71 -74
- package/bin/ditto.js.map +1 -0
- package/bin/init/init.js +39 -0
- package/bin/init/init.js.map +1 -0
- package/bin/init/project.js +115 -0
- package/bin/init/project.js.map +1 -0
- package/bin/init/token.js +89 -0
- package/bin/init/token.js.map +1 -0
- package/bin/output.js +34 -0
- package/bin/output.js.map +1 -0
- package/bin/pull.js +288 -0
- package/bin/pull.js.map +1 -0
- package/bin/remove-project.js +40 -0
- package/bin/remove-project.js.map +1 -0
- package/bin/types.js +3 -0
- package/bin/types.js.map +1 -0
- package/bin/utils/getSelectedProjects.js +76 -0
- package/bin/utils/getSelectedProjects.js.map +1 -0
- package/bin/utils/processMetaOption.js +15 -0
- package/bin/utils/processMetaOption.js.map +1 -0
- package/bin/utils/projectsToText.js +16 -0
- package/bin/utils/projectsToText.js.map +1 -0
- package/bin/utils/promptForProject.js +44 -0
- package/bin/utils/promptForProject.js.map +1 -0
- package/bin/utils/sourcesToText.js +25 -0
- package/bin/utils/sourcesToText.js.map +1 -0
- package/jest.config.js +1 -1
- package/lib/add-project.ts +51 -0
- package/lib/api.ts +15 -0
- package/lib/{config.test.js → config.test.ts} +14 -25
- package/lib/config.ts +214 -0
- package/lib/consts.ts +20 -0
- package/lib/ditto.ts +97 -0
- package/lib/init/{init.js → init.ts} +11 -12
- package/lib/init/project.test.ts +49 -0
- package/lib/init/{project.js → project.ts} +58 -32
- package/lib/init/{token.test.js → token.test.ts} +3 -3
- package/lib/init/{token.js → token.ts} +23 -19
- package/lib/output.ts +21 -0
- package/lib/pull.test.ts +142 -0
- package/lib/{pull.js → pull.ts} +119 -92
- package/lib/remove-project.ts +50 -0
- package/lib/types.ts +23 -0
- package/lib/utils/getSelectedProjects.ts +55 -0
- package/lib/utils/processMetaOption.test.ts +18 -0
- package/lib/utils/processMetaOption.ts +16 -0
- package/lib/utils/{projectsToText.js → projectsToText.ts} +5 -4
- package/lib/utils/{promptForProject.js → promptForProject.ts} +18 -9
- package/lib/utils/{sourcesToText.js → sourcesToText.ts} +6 -5
- package/package.json +20 -15
- package/testing/fixtures/project-config-pull.yml +0 -0
- package/tsconfig.json +12 -0
- package/lib/add-project.js +0 -30
- package/lib/api.js +0 -18
- package/lib/config.js +0 -169
- package/lib/consts.js +0 -14
- package/lib/init/project.test.js +0 -99
- package/lib/output.js +0 -21
- package/lib/pull.test.js +0 -173
- package/lib/remove-project.js +0 -39
- package/lib/utils/getSelectedProjects.js +0 -35
- package/lib/utils/processMetaOption.js +0 -16
- package/lib/utils/processMetaOption.test.js +0 -16
package/lib/{pull.js → pull.ts}
RENAMED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
import ora from "ora";
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
import api from "./api";
|
|
7
|
+
import config from "./config";
|
|
8
|
+
import consts from "./consts";
|
|
9
|
+
import output from "./output";
|
|
10
|
+
import { collectAndSaveToken } from "./init/token";
|
|
11
|
+
import sourcesToText from "./utils/sourcesToText";
|
|
12
|
+
import { SourceInformation, Token, Project } from "./types";
|
|
13
13
|
|
|
14
14
|
const NON_DEFAULT_FORMATS = ["flat", "structured"];
|
|
15
15
|
|
|
16
16
|
const DEFAULT_FORMAT_KEYS = ["projects", "exported_at"];
|
|
17
|
-
const hasVariantData = (data) => {
|
|
17
|
+
const hasVariantData = (data: any) => {
|
|
18
18
|
const hasTopLevelKeys =
|
|
19
19
|
Object.keys(data).filter((key) => !DEFAULT_FORMAT_KEYS.includes(key))
|
|
20
20
|
.length > 0;
|
|
@@ -38,15 +38,22 @@ async function askForAnotherToken() {
|
|
|
38
38
|
* - if format is `flat` or `structured`, fetch data for each project from `/project/:project_id` and
|
|
39
39
|
* save in `{projectName}-${variantApiId}.json`
|
|
40
40
|
*/
|
|
41
|
-
async function downloadAndSaveVariant(
|
|
42
|
-
|
|
41
|
+
async function downloadAndSaveVariant(
|
|
42
|
+
variantApiId: string | null,
|
|
43
|
+
projects: Project[],
|
|
44
|
+
format: string | undefined,
|
|
45
|
+
token?: Token
|
|
46
|
+
) {
|
|
47
|
+
const params: Record<string, string | null> = {
|
|
48
|
+
variant: variantApiId,
|
|
49
|
+
};
|
|
43
50
|
if (format) {
|
|
44
51
|
params.format = format;
|
|
45
52
|
}
|
|
46
53
|
|
|
47
|
-
if (NON_DEFAULT_FORMATS.includes(format)) {
|
|
54
|
+
if (format && NON_DEFAULT_FORMATS.includes(format)) {
|
|
48
55
|
const savedMessages = await Promise.all(
|
|
49
|
-
projects.map(async ({ id, fileName }) => {
|
|
56
|
+
projects.map(async ({ id, fileName }: Project) => {
|
|
50
57
|
const { data } = await api.get(`/projects/${id}`, {
|
|
51
58
|
params,
|
|
52
59
|
headers: { Authorization: `token ${token}` },
|
|
@@ -89,10 +96,12 @@ async function downloadAndSaveVariant(variantApiId, projects, format, token) {
|
|
|
89
96
|
}
|
|
90
97
|
}
|
|
91
98
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
99
|
+
async function downloadAndSaveVariants(
|
|
100
|
+
projects: Project[],
|
|
101
|
+
format: string | undefined,
|
|
102
|
+
token?: Token,
|
|
103
|
+
options?: PullOptions
|
|
104
|
+
) {
|
|
96
105
|
const meta = options ? options.meta : {};
|
|
97
106
|
|
|
98
107
|
const { data: variants } = await api.get("/variants", {
|
|
@@ -105,7 +114,7 @@ async function downloadAndSaveVariants(projects, format, token, options) {
|
|
|
105
114
|
|
|
106
115
|
const messages = await Promise.all([
|
|
107
116
|
downloadAndSaveVariant(null, projects, format, token),
|
|
108
|
-
...variants.map(({ apiID }) =>
|
|
117
|
+
...variants.map(({ apiID }: { apiID: string }) =>
|
|
109
118
|
downloadAndSaveVariant(apiID, projects, format, token)
|
|
110
119
|
),
|
|
111
120
|
]);
|
|
@@ -113,10 +122,12 @@ async function downloadAndSaveVariants(projects, format, token, options) {
|
|
|
113
122
|
return messages.join("");
|
|
114
123
|
}
|
|
115
124
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
125
|
+
async function downloadAndSaveBase(
|
|
126
|
+
projects: Project[],
|
|
127
|
+
format: string | undefined,
|
|
128
|
+
token?: Token,
|
|
129
|
+
options?: PullOptions
|
|
130
|
+
) {
|
|
120
131
|
const meta = options ? options.meta : {};
|
|
121
132
|
|
|
122
133
|
const params = {
|
|
@@ -126,9 +137,9 @@ async function downloadAndSaveBase(projects, format, token, options) {
|
|
|
126
137
|
params.format = format;
|
|
127
138
|
}
|
|
128
139
|
|
|
129
|
-
if (NON_DEFAULT_FORMATS.includes(format)) {
|
|
140
|
+
if (format && NON_DEFAULT_FORMATS.includes(format)) {
|
|
130
141
|
const savedMessages = await Promise.all(
|
|
131
|
-
projects.map(async ({ id, fileName }) => {
|
|
142
|
+
projects.map(async ({ id, fileName }: Project) => {
|
|
132
143
|
const { data } = await api.get(`/projects/${id}`, {
|
|
133
144
|
params,
|
|
134
145
|
headers: { Authorization: `token ${token}` },
|
|
@@ -160,7 +171,7 @@ async function downloadAndSaveBase(projects, format, token, options) {
|
|
|
160
171
|
}
|
|
161
172
|
}
|
|
162
173
|
|
|
163
|
-
function getSavedMessage(file) {
|
|
174
|
+
function getSavedMessage(file: string) {
|
|
164
175
|
return `Successfully saved to ${output.info(file)}\n`;
|
|
165
176
|
}
|
|
166
177
|
|
|
@@ -181,7 +192,7 @@ function cleanOutputFiles() {
|
|
|
181
192
|
|
|
182
193
|
// compatability with legacy method of specifying project ids
|
|
183
194
|
// that is still used by the default format
|
|
184
|
-
const stringifyProjectId = (projectId) =>
|
|
195
|
+
const stringifyProjectId = (projectId: string) =>
|
|
185
196
|
projectId === "ditto_component_library" ? projectId : `project_${projectId}`;
|
|
186
197
|
|
|
187
198
|
/**
|
|
@@ -195,74 +206,88 @@ const stringifyProjectId = (projectId) =>
|
|
|
195
206
|
* independent of the CLI configuration used to fetch
|
|
196
207
|
* data from Ditto.
|
|
197
208
|
*/
|
|
198
|
-
function generateJsDriver(
|
|
209
|
+
function generateJsDriver(
|
|
210
|
+
projects: Project[],
|
|
211
|
+
variants: boolean,
|
|
212
|
+
format: string | undefined
|
|
213
|
+
) {
|
|
199
214
|
const fileNames = fs
|
|
200
215
|
.readdirSync(consts.TEXT_DIR)
|
|
201
216
|
.filter((fileName) => /\.json$/.test(fileName));
|
|
202
217
|
|
|
203
|
-
const projectIdsByName = projects.reduce(
|
|
204
|
-
(agg, project) =>
|
|
218
|
+
const projectIdsByName: Record<string, string> = projects.reduce(
|
|
219
|
+
(agg, project) => {
|
|
220
|
+
if (project.fileName) {
|
|
221
|
+
return { ...agg, [project.fileName]: project.id };
|
|
222
|
+
}
|
|
223
|
+
return agg;
|
|
224
|
+
},
|
|
205
225
|
{}
|
|
206
226
|
);
|
|
207
227
|
|
|
208
|
-
const data = fileNames.reduce(
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
228
|
+
const data = fileNames.reduce(
|
|
229
|
+
(obj: Record<string, Record<string, string>>, fileName) => {
|
|
230
|
+
// filename format: {project-name}__{variant-api-id}.json
|
|
231
|
+
// file format: flat or structured
|
|
232
|
+
if (variants && format) {
|
|
233
|
+
const [projectName, rest] = fileName.split("__");
|
|
234
|
+
const [variantApiId] = rest.split(".");
|
|
235
|
+
|
|
236
|
+
const projectId = projectIdsByName[projectName];
|
|
237
|
+
if (!projectId) {
|
|
238
|
+
throw new Error(`Couldn't find id for ${projectName}`);
|
|
239
|
+
}
|
|
214
240
|
|
|
215
|
-
|
|
216
|
-
if (!projectId) {
|
|
217
|
-
throw new Error(`Couldn't find id for ${projectName}`);
|
|
218
|
-
}
|
|
241
|
+
const projectIdStr = stringifyProjectId(projectId);
|
|
219
242
|
|
|
220
|
-
|
|
243
|
+
if (!obj[projectIdStr]) {
|
|
244
|
+
obj[projectIdStr] = {};
|
|
245
|
+
}
|
|
221
246
|
|
|
222
|
-
|
|
223
|
-
obj[projectIdStr] = {};
|
|
247
|
+
obj[projectIdStr][variantApiId] = `require('./${fileName}')`;
|
|
224
248
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
249
|
+
// filename format: {variant-api-id}.json
|
|
250
|
+
// file format: default
|
|
251
|
+
else if (variants) {
|
|
252
|
+
const file = require(path.resolve(consts.TEXT_DIR, `./${fileName}`));
|
|
253
|
+
const [variantApiId] = fileName.split(".");
|
|
254
|
+
|
|
255
|
+
Object.keys(file.projects).forEach((projectId) => {
|
|
256
|
+
if (!obj[projectId]) {
|
|
257
|
+
obj[projectId] = {};
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const project = file.projects[projectId];
|
|
261
|
+
obj[projectId][variantApiId] = project.frames || project.components;
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
// filename format: {project-name}.json
|
|
265
|
+
// file format: flat or structured
|
|
266
|
+
else if (format) {
|
|
267
|
+
const [projectName] = fileName.split(".");
|
|
268
|
+
const projectId = projectIdsByName[projectName];
|
|
269
|
+
if (!projectId) {
|
|
270
|
+
throw new Error(`Couldn't find id for ${projectName}`);
|
|
237
271
|
}
|
|
238
272
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
273
|
+
obj[stringifyProjectId(projectId)] = {
|
|
274
|
+
base: `require('./${fileName}')`,
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
// filename format: text.json (single file)
|
|
278
|
+
// file format: default
|
|
279
|
+
else {
|
|
280
|
+
const file = require(path.resolve(consts.TEXT_DIR, `./${fileName}`));
|
|
281
|
+
Object.keys(file.projects).forEach((projectId) => {
|
|
282
|
+
const project = file.projects[projectId];
|
|
283
|
+
obj[projectId] = { base: project.frames || project.components };
|
|
284
|
+
});
|
|
250
285
|
}
|
|
251
286
|
|
|
252
|
-
obj
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
else {
|
|
257
|
-
const file = require(path.resolve(consts.TEXT_DIR, `./${fileName}`));
|
|
258
|
-
Object.keys(file.projects).forEach((projectId) => {
|
|
259
|
-
const project = file.projects[projectId];
|
|
260
|
-
obj[projectId] = { base: project.frames || project.components };
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
return obj;
|
|
265
|
-
}, {});
|
|
287
|
+
return obj;
|
|
288
|
+
},
|
|
289
|
+
{}
|
|
290
|
+
);
|
|
266
291
|
|
|
267
292
|
let dataString = `module.exports = ${JSON.stringify(data, null, 2)}`
|
|
268
293
|
// remove quotes around require statements
|
|
@@ -274,10 +299,11 @@ function generateJsDriver(projects, variants, format) {
|
|
|
274
299
|
return `Generated .js SDK driver at ${output.info(filePath)}`;
|
|
275
300
|
}
|
|
276
301
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
302
|
+
async function downloadAndSave(
|
|
303
|
+
sourceInformation: SourceInformation,
|
|
304
|
+
token?: Token,
|
|
305
|
+
options?: PullOptions
|
|
306
|
+
) {
|
|
281
307
|
const { validProjects, variants, format, shouldFetchComponentLibrary } =
|
|
282
308
|
sourceInformation;
|
|
283
309
|
|
|
@@ -314,7 +340,7 @@ async function downloadAndSave(sourceInformation, token, options) {
|
|
|
314
340
|
|
|
315
341
|
spinner.stop();
|
|
316
342
|
return console.log(msg);
|
|
317
|
-
} catch (e) {
|
|
343
|
+
} catch (e: any) {
|
|
318
344
|
spinner.stop();
|
|
319
345
|
let error = e.message;
|
|
320
346
|
if (e.response && e.response.status === 404) {
|
|
@@ -351,18 +377,19 @@ async function downloadAndSave(sourceInformation, token, options) {
|
|
|
351
377
|
}
|
|
352
378
|
}
|
|
353
379
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
380
|
+
interface PullOptions {
|
|
381
|
+
meta?: Record<string, string>;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
export const pull = (options?: PullOptions) => {
|
|
358
385
|
const meta = options ? options.meta : {};
|
|
359
386
|
const token = config.getToken(consts.CONFIG_FILE, consts.API_HOST);
|
|
360
387
|
const sourceInformation = config.parseSourceInformation();
|
|
361
388
|
|
|
362
389
|
return downloadAndSave(sourceInformation, token, { meta });
|
|
363
|
-
}
|
|
390
|
+
};
|
|
364
391
|
|
|
365
|
-
|
|
392
|
+
export default {
|
|
366
393
|
pull,
|
|
367
394
|
_testing: {
|
|
368
395
|
cleanOutputFiles,
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import config from "./config";
|
|
2
|
+
import consts from "./consts";
|
|
3
|
+
import output from "./output";
|
|
4
|
+
import {
|
|
5
|
+
getSelectedProjects,
|
|
6
|
+
getIsUsingComponents,
|
|
7
|
+
} from "./utils/getSelectedProjects";
|
|
8
|
+
import promptForProject from "./utils/promptForProject";
|
|
9
|
+
|
|
10
|
+
async function removeProject() {
|
|
11
|
+
const projects = getSelectedProjects();
|
|
12
|
+
const isUsingComponents = getIsUsingComponents();
|
|
13
|
+
if (!projects.length && !isUsingComponents) {
|
|
14
|
+
console.log(
|
|
15
|
+
"\n" +
|
|
16
|
+
"No projects found in your current configuration.\n" +
|
|
17
|
+
`Try adding one with: ${output.info("ditto-cli project add")}\n`
|
|
18
|
+
);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const allProjects = isUsingComponents
|
|
23
|
+
? [{ id: "components", name: "Ditto Component Library" }, ...projects]
|
|
24
|
+
: projects;
|
|
25
|
+
|
|
26
|
+
const projectToRemove = await promptForProject({
|
|
27
|
+
projects: allProjects,
|
|
28
|
+
message: isUsingComponents
|
|
29
|
+
? "Select a project or library to remove"
|
|
30
|
+
: "Select a project to remove",
|
|
31
|
+
});
|
|
32
|
+
if (!projectToRemove) return;
|
|
33
|
+
|
|
34
|
+
config.writeProjectConfigData(consts.PROJECT_CONFIG_FILE, {
|
|
35
|
+
components: isUsingComponents && projectToRemove.id !== "components",
|
|
36
|
+
projects: projects.filter(({ id }) => id !== projectToRemove.id),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
console.log(
|
|
40
|
+
`\n${output.info(
|
|
41
|
+
projectToRemove.name
|
|
42
|
+
)} has been removed from your selected projects. ` +
|
|
43
|
+
`\nWe saved your updated configuration to: ${output.info(
|
|
44
|
+
consts.PROJECT_CONFIG_FILE
|
|
45
|
+
)}` +
|
|
46
|
+
"\n"
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export default removeProject;
|
package/lib/types.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface Project {
|
|
2
|
+
name: string;
|
|
3
|
+
id: string;
|
|
4
|
+
url?: string;
|
|
5
|
+
fileName?: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface ConfigYAML {
|
|
9
|
+
components?: boolean;
|
|
10
|
+
projects?: Project[];
|
|
11
|
+
format?: string;
|
|
12
|
+
variants?: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface SourceInformation {
|
|
16
|
+
hasSourceData: boolean;
|
|
17
|
+
validProjects: Project[];
|
|
18
|
+
shouldFetchComponentLibrary: boolean;
|
|
19
|
+
variants: boolean;
|
|
20
|
+
format: string | undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type Token = string | undefined;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import yaml, { YAMLException } from "js-yaml";
|
|
3
|
+
|
|
4
|
+
import { PROJECT_CONFIG_FILE } from "../consts";
|
|
5
|
+
import { ConfigYAML, Project } from "../types";
|
|
6
|
+
|
|
7
|
+
function jsonIsConfigYAML(json: unknown): json is ConfigYAML {
|
|
8
|
+
return typeof json === "object";
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function yamlToJson(_yaml: string): ConfigYAML | null {
|
|
12
|
+
try {
|
|
13
|
+
let configYaml = yaml.load(_yaml);
|
|
14
|
+
if (!jsonIsConfigYAML(configYaml)) {
|
|
15
|
+
return {};
|
|
16
|
+
}
|
|
17
|
+
return configYaml;
|
|
18
|
+
} catch (e) {
|
|
19
|
+
if (e instanceof YAMLException) {
|
|
20
|
+
return null;
|
|
21
|
+
} else {
|
|
22
|
+
throw e;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Returns an array containing all valid projects ({ id, name })
|
|
29
|
+
* currently contained in the project config file.
|
|
30
|
+
*/
|
|
31
|
+
export const getSelectedProjects = (
|
|
32
|
+
configFile = PROJECT_CONFIG_FILE
|
|
33
|
+
): Project[] => {
|
|
34
|
+
if (!fs.existsSync(configFile)) return [];
|
|
35
|
+
|
|
36
|
+
const contentYaml = fs.readFileSync(configFile, "utf8");
|
|
37
|
+
const contentJson = yamlToJson(contentYaml);
|
|
38
|
+
|
|
39
|
+
if (!(contentJson && contentJson.projects)) {
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return contentJson.projects.filter(({ name, id }) => name && id);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const getIsUsingComponents = (
|
|
47
|
+
configFile = PROJECT_CONFIG_FILE
|
|
48
|
+
): boolean => {
|
|
49
|
+
if (!fs.existsSync(configFile)) return false;
|
|
50
|
+
|
|
51
|
+
const contentYaml = fs.readFileSync(configFile, "utf8");
|
|
52
|
+
const contentJson = yamlToJson(contentYaml);
|
|
53
|
+
|
|
54
|
+
return !!contentJson && !!contentJson.components;
|
|
55
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import processMetaOption from "./processMetaOption";
|
|
2
|
+
|
|
3
|
+
describe("processMetaOption tests", () => {
|
|
4
|
+
it("It parses correctly", () => {
|
|
5
|
+
expect(
|
|
6
|
+
processMetaOption(["githubActionRequest:true", "trigger:manual"])
|
|
7
|
+
).toEqual({
|
|
8
|
+
githubActionRequest: "true",
|
|
9
|
+
trigger: "manual",
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
it("Malformed doesnt crash", () => {
|
|
13
|
+
expect(processMetaOption(["context:github-action", "trigger"])).toEqual({
|
|
14
|
+
context: "github-action",
|
|
15
|
+
trigger: undefined,
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const processMetaOption = (inputArr: string[] | null) => {
|
|
2
|
+
const res: Record<string, string> = {};
|
|
3
|
+
|
|
4
|
+
if (!Array.isArray(inputArr)) {
|
|
5
|
+
return res;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
inputArr.forEach((element) => {
|
|
9
|
+
const [key, value] = element.split(":");
|
|
10
|
+
res[key] = value;
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
return res;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export default processMetaOption;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import output from "../output";
|
|
2
|
+
import { Project } from "../types";
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
const projectsToText = (projects: Project[]) => {
|
|
4
5
|
return (
|
|
5
6
|
(projects || []).reduce(
|
|
6
7
|
(outputString, { name, id }) =>
|
|
@@ -13,6 +14,6 @@ function projectsToText(projects) {
|
|
|
13
14
|
""
|
|
14
15
|
) + "\n"
|
|
15
16
|
);
|
|
16
|
-
}
|
|
17
|
+
};
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
export default projectsToText;
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
const { AutoComplete } = require("enquirer");
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import output from "../output";
|
|
4
|
+
import { Project } from "../types";
|
|
4
5
|
|
|
5
|
-
function formatProjectChoice(project) {
|
|
6
|
+
function formatProjectChoice(project: Project) {
|
|
6
7
|
return (
|
|
7
8
|
project.name +
|
|
8
9
|
" " +
|
|
9
|
-
output.subtle(
|
|
10
|
-
project.url || `https://app.dittowords.com/doc/${project.id}`
|
|
11
|
-
)
|
|
10
|
+
output.subtle(project.url || `https://app.dittowords.com/doc/${project.id}`)
|
|
12
11
|
);
|
|
13
12
|
}
|
|
14
13
|
|
|
15
|
-
function parseResponse(response) {
|
|
14
|
+
function parseResponse(response: string) {
|
|
16
15
|
if (!response) {
|
|
17
16
|
return null;
|
|
18
17
|
}
|
|
@@ -26,7 +25,17 @@ function parseResponse(response) {
|
|
|
26
25
|
return { name, id };
|
|
27
26
|
}
|
|
28
27
|
|
|
29
|
-
|
|
28
|
+
interface ProjectPromptParams {
|
|
29
|
+
message: string;
|
|
30
|
+
projects: Project[];
|
|
31
|
+
limit?: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const promptForProject = async ({
|
|
35
|
+
message,
|
|
36
|
+
projects,
|
|
37
|
+
limit = 10,
|
|
38
|
+
}: ProjectPromptParams) => {
|
|
30
39
|
output.nl();
|
|
31
40
|
|
|
32
41
|
const choices = projects.map(formatProjectChoice);
|
|
@@ -48,6 +57,6 @@ async function promptForProject({ message, projects, limit = 10 }) {
|
|
|
48
57
|
}
|
|
49
58
|
|
|
50
59
|
return parseResponse(response);
|
|
51
|
-
}
|
|
60
|
+
};
|
|
52
61
|
|
|
53
|
-
|
|
62
|
+
export default promptForProject;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import output from "../output";
|
|
2
|
+
import projectsToText from "./projectsToText";
|
|
3
|
+
import { Project } from "../types";
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
const sourcesToText = (projects: Project[], componentLibrary: boolean) => {
|
|
5
6
|
let message = "";
|
|
6
7
|
|
|
7
8
|
if (componentLibrary) {
|
|
@@ -19,6 +20,6 @@ function sourcesToText(projects, componentLibrary) {
|
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
return message;
|
|
22
|
-
}
|
|
23
|
+
};
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
export default sourcesToText;
|
package/package.json
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dittowords/cli",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.2",
|
|
4
4
|
"description": "Command Line Interface for Ditto (dittowords.com).",
|
|
5
5
|
"main": "bin/index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
+
"prepublish": "tsc",
|
|
7
8
|
"prepare": "husky install",
|
|
8
|
-
"
|
|
9
|
+
"start": "tsc && node bin/ditto.js",
|
|
10
|
+
"sync": "tsc && node bin/ditto.js pull",
|
|
11
|
+
"dev": "tsc --watch"
|
|
9
12
|
},
|
|
10
13
|
"repository": {
|
|
11
14
|
"type": "git",
|
|
@@ -25,36 +28,38 @@
|
|
|
25
28
|
"cli",
|
|
26
29
|
"api"
|
|
27
30
|
],
|
|
31
|
+
"types": "bin/ditto.d.ts",
|
|
28
32
|
"bin": {
|
|
29
|
-
"ditto-cli": "
|
|
33
|
+
"ditto-cli": "bin/ditto.js"
|
|
30
34
|
},
|
|
31
35
|
"devDependencies": {
|
|
32
36
|
"@babel/core": "^7.11.4",
|
|
33
|
-
"@babel/preset-env": "^7.
|
|
37
|
+
"@babel/preset-env": "^7.20.2",
|
|
38
|
+
"@babel/preset-typescript": "^7.18.6",
|
|
39
|
+
"@tsconfig/node16": "^1.0.3",
|
|
34
40
|
"@types/jest": "^26.0.9",
|
|
35
|
-
"
|
|
36
|
-
"
|
|
41
|
+
"@types/js-yaml": "^4.0.5",
|
|
42
|
+
"@types/node": "^18.0.0",
|
|
43
|
+
"babel-jest": "^29.3.1",
|
|
44
|
+
"eslint": "^8.27.0",
|
|
37
45
|
"eslint-config-airbnb-base": "^14.2.0",
|
|
38
|
-
"eslint-plugin-import": "^2.22.0",
|
|
39
|
-
"eslint-plugin-jest": "^23.20.0",
|
|
40
46
|
"husky": "^7.0.4",
|
|
47
|
+
"jest": "^29.3.1",
|
|
41
48
|
"lint-staged": "^11.2.4",
|
|
42
49
|
"prettier": "2.4.1",
|
|
43
|
-
"
|
|
44
|
-
"rewire": "^5.0.0",
|
|
50
|
+
"rewire": "^6.0.0",
|
|
45
51
|
"source-map": "^0.7.3",
|
|
46
52
|
"tempy": "^0.6.0",
|
|
47
|
-
"
|
|
48
|
-
"typescript": "^4.0.2"
|
|
53
|
+
"typescript": "^4.7.4"
|
|
49
54
|
},
|
|
50
55
|
"dependencies": {
|
|
51
|
-
"axios": "^0.
|
|
52
|
-
"boxen": "^
|
|
56
|
+
"axios": "^0.27.2",
|
|
57
|
+
"boxen": "^5.1.2",
|
|
53
58
|
"chalk": "^4.1.0",
|
|
54
59
|
"commander": "^6.1.0",
|
|
55
60
|
"enquirer": "^2.3.6",
|
|
56
61
|
"faker": "^5.1.0",
|
|
57
|
-
"js-yaml": "^
|
|
62
|
+
"js-yaml": "^4.1.0",
|
|
58
63
|
"ora": "^5.0.0",
|
|
59
64
|
"v8-compile-cache": "^2.1.1"
|
|
60
65
|
},
|
|
File without changes
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "@tsconfig/node16/tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"allowJs": true,
|
|
5
|
+
"outDir": "bin",
|
|
6
|
+
"allowSyntheticDefaultImports": true,
|
|
7
|
+
"resolveJsonModule": true,
|
|
8
|
+
"strictNullChecks": true,
|
|
9
|
+
"sourceMap": true
|
|
10
|
+
},
|
|
11
|
+
"include": ["lib/ditto.ts"]
|
|
12
|
+
}
|