@featurevisor/core 1.34.1 → 1.35.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/CHANGELOG.md +22 -0
- package/coverage/clover.xml +2 -2
- package/coverage/lcov-report/index.html +1 -1
- package/coverage/lcov-report/lib/builder/allocator.js.html +1 -1
- package/coverage/lcov-report/lib/builder/index.html +1 -1
- package/coverage/lcov-report/lib/builder/revision.js.html +1 -1
- package/coverage/lcov-report/lib/builder/traffic.js.html +1 -1
- package/coverage/lcov-report/lib/tester/checkIfObjectsAreEqual.js.html +1 -1
- package/coverage/lcov-report/lib/tester/index.html +1 -1
- package/coverage/lcov-report/lib/tester/matrix.js.html +1 -1
- package/coverage/lcov-report/src/builder/allocator.ts.html +1 -1
- package/coverage/lcov-report/src/builder/index.html +1 -1
- package/coverage/lcov-report/src/builder/revision.ts.html +1 -1
- package/coverage/lcov-report/src/builder/traffic.ts.html +1 -1
- package/coverage/lcov-report/src/tester/checkIfObjectsAreEqual.ts.html +1 -1
- package/coverage/lcov-report/src/tester/index.html +1 -1
- package/coverage/lcov-report/src/tester/matrix.ts.html +1 -1
- package/lib/cli/plugins.js +2 -0
- package/lib/cli/plugins.js.map +1 -1
- package/lib/datasource/filesystemAdapter.d.ts +1 -1
- package/lib/datasource/filesystemAdapter.js +84 -57
- package/lib/datasource/filesystemAdapter.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/list/index.d.ts +4 -0
- package/lib/list/index.js +555 -0
- package/lib/list/index.js.map +1 -0
- package/lib/tester/index.d.ts +1 -0
- package/lib/tester/index.js +1 -0
- package/lib/tester/index.js.map +1 -1
- package/package.json +5 -5
- package/src/cli/plugins.ts +2 -0
- package/src/datasource/filesystemAdapter.ts +23 -4
- package/src/index.ts +1 -0
- package/src/list/index.ts +496 -0
- package/src/tester/index.ts +1 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as fs from "fs";
|
|
2
2
|
import * as path from "path";
|
|
3
|
-
import { execSync } from "child_process";
|
|
3
|
+
import { execSync, spawn } from "child_process";
|
|
4
4
|
|
|
5
5
|
import * as mkdirp from "mkdirp";
|
|
6
6
|
|
|
@@ -255,13 +255,32 @@ export class FilesystemAdapter extends Adapter {
|
|
|
255
255
|
/**
|
|
256
256
|
* History
|
|
257
257
|
*/
|
|
258
|
-
getRawHistory(pathPatterns: string[]) {
|
|
258
|
+
async getRawHistory(pathPatterns: string[]): Promise<string> {
|
|
259
259
|
const gitPaths = pathPatterns.join(" ");
|
|
260
260
|
|
|
261
261
|
const logCommand = `git log --name-only --pretty=format:"%h|%an|%aI" --relative --no-merges -- ${gitPaths}`;
|
|
262
262
|
const fullCommand = `(cd ${this.rootDirectoryPath} && ${logCommand})`;
|
|
263
263
|
|
|
264
|
-
return
|
|
264
|
+
return new Promise(function (resolve, reject) {
|
|
265
|
+
const child = spawn(fullCommand, { shell: true });
|
|
266
|
+
let result = "";
|
|
267
|
+
|
|
268
|
+
child.stdout.on("data", function (data) {
|
|
269
|
+
result += data.toString();
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
child.stderr.on("data", function (data) {
|
|
273
|
+
console.error(data.toString());
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
child.on("close", function (code) {
|
|
277
|
+
if (code === 0) {
|
|
278
|
+
resolve(result);
|
|
279
|
+
} else {
|
|
280
|
+
reject(code);
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
});
|
|
265
284
|
}
|
|
266
285
|
|
|
267
286
|
getPathPatterns(entityType?: EntityType, entityKey?: string): string[] {
|
|
@@ -296,7 +315,7 @@ export class FilesystemAdapter extends Adapter {
|
|
|
296
315
|
|
|
297
316
|
async listHistoryEntries(entityType?: EntityType, entityKey?: string): Promise<HistoryEntry[]> {
|
|
298
317
|
const pathPatterns = this.getPathPatterns(entityType, entityKey);
|
|
299
|
-
const rawHistory = this.getRawHistory(pathPatterns);
|
|
318
|
+
const rawHistory = await this.getRawHistory(pathPatterns);
|
|
300
319
|
|
|
301
320
|
const fullHistory: HistoryEntry[] = [];
|
|
302
321
|
const blocks = rawHistory.split("\n\n");
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,496 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ParsedFeature,
|
|
3
|
+
Segment,
|
|
4
|
+
Attribute,
|
|
5
|
+
TestFeature,
|
|
6
|
+
TestSegment,
|
|
7
|
+
FeatureAssertion,
|
|
8
|
+
SegmentAssertion,
|
|
9
|
+
} from "@featurevisor/types";
|
|
10
|
+
|
|
11
|
+
import { Dependencies } from "../dependencies";
|
|
12
|
+
import { Plugin } from "../cli";
|
|
13
|
+
import { getFeatureAssertionsFromMatrix, getSegmentAssertionsFromMatrix } from "../tester";
|
|
14
|
+
|
|
15
|
+
async function getEntitiesWithTests(
|
|
16
|
+
deps: Dependencies,
|
|
17
|
+
): Promise<{ features: string[]; segments: string[] }> {
|
|
18
|
+
const { datasource } = deps;
|
|
19
|
+
|
|
20
|
+
const featuresWithTests = new Set<string>();
|
|
21
|
+
const segmentsWithTests = new Set<string>();
|
|
22
|
+
|
|
23
|
+
const tests = await datasource.listTests();
|
|
24
|
+
for (const testKey of tests) {
|
|
25
|
+
const test = await datasource.readTest(testKey);
|
|
26
|
+
|
|
27
|
+
if ((test as TestFeature).feature) {
|
|
28
|
+
featuresWithTests.add((test as TestFeature).feature);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if ((test as TestSegment).segment) {
|
|
32
|
+
segmentsWithTests.add((test as TestSegment).segment);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
features: Array.from(featuresWithTests),
|
|
38
|
+
segments: Array.from(segmentsWithTests),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function listEntities<T>(deps: Dependencies, entityType): Promise<T[]> {
|
|
43
|
+
const { datasource, options } = deps;
|
|
44
|
+
|
|
45
|
+
const result: T[] = [];
|
|
46
|
+
let entityKeys: string[] = [];
|
|
47
|
+
|
|
48
|
+
if (entityType === "feature") {
|
|
49
|
+
entityKeys = await datasource.listFeatures();
|
|
50
|
+
} else if (entityType === "segment") {
|
|
51
|
+
entityKeys = await datasource.listSegments();
|
|
52
|
+
} else if (entityType === "attribute") {
|
|
53
|
+
entityKeys = await datasource.listAttributes();
|
|
54
|
+
} else if (entityType === "test") {
|
|
55
|
+
entityKeys = await datasource.listTests();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (entityKeys.length === 0) {
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
let entitiesWithTests: { features: string[]; segments: string[] } = {
|
|
63
|
+
features: [],
|
|
64
|
+
segments: [],
|
|
65
|
+
};
|
|
66
|
+
let entitiesWithTestsInitialized = false;
|
|
67
|
+
|
|
68
|
+
async function initializeEntitiesWithTests() {
|
|
69
|
+
if (entitiesWithTestsInitialized) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
entitiesWithTests = await getEntitiesWithTests(deps);
|
|
74
|
+
entitiesWithTestsInitialized = true;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
for (const key of entityKeys) {
|
|
78
|
+
let entity = {} as T;
|
|
79
|
+
|
|
80
|
+
if (entityType === "feature") {
|
|
81
|
+
entity = (await datasource.readFeature(key)) as T;
|
|
82
|
+
} else if (entityType === "segment") {
|
|
83
|
+
entity = (await datasource.readSegment(key)) as T;
|
|
84
|
+
} else if (entityType === "attribute") {
|
|
85
|
+
entity = (await datasource.readAttribute(key)) as T;
|
|
86
|
+
} else if (entityType === "test") {
|
|
87
|
+
entity = (await datasource.readTest(key)) as T;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// filter
|
|
91
|
+
if (entityType === "feature") {
|
|
92
|
+
const parsedFeature = entity as ParsedFeature;
|
|
93
|
+
|
|
94
|
+
// --archived=true|false
|
|
95
|
+
if (parsedFeature.archived) {
|
|
96
|
+
const archivedStatus = options.archived === "false";
|
|
97
|
+
|
|
98
|
+
if (parsedFeature.archived !== archivedStatus) {
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// --description=<pattern>
|
|
104
|
+
if (options.description) {
|
|
105
|
+
const description = parsedFeature.description || "";
|
|
106
|
+
|
|
107
|
+
const regex = new RegExp(options.description, "i");
|
|
108
|
+
if (!regex.test(description)) {
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// --disabledIn=<environment>
|
|
114
|
+
if (
|
|
115
|
+
options.disabledIn &&
|
|
116
|
+
parsedFeature.environments &&
|
|
117
|
+
parsedFeature.environments[options.disabledIn]
|
|
118
|
+
) {
|
|
119
|
+
const disabledInEnvironment = parsedFeature.environments[options.disabledIn].rules.every(
|
|
120
|
+
(rule) => {
|
|
121
|
+
return rule.percentage === 0;
|
|
122
|
+
},
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
if (!disabledInEnvironment) {
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// --enabledIn=<environment>
|
|
131
|
+
if (
|
|
132
|
+
options.enabledIn &&
|
|
133
|
+
parsedFeature.environments &&
|
|
134
|
+
parsedFeature.environments[options.enabledIn]
|
|
135
|
+
) {
|
|
136
|
+
const enabledInEnvironment = parsedFeature.environments[options.enabledIn].rules.some(
|
|
137
|
+
(rule) => {
|
|
138
|
+
return rule.percentage > 0;
|
|
139
|
+
},
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
if (!enabledInEnvironment) {
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// --keyPattern=<pattern>
|
|
148
|
+
if (options.keyPattern) {
|
|
149
|
+
const regex = new RegExp(options.keyPattern, "i");
|
|
150
|
+
if (!regex.test(key)) {
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// --tag=<tag>
|
|
156
|
+
if (options.tag) {
|
|
157
|
+
const tags = Array.isArray(options.tag) ? options.tag : [options.tag];
|
|
158
|
+
const hasTags = tags.every((tag) => parsedFeature.tags.includes(tag));
|
|
159
|
+
|
|
160
|
+
if (!hasTags) {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// --variable=<variableKey>
|
|
166
|
+
if (options.variable) {
|
|
167
|
+
const lookForVariables = Array.isArray(options.variable)
|
|
168
|
+
? options.variable
|
|
169
|
+
: [options.variable];
|
|
170
|
+
|
|
171
|
+
let variablesInFeature: string[] = [];
|
|
172
|
+
if (Array.isArray(parsedFeature.variablesSchema)) {
|
|
173
|
+
variablesInFeature = parsedFeature.variablesSchema.map((variable) => variable.key);
|
|
174
|
+
} else if (parsedFeature.variablesSchema) {
|
|
175
|
+
variablesInFeature = Object.keys(parsedFeature.variablesSchema);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const hasVariables = lookForVariables.every((variable) =>
|
|
179
|
+
variablesInFeature.includes(variable),
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
if (!hasVariables) {
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// --variation=<variationValue>
|
|
188
|
+
if (options.variation) {
|
|
189
|
+
const lookForVariations = Array.isArray(options.variation)
|
|
190
|
+
? options.variation
|
|
191
|
+
: [options.variation];
|
|
192
|
+
|
|
193
|
+
let variationsInFeature: string[] = parsedFeature.variations
|
|
194
|
+
? parsedFeature.variations.map((v) => v.value)
|
|
195
|
+
: [];
|
|
196
|
+
|
|
197
|
+
const hasVariations = lookForVariations.every((variation) =>
|
|
198
|
+
variationsInFeature.includes(variation),
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
if (!hasVariations) {
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// --with-tests
|
|
207
|
+
if (options.withTests) {
|
|
208
|
+
await initializeEntitiesWithTests();
|
|
209
|
+
|
|
210
|
+
if (!entitiesWithTests.features.includes(key)) {
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// --with-variables
|
|
216
|
+
if (options.withVariables) {
|
|
217
|
+
const hasVariables = parsedFeature.variablesSchema;
|
|
218
|
+
|
|
219
|
+
if (!hasVariables) {
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// --with-variations
|
|
225
|
+
if (options.withVariations) {
|
|
226
|
+
const hasVariations = parsedFeature.variations;
|
|
227
|
+
|
|
228
|
+
if (!hasVariations) {
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// --without-tests
|
|
234
|
+
if (options.withoutTests) {
|
|
235
|
+
await initializeEntitiesWithTests();
|
|
236
|
+
|
|
237
|
+
if (entitiesWithTests.features.includes(key)) {
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// --without-variables
|
|
243
|
+
if (options.withoutVariables) {
|
|
244
|
+
const hasVariables = parsedFeature.variablesSchema;
|
|
245
|
+
|
|
246
|
+
if (hasVariables) {
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// --without-variations
|
|
252
|
+
if (options.withoutVariations) {
|
|
253
|
+
const hasVariations = parsedFeature.variations;
|
|
254
|
+
|
|
255
|
+
if (hasVariations) {
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
} else if (entityType === "segment") {
|
|
260
|
+
const segment = entity as Segment;
|
|
261
|
+
|
|
262
|
+
// --archived=true|false
|
|
263
|
+
if (segment.archived) {
|
|
264
|
+
const archivedStatus = options.archived === "false";
|
|
265
|
+
|
|
266
|
+
if (segment.archived !== archivedStatus) {
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// --description=<pattern>
|
|
272
|
+
if (options.description) {
|
|
273
|
+
const description = segment.description || "";
|
|
274
|
+
|
|
275
|
+
const regex = new RegExp(options.description, "i");
|
|
276
|
+
if (!regex.test(description)) {
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// --keyPattern=<pattern>
|
|
282
|
+
if (options.keyPattern) {
|
|
283
|
+
const regex = new RegExp(options.keyPattern, "i");
|
|
284
|
+
if (!regex.test(key)) {
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// --with-tests
|
|
290
|
+
if (options.withTests) {
|
|
291
|
+
await initializeEntitiesWithTests();
|
|
292
|
+
|
|
293
|
+
if (!entitiesWithTests.segments.includes(key)) {
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// --without-tests
|
|
299
|
+
if (options.withoutTests) {
|
|
300
|
+
await initializeEntitiesWithTests();
|
|
301
|
+
|
|
302
|
+
if (entitiesWithTests.segments.includes(key)) {
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
} else if (entityType === "attribute") {
|
|
307
|
+
const attribute = entity as Attribute;
|
|
308
|
+
|
|
309
|
+
// --archived=true|false
|
|
310
|
+
if (options.archived) {
|
|
311
|
+
const archivedStatus = options.archived === "false";
|
|
312
|
+
|
|
313
|
+
if (attribute.archived !== archivedStatus) {
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// --description=<pattern>
|
|
319
|
+
if (options.description) {
|
|
320
|
+
const description = attribute.description || "";
|
|
321
|
+
|
|
322
|
+
const regex = new RegExp(options.description, "i");
|
|
323
|
+
if (!regex.test(description)) {
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// --keyPattern=<pattern>
|
|
329
|
+
if (options.keyPattern) {
|
|
330
|
+
const regex = new RegExp(options.keyPattern, "i");
|
|
331
|
+
if (!regex.test(key)) {
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
} else if (entityType === "test") {
|
|
336
|
+
let test = entity as TestFeature | TestSegment;
|
|
337
|
+
const testEntityKey = (test as TestFeature).feature || (test as TestSegment).segment;
|
|
338
|
+
const testEntityType = (test as TestSegment).segment ? "segment" : "feature";
|
|
339
|
+
let testAssertions = test.assertions;
|
|
340
|
+
|
|
341
|
+
// --apply-matrix
|
|
342
|
+
if (options.applyMatrix) {
|
|
343
|
+
if (testEntityType === "feature") {
|
|
344
|
+
let assertionsAfterApplyingMatrix: FeatureAssertion[] = [];
|
|
345
|
+
for (let aIndex = 0; aIndex < testAssertions.length; aIndex++) {
|
|
346
|
+
const processedAssertions = getFeatureAssertionsFromMatrix(
|
|
347
|
+
aIndex,
|
|
348
|
+
testAssertions[aIndex] as FeatureAssertion,
|
|
349
|
+
);
|
|
350
|
+
assertionsAfterApplyingMatrix =
|
|
351
|
+
assertionsAfterApplyingMatrix.concat(processedAssertions);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
testAssertions = assertionsAfterApplyingMatrix;
|
|
355
|
+
} else if (testEntityType === "segment") {
|
|
356
|
+
let assertionsAfterApplyingMatrix: SegmentAssertion[] = [];
|
|
357
|
+
for (let aIndex = 0; aIndex < testAssertions.length; aIndex++) {
|
|
358
|
+
const processedAssertions = getSegmentAssertionsFromMatrix(
|
|
359
|
+
aIndex,
|
|
360
|
+
testAssertions[aIndex] as SegmentAssertion,
|
|
361
|
+
);
|
|
362
|
+
assertionsAfterApplyingMatrix =
|
|
363
|
+
assertionsAfterApplyingMatrix.concat(processedAssertions);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
testAssertions = assertionsAfterApplyingMatrix;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// --keyPattern=<pattern>
|
|
371
|
+
if (options.keyPattern) {
|
|
372
|
+
const regex = new RegExp(options.keyPattern, "i");
|
|
373
|
+
if (!regex.test(testEntityKey)) {
|
|
374
|
+
continue;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// --assertionPattern=<pattern>
|
|
379
|
+
if (options.assertionPattern) {
|
|
380
|
+
const regex = new RegExp(options.assertionPattern, "i");
|
|
381
|
+
testAssertions = testAssertions.filter((assertion) => {
|
|
382
|
+
if (!assertion.description) {
|
|
383
|
+
return false;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
return regex.test(assertion.description);
|
|
387
|
+
}) as FeatureAssertion[] | SegmentAssertion[];
|
|
388
|
+
|
|
389
|
+
if (testAssertions.length === 0) {
|
|
390
|
+
continue;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
(entity as TestFeature | TestSegment).assertions = testAssertions;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
result.push({
|
|
398
|
+
...entity,
|
|
399
|
+
key,
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
return result;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
function ucfirst(str: string) {
|
|
407
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
function printResult({ result, entityType, options }) {
|
|
411
|
+
if (options.json) {
|
|
412
|
+
console.log(options.pretty ? JSON.stringify(result, null, 2) : JSON.stringify(result));
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
if (result.length === 0) {
|
|
417
|
+
console.log(`No ${entityType}s found.`);
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
console.log(`\n${ucfirst(entityType)}s:\n`);
|
|
422
|
+
|
|
423
|
+
for (const item of result) {
|
|
424
|
+
console.log(`- ${item.key}`);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
console.log(`\n\nFound ${result.length} ${entityType}s.`);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
export async function listProject(deps: Dependencies) {
|
|
431
|
+
const { rootDirectoryPath, projectConfig, datasource, options } = deps;
|
|
432
|
+
|
|
433
|
+
// features
|
|
434
|
+
if (options.features) {
|
|
435
|
+
const result = await listEntities<ParsedFeature>(deps, "feature");
|
|
436
|
+
|
|
437
|
+
return printResult({
|
|
438
|
+
result,
|
|
439
|
+
entityType: "feature",
|
|
440
|
+
options,
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// segments
|
|
445
|
+
if (options.segments) {
|
|
446
|
+
const result = await listEntities<Segment>(deps, "segment");
|
|
447
|
+
|
|
448
|
+
return printResult({
|
|
449
|
+
result,
|
|
450
|
+
entityType: "segment",
|
|
451
|
+
options,
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// attributes
|
|
456
|
+
if (options.attributes) {
|
|
457
|
+
const result = await listEntities<Attribute>(deps, "attribute");
|
|
458
|
+
|
|
459
|
+
return printResult({
|
|
460
|
+
result,
|
|
461
|
+
entityType: "attribute",
|
|
462
|
+
options,
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// tests
|
|
467
|
+
if (options.tests) {
|
|
468
|
+
const result = await listEntities<Attribute>(deps, "test");
|
|
469
|
+
|
|
470
|
+
return printResult({
|
|
471
|
+
result,
|
|
472
|
+
entityType: "test",
|
|
473
|
+
options,
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
console.log("\nNothing to list. \n\nPlease pass `--features`, `--segments`, or `--attributes`.");
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
export const listPlugin: Plugin = {
|
|
481
|
+
command: "list",
|
|
482
|
+
handler: async function ({ rootDirectoryPath, projectConfig, datasource, parsed }) {
|
|
483
|
+
await listProject({
|
|
484
|
+
rootDirectoryPath,
|
|
485
|
+
projectConfig,
|
|
486
|
+
datasource,
|
|
487
|
+
options: parsed,
|
|
488
|
+
});
|
|
489
|
+
},
|
|
490
|
+
examples: [
|
|
491
|
+
{
|
|
492
|
+
command: "list",
|
|
493
|
+
description: "list entities",
|
|
494
|
+
},
|
|
495
|
+
],
|
|
496
|
+
};
|
package/src/tester/index.ts
CHANGED