@featurevisor/core 0.33.0 → 0.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 +19 -0
- package/coverage/clover.xml +2 -2
- package/coverage/lcov-report/index.html +1 -1
- package/coverage/lcov-report/lib/allocator.js.html +1 -1
- package/coverage/lcov-report/lib/index.html +1 -1
- package/coverage/lcov-report/lib/traffic.js.html +1 -1
- package/coverage/lcov-report/src/allocator.ts.html +1 -1
- package/coverage/lcov-report/src/index.html +1 -1
- package/coverage/lcov-report/src/traffic.ts.html +1 -1
- package/lib/generate-code/index.d.ts +7 -0
- package/lib/generate-code/index.js +34 -0
- package/lib/generate-code/index.js.map +1 -0
- package/lib/generate-code/typescript.d.ts +2 -0
- package/lib/generate-code/typescript.js +134 -0
- package/lib/generate-code/typescript.js.map +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/package.json +5 -5
- package/src/generate-code/index.ts +51 -0
- package/src/generate-code/typescript.ts +207 -0
- package/src/index.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,25 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [0.35.0](https://github.com/fahad19/featurevisor/compare/v0.34.0...v0.35.0) (2023-07-13)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @featurevisor/core
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# [0.34.0](https://github.com/fahad19/featurevisor/compare/v0.33.1...v0.34.0) (2023-07-08)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Features
|
|
18
|
+
|
|
19
|
+
* code generation ([#98](https://github.com/fahad19/featurevisor/issues/98)) ([7474443](https://github.com/fahad19/featurevisor/commit/7474443d26fd526f471ef5258cbe39b42c0fad60))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
6
25
|
# [0.33.0](https://github.com/fahad19/featurevisor/compare/v0.32.1...v0.33.0) (2023-07-06)
|
|
7
26
|
|
|
8
27
|
**Note:** Version bump only for package @featurevisor/core
|
package/coverage/clover.xml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<coverage generated="
|
|
3
|
-
<project timestamp="
|
|
2
|
+
<coverage generated="1689264623176" clover="3.2.0">
|
|
3
|
+
<project timestamp="1689264623176" name="All files">
|
|
4
4
|
<metrics statements="169" coveredstatements="161" conditionals="75" coveredconditionals="62" methods="28" coveredmethods="28" elements="272" coveredelements="251" complexity="0" loc="169" ncloc="169" packages="2" files="4" classes="4"/>
|
|
5
5
|
<package name="lib">
|
|
6
6
|
<metrics statements="88" coveredstatements="84" conditionals="42" coveredconditionals="35" methods="14" coveredmethods="14"/>
|
|
@@ -116,7 +116,7 @@
|
|
|
116
116
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
117
117
|
Code coverage generated by
|
|
118
118
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
119
|
-
at 2023-07-
|
|
119
|
+
at 2023-07-13T16:10:23.164Z
|
|
120
120
|
</div>
|
|
121
121
|
<script src="prettify.js"></script>
|
|
122
122
|
<script>
|
|
@@ -175,7 +175,7 @@ exports.getUpdatedAvailableRangesAfterFilling = getUpdatedAvailableRangesAfterFi
|
|
|
175
175
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
176
176
|
Code coverage generated by
|
|
177
177
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
178
|
-
at 2023-07-
|
|
178
|
+
at 2023-07-13T16:10:23.164Z
|
|
179
179
|
</div>
|
|
180
180
|
<script src="../prettify.js"></script>
|
|
181
181
|
<script>
|
|
@@ -116,7 +116,7 @@
|
|
|
116
116
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
117
117
|
Code coverage generated by
|
|
118
118
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
119
|
-
at 2023-07-
|
|
119
|
+
at 2023-07-13T16:10:23.164Z
|
|
120
120
|
</div>
|
|
121
121
|
<script src="../prettify.js"></script>
|
|
122
122
|
<script>
|
|
@@ -427,7 +427,7 @@ exports.getTraffic = getTraffic;
|
|
|
427
427
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
428
428
|
Code coverage generated by
|
|
429
429
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
430
|
-
at 2023-07-
|
|
430
|
+
at 2023-07-13T16:10:23.164Z
|
|
431
431
|
</div>
|
|
432
432
|
<script src="../prettify.js"></script>
|
|
433
433
|
<script>
|
|
@@ -193,7 +193,7 @@ export function getUpdatedAvailableRangesAfterFilling(
|
|
|
193
193
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
194
194
|
Code coverage generated by
|
|
195
195
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
196
|
-
at 2023-07-
|
|
196
|
+
at 2023-07-13T16:10:23.164Z
|
|
197
197
|
</div>
|
|
198
198
|
<script src="../prettify.js"></script>
|
|
199
199
|
<script>
|
|
@@ -116,7 +116,7 @@
|
|
|
116
116
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
117
117
|
Code coverage generated by
|
|
118
118
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
119
|
-
at 2023-07-
|
|
119
|
+
at 2023-07-13T16:10:23.164Z
|
|
120
120
|
</div>
|
|
121
121
|
<script src="../prettify.js"></script>
|
|
122
122
|
<script>
|
|
@@ -535,7 +535,7 @@ export function getTraffic(
|
|
|
535
535
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
536
536
|
Code coverage generated by
|
|
537
537
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
538
|
-
at 2023-07-
|
|
538
|
+
at 2023-07-13T16:10:23.164Z
|
|
539
539
|
</div>
|
|
540
540
|
<script src="../prettify.js"></script>
|
|
541
541
|
<script>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ProjectConfig } from "../config";
|
|
2
|
+
export declare const ALLOWED_LANGUAGES_FOR_CODE_GENERATION: string[];
|
|
3
|
+
export interface GenerateCodeCLIOptions {
|
|
4
|
+
language: string;
|
|
5
|
+
outDir: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function generateCodeForProject(rootDirectoryPath: any, projectConfig: ProjectConfig, cliOptions: GenerateCodeCLIOptions): void;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateCodeForProject = exports.ALLOWED_LANGUAGES_FOR_CODE_GENERATION = void 0;
|
|
4
|
+
var fs = require("fs");
|
|
5
|
+
var path = require("path");
|
|
6
|
+
var mkdirp = require("mkdirp");
|
|
7
|
+
var typescript_1 = require("./typescript");
|
|
8
|
+
exports.ALLOWED_LANGUAGES_FOR_CODE_GENERATION = ["typescript"];
|
|
9
|
+
function generateCodeForProject(rootDirectoryPath, projectConfig, cliOptions) {
|
|
10
|
+
if (!cliOptions.language) {
|
|
11
|
+
throw new Error("Option `--language` is required");
|
|
12
|
+
}
|
|
13
|
+
if (!cliOptions.outDir) {
|
|
14
|
+
throw new Error("Option `--out-dir` is required");
|
|
15
|
+
}
|
|
16
|
+
var absolutePath = path.resolve(rootDirectoryPath, cliOptions.outDir);
|
|
17
|
+
if (!fs.existsSync(absolutePath)) {
|
|
18
|
+
console.log("Creating output directory: ".concat(absolutePath));
|
|
19
|
+
mkdirp.sync(absolutePath);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
console.log("Output directory already exists at: ".concat(absolutePath));
|
|
23
|
+
}
|
|
24
|
+
if (!exports.ALLOWED_LANGUAGES_FOR_CODE_GENERATION.includes(cliOptions.language)) {
|
|
25
|
+
console.log("Only these languages are supported: ".concat(exports.ALLOWED_LANGUAGES_FOR_CODE_GENERATION.join(", ")));
|
|
26
|
+
throw new Error("Language ".concat(cliOptions.language, " is not supported for code generation"));
|
|
27
|
+
}
|
|
28
|
+
if (cliOptions.language === "typescript") {
|
|
29
|
+
return (0, typescript_1.generateTypeScriptCodeForProject)(rootDirectoryPath, projectConfig, absolutePath);
|
|
30
|
+
}
|
|
31
|
+
throw new Error("Language ".concat(cliOptions.language, " is not supported"));
|
|
32
|
+
}
|
|
33
|
+
exports.generateCodeForProject = generateCodeForProject;
|
|
34
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/generate-code/index.ts"],"names":[],"mappings":";;;AAAA,uBAAyB;AACzB,2BAA6B;AAE7B,+BAAiC;AAGjC,2CAAgE;AAEnD,QAAA,qCAAqC,GAAG,CAAC,YAAY,CAAC,CAAC;AAOpE,SAAgB,sBAAsB,CACpC,iBAAiB,EACjB,aAA4B,EAC5B,UAAkC;IAElC,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE;QACxB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;KACpD;IAED,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE;QACtB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;KACnD;IAED,IAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAExE,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE;QAChC,OAAO,CAAC,GAAG,CAAC,qCAA8B,YAAY,CAAE,CAAC,CAAC;QAC1D,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;KAC3B;SAAM;QACL,OAAO,CAAC,GAAG,CAAC,8CAAuC,YAAY,CAAE,CAAC,CAAC;KACpE;IAED,IAAI,CAAC,6CAAqC,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;QACxE,OAAO,CAAC,GAAG,CACT,8CAAuC,6CAAqC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAE,CAC1F,CAAC;QAEF,MAAM,IAAI,KAAK,CAAC,mBAAY,UAAU,CAAC,QAAQ,0CAAuC,CAAC,CAAC;KACzF;IAED,IAAI,UAAU,CAAC,QAAQ,KAAK,YAAY,EAAE;QACxC,OAAO,IAAA,6CAAgC,EAAC,iBAAiB,EAAE,aAAa,EAAE,YAAY,CAAC,CAAC;KACzF;IAED,MAAM,IAAI,KAAK,CAAC,mBAAY,UAAU,CAAC,QAAQ,sBAAmB,CAAC,CAAC;AACtE,CAAC;AAnCD,wDAmCC"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateTypeScriptCodeForProject = void 0;
|
|
4
|
+
var fs = require("fs");
|
|
5
|
+
var path = require("path");
|
|
6
|
+
var utils_1 = require("../utils");
|
|
7
|
+
function convertFeaturevisorTypeToTypeScriptType(featurevisorType) {
|
|
8
|
+
switch (featurevisorType) {
|
|
9
|
+
case "boolean":
|
|
10
|
+
return "boolean";
|
|
11
|
+
case "string":
|
|
12
|
+
return "string";
|
|
13
|
+
case "integer":
|
|
14
|
+
return "number";
|
|
15
|
+
case "double":
|
|
16
|
+
return "number";
|
|
17
|
+
case "date":
|
|
18
|
+
return "Date | string";
|
|
19
|
+
case "array":
|
|
20
|
+
return "string[]";
|
|
21
|
+
case "object":
|
|
22
|
+
return "any"; // @TODO: do a flat dictionary
|
|
23
|
+
case "json":
|
|
24
|
+
return "any";
|
|
25
|
+
default:
|
|
26
|
+
throw new Error("Unknown type: ".concat(featurevisorType));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function getPascalCase(str) {
|
|
30
|
+
// Remove special characters and split the string into an array of words
|
|
31
|
+
var words = str.replace(/[^a-zA-Z0-9]/g, " ").split(" ");
|
|
32
|
+
// Capitalize the first letter of each word and join them together
|
|
33
|
+
var pascalCased = words.map(function (word) { return word.charAt(0).toUpperCase() + word.slice(1); }).join("");
|
|
34
|
+
return pascalCased;
|
|
35
|
+
}
|
|
36
|
+
function getFeaturevisorTypeFromValue(value) {
|
|
37
|
+
if (typeof value === "boolean") {
|
|
38
|
+
return "boolean";
|
|
39
|
+
}
|
|
40
|
+
if (typeof value === "string") {
|
|
41
|
+
return "string";
|
|
42
|
+
}
|
|
43
|
+
if (typeof value === "number") {
|
|
44
|
+
if (Number.isInteger(value)) {
|
|
45
|
+
return "integer";
|
|
46
|
+
}
|
|
47
|
+
return "double";
|
|
48
|
+
}
|
|
49
|
+
if (value instanceof Date) {
|
|
50
|
+
return "date";
|
|
51
|
+
}
|
|
52
|
+
throw new Error("Could not detect Featurevisor type from value");
|
|
53
|
+
}
|
|
54
|
+
var instanceSnippet = "\nimport { FeaturevisorInstance } from \"@featurevisor/sdk\";\n\nlet _instance: FeaturevisorInstance;\n\nexport function setInstance(instance: FeaturevisorInstance) {\n _instance = instance;\n}\n\nexport function getInstance(): FeaturevisorInstance {\n return _instance as FeaturevisorInstance;\n}\n".trimStart();
|
|
55
|
+
function generateTypeScriptCodeForProject(rootDirectoryPath, projectConfig, outputPath) {
|
|
56
|
+
console.log("Generating TypeScript code...");
|
|
57
|
+
// instance
|
|
58
|
+
var instanceFilePath = path.join(outputPath, "instance.ts");
|
|
59
|
+
fs.writeFileSync(instanceFilePath, instanceSnippet);
|
|
60
|
+
console.log("Instance file written at: ".concat(instanceFilePath));
|
|
61
|
+
// attributes
|
|
62
|
+
var attributeFiles = (0, utils_1.getYAMLFiles)(projectConfig.attributesDirectoryPath);
|
|
63
|
+
var attributes = attributeFiles
|
|
64
|
+
.map(function (attributeFile) {
|
|
65
|
+
var parsedAttribute = (0, utils_1.parseYaml)(fs.readFileSync(attributeFile, "utf8"));
|
|
66
|
+
var attributeKey = path.basename(attributeFile, ".yml");
|
|
67
|
+
return {
|
|
68
|
+
archived: parsedAttribute.archived,
|
|
69
|
+
key: attributeKey,
|
|
70
|
+
type: parsedAttribute.type,
|
|
71
|
+
typescriptType: convertFeaturevisorTypeToTypeScriptType(parsedAttribute.type),
|
|
72
|
+
};
|
|
73
|
+
})
|
|
74
|
+
.filter(function (attribute) {
|
|
75
|
+
if (typeof attribute.archived === "undefined") {
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
return !attribute.archived;
|
|
79
|
+
});
|
|
80
|
+
var attributeProperties = attributes
|
|
81
|
+
.map(function (attribute) {
|
|
82
|
+
return " ".concat(attribute.key, "?: ").concat(attribute.typescriptType, ";");
|
|
83
|
+
})
|
|
84
|
+
.join("\n");
|
|
85
|
+
var attributesContent = "\nimport { AttributeKey, AttributeValue } from \"@featurevisor/types\";\n\nexport interface Attributes {\n".concat(attributeProperties, "\n [key: AttributeKey]: AttributeValue;\n}\n").trimStart();
|
|
86
|
+
var attributesTypeFilePath = path.join(outputPath, "Attributes.ts");
|
|
87
|
+
fs.writeFileSync(attributesTypeFilePath, attributesContent);
|
|
88
|
+
console.log("Attributes type file written at: ".concat(attributesTypeFilePath));
|
|
89
|
+
// features
|
|
90
|
+
var featureNamespaces = [];
|
|
91
|
+
var featureFiles = (0, utils_1.getYAMLFiles)(projectConfig.featuresDirectoryPath);
|
|
92
|
+
for (var _i = 0, featureFiles_1 = featureFiles; _i < featureFiles_1.length; _i++) {
|
|
93
|
+
var featureFile = featureFiles_1[_i];
|
|
94
|
+
var featureKey = path.basename(featureFile, ".yml");
|
|
95
|
+
var parsedFeature = (0, utils_1.parseYaml)(fs.readFileSync(featureFile, "utf8"));
|
|
96
|
+
var variationType = getFeaturevisorTypeFromValue(parsedFeature.defaultVariation);
|
|
97
|
+
var variationTypeScriptType = convertFeaturevisorTypeToTypeScriptType(variationType);
|
|
98
|
+
if (typeof parsedFeature.archived !== "undefined" && parsedFeature.archived) {
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
var namespaceValue = getPascalCase(featureKey) + "Feature";
|
|
102
|
+
featureNamespaces.push(namespaceValue);
|
|
103
|
+
var variableMethods = "";
|
|
104
|
+
if (parsedFeature.variablesSchema) {
|
|
105
|
+
for (var _a = 0, _b = parsedFeature.variablesSchema; _a < _b.length; _a++) {
|
|
106
|
+
var variableSchema = _b[_a];
|
|
107
|
+
var variableKey = variableSchema.key;
|
|
108
|
+
var variableType = variableSchema.type;
|
|
109
|
+
var internalMethodName = "getVariable".concat(variableType === "json" ? "JSON" : getPascalCase(variableType));
|
|
110
|
+
if (variableType === "json" || variableType === "object") {
|
|
111
|
+
variableMethods += "\n\n export function get".concat(getPascalCase(variableKey), "<T>(attributes: Attributes = {}) {\n return getInstance().").concat(internalMethodName, "<T>(key, \"").concat(variableKey, "\", attributes);\n }");
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
variableMethods += "\n\n export function get".concat(getPascalCase(variableKey), "(attributes: Attributes = {}) {\n return getInstance().").concat(internalMethodName, "(key, \"").concat(variableKey, "\", attributes);\n }");
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
var featureContent = "\nimport { Attributes } from \"./Attributes\";\nimport { getInstance } from \"./instance\";\n\nexport namespace ".concat(namespaceValue, " {\n export const key = \"").concat(featureKey, "\";\n\n export function getVariation(attributes: Attributes = {}) {\n return getInstance().getVariation").concat(getPascalCase(variationType), "(key, attributes);\n }").concat(variableMethods, "\n}\n").trimStart();
|
|
119
|
+
var featureNamespaceFilePath = path.join(outputPath, "".concat(namespaceValue, ".ts"));
|
|
120
|
+
fs.writeFileSync(featureNamespaceFilePath, featureContent);
|
|
121
|
+
console.log("Feature ".concat(featureKey, " file written at: ").concat(featureNamespaceFilePath));
|
|
122
|
+
}
|
|
123
|
+
// index
|
|
124
|
+
var indexContent = ["export * from \"./Attributes\";", "export * from \"./instance\";"]
|
|
125
|
+
.concat(featureNamespaces.map(function (featureNamespace) {
|
|
126
|
+
return "export * from \"./".concat(featureNamespace, "\";");
|
|
127
|
+
}))
|
|
128
|
+
.join("\n") + "\n";
|
|
129
|
+
var indexFilePath = path.join(outputPath, "index.ts");
|
|
130
|
+
fs.writeFileSync(indexFilePath, indexContent);
|
|
131
|
+
console.log("Index file written at: ".concat(indexFilePath));
|
|
132
|
+
}
|
|
133
|
+
exports.generateTypeScriptCodeForProject = generateTypeScriptCodeForProject;
|
|
134
|
+
//# sourceMappingURL=typescript.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typescript.js","sourceRoot":"","sources":["../../src/generate-code/typescript.ts"],"names":[],"mappings":"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"}
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -20,4 +20,5 @@ __exportStar(require("./builder"), exports);
|
|
|
20
20
|
__exportStar(require("./tester"), exports);
|
|
21
21
|
__exportStar(require("./init"), exports);
|
|
22
22
|
__exportStar(require("./site"), exports);
|
|
23
|
+
__exportStar(require("./generate-code"), exports);
|
|
23
24
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,2CAAyB;AACzB,4CAA0B;AAC1B,2CAAyB;AACzB,yCAAuB;AACvB,yCAAuB"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,2CAAyB;AACzB,4CAA0B;AAC1B,2CAAyB;AACzB,yCAAuB;AACvB,yCAAuB;AACvB,kDAAgC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@featurevisor/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.35.0",
|
|
4
4
|
"description": "Core package of Featurevisor for Node.js usage",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
},
|
|
42
42
|
"license": "MIT",
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@featurevisor/sdk": "^0.
|
|
45
|
-
"@featurevisor/site": "^0.
|
|
46
|
-
"@featurevisor/types": "^0.
|
|
44
|
+
"@featurevisor/sdk": "^0.35.0",
|
|
45
|
+
"@featurevisor/site": "^0.35.0",
|
|
46
|
+
"@featurevisor/types": "^0.35.0",
|
|
47
47
|
"axios": "^1.3.4",
|
|
48
48
|
"joi": "^17.8.3",
|
|
49
49
|
"js-yaml": "^4.1.0",
|
|
@@ -54,5 +54,5 @@
|
|
|
54
54
|
"@types/js-yaml": "^4.0.5",
|
|
55
55
|
"@types/tar": "^6.1.4"
|
|
56
56
|
},
|
|
57
|
-
"gitHead": "
|
|
57
|
+
"gitHead": "1c8bb99f1dce49b87a95c7e1903bc0308fc7db4d"
|
|
58
58
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
|
|
4
|
+
import * as mkdirp from "mkdirp";
|
|
5
|
+
|
|
6
|
+
import { ProjectConfig } from "../config";
|
|
7
|
+
import { generateTypeScriptCodeForProject } from "./typescript";
|
|
8
|
+
|
|
9
|
+
export const ALLOWED_LANGUAGES_FOR_CODE_GENERATION = ["typescript"];
|
|
10
|
+
|
|
11
|
+
export interface GenerateCodeCLIOptions {
|
|
12
|
+
language: string;
|
|
13
|
+
outDir: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function generateCodeForProject(
|
|
17
|
+
rootDirectoryPath,
|
|
18
|
+
projectConfig: ProjectConfig,
|
|
19
|
+
cliOptions: GenerateCodeCLIOptions,
|
|
20
|
+
) {
|
|
21
|
+
if (!cliOptions.language) {
|
|
22
|
+
throw new Error("Option `--language` is required");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (!cliOptions.outDir) {
|
|
26
|
+
throw new Error("Option `--out-dir` is required");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const absolutePath = path.resolve(rootDirectoryPath, cliOptions.outDir);
|
|
30
|
+
|
|
31
|
+
if (!fs.existsSync(absolutePath)) {
|
|
32
|
+
console.log(`Creating output directory: ${absolutePath}`);
|
|
33
|
+
mkdirp.sync(absolutePath);
|
|
34
|
+
} else {
|
|
35
|
+
console.log(`Output directory already exists at: ${absolutePath}`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!ALLOWED_LANGUAGES_FOR_CODE_GENERATION.includes(cliOptions.language)) {
|
|
39
|
+
console.log(
|
|
40
|
+
`Only these languages are supported: ${ALLOWED_LANGUAGES_FOR_CODE_GENERATION.join(", ")}`,
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
throw new Error(`Language ${cliOptions.language} is not supported for code generation`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (cliOptions.language === "typescript") {
|
|
47
|
+
return generateTypeScriptCodeForProject(rootDirectoryPath, projectConfig, absolutePath);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
throw new Error(`Language ${cliOptions.language} is not supported`);
|
|
51
|
+
}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
|
|
4
|
+
import { Attribute, ParsedFeature } from "@featurevisor/types";
|
|
5
|
+
|
|
6
|
+
import { ProjectConfig } from "../config";
|
|
7
|
+
import { getYAMLFiles, parseYaml } from "../utils";
|
|
8
|
+
|
|
9
|
+
function convertFeaturevisorTypeToTypeScriptType(featurevisorType: string) {
|
|
10
|
+
switch (featurevisorType) {
|
|
11
|
+
case "boolean":
|
|
12
|
+
return "boolean";
|
|
13
|
+
case "string":
|
|
14
|
+
return "string";
|
|
15
|
+
case "integer":
|
|
16
|
+
return "number";
|
|
17
|
+
case "double":
|
|
18
|
+
return "number";
|
|
19
|
+
case "date":
|
|
20
|
+
return "Date | string";
|
|
21
|
+
case "array":
|
|
22
|
+
return "string[]";
|
|
23
|
+
case "object":
|
|
24
|
+
return "any"; // @TODO: do a flat dictionary
|
|
25
|
+
case "json":
|
|
26
|
+
return "any";
|
|
27
|
+
default:
|
|
28
|
+
throw new Error(`Unknown type: ${featurevisorType}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function getPascalCase(str) {
|
|
33
|
+
// Remove special characters and split the string into an array of words
|
|
34
|
+
const words = str.replace(/[^a-zA-Z0-9]/g, " ").split(" ");
|
|
35
|
+
|
|
36
|
+
// Capitalize the first letter of each word and join them together
|
|
37
|
+
const pascalCased = words.map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
|
|
38
|
+
|
|
39
|
+
return pascalCased;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function getFeaturevisorTypeFromValue(value) {
|
|
43
|
+
if (typeof value === "boolean") {
|
|
44
|
+
return "boolean";
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (typeof value === "string") {
|
|
48
|
+
return "string";
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (typeof value === "number") {
|
|
52
|
+
if (Number.isInteger(value)) {
|
|
53
|
+
return "integer";
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return "double";
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (value instanceof Date) {
|
|
60
|
+
return "date";
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
throw new Error("Could not detect Featurevisor type from value");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const instanceSnippet = `
|
|
67
|
+
import { FeaturevisorInstance } from "@featurevisor/sdk";
|
|
68
|
+
|
|
69
|
+
let _instance: FeaturevisorInstance;
|
|
70
|
+
|
|
71
|
+
export function setInstance(instance: FeaturevisorInstance) {
|
|
72
|
+
_instance = instance;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function getInstance(): FeaturevisorInstance {
|
|
76
|
+
return _instance as FeaturevisorInstance;
|
|
77
|
+
}
|
|
78
|
+
`.trimStart();
|
|
79
|
+
|
|
80
|
+
export function generateTypeScriptCodeForProject(
|
|
81
|
+
rootDirectoryPath: string,
|
|
82
|
+
projectConfig: ProjectConfig,
|
|
83
|
+
outputPath: string,
|
|
84
|
+
) {
|
|
85
|
+
console.log("Generating TypeScript code...");
|
|
86
|
+
|
|
87
|
+
// instance
|
|
88
|
+
const instanceFilePath = path.join(outputPath, "instance.ts");
|
|
89
|
+
fs.writeFileSync(instanceFilePath, instanceSnippet);
|
|
90
|
+
console.log(`Instance file written at: ${instanceFilePath}`);
|
|
91
|
+
|
|
92
|
+
// attributes
|
|
93
|
+
const attributeFiles = getYAMLFiles(projectConfig.attributesDirectoryPath);
|
|
94
|
+
const attributes = attributeFiles
|
|
95
|
+
.map((attributeFile) => {
|
|
96
|
+
const parsedAttribute = parseYaml(fs.readFileSync(attributeFile, "utf8")) as Attribute;
|
|
97
|
+
|
|
98
|
+
const attributeKey = path.basename(attributeFile, ".yml");
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
archived: parsedAttribute.archived,
|
|
102
|
+
key: attributeKey,
|
|
103
|
+
type: parsedAttribute.type,
|
|
104
|
+
typescriptType: convertFeaturevisorTypeToTypeScriptType(parsedAttribute.type),
|
|
105
|
+
};
|
|
106
|
+
})
|
|
107
|
+
.filter((attribute) => {
|
|
108
|
+
if (typeof attribute.archived === "undefined") {
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return !attribute.archived;
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
const attributeProperties = attributes
|
|
116
|
+
.map((attribute) => {
|
|
117
|
+
return ` ${attribute.key}?: ${attribute.typescriptType};`;
|
|
118
|
+
})
|
|
119
|
+
.join("\n");
|
|
120
|
+
const attributesContent = `
|
|
121
|
+
import { AttributeKey, AttributeValue } from "@featurevisor/types";
|
|
122
|
+
|
|
123
|
+
export interface Attributes {
|
|
124
|
+
${attributeProperties}
|
|
125
|
+
[key: AttributeKey]: AttributeValue;
|
|
126
|
+
}
|
|
127
|
+
`.trimStart();
|
|
128
|
+
|
|
129
|
+
const attributesTypeFilePath = path.join(outputPath, "Attributes.ts");
|
|
130
|
+
fs.writeFileSync(attributesTypeFilePath, attributesContent);
|
|
131
|
+
console.log(`Attributes type file written at: ${attributesTypeFilePath}`);
|
|
132
|
+
|
|
133
|
+
// features
|
|
134
|
+
const featureNamespaces: string[] = [];
|
|
135
|
+
const featureFiles = getYAMLFiles(projectConfig.featuresDirectoryPath);
|
|
136
|
+
for (const featureFile of featureFiles) {
|
|
137
|
+
const featureKey = path.basename(featureFile, ".yml");
|
|
138
|
+
const parsedFeature = parseYaml(fs.readFileSync(featureFile, "utf8")) as ParsedFeature;
|
|
139
|
+
|
|
140
|
+
const variationType = getFeaturevisorTypeFromValue(parsedFeature.defaultVariation);
|
|
141
|
+
const variationTypeScriptType = convertFeaturevisorTypeToTypeScriptType(variationType);
|
|
142
|
+
|
|
143
|
+
if (typeof parsedFeature.archived !== "undefined" && parsedFeature.archived) {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const namespaceValue = getPascalCase(featureKey) + "Feature";
|
|
148
|
+
featureNamespaces.push(namespaceValue);
|
|
149
|
+
|
|
150
|
+
let variableMethods = "";
|
|
151
|
+
|
|
152
|
+
if (parsedFeature.variablesSchema) {
|
|
153
|
+
for (const variableSchema of parsedFeature.variablesSchema) {
|
|
154
|
+
const variableKey = variableSchema.key;
|
|
155
|
+
const variableType = variableSchema.type;
|
|
156
|
+
|
|
157
|
+
const internalMethodName = `getVariable${
|
|
158
|
+
variableType === "json" ? "JSON" : getPascalCase(variableType)
|
|
159
|
+
}`;
|
|
160
|
+
|
|
161
|
+
if (variableType === "json" || variableType === "object") {
|
|
162
|
+
variableMethods += `
|
|
163
|
+
|
|
164
|
+
export function get${getPascalCase(variableKey)}<T>(attributes: Attributes = {}) {
|
|
165
|
+
return getInstance().${internalMethodName}<T>(key, "${variableKey}", attributes);
|
|
166
|
+
}`;
|
|
167
|
+
} else {
|
|
168
|
+
variableMethods += `
|
|
169
|
+
|
|
170
|
+
export function get${getPascalCase(variableKey)}(attributes: Attributes = {}) {
|
|
171
|
+
return getInstance().${internalMethodName}(key, "${variableKey}", attributes);
|
|
172
|
+
}`;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const featureContent = `
|
|
178
|
+
import { Attributes } from "./Attributes";
|
|
179
|
+
import { getInstance } from "./instance";
|
|
180
|
+
|
|
181
|
+
export namespace ${namespaceValue} {
|
|
182
|
+
export const key = "${featureKey}";
|
|
183
|
+
|
|
184
|
+
export function getVariation(attributes: Attributes = {}) {
|
|
185
|
+
return getInstance().getVariation${getPascalCase(variationType)}(key, attributes);
|
|
186
|
+
}${variableMethods}
|
|
187
|
+
}
|
|
188
|
+
`.trimStart();
|
|
189
|
+
|
|
190
|
+
const featureNamespaceFilePath = path.join(outputPath, `${namespaceValue}.ts`);
|
|
191
|
+
fs.writeFileSync(featureNamespaceFilePath, featureContent);
|
|
192
|
+
console.log(`Feature ${featureKey} file written at: ${featureNamespaceFilePath}`);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// index
|
|
196
|
+
const indexContent =
|
|
197
|
+
[`export * from "./Attributes";`, `export * from "./instance";`]
|
|
198
|
+
.concat(
|
|
199
|
+
featureNamespaces.map((featureNamespace) => {
|
|
200
|
+
return `export * from "./${featureNamespace}";`;
|
|
201
|
+
}),
|
|
202
|
+
)
|
|
203
|
+
.join("\n") + "\n";
|
|
204
|
+
const indexFilePath = path.join(outputPath, "index.ts");
|
|
205
|
+
fs.writeFileSync(indexFilePath, indexContent);
|
|
206
|
+
console.log(`Index file written at: ${indexFilePath}`);
|
|
207
|
+
}
|
package/src/index.ts
CHANGED