@featurevisor/core 1.34.2 → 1.35.1
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.js +6 -2
- 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 +7 -1
- package/src/index.ts +1 -0
- package/src/list/index.ts +496 -0
- package/src/tester/index.ts +1 -0
|
@@ -86,7 +86,10 @@ export class FilesystemAdapter extends Adapter {
|
|
|
86
86
|
getEntityPath(entityType: EntityType, entityKey: string): string {
|
|
87
87
|
const basePath = this.getEntityDirectoryPath(entityType);
|
|
88
88
|
|
|
89
|
-
|
|
89
|
+
// taking care of windows paths
|
|
90
|
+
const relativeEntityPath = entityKey.replace(/\//g, path.sep);
|
|
91
|
+
|
|
92
|
+
return path.join(basePath, `${relativeEntityPath}.${this.parser.extension}`);
|
|
90
93
|
}
|
|
91
94
|
|
|
92
95
|
async listEntities(entityType: EntityType): Promise<string[]> {
|
|
@@ -103,6 +106,9 @@ export class FilesystemAdapter extends Adapter {
|
|
|
103
106
|
|
|
104
107
|
// remove the extension from the end
|
|
105
108
|
.map((filterPath) => filterPath.replace(`.${this.parser.extension}`, ""))
|
|
109
|
+
|
|
110
|
+
// take care of windows paths
|
|
111
|
+
.map((filterPath) => filterPath.replace(/\\/g, "/"))
|
|
106
112
|
);
|
|
107
113
|
}
|
|
108
114
|
|
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