@featurevisor/core 0.53.4 → 0.54.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.
Files changed (104) hide show
  1. package/.eslintcache +1 -1
  2. package/CHANGELOG.md +19 -0
  3. package/coverage/clover.xml +2 -2
  4. package/coverage/lcov-report/index.html +1 -1
  5. package/coverage/lcov-report/lib/builder/allocator.js.html +1 -1
  6. package/coverage/lcov-report/lib/builder/index.html +1 -1
  7. package/coverage/lcov-report/lib/builder/traffic.js.html +1 -1
  8. package/coverage/lcov-report/src/builder/allocator.ts.html +1 -1
  9. package/coverage/lcov-report/src/builder/index.html +1 -1
  10. package/coverage/lcov-report/src/builder/traffic.ts.html +1 -1
  11. package/lib/builder/buildProject.d.ts +2 -1
  12. package/lib/builder/buildProject.js +3 -4
  13. package/lib/builder/buildProject.js.map +1 -1
  14. package/lib/config/index.d.ts +2 -0
  15. package/lib/config/index.js +19 -0
  16. package/lib/config/index.js.map +1 -0
  17. package/lib/{datasource → config}/parsers.d.ts +3 -3
  18. package/lib/config/parsers.js +32 -0
  19. package/lib/config/parsers.js.map +1 -0
  20. package/lib/{config.d.ts → config/projectConfig.d.ts} +2 -1
  21. package/lib/{config.js → config/projectConfig.js} +16 -5
  22. package/lib/config/projectConfig.js.map +1 -0
  23. package/lib/datasource/adapter.d.ts +10 -0
  24. package/lib/datasource/adapter.js +10 -0
  25. package/lib/datasource/adapter.js.map +1 -0
  26. package/lib/datasource/datasource.d.ts +11 -18
  27. package/lib/datasource/datasource.js +32 -130
  28. package/lib/datasource/datasource.js.map +1 -1
  29. package/lib/datasource/filesystemAdapter.d.ts +20 -0
  30. package/lib/datasource/filesystemAdapter.js +173 -0
  31. package/lib/datasource/filesystemAdapter.js.map +1 -0
  32. package/lib/datasource/index.d.ts +2 -1
  33. package/lib/datasource/index.js +2 -1
  34. package/lib/datasource/index.js.map +1 -1
  35. package/lib/dependencies.d.ts +11 -0
  36. package/lib/dependencies.js +3 -0
  37. package/lib/dependencies.js.map +1 -0
  38. package/lib/find-duplicate-segments/index.d.ts +2 -2
  39. package/lib/find-duplicate-segments/index.js +2 -3
  40. package/lib/find-duplicate-segments/index.js.map +1 -1
  41. package/lib/generate-code/index.d.ts +2 -2
  42. package/lib/generate-code/index.js +4 -5
  43. package/lib/generate-code/index.js.map +1 -1
  44. package/lib/generate-code/typescript.d.ts +2 -3
  45. package/lib/generate-code/typescript.js +3 -2
  46. package/lib/generate-code/typescript.js.map +1 -1
  47. package/lib/index.d.ts +2 -0
  48. package/lib/index.js +2 -0
  49. package/lib/index.js.map +1 -1
  50. package/lib/{init.js → init/index.js} +1 -1
  51. package/lib/init/index.js.map +1 -0
  52. package/lib/linter/checkCircularDependency.js +1 -1
  53. package/lib/linter/checkCircularDependency.js.map +1 -1
  54. package/lib/linter/lintProject.d.ts +2 -2
  55. package/lib/linter/lintProject.js +3 -4
  56. package/lib/linter/lintProject.js.map +1 -1
  57. package/lib/restore/index.d.ts +2 -0
  58. package/lib/{restore.js → restore/index.js} +4 -3
  59. package/lib/restore/index.js.map +1 -0
  60. package/lib/site/exportSite.d.ts +2 -2
  61. package/lib/site/exportSite.js +4 -3
  62. package/lib/site/exportSite.js.map +1 -1
  63. package/lib/site/generateSiteSearchIndex.d.ts +2 -2
  64. package/lib/site/generateSiteSearchIndex.js +3 -4
  65. package/lib/site/generateSiteSearchIndex.js.map +1 -1
  66. package/lib/site/serveSite.d.ts +2 -2
  67. package/lib/site/serveSite.js +2 -2
  68. package/lib/site/serveSite.js.map +1 -1
  69. package/lib/tester/testProject.d.ts +2 -2
  70. package/lib/tester/testProject.js +4 -5
  71. package/lib/tester/testProject.js.map +1 -1
  72. package/lib/tester/testSegment.js +1 -1
  73. package/lib/tester/testSegment.js.map +1 -1
  74. package/package.json +5 -5
  75. package/src/builder/buildProject.ts +4 -7
  76. package/src/config/index.ts +2 -0
  77. package/src/config/parsers.ts +40 -0
  78. package/src/{config.ts → config/projectConfig.ts} +20 -5
  79. package/src/datasource/adapter.ts +15 -0
  80. package/src/datasource/datasource.ts +44 -131
  81. package/src/datasource/filesystemAdapter.ts +108 -0
  82. package/src/datasource/index.ts +2 -1
  83. package/src/dependencies.ts +13 -0
  84. package/src/find-duplicate-segments/index.ts +3 -8
  85. package/src/generate-code/index.ts +5 -12
  86. package/src/generate-code/typescript.ts +4 -8
  87. package/src/index.ts +2 -0
  88. package/src/linter/checkCircularDependency.ts +1 -1
  89. package/src/linter/lintProject.ts +4 -5
  90. package/src/{restore.ts → restore/index.ts} +4 -2
  91. package/src/site/exportSite.ts +5 -9
  92. package/src/site/generateSiteSearchIndex.ts +4 -5
  93. package/src/site/serveSite.ts +4 -6
  94. package/src/tester/testProject.ts +5 -9
  95. package/src/tester/testSegment.ts +1 -1
  96. package/lib/config.js.map +0 -1
  97. package/lib/datasource/parsers.js +0 -19
  98. package/lib/datasource/parsers.js.map +0 -1
  99. package/lib/init.js.map +0 -1
  100. package/lib/restore.d.ts +0 -2
  101. package/lib/restore.js.map +0 -1
  102. package/src/datasource/parsers.ts +0 -26
  103. /package/lib/{init.d.ts → init/index.d.ts} +0 -0
  104. /package/src/{init.ts → init/index.ts} +0 -0
@@ -1,8 +1,3 @@
1
- import * as path from "path";
2
- import * as fs from "fs";
3
-
4
- import * as mkdirp from "mkdirp";
5
-
6
1
  import {
7
2
  ParsedFeature,
8
3
  Segment,
@@ -12,137 +7,35 @@ import {
12
7
  Test,
13
8
  EnvironmentKey,
14
9
  ExistingState,
10
+ SegmentKey,
11
+ AttributeKey,
15
12
  } from "@featurevisor/types";
16
13
 
17
- import { ProjectConfig } from "../config";
18
- import { parsers } from "./parsers";
19
-
20
- export type EntityType = "feature" | "group" | "segment" | "attribute" | "test";
14
+ import { ProjectConfig, CustomParser } from "../config";
21
15
 
22
- export function getExistingStateFilePath(
23
- projectConfig: ProjectConfig,
24
- environment: EnvironmentKey,
25
- ): string {
26
- return path.join(projectConfig.stateDirectoryPath, `existing-state-${environment}.json`);
27
- }
16
+ import { Adapter } from "./adapter";
28
17
 
29
18
  export class Datasource {
30
- private extension;
31
- private parse;
19
+ private adapter: Adapter;
32
20
 
33
21
  constructor(private config: ProjectConfig) {
34
- if (typeof config.parser === "string") {
35
- // built-in parsers
36
- if (typeof parsers[config.parser] !== "function") {
37
- throw new Error(`Invalid parser: ${config.parser}`);
38
- }
39
-
40
- this.extension = config.parser;
41
- this.parse = parsers[config.parser];
42
- } else if (typeof config.parser === "object") {
43
- // custom parser
44
- if (typeof config.parser.extension !== "string") {
45
- throw new Error(`Invalid parser extension: ${config.parser.extension}`);
46
- }
47
-
48
- if (typeof config.parser.parse !== "function") {
49
- throw new Error(`Invalid parser parse function: ${config.parser.parse}`);
50
- }
51
-
52
- this.extension = config.parser.extension;
53
- this.parse = config.parser.parse;
54
- } else {
55
- throw new Error(`Invalid parser: ${config.parser}`);
56
- }
22
+ this.adapter = new config.adapter(config);
57
23
  }
58
24
 
25
+ // @TODO: only site generator needs it, find a way to get it out of here later
59
26
  getExtension() {
60
- return this.extension;
61
- }
62
-
63
- /**
64
- * Common methods for entities
65
- */
66
- async listEntities(entityType: EntityType): Promise<string[]> {
67
- const directoryPath = this.getEntityDirectoryPath(entityType);
68
-
69
- if (!fs.existsSync(directoryPath)) {
70
- return [];
71
- }
72
-
73
- return fs
74
- .readdirSync(directoryPath)
75
- .filter((fileName) => fileName.endsWith(`.${this.extension}`))
76
- .map((fileName) => fileName.replace(`.${this.extension}`, ""));
77
- }
78
-
79
- getEntityDirectoryPath(entityType: EntityType): string {
80
- if (entityType === "feature") {
81
- return this.config.featuresDirectoryPath;
82
- } else if (entityType === "group") {
83
- return this.config.groupsDirectoryPath;
84
- } else if (entityType === "segment") {
85
- return this.config.segmentsDirectoryPath;
86
- } else if (entityType === "test") {
87
- return this.config.testsDirectoryPath;
88
- }
89
-
90
- return this.config.attributesDirectoryPath;
91
- }
92
-
93
- getEntityPath(entityType: EntityType, entityKey: string): string {
94
- const basePath = this.getEntityDirectoryPath(entityType);
95
-
96
- return path.join(basePath, `${entityKey}.${this.extension}`);
97
- }
98
-
99
- async entityExists(entityType: EntityType, entityKey: string): Promise<boolean> {
100
- const entityPath = this.getEntityPath(entityType, entityKey);
101
-
102
- return fs.existsSync(entityPath);
103
- }
104
-
105
- async readEntity(entityType: EntityType, entityKey: string): Promise<string> {
106
- const filePath = this.getEntityPath(entityType, entityKey);
107
-
108
- return fs.readFileSync(filePath, "utf8");
109
- }
110
-
111
- async parseEntity<T>(entityType: EntityType, entityKey: string): Promise<T> {
112
- const entityContent = await this.readEntity(entityType, entityKey);
113
-
114
- return this.parse(entityContent) as T;
27
+ return (this.config.parser as CustomParser).extension;
115
28
  }
116
29
 
117
30
  /**
118
31
  * State
119
32
  */
120
33
  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);
34
+ return this.adapter.readState(environment);
130
35
  }
131
36
 
132
37
  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));
38
+ return this.adapter.writeState(environment, existingState);
146
39
  }
147
40
 
148
41
  /**
@@ -151,11 +44,15 @@ export class Datasource {
151
44
 
152
45
  // features
153
46
  async listFeatures() {
154
- return await this.listEntities("feature");
47
+ return await this.adapter.listEntities("feature");
48
+ }
49
+
50
+ featureExists(featureKey: FeatureKey) {
51
+ return this.adapter.entityExists("feature", featureKey);
155
52
  }
156
53
 
157
- readFeature(featureKey: string) {
158
- return this.parseEntity<ParsedFeature>("feature", featureKey);
54
+ readFeature(featureKey: FeatureKey) {
55
+ return this.adapter.parseEntity<ParsedFeature>("feature", featureKey);
159
56
  }
160
57
 
161
58
  async getRequiredFeaturesChain(
@@ -164,7 +61,7 @@ export class Datasource {
164
61
  ): Promise<Set<FeatureKey>> {
165
62
  chain.add(featureKey);
166
63
 
167
- if (!this.entityExists("feature", featureKey)) {
64
+ if (!this.adapter.entityExists("feature", featureKey)) {
168
65
  throw new Error(`Feature not found: ${featureKey}`);
169
66
  }
170
67
 
@@ -189,37 +86,53 @@ export class Datasource {
189
86
 
190
87
  // segments
191
88
  listSegments() {
192
- return this.listEntities("segment");
89
+ return this.adapter.listEntities("segment");
90
+ }
91
+
92
+ segmentExists(segmentKey: SegmentKey) {
93
+ return this.adapter.entityExists("segment", segmentKey);
193
94
  }
194
95
 
195
- readSegment(segmentKey: string) {
196
- return this.parseEntity<Segment>("segment", segmentKey);
96
+ readSegment(segmentKey: SegmentKey) {
97
+ return this.adapter.parseEntity<Segment>("segment", segmentKey);
197
98
  }
198
99
 
199
100
  // attributes
200
101
  listAttributes() {
201
- return this.listEntities("attribute");
102
+ return this.adapter.listEntities("attribute");
202
103
  }
203
104
 
204
- readAttribute(attributeKey: string) {
205
- return this.parseEntity<Attribute>("attribute", attributeKey);
105
+ attributeExists(attributeKey: AttributeKey) {
106
+ return this.adapter.entityExists("attribute", attributeKey);
107
+ }
108
+
109
+ readAttribute(attributeKey: AttributeKey) {
110
+ return this.adapter.parseEntity<Attribute>("attribute", attributeKey);
206
111
  }
207
112
 
208
113
  // groups
209
114
  async listGroups() {
210
- return this.listEntities("group");
115
+ return this.adapter.listEntities("group");
116
+ }
117
+
118
+ groupExists(groupKey: string) {
119
+ return this.adapter.entityExists("group", groupKey);
211
120
  }
212
121
 
213
122
  readGroup(groupKey: string) {
214
- return this.parseEntity<Group>("group", groupKey);
123
+ return this.adapter.parseEntity<Group>("group", groupKey);
215
124
  }
216
125
 
217
126
  // tests
218
127
  listTests() {
219
- return this.listEntities("test");
128
+ return this.adapter.listEntities("test");
220
129
  }
221
130
 
222
131
  readTest(testKey: string) {
223
- return this.parseEntity<Test>("test", testKey);
132
+ return this.adapter.parseEntity<Test>("test", testKey);
133
+ }
134
+
135
+ getTestSpecName(testKey: string) {
136
+ return `${testKey}.${this.getExtension()}`;
224
137
  }
225
138
  }
@@ -0,0 +1,108 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+
4
+ import * as mkdirp from "mkdirp";
5
+
6
+ import { ExistingState, EnvironmentKey } from "@featurevisor/types";
7
+
8
+ import { Adapter, EntityType } from "./adapter";
9
+ import { ProjectConfig, CustomParser } from "../config";
10
+
11
+ export function getExistingStateFilePath(
12
+ projectConfig: ProjectConfig,
13
+ environment: EnvironmentKey,
14
+ ): string {
15
+ return path.join(projectConfig.stateDirectoryPath, `existing-state-${environment}.json`);
16
+ }
17
+
18
+ export class FilesystemAdapter extends Adapter {
19
+ private parser: CustomParser;
20
+
21
+ constructor(private config: ProjectConfig) {
22
+ super();
23
+
24
+ this.parser = config.parser as CustomParser;
25
+ }
26
+
27
+ getEntityDirectoryPath(entityType: EntityType): string {
28
+ if (entityType === "feature") {
29
+ return this.config.featuresDirectoryPath;
30
+ } else if (entityType === "group") {
31
+ return this.config.groupsDirectoryPath;
32
+ } else if (entityType === "segment") {
33
+ return this.config.segmentsDirectoryPath;
34
+ } else if (entityType === "test") {
35
+ return this.config.testsDirectoryPath;
36
+ }
37
+
38
+ return this.config.attributesDirectoryPath;
39
+ }
40
+
41
+ getEntityPath(entityType: EntityType, entityKey: string): string {
42
+ const basePath = this.getEntityDirectoryPath(entityType);
43
+
44
+ return path.join(basePath, `${entityKey}.${this.parser.extension}`);
45
+ }
46
+
47
+ async listEntities(entityType: EntityType): Promise<string[]> {
48
+ const directoryPath = this.getEntityDirectoryPath(entityType);
49
+
50
+ if (!fs.existsSync(directoryPath)) {
51
+ return [];
52
+ }
53
+
54
+ return fs
55
+ .readdirSync(directoryPath)
56
+ .filter((fileName) => fileName.endsWith(`.${this.parser.extension}`))
57
+ .map((fileName) => fileName.replace(`.${this.parser.extension}`, ""));
58
+ }
59
+
60
+ async entityExists(entityType: EntityType, entityKey: string): Promise<boolean> {
61
+ const entityPath = this.getEntityPath(entityType, entityKey);
62
+
63
+ return fs.existsSync(entityPath);
64
+ }
65
+
66
+ async readEntity(entityType: EntityType, entityKey: string): Promise<string> {
67
+ const filePath = this.getEntityPath(entityType, entityKey);
68
+
69
+ return fs.readFileSync(filePath, "utf8");
70
+ }
71
+
72
+ async parseEntity<T>(entityType: EntityType, entityKey: string): Promise<T> {
73
+ const entityContent = await this.readEntity(entityType, entityKey);
74
+
75
+ return this.parser.parse<T>(entityContent);
76
+ }
77
+
78
+ /**
79
+ * State
80
+ */
81
+ async readState(environment: EnvironmentKey): Promise<ExistingState> {
82
+ const filePath = getExistingStateFilePath(this.config, environment);
83
+
84
+ if (!fs.existsSync(filePath)) {
85
+ return {
86
+ features: {},
87
+ };
88
+ }
89
+
90
+ return require(filePath);
91
+ }
92
+
93
+ async writeState(environment: EnvironmentKey, existingState: ExistingState) {
94
+ const filePath = getExistingStateFilePath(this.config, environment);
95
+
96
+ if (!fs.existsSync(this.config.stateDirectoryPath)) {
97
+ mkdirp.sync(this.config.stateDirectoryPath);
98
+ }
99
+ fs.writeFileSync(
100
+ filePath,
101
+ this.config.prettyState
102
+ ? JSON.stringify(existingState, null, 2)
103
+ : JSON.stringify(existingState),
104
+ );
105
+
106
+ fs.writeFileSync(filePath, JSON.stringify(existingState, null, 2));
107
+ }
108
+ }
@@ -1,2 +1,3 @@
1
1
  export * from "./datasource";
2
- export * from "./parsers";
2
+ export * from "./adapter";
3
+ export * from "./filesystemAdapter";
@@ -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
- rootDirectoryPath,
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
- rootDirectoryPath,
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: string,
92
- projectConfig: ProjectConfig,
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
@@ -7,3 +7,5 @@ export * from "./site";
7
7
  export * from "./generate-code";
8
8
  export * from "./restore";
9
9
  export * from "./find-duplicate-segments";
10
+ export * from "./dependencies";
11
+ export * from "./datasource";
@@ -25,7 +25,7 @@ export async function checkForCircularDependencyInRequired(
25
25
  throw new Error(`circular dependency found: ${chain.join(" -> ")}`);
26
26
  }
27
27
 
28
- const requiredFeatureExists = await datasource.entityExists("feature", requiredKey);
28
+ const requiredFeatureExists = await datasource.featureExists(featureKey);
29
29
 
30
30
  if (!requiredFeatureExists) {
31
31
  throw new Error(`required feature "${requiredKey}" not found`);
@@ -1,9 +1,6 @@
1
1
  // for use in node only
2
2
  import * as Joi from "joi";
3
3
 
4
- import { Datasource } from "../datasource";
5
- import { ProjectConfig } from "../config";
6
-
7
4
  import { getAttributeJoiSchema } from "./attributeSchema";
8
5
  import { getConditionsJoiSchema } from "./conditionSchema";
9
6
  import { getSegmentJoiSchema } from "./segmentSchema";
@@ -13,10 +10,12 @@ import { getTestsJoiSchema } from "./testSchema";
13
10
 
14
11
  import { checkForCircularDependencyInRequired } from "./checkCircularDependency";
15
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;
16
17
 
17
- export async function lintProject(projectConfig: ProjectConfig): Promise<boolean> {
18
18
  let hasError = false;
19
- const datasource = new Datasource(projectConfig);
20
19
 
21
20
  const availableAttributeKeys: string[] = [];
22
21
  const availableSegmentKeys: string[] = [];
@@ -1,9 +1,11 @@
1
1
  import * as path from "path";
2
2
  import { execSync } from "child_process";
3
3
 
4
- import { ProjectConfig } from "./config";
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
 
@@ -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
- rootDirectoryPath: string,
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
@@ -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 { ProjectConfig } from "../config";
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
@@ -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}`);
@@ -33,7 +29,7 @@ export async function testProject(
33
29
  }
34
30
 
35
31
  for (const testFile of testFiles) {
36
- const testFilePath = datasource.getEntityPath("test", testFile);
32
+ const testFilePath = datasource.getTestSpecName(testFile);
37
33
 
38
34
  console.log("");
39
35
  console.log(CLI_FORMAT_BOLD, `Testing: ${testFilePath.replace(rootDirectoryPath, "")}`);
@@ -12,7 +12,7 @@ export async function testSegment(datasource: Datasource, test: TestSegment): Pr
12
12
 
13
13
  console.log(CLI_FORMAT_BOLD, ` Segment "${segmentKey}":`);
14
14
 
15
- const segmentExists = await datasource.entityExists("segment", segmentKey);
15
+ const segmentExists = await datasource.segmentExists(segmentKey);
16
16
 
17
17
  if (!segmentExists) {
18
18
  console.error(CLI_FORMAT_RED, ` Segment does not exist: ${segmentKey}`);
package/lib/config.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;;AAAA,2BAA6B;AAMhB,QAAA,uBAAuB,GAAG,UAAU,CAAC;AACrC,QAAA,uBAAuB,GAAG,UAAU,CAAC;AACrC,QAAA,yBAAyB,GAAG,YAAY,CAAC;AACzC,QAAA,qBAAqB,GAAG,QAAQ,CAAC;AACjC,QAAA,oBAAoB,GAAG,OAAO,CAAC;AAC/B,QAAA,oBAAoB,GAAG,eAAe,CAAC;AACvC,QAAA,qBAAqB,GAAG,MAAM,CAAC;AAC/B,QAAA,0BAA0B,GAAG,KAAK,CAAC;AAEnC,QAAA,kBAAkB,GAAG,wBAAwB,CAAC;AAC9C,QAAA,oBAAoB,GAAG,WAAW,CAAC;AAEnC,QAAA,oBAAoB,GAAG,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;AACjD,QAAA,YAAY,GAAG,CAAC,KAAK,CAAC,CAAC;AACvB,QAAA,2BAA2B,GAAG,QAAQ,CAAC;AAEvC,QAAA,oBAAoB,GAAG,KAAK,CAAC;AAC7B,QAAA,uBAAuB,GAAG,KAAK,CAAC;AAEhC,QAAA,cAAc,GAAW,KAAK,CAAC;AAE/B,QAAA,cAAc,GAAG,GAAG,CAAC;AAmBlC,6FAA6F;AAC7F,SAAgB,gBAAgB,CAAC,iBAAyB;IACxD,IAAM,UAAU,GAAkB;QAChC,qBAAqB,EAAE,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,+BAAuB,CAAC;QAC5E,qBAAqB,EAAE,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,+BAAuB,CAAC;QAC5E,uBAAuB,EAAE,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,iCAAyB,CAAC;QAChF,mBAAmB,EAAE,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,6BAAqB,CAAC;QACxE,kBAAkB,EAAE,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,4BAAoB,CAAC;QAEtE,kBAAkB,EAAE,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,4BAAoB,CAAC;QACtE,mBAAmB,EAAE,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,6BAAqB,CAAC;QAExE,YAAY,EAAE,4BAAoB;QAClC,IAAI,EAAE,oBAAY;QAClB,eAAe,EAAE,QAAQ;QAEzB,MAAM,EAAE,sBAAc;QAEtB,WAAW,EAAE,4BAAoB;QACjC,cAAc,EAAE,+BAAuB;QAEvC,uBAAuB,EAAE,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,kCAA0B,CAAC;KAClF,CAAC;IAEF,IAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,0BAAkB,CAAC,CAAC;IAC1E,IAAM,YAAY,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAE/C,IAAM,WAAW,GAAG,EAAE,CAAC;IAEvB,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,UAAC,GAAG;QAClC,WAAW,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC,GAAG,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;QAExD,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,WAAW,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,4BAAoB,CAAC,KAAK,CAAC,CAAC,EAAE;YACjF,WAAW,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,4BAAoB,EAAE,iBAAiB,CAAC,CAAC;SACtF;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,WAA4B,CAAC;AACtC,CAAC;AArCD,4CAqCC"}
@@ -1,19 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parsers = void 0;
4
- var YAML = require("js-yaml");
5
- /**
6
- * If we want to add more built-in parsers,
7
- * add them to this object with new file extension as the key,
8
- * and a function that takes file content as string and returns parsed object as the value.
9
- */
10
- exports.parsers = {
11
- // extension => function
12
- yml: function (content) {
13
- return YAML.load(content);
14
- },
15
- json: function (content) {
16
- return JSON.parse(content);
17
- },
18
- };
19
- //# sourceMappingURL=parsers.js.map