@featurevisor/core 0.53.3 → 0.53.5
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/.eslintcache +1 -1
- package/CHANGELOG.md +16 -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/traffic.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/traffic.ts.html +1 -1
- package/lib/builder/buildProject.d.ts +2 -2
- package/lib/builder/buildProject.js +23 -33
- package/lib/builder/buildProject.js.map +1 -1
- package/lib/datasource/datasource.d.ts +8 -2
- package/lib/datasource/datasource.js +43 -2
- package/lib/datasource/datasource.js.map +1 -1
- package/lib/datasource/parsers.js +2 -2
- package/lib/datasource/parsers.js.map +1 -1
- package/lib/dependencies.d.ts +11 -0
- package/lib/dependencies.js +3 -0
- package/lib/dependencies.js.map +1 -0
- package/lib/find-duplicate-segments/index.d.ts +2 -2
- package/lib/find-duplicate-segments/index.js +2 -3
- package/lib/find-duplicate-segments/index.js.map +1 -1
- package/lib/generate-code/index.d.ts +2 -2
- package/lib/generate-code/index.js +4 -5
- package/lib/generate-code/index.js.map +1 -1
- package/lib/generate-code/typescript.d.ts +2 -3
- package/lib/generate-code/typescript.js +3 -2
- package/lib/generate-code/typescript.js.map +1 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -1
- package/lib/linter/lintProject.d.ts +2 -2
- package/lib/linter/lintProject.js +5 -11
- package/lib/linter/lintProject.js.map +1 -1
- package/lib/restore.d.ts +2 -2
- package/lib/restore.js +3 -2
- package/lib/restore.js.map +1 -1
- package/lib/site/exportSite.d.ts +2 -2
- package/lib/site/exportSite.js +4 -3
- package/lib/site/exportSite.js.map +1 -1
- package/lib/site/generateSiteSearchIndex.d.ts +2 -2
- package/lib/site/generateSiteSearchIndex.js +3 -4
- package/lib/site/generateSiteSearchIndex.js.map +1 -1
- package/lib/site/serveSite.d.ts +2 -2
- package/lib/site/serveSite.js +2 -2
- package/lib/site/serveSite.js.map +1 -1
- package/lib/tester/testFeature.js +6 -4
- package/lib/tester/testFeature.js.map +1 -1
- package/lib/tester/testProject.d.ts +2 -2
- package/lib/tester/testProject.js +3 -4
- package/lib/tester/testProject.js.map +1 -1
- package/lib/utils.d.ts +0 -2
- package/lib/utils.js +1 -15
- package/lib/utils.js.map +1 -1
- package/package.json +2 -2
- package/src/builder/buildProject.ts +6 -29
- package/src/datasource/datasource.ts +55 -2
- package/src/datasource/parsers.ts +2 -2
- package/src/dependencies.ts +13 -0
- package/src/find-duplicate-segments/index.ts +3 -8
- package/src/generate-code/index.ts +5 -12
- package/src/generate-code/typescript.ts +4 -8
- package/src/index.ts +2 -0
- package/src/linter/lintProject.ts +39 -47
- package/src/restore.ts +4 -2
- package/src/site/exportSite.ts +5 -9
- package/src/site/generateSiteSearchIndex.ts +4 -5
- package/src/site/serveSite.ts +4 -6
- package/src/tester/testFeature.ts +4 -7
- package/src/tester/testProject.ts +4 -8
- package/src/utils.ts +0 -18
|
@@ -1,13 +1,31 @@
|
|
|
1
1
|
import * as path from "path";
|
|
2
2
|
import * as fs from "fs";
|
|
3
3
|
|
|
4
|
-
import
|
|
4
|
+
import * as mkdirp from "mkdirp";
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
ParsedFeature,
|
|
8
|
+
Segment,
|
|
9
|
+
Attribute,
|
|
10
|
+
Group,
|
|
11
|
+
FeatureKey,
|
|
12
|
+
Test,
|
|
13
|
+
EnvironmentKey,
|
|
14
|
+
ExistingState,
|
|
15
|
+
} from "@featurevisor/types";
|
|
5
16
|
|
|
6
17
|
import { ProjectConfig } from "../config";
|
|
7
18
|
import { parsers } from "./parsers";
|
|
8
19
|
|
|
9
20
|
export type EntityType = "feature" | "group" | "segment" | "attribute" | "test";
|
|
10
21
|
|
|
22
|
+
export function getExistingStateFilePath(
|
|
23
|
+
projectConfig: ProjectConfig,
|
|
24
|
+
environment: EnvironmentKey,
|
|
25
|
+
): string {
|
|
26
|
+
return path.join(projectConfig.stateDirectoryPath, `existing-state-${environment}.json`);
|
|
27
|
+
}
|
|
28
|
+
|
|
11
29
|
export class Datasource {
|
|
12
30
|
private extension;
|
|
13
31
|
private parse;
|
|
@@ -43,11 +61,15 @@ export class Datasource {
|
|
|
43
61
|
}
|
|
44
62
|
|
|
45
63
|
/**
|
|
46
|
-
* Common methods
|
|
64
|
+
* Common methods for entities
|
|
47
65
|
*/
|
|
48
66
|
async listEntities(entityType: EntityType): Promise<string[]> {
|
|
49
67
|
const directoryPath = this.getEntityDirectoryPath(entityType);
|
|
50
68
|
|
|
69
|
+
if (!fs.existsSync(directoryPath)) {
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
|
|
51
73
|
return fs
|
|
52
74
|
.readdirSync(directoryPath)
|
|
53
75
|
.filter((fileName) => fileName.endsWith(`.${this.extension}`))
|
|
@@ -92,6 +114,37 @@ export class Datasource {
|
|
|
92
114
|
return this.parse(entityContent) as T;
|
|
93
115
|
}
|
|
94
116
|
|
|
117
|
+
/**
|
|
118
|
+
* State
|
|
119
|
+
*/
|
|
120
|
+
async readState(environment: EnvironmentKey): Promise<ExistingState> {
|
|
121
|
+
const filePath = getExistingStateFilePath(this.config, environment);
|
|
122
|
+
|
|
123
|
+
if (!fs.existsSync(filePath)) {
|
|
124
|
+
return {
|
|
125
|
+
features: {},
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return require(filePath);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async writeState(environment: EnvironmentKey, existingState: ExistingState) {
|
|
133
|
+
const filePath = getExistingStateFilePath(this.config, environment);
|
|
134
|
+
|
|
135
|
+
if (!fs.existsSync(this.config.stateDirectoryPath)) {
|
|
136
|
+
mkdirp.sync(this.config.stateDirectoryPath);
|
|
137
|
+
}
|
|
138
|
+
fs.writeFileSync(
|
|
139
|
+
filePath,
|
|
140
|
+
this.config.prettyState
|
|
141
|
+
? JSON.stringify(existingState, null, 2)
|
|
142
|
+
: JSON.stringify(existingState),
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
fs.writeFileSync(filePath, JSON.stringify(existingState, null, 2));
|
|
146
|
+
}
|
|
147
|
+
|
|
95
148
|
/**
|
|
96
149
|
* Entity specific methods
|
|
97
150
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as YAML from "js-yaml";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* If we want to add more built-in parsers,
|
|
@@ -8,7 +8,7 @@ import { parseYaml } from "../utils";
|
|
|
8
8
|
export const parsers = {
|
|
9
9
|
// extension => function
|
|
10
10
|
yml(content: string) {
|
|
11
|
-
return
|
|
11
|
+
return YAML.load(content);
|
|
12
12
|
},
|
|
13
13
|
|
|
14
14
|
json(content: string) {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ProjectConfig } from "./config";
|
|
2
|
+
import { Datasource } from "./datasource";
|
|
3
|
+
|
|
4
|
+
export interface Options {
|
|
5
|
+
[key: string]: any;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface Dependencies {
|
|
9
|
+
rootDirectoryPath: string;
|
|
10
|
+
projectConfig: ProjectConfig;
|
|
11
|
+
datasource: Datasource;
|
|
12
|
+
options: Options;
|
|
13
|
+
}
|
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
import { Datasource } from "../datasource";
|
|
2
|
-
import { ProjectConfig } from "../config";
|
|
3
|
-
|
|
4
1
|
import { findDuplicateSegments } from "./findDuplicateSegments";
|
|
2
|
+
import { Dependencies } from "../dependencies";
|
|
5
3
|
|
|
6
|
-
export async function findDuplicateSegmentsInProject(
|
|
7
|
-
|
|
8
|
-
projectConfig: ProjectConfig,
|
|
9
|
-
) {
|
|
10
|
-
const datasource = new Datasource(projectConfig);
|
|
4
|
+
export async function findDuplicateSegmentsInProject(deps: Dependencies) {
|
|
5
|
+
const { datasource } = deps;
|
|
11
6
|
|
|
12
7
|
const duplicates = await findDuplicateSegments(datasource);
|
|
13
8
|
|
|
@@ -3,9 +3,8 @@ import * as path from "path";
|
|
|
3
3
|
|
|
4
4
|
import * as mkdirp from "mkdirp";
|
|
5
5
|
|
|
6
|
-
import { ProjectConfig } from "../config";
|
|
7
|
-
import { Datasource } from "../datasource";
|
|
8
6
|
import { generateTypeScriptCodeForProject } from "./typescript";
|
|
7
|
+
import { Dependencies } from "../dependencies";
|
|
9
8
|
|
|
10
9
|
export const ALLOWED_LANGUAGES_FOR_CODE_GENERATION = ["typescript"];
|
|
11
10
|
|
|
@@ -15,10 +14,11 @@ export interface GenerateCodeCLIOptions {
|
|
|
15
14
|
}
|
|
16
15
|
|
|
17
16
|
export async function generateCodeForProject(
|
|
18
|
-
|
|
19
|
-
projectConfig: ProjectConfig,
|
|
17
|
+
deps: Dependencies,
|
|
20
18
|
cliOptions: GenerateCodeCLIOptions,
|
|
21
19
|
) {
|
|
20
|
+
const { rootDirectoryPath } = deps;
|
|
21
|
+
|
|
22
22
|
if (!cliOptions.language) {
|
|
23
23
|
throw new Error("Option `--language` is required");
|
|
24
24
|
}
|
|
@@ -27,8 +27,6 @@ export async function generateCodeForProject(
|
|
|
27
27
|
throw new Error("Option `--out-dir` is required");
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
const datasource = new Datasource(projectConfig);
|
|
31
|
-
|
|
32
30
|
const absolutePath = path.resolve(rootDirectoryPath, cliOptions.outDir);
|
|
33
31
|
|
|
34
32
|
if (!fs.existsSync(absolutePath)) {
|
|
@@ -47,12 +45,7 @@ export async function generateCodeForProject(
|
|
|
47
45
|
}
|
|
48
46
|
|
|
49
47
|
if (cliOptions.language === "typescript") {
|
|
50
|
-
return await generateTypeScriptCodeForProject(
|
|
51
|
-
rootDirectoryPath,
|
|
52
|
-
projectConfig,
|
|
53
|
-
datasource,
|
|
54
|
-
absolutePath,
|
|
55
|
-
);
|
|
48
|
+
return await generateTypeScriptCodeForProject(deps, absolutePath);
|
|
56
49
|
}
|
|
57
50
|
|
|
58
51
|
throw new Error(`Language ${cliOptions.language} is not supported`);
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import * as fs from "fs";
|
|
2
2
|
import * as path from "path";
|
|
3
3
|
|
|
4
|
-
import { ProjectConfig } from "../config";
|
|
5
|
-
import { Datasource } from "../datasource";
|
|
6
4
|
import { Attribute } from "@featurevisor/types";
|
|
5
|
+
import { Dependencies } from "../dependencies";
|
|
7
6
|
|
|
8
7
|
function convertFeaturevisorTypeToTypeScriptType(featurevisorType: string) {
|
|
9
8
|
switch (featurevisorType) {
|
|
@@ -87,12 +86,9 @@ export function getInstance(): FeaturevisorInstance {
|
|
|
87
86
|
}
|
|
88
87
|
`.trimStart();
|
|
89
88
|
|
|
90
|
-
export async function generateTypeScriptCodeForProject(
|
|
91
|
-
rootDirectoryPath
|
|
92
|
-
|
|
93
|
-
datasource: Datasource,
|
|
94
|
-
outputPath: string,
|
|
95
|
-
) {
|
|
89
|
+
export async function generateTypeScriptCodeForProject(deps: Dependencies, outputPath: string) {
|
|
90
|
+
const { rootDirectoryPath, datasource } = deps;
|
|
91
|
+
|
|
96
92
|
console.log("\nGenerating TypeScript code...\n");
|
|
97
93
|
|
|
98
94
|
// instance
|
package/src/index.ts
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
// for use in node only
|
|
2
|
-
import * as fs from "fs";
|
|
3
|
-
|
|
4
2
|
import * as Joi from "joi";
|
|
5
3
|
|
|
6
|
-
import { Datasource } from "../datasource";
|
|
7
|
-
import { ProjectConfig } from "../config";
|
|
8
|
-
|
|
9
4
|
import { getAttributeJoiSchema } from "./attributeSchema";
|
|
10
5
|
import { getConditionsJoiSchema } from "./conditionSchema";
|
|
11
6
|
import { getSegmentJoiSchema } from "./segmentSchema";
|
|
@@ -15,10 +10,12 @@ import { getTestsJoiSchema } from "./testSchema";
|
|
|
15
10
|
|
|
16
11
|
import { checkForCircularDependencyInRequired } from "./checkCircularDependency";
|
|
17
12
|
import { printJoiError } from "./printJoiError";
|
|
13
|
+
import { Dependencies } from "../dependencies";
|
|
14
|
+
|
|
15
|
+
export async function lintProject(deps: Dependencies): Promise<boolean> {
|
|
16
|
+
const { projectConfig, datasource } = deps;
|
|
18
17
|
|
|
19
|
-
export async function lintProject(projectConfig: ProjectConfig): Promise<boolean> {
|
|
20
18
|
let hasError = false;
|
|
21
|
-
const datasource = new Datasource(projectConfig);
|
|
22
19
|
|
|
23
20
|
const availableAttributeKeys: string[] = [];
|
|
24
21
|
const availableSegmentKeys: string[] = [];
|
|
@@ -116,62 +113,57 @@ export async function lintProject(projectConfig: ProjectConfig): Promise<boolean
|
|
|
116
113
|
}
|
|
117
114
|
|
|
118
115
|
// lint groups
|
|
116
|
+
const groups = await datasource.listGroups();
|
|
117
|
+
console.log(`\nLinting ${groups.length} groups...\n`);
|
|
119
118
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
console.log(`\nLinting ${groups.length} groups...\n`);
|
|
119
|
+
// @TODO: feature it slots can be from availableFeatureKeys only
|
|
120
|
+
const groupJoiSchema = getGroupJoiSchema(projectConfig, datasource, availableFeatureKeys);
|
|
123
121
|
|
|
124
|
-
|
|
125
|
-
const
|
|
122
|
+
for (const key of groups) {
|
|
123
|
+
const parsed = await datasource.readGroup(key);
|
|
126
124
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
await groupJoiSchema.validateAsync(parsed);
|
|
132
|
-
} catch (e) {
|
|
133
|
-
console.log(" =>", key);
|
|
134
|
-
|
|
135
|
-
if (e instanceof Joi.ValidationError) {
|
|
136
|
-
printJoiError(e);
|
|
137
|
-
} else {
|
|
138
|
-
console.log(e);
|
|
139
|
-
}
|
|
125
|
+
try {
|
|
126
|
+
await groupJoiSchema.validateAsync(parsed);
|
|
127
|
+
} catch (e) {
|
|
128
|
+
console.log(" =>", key);
|
|
140
129
|
|
|
141
|
-
|
|
130
|
+
if (e instanceof Joi.ValidationError) {
|
|
131
|
+
printJoiError(e);
|
|
132
|
+
} else {
|
|
133
|
+
console.log(e);
|
|
142
134
|
}
|
|
135
|
+
|
|
136
|
+
hasError = true;
|
|
143
137
|
}
|
|
144
138
|
}
|
|
145
139
|
|
|
146
140
|
// @TODO: feature cannot exist in multiple groups
|
|
147
141
|
|
|
148
142
|
// lint tests
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
console.log(`\nLinting ${tests.length} tests...\n`);
|
|
143
|
+
const tests = await datasource.listTests();
|
|
144
|
+
console.log(`\nLinting ${tests.length} tests...\n`);
|
|
152
145
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
146
|
+
const testsJoiSchema = getTestsJoiSchema(
|
|
147
|
+
projectConfig,
|
|
148
|
+
availableFeatureKeys,
|
|
149
|
+
availableSegmentKeys,
|
|
150
|
+
);
|
|
158
151
|
|
|
159
|
-
|
|
160
|
-
|
|
152
|
+
for (const key of tests) {
|
|
153
|
+
const parsed = await datasource.readTest(key);
|
|
161
154
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
if (e instanceof Joi.ValidationError) {
|
|
168
|
-
printJoiError(e);
|
|
169
|
-
} else {
|
|
170
|
-
console.log(e);
|
|
171
|
-
}
|
|
155
|
+
try {
|
|
156
|
+
await testsJoiSchema.validateAsync(parsed);
|
|
157
|
+
} catch (e) {
|
|
158
|
+
console.log(" =>", key);
|
|
172
159
|
|
|
173
|
-
|
|
160
|
+
if (e instanceof Joi.ValidationError) {
|
|
161
|
+
printJoiError(e);
|
|
162
|
+
} else {
|
|
163
|
+
console.log(e);
|
|
174
164
|
}
|
|
165
|
+
|
|
166
|
+
hasError = true;
|
|
175
167
|
}
|
|
176
168
|
}
|
|
177
169
|
|
package/src/restore.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import * as path from "path";
|
|
2
2
|
import { execSync } from "child_process";
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { Dependencies } from "./dependencies";
|
|
5
|
+
|
|
6
|
+
export async function restoreProject(deps: Dependencies) {
|
|
7
|
+
const { rootDirectoryPath, projectConfig } = deps;
|
|
5
8
|
|
|
6
|
-
export async function restoreProject(rootDirectoryPath, projectConfig: ProjectConfig) {
|
|
7
9
|
const relativeStateDirPath = path.relative(rootDirectoryPath, projectConfig.stateDirectoryPath);
|
|
8
10
|
const cmd = `git checkout -- ${relativeStateDirPath}${path.sep}`;
|
|
9
11
|
|
package/src/site/exportSite.ts
CHANGED
|
@@ -3,13 +3,14 @@ import * as path from "path";
|
|
|
3
3
|
|
|
4
4
|
import * as mkdirp from "mkdirp";
|
|
5
5
|
|
|
6
|
-
import { ProjectConfig } from "../config";
|
|
7
|
-
|
|
8
6
|
import { generateHistory } from "./generateHistory";
|
|
9
7
|
import { getRepoDetails } from "./getRepoDetails";
|
|
10
8
|
import { generateSiteSearchIndex } from "./generateSiteSearchIndex";
|
|
9
|
+
import { Dependencies } from "../dependencies";
|
|
10
|
+
|
|
11
|
+
export async function exportSite(deps: Dependencies) {
|
|
12
|
+
const { rootDirectoryPath, projectConfig } = deps;
|
|
11
13
|
|
|
12
|
-
export async function exportSite(rootDirectoryPath: string, projectConfig: ProjectConfig) {
|
|
13
14
|
const hasError = false;
|
|
14
15
|
|
|
15
16
|
mkdirp.sync(projectConfig.siteExportDirectoryPath);
|
|
@@ -30,12 +31,7 @@ export async function exportSite(rootDirectoryPath: string, projectConfig: Proje
|
|
|
30
31
|
|
|
31
32
|
// site search index
|
|
32
33
|
const repoDetails = getRepoDetails();
|
|
33
|
-
const searchIndex = await generateSiteSearchIndex(
|
|
34
|
-
rootDirectoryPath,
|
|
35
|
-
projectConfig,
|
|
36
|
-
fullHistory,
|
|
37
|
-
repoDetails,
|
|
38
|
-
);
|
|
34
|
+
const searchIndex = await generateSiteSearchIndex(deps, fullHistory, repoDetails);
|
|
39
35
|
const searchIndexFilePath = path.join(projectConfig.siteExportDirectoryPath, "search-index.json");
|
|
40
36
|
fs.writeFileSync(searchIndexFilePath, JSON.stringify(searchIndex));
|
|
41
37
|
console.log(`Site search index written at: ${searchIndexFilePath}`);
|
|
@@ -7,20 +7,20 @@ import {
|
|
|
7
7
|
Condition,
|
|
8
8
|
} from "@featurevisor/types";
|
|
9
9
|
|
|
10
|
-
import { Datasource } from "../datasource";
|
|
11
|
-
import { ProjectConfig } from "../config";
|
|
12
10
|
import { extractAttributeKeysFromConditions, extractSegmentKeysFromGroupSegments } from "../utils";
|
|
13
11
|
|
|
14
12
|
import { getRelativePaths } from "./getRelativePaths";
|
|
15
13
|
import { getLastModifiedFromHistory } from "./getLastModifiedFromHistory";
|
|
16
14
|
import { RepoDetails } from "./getRepoDetails";
|
|
15
|
+
import { Dependencies } from "../dependencies";
|
|
17
16
|
|
|
18
17
|
export async function generateSiteSearchIndex(
|
|
19
|
-
|
|
20
|
-
projectConfig: ProjectConfig,
|
|
18
|
+
deps: Dependencies,
|
|
21
19
|
fullHistory: HistoryEntry[],
|
|
22
20
|
repoDetails: RepoDetails | undefined,
|
|
23
21
|
): Promise<SearchIndex> {
|
|
22
|
+
const { rootDirectoryPath, projectConfig, datasource } = deps;
|
|
23
|
+
|
|
24
24
|
const result: SearchIndex = {
|
|
25
25
|
links: undefined,
|
|
26
26
|
entities: {
|
|
@@ -29,7 +29,6 @@ export async function generateSiteSearchIndex(
|
|
|
29
29
|
features: [],
|
|
30
30
|
},
|
|
31
31
|
};
|
|
32
|
-
const datasource = new Datasource(projectConfig);
|
|
33
32
|
|
|
34
33
|
/**
|
|
35
34
|
* Links
|
package/src/site/serveSite.ts
CHANGED
|
@@ -2,13 +2,11 @@ import * as fs from "fs";
|
|
|
2
2
|
import * as path from "path";
|
|
3
3
|
import * as http from "http";
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { Dependencies } from "../dependencies";
|
|
6
|
+
|
|
7
|
+
export function serveSite(deps: Dependencies) {
|
|
8
|
+
const { projectConfig, options } = deps;
|
|
6
9
|
|
|
7
|
-
export function serveSite(
|
|
8
|
-
rootDirectoryPath: string,
|
|
9
|
-
projectConfig: ProjectConfig,
|
|
10
|
-
options: any = {},
|
|
11
|
-
) {
|
|
12
10
|
const port = options.p || 3000;
|
|
13
11
|
|
|
14
12
|
http
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
import { TestFeature, ExistingState } from "@featurevisor/types";
|
|
1
|
+
import { TestFeature } from "@featurevisor/types";
|
|
4
2
|
import { createInstance, MAX_BUCKETED_NUMBER } from "@featurevisor/sdk";
|
|
5
3
|
|
|
6
4
|
import { Datasource } from "../datasource";
|
|
7
5
|
import { ProjectConfig } from "../config";
|
|
8
|
-
import { buildDatafile
|
|
6
|
+
import { buildDatafile } from "../builder";
|
|
9
7
|
import { SCHEMA_VERSION } from "../config";
|
|
10
8
|
|
|
11
9
|
import { checkIfArraysAreEqual } from "./checkIfArraysAreEqual";
|
|
@@ -31,6 +29,7 @@ export async function testFeature(
|
|
|
31
29
|
const requiredChain = await datasource.getRequiredFeaturesChain(test.feature);
|
|
32
30
|
const featuresToInclude = Array.from(requiredChain);
|
|
33
31
|
|
|
32
|
+
const existingState = await datasource.readState(assertion.environment);
|
|
34
33
|
const datafileContent = await buildDatafile(
|
|
35
34
|
projectConfig,
|
|
36
35
|
datasource,
|
|
@@ -40,9 +39,7 @@ export async function testFeature(
|
|
|
40
39
|
environment: assertion.environment,
|
|
41
40
|
features: featuresToInclude,
|
|
42
41
|
},
|
|
43
|
-
|
|
44
|
-
fs.readFileSync(getExistingStateFilePath(projectConfig, assertion.environment), "utf8"),
|
|
45
|
-
) as ExistingState,
|
|
42
|
+
existingState,
|
|
46
43
|
);
|
|
47
44
|
|
|
48
45
|
const sdk = createInstance({
|
|
@@ -2,19 +2,15 @@ import * as fs from "fs";
|
|
|
2
2
|
|
|
3
3
|
import { TestSegment, TestFeature } from "@featurevisor/types";
|
|
4
4
|
|
|
5
|
-
import { ProjectConfig } from "../config";
|
|
6
|
-
import { Datasource } from "../datasource";
|
|
7
|
-
|
|
8
5
|
import { testSegment } from "./testSegment";
|
|
9
6
|
import { testFeature } from "./testFeature";
|
|
10
7
|
import { CLI_FORMAT_BOLD, CLI_FORMAT_GREEN, CLI_FORMAT_RED } from "./cliFormat";
|
|
8
|
+
import { Dependencies } from "../dependencies";
|
|
9
|
+
|
|
10
|
+
export async function testProject(deps: Dependencies): Promise<boolean> {
|
|
11
|
+
const { rootDirectoryPath, projectConfig, datasource } = deps;
|
|
11
12
|
|
|
12
|
-
export async function testProject(
|
|
13
|
-
rootDirectoryPath: string,
|
|
14
|
-
projectConfig: ProjectConfig,
|
|
15
|
-
): Promise<boolean> {
|
|
16
13
|
let hasError = false;
|
|
17
|
-
const datasource = new Datasource(projectConfig);
|
|
18
14
|
|
|
19
15
|
if (!fs.existsSync(projectConfig.testsDirectoryPath)) {
|
|
20
16
|
console.error(`Tests directory does not exist: ${projectConfig.testsDirectoryPath}`);
|
package/src/utils.ts
CHANGED
|
@@ -1,23 +1,5 @@
|
|
|
1
|
-
import * as fs from "fs";
|
|
2
|
-
import * as path from "path";
|
|
3
|
-
|
|
4
|
-
import * as yaml from "js-yaml";
|
|
5
|
-
|
|
6
1
|
import { Condition, AttributeKey, GroupSegment, SegmentKey } from "@featurevisor/types";
|
|
7
2
|
|
|
8
|
-
export function getYAMLFiles(directoryPath: string) {
|
|
9
|
-
const files = fs.readdirSync(directoryPath);
|
|
10
|
-
const yamlFiles = files.filter((file) => file.endsWith(".yml"));
|
|
11
|
-
|
|
12
|
-
return yamlFiles.map((file) => path.join(directoryPath, file));
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function parseYaml(content: string) {
|
|
16
|
-
const parsed = yaml.load(content);
|
|
17
|
-
|
|
18
|
-
return parsed;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
3
|
export function extractSegmentKeysFromGroupSegments(
|
|
22
4
|
segments: GroupSegment | GroupSegment[],
|
|
23
5
|
): Set<SegmentKey> {
|