@featurevisor/core 2.7.0 → 2.9.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 (78) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/coverage/clover.xml +110 -443
  3. package/coverage/coverage-final.json +3 -9
  4. package/coverage/lcov-report/{src/builder → builder}/allocator.ts.html +10 -10
  5. package/coverage/lcov-report/{src/builder → builder}/buildScopedConditions.ts.html +10 -10
  6. package/coverage/lcov-report/{src/builder → builder}/buildScopedDatafile.ts.html +10 -10
  7. package/coverage/lcov-report/{src/builder → builder}/buildScopedSegments.ts.html +10 -10
  8. package/coverage/lcov-report/{src/builder → builder}/index.html +10 -10
  9. package/coverage/lcov-report/{src/builder → builder}/revision.ts.html +10 -10
  10. package/coverage/lcov-report/{src/builder → builder}/traffic.ts.html +10 -10
  11. package/coverage/lcov-report/index.html +27 -57
  12. package/coverage/lcov-report/{src/list → list}/index.html +10 -10
  13. package/coverage/lcov-report/{src/list → list}/matrix.ts.html +10 -10
  14. package/coverage/lcov-report/{lib/tester → parsers}/index.html +41 -26
  15. package/coverage/lcov-report/parsers/json.ts.html +118 -0
  16. package/coverage/lcov-report/parsers/yml.ts.html +589 -0
  17. package/coverage/lcov-report/{src/tester → tester}/helpers.ts.html +10 -10
  18. package/coverage/lcov-report/{src/tester → tester}/index.html +10 -10
  19. package/coverage/lcov.info +198 -858
  20. package/jest.config.js +1 -0
  21. package/lib/config/index.d.ts +0 -1
  22. package/lib/config/index.js +0 -1
  23. package/lib/config/index.js.map +1 -1
  24. package/lib/config/projectConfig.d.ts +1 -1
  25. package/lib/config/projectConfig.js +1 -1
  26. package/lib/config/projectConfig.js.map +1 -1
  27. package/lib/datasource/datasource.js.map +1 -1
  28. package/lib/datasource/filesystemAdapter.js +1 -1
  29. package/lib/datasource/filesystemAdapter.js.map +1 -1
  30. package/lib/index.d.ts +1 -0
  31. package/lib/index.js +1 -0
  32. package/lib/index.js.map +1 -1
  33. package/lib/linter/conditionSchema.js +45 -6
  34. package/lib/linter/conditionSchema.js.map +1 -1
  35. package/lib/linter/featureSchema.d.ts +88 -88
  36. package/lib/{config/parsers.d.ts → parsers/index.d.ts} +5 -5
  37. package/lib/parsers/index.js +15 -0
  38. package/lib/parsers/index.js.map +1 -0
  39. package/lib/parsers/json.d.ts +2 -0
  40. package/lib/parsers/json.js +13 -0
  41. package/lib/parsers/json.js.map +1 -0
  42. package/lib/parsers/json.spec.d.ts +1 -0
  43. package/lib/parsers/json.spec.js +35 -0
  44. package/lib/parsers/json.spec.js.map +1 -0
  45. package/lib/parsers/yml.d.ts +2 -0
  46. package/lib/parsers/yml.js +154 -0
  47. package/lib/parsers/yml.js.map +1 -0
  48. package/lib/parsers/yml.spec.d.ts +1 -0
  49. package/lib/parsers/yml.spec.js +143 -0
  50. package/lib/parsers/yml.spec.js.map +1 -0
  51. package/lib/utils/git.js.map +1 -1
  52. package/package.json +4 -8
  53. package/src/config/index.ts +0 -1
  54. package/src/config/projectConfig.ts +1 -1
  55. package/src/datasource/datasource.ts +2 -1
  56. package/src/datasource/filesystemAdapter.ts +3 -2
  57. package/src/index.ts +1 -0
  58. package/src/linter/conditionSchema.ts +43 -6
  59. package/src/parsers/index.ts +22 -0
  60. package/src/parsers/json.spec.ts +36 -0
  61. package/src/parsers/json.ts +11 -0
  62. package/src/parsers/yml.spec.ts +174 -0
  63. package/src/parsers/yml.ts +168 -0
  64. package/src/utils/git.ts +2 -1
  65. package/tsconfig.cjs.json +2 -1
  66. package/coverage/lcov-report/lib/builder/allocator.js.html +0 -196
  67. package/coverage/lcov-report/lib/builder/buildScopedConditions.js.html +0 -373
  68. package/coverage/lcov-report/lib/builder/buildScopedDatafile.js.html +0 -403
  69. package/coverage/lcov-report/lib/builder/buildScopedSegments.js.html +0 -379
  70. package/coverage/lcov-report/lib/builder/index.html +0 -191
  71. package/coverage/lcov-report/lib/builder/revision.js.html +0 -148
  72. package/coverage/lcov-report/lib/builder/traffic.js.html +0 -493
  73. package/coverage/lcov-report/lib/list/index.html +0 -116
  74. package/coverage/lcov-report/lib/list/matrix.js.html +0 -532
  75. package/coverage/lcov-report/lib/tester/helpers.js.html +0 -295
  76. package/lib/config/parsers.js +0 -32
  77. package/lib/config/parsers.js.map +0 -1
  78. package/src/config/parsers.ts +0 -40
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const json_1 = require("./json");
4
+ describe("core :: parser :: jsonParser", () => {
5
+ it("should parse JSON string into object", () => {
6
+ const jsonString = '{"foo":1,"bar":"baz","arr":[1,2]}';
7
+ const result = json_1.jsonParser.parse(jsonString);
8
+ expect(result).toEqual({ foo: 1, bar: "baz", arr: [1, 2] });
9
+ });
10
+ it("should stringify object into JSON string (pretty-printed)", () => {
11
+ const obj = { foo: 1, bar: "baz", arr: [1, 2] };
12
+ const jsonString = json_1.jsonParser.stringify(obj);
13
+ const expectedString = `{
14
+ "foo": 1,
15
+ "bar": "baz",
16
+ "arr": [
17
+ 1,
18
+ 2
19
+ ]
20
+ }`;
21
+ expect(jsonString).toBe(expectedString);
22
+ });
23
+ it("should parse and then stringify to preserve content", () => {
24
+ const original = { alpha: "a", num: 42, bool: true, nullish: null, nested: { z: "x" } };
25
+ const str = json_1.jsonParser.stringify(original);
26
+ const reparsed = json_1.jsonParser.parse(str);
27
+ expect(reparsed).toEqual(original);
28
+ });
29
+ it("should throw if invalid JSON string is provided to parse", () => {
30
+ expect(() => {
31
+ json_1.jsonParser.parse("this is not json");
32
+ }).toThrow();
33
+ });
34
+ });
35
+ //# sourceMappingURL=json.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.spec.js","sourceRoot":"","sources":["../../src/parsers/json.spec.ts"],"names":[],"mappings":";;AAAA,iCAAoC;AAEpC,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;IAC5C,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,UAAU,GAAG,mCAAmC,CAAC;QACvD,MAAM,MAAM,GAAG,iBAAU,CAAC,KAAK,CAA8C,UAAU,CAAC,CAAC;QACzF,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,GAAG,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QAChD,MAAM,UAAU,GAAG,iBAAU,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAC7C,MAAM,cAAc,GAAG;;;;;;;EAOzB,CAAC;QACC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,QAAQ,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC;QACxF,MAAM,GAAG,GAAG,iBAAU,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC3C,MAAM,QAAQ,GAAG,iBAAU,CAAC,KAAK,CAAkB,GAAG,CAAC,CAAC;QACxD,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,CAAC,GAAG,EAAE;YACV,iBAAU,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;IACf,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { CustomParser } from "./index";
2
+ export declare const ymlParser: CustomParser;
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ymlParser = void 0;
4
+ const fs = require("fs");
5
+ const yaml_1 = require("yaml");
6
+ const types_1 = require("yaml/types");
7
+ function getKeyString(keyNode) {
8
+ if (keyNode == null)
9
+ return undefined;
10
+ if (typeof keyNode.value !== "undefined") {
11
+ return String(keyNode.value);
12
+ }
13
+ return typeof keyNode === "string" ? keyNode : undefined;
14
+ }
15
+ function copyComments(source, target) {
16
+ if (source.comment != null)
17
+ target.comment = source.comment;
18
+ if (source.commentBefore != null)
19
+ target.commentBefore = source.commentBefore;
20
+ const srcVal = source.value;
21
+ const tgtVal = target.value;
22
+ if (srcVal && tgtVal && typeof tgtVal === "object" && tgtVal !== null) {
23
+ const t = tgtVal;
24
+ if (srcVal.comment != null)
25
+ t.comment = srcVal.comment;
26
+ if (srcVal.commentBefore != null)
27
+ t.commentBefore = srcVal.commentBefore;
28
+ }
29
+ }
30
+ function isYamlMap(node) {
31
+ return node != null && typeof node === "object" && Array.isArray(node.items);
32
+ }
33
+ function isYamlSeq(node) {
34
+ return node != null && typeof node === "object" && Array.isArray(node.items);
35
+ }
36
+ function seqItemValueKey(item) {
37
+ if (item == null)
38
+ return String(item);
39
+ const n = item;
40
+ if (typeof n.value !== "undefined")
41
+ return JSON.stringify(n.value);
42
+ if (typeof n.toJSON === "function")
43
+ return JSON.stringify(n.toJSON());
44
+ return JSON.stringify(item);
45
+ }
46
+ function primitiveValueKey(v) {
47
+ return JSON.stringify(v);
48
+ }
49
+ function createValueWithComments(schema, oldNode, newValue) {
50
+ if (newValue === null || typeof newValue !== "object") {
51
+ const node = new types_1.Scalar(newValue);
52
+ const old = oldNode;
53
+ if (old) {
54
+ if (old.comment != null)
55
+ node.comment = old.comment;
56
+ if (old.commentBefore != null)
57
+ node.commentBefore = old.commentBefore;
58
+ }
59
+ return node;
60
+ }
61
+ if (Array.isArray(newValue)) {
62
+ const oldSeq = isYamlSeq(oldNode) ? oldNode : null;
63
+ const oldItemsByValue = new Map();
64
+ if (oldSeq && oldSeq.items) {
65
+ for (const item of oldSeq.items) {
66
+ oldItemsByValue.set(seqItemValueKey(item), item);
67
+ }
68
+ }
69
+ const newSeq = schema.createNode([]);
70
+ for (const el of newValue) {
71
+ const oldItem = oldItemsByValue.get(primitiveValueKey(el));
72
+ const itemNode = createValueWithComments(schema, oldItem, el);
73
+ newSeq.add(itemNode);
74
+ }
75
+ return newSeq;
76
+ }
77
+ // newValue is a plain object; preserve comments from old map if present
78
+ const oldMap = isYamlMap(oldNode) ? oldNode : null;
79
+ const oldPairsByKey = new Map();
80
+ if (oldMap) {
81
+ for (const pair of (oldMap.items || [])) {
82
+ const keyStr = getKeyString(pair.key);
83
+ if (keyStr !== undefined)
84
+ oldPairsByKey.set(keyStr, pair);
85
+ }
86
+ }
87
+ const newMap = schema.createNode({});
88
+ const obj = newValue;
89
+ for (const k of Object.keys(obj)) {
90
+ const oldPair = oldPairsByKey.get(k);
91
+ const childOldNode = oldPair ? oldPair.value : undefined;
92
+ const childNewValue = createValueWithComments(schema, childOldNode, obj[k]);
93
+ const newPair = schema.createPair(k, childNewValue);
94
+ if (oldPair)
95
+ copyComments(oldPair, newPair);
96
+ newMap.add(newPair);
97
+ }
98
+ const result = newMap;
99
+ const oldVal = oldNode;
100
+ if (oldVal && result) {
101
+ if (oldVal.comment != null)
102
+ result.comment = oldVal.comment;
103
+ if (oldVal.commentBefore != null)
104
+ result.commentBefore = oldVal.commentBefore;
105
+ }
106
+ return result;
107
+ }
108
+ function replaceContentsPreservingComments(doc, newContent) {
109
+ const oldRoot = doc.contents;
110
+ if (!oldRoot || !Array.isArray(oldRoot.items)) {
111
+ doc.contents = doc.schema.createNode(newContent);
112
+ return;
113
+ }
114
+ const schema = doc.schema;
115
+ const oldPairsByKey = new Map();
116
+ for (const pair of oldRoot.items) {
117
+ const keyStr = getKeyString(pair.key);
118
+ if (keyStr !== undefined)
119
+ oldPairsByKey.set(keyStr, pair);
120
+ }
121
+ const newMap = schema.createNode({});
122
+ for (const key of Object.keys(newContent)) {
123
+ const oldPair = oldPairsByKey.get(key);
124
+ const valueNode = createValueWithComments(schema, oldPair?.value, newContent[key]);
125
+ const newPair = schema.createPair(key, valueNode);
126
+ if (oldPair)
127
+ copyComments(oldPair, newPair);
128
+ newMap.add(newPair);
129
+ }
130
+ doc.contents = newMap;
131
+ }
132
+ exports.ymlParser = {
133
+ extension: "yml",
134
+ parse: function (content) {
135
+ return (0, yaml_1.parse)(content);
136
+ },
137
+ stringify: function (content, filePath) {
138
+ if (!filePath || !fs.existsSync(filePath)) {
139
+ return (0, yaml_1.stringify)(content);
140
+ }
141
+ const fileContent = fs.readFileSync(filePath, "utf8");
142
+ if (!fileContent.trim()) {
143
+ return (0, yaml_1.stringify)(content);
144
+ }
145
+ // newObject is the final saved object; existing file is only for ordering/comments
146
+ if (content === null || typeof content !== "object" || Array.isArray(content)) {
147
+ throw new Error("Cannot set root document to a primitive value");
148
+ }
149
+ const doc = (0, yaml_1.parseDocument)(fileContent);
150
+ replaceContentsPreservingComments(doc, content);
151
+ return doc.toString();
152
+ },
153
+ };
154
+ //# sourceMappingURL=yml.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yml.js","sourceRoot":"","sources":["../../src/parsers/yml.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,143 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const yml_1 = require("./yml");
4
+ describe("core :: parser :: ymlParser", () => {
5
+ it("should parse YAML string into object", () => {
6
+ const yamlString = `
7
+ foo: 1
8
+ bar: baz
9
+ arr:
10
+ - 1
11
+ - 2
12
+ `;
13
+ const result = yml_1.ymlParser.parse(yamlString);
14
+ expect(result).toEqual({ foo: 1, bar: "baz", arr: [1, 2] });
15
+ });
16
+ it("should stringify object into YAML string", () => {
17
+ const obj = { foo: 1, bar: "baz", arr: [1, 2] };
18
+ const yamlString = yml_1.ymlParser.stringify(obj);
19
+ expect(yamlString.trim()).toBe(`foo: 1
20
+ bar: baz
21
+ arr:
22
+ - 1
23
+ - 2`);
24
+ });
25
+ it("should parse and then stringify to preserve YAML content semantically", () => {
26
+ const original = {
27
+ alpha: "a",
28
+ num: 42,
29
+ bool: true,
30
+ nullish: null,
31
+ nested: { z: "x", y: [1, 2] },
32
+ };
33
+ const str = yml_1.ymlParser.stringify(original);
34
+ const reparsed = yml_1.ymlParser.parse(str);
35
+ expect(reparsed).toEqual(original);
36
+ });
37
+ it("should throw if invalid YAML string is provided to parse", () => {
38
+ expect(() => {
39
+ yml_1.ymlParser.parse("foo: : bar");
40
+ }).toThrow();
41
+ });
42
+ describe("stringify() with filePath argument (existing file for ordering/comments only)", () => {
43
+ const fs = require("fs");
44
+ const path = require("path");
45
+ const os = require("os");
46
+ let tempFile;
47
+ beforeEach(() => {
48
+ tempFile = path.join(os.tmpdir(), `test_${Math.random()}.yml`);
49
+ });
50
+ afterEach(() => {
51
+ if (fs.existsSync(tempFile)) {
52
+ fs.unlinkSync(tempFile);
53
+ }
54
+ });
55
+ it("should save exactly the new object; existing file is only for ordering/comments", () => {
56
+ const beforeYaml = `
57
+ foo: 1 # foo comment here
58
+ extra: blah
59
+
60
+ ##
61
+ # Comment above nested
62
+ #
63
+ nested:
64
+ a: x
65
+ b: y # b comment
66
+ array:
67
+ - one # one
68
+ - two # two
69
+ - three # three
70
+ `.trim() + "\n";
71
+ const newContent = {
72
+ foo: 42,
73
+ bar: "new",
74
+ nested: { b: "updated", c: "added" },
75
+ array: ["two", "three", "four"],
76
+ };
77
+ const afterYaml = `
78
+ foo: 42 # foo comment here
79
+ bar: new
80
+ ##
81
+ # Comment above nested
82
+ #
83
+ nested:
84
+ b: updated # b comment
85
+ c: added
86
+ array:
87
+ - two # two
88
+ - three # three
89
+ - four
90
+ `.trim() + "\n";
91
+ fs.writeFileSync(tempFile, beforeYaml);
92
+ const output = yml_1.ymlParser.stringify(newContent, tempFile);
93
+ expect(output).toBe(afterYaml);
94
+ });
95
+ it("should replace the root if YAML file is empty", () => {
96
+ const beforeYaml = "";
97
+ const afterYaml = `
98
+ hello: world
99
+ test:
100
+ - 1
101
+ - 2
102
+ - 3
103
+ `.trim() + "\n";
104
+ fs.writeFileSync(tempFile, beforeYaml);
105
+ const obj = { hello: "world", test: [1, 2, 3] };
106
+ const output = yml_1.ymlParser.stringify(obj, tempFile);
107
+ expect(output).toBe(afterYaml);
108
+ });
109
+ it("should throw if trying to set YAML document root to a primitive", () => {
110
+ const beforeYaml = `
111
+ foo: bar
112
+ `.trim() + "\n";
113
+ fs.writeFileSync(tempFile, beforeYaml);
114
+ // Root must be an object when using filePath; primitives throw
115
+ expect(() => {
116
+ yml_1.ymlParser.stringify("primitive", tempFile);
117
+ }).toThrow(/Cannot set root document to a primitive value/);
118
+ });
119
+ it("should fall back to simple stringify if filePath does not exist", () => {
120
+ const fakeFilePath = path.join(os.tmpdir(), `notfound_${Math.random()}.yml`);
121
+ const afterYaml = `
122
+ only: in-memory
123
+ `.trim() + "\n";
124
+ const obj = { only: "in-memory" };
125
+ const output = yml_1.ymlParser.stringify(obj, fakeFilePath);
126
+ expect(output).toBe(afterYaml);
127
+ expect(fs.existsSync(fakeFilePath)).toBe(false); // should not create the file
128
+ });
129
+ it("should not mutate the original YAML file", () => {
130
+ const beforeYaml = `
131
+ foo: unchanged
132
+ bar: before
133
+ `.trim() + "\n";
134
+ fs.writeFileSync(tempFile, beforeYaml);
135
+ const onDiskBefore = fs.readFileSync(tempFile, "utf8");
136
+ const obj = { bar: "after" };
137
+ yml_1.ymlParser.stringify(obj, tempFile);
138
+ const onDiskAfter = fs.readFileSync(tempFile, "utf8");
139
+ expect(onDiskAfter).toBe(onDiskBefore); // file on disk unchanged
140
+ });
141
+ });
142
+ });
143
+ //# sourceMappingURL=yml.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yml.spec.js","sourceRoot":"","sources":["../../src/parsers/yml.spec.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":";;AA8DA,8BAmEC;AAjID,6BAA6B;AAO7B,SAAS,wBAAwB,CAAC,aAAqB;IACrD,MAAM,MAAM,GAAG;QACb,IAAI,EAAE,EAAE;QACR,MAAM,EAAE,EAAE;QACV,IAAI,EAAE,EAAE;QACR,OAAO,EAAE,EAAE;QACX,KAAK,EAAE,EAAE;KACV,CAAC;IAEF,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACxC,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,IAAI,cAAc,GAAG,KAAK,CAAC;IAE3B,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QACrB,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC/B,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACnD,CAAC;aAAM,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACtC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YACnD,cAAc,GAAG,KAAK,CAAC;QACzB,CAAC;aAAM,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACpC,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YAC/C,cAAc,GAAG,IAAI,CAAC,CAAC,+BAA+B;QACxD,CAAC;aAAM,IAAI,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YACzC,IAAI,WAAW,EAAE,CAAC;gBAChB,4CAA4C;gBAC5C,YAAY,GAAG,KAAK,CAAC;YACvB,CAAC;YACD,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YAC9C,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,8BAA8B;YACvE,YAAY,GAAG,IAAI,CAAC;YACpB,cAAc,GAAG,KAAK,CAAC,CAAC,8BAA8B;QACxD,CAAC;aAAM,IAAI,YAAY,EAAE,CAAC;YACxB,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,IAAI,GAAG,IAAI,CAAC;QAC3C,CAAC;aAAM,IAAI,cAAc,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAChD,MAAM,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC,yBAAyB;QACjE,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAI;IAC7B,IAAI,MAAM,GAAG,SAAS,CAAC,CAAC,uBAAuB;IAE/C,sCAAsC;IACtC,IAAI,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;QACnC,MAAM,GAAG,SAAS,CAAC;IACrB,CAAC;SAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;QAC9C,MAAM,GAAG,SAAS,CAAC;IACrB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAgB,SAAS,CACvB,aAAqB,EACrB,OAAoE;IAEpE,MAAM,MAAM,GAAG,wBAAwB,CAAC,aAAa,CAAC,CAAC;IACvD,MAAM,EAAE,iBAAiB,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC;IAErD,MAAM,MAAM,GAAW;QACrB,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,SAAS,EAAE,MAAM,CAAC,IAAI;QACtB,QAAQ,EAAE,EAAE;KACb,CAAC;IAEF,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QACzC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;QAEvC,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;QACxD,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QAE/C,kBAAkB;QAClB,IAAI,IAAI,GAAe,WAAW,CAAC;QACnC,IAAI,WAAW,KAAK,aAAa,CAAC,uBAAuB,EAAE,CAAC;YAC1D,IAAI,GAAG,WAAW,CAAC;QACrB,CAAC;aAAM,IAAI,WAAW,KAAK,aAAa,CAAC,qBAAqB,EAAE,CAAC;YAC/D,IAAI,GAAG,SAAS,CAAC;QACnB,CAAC;aAAM,IAAI,WAAW,KAAK,aAAa,CAAC,qBAAqB,EAAE,CAAC;YAC/D,IAAI,GAAG,SAAS,CAAC;QACnB,CAAC;aAAM,IAAI,WAAW,KAAK,aAAa,CAAC,mBAAmB,EAAE,CAAC;YAC7D,IAAI,GAAG,OAAO,CAAC;QACjB,CAAC;aAAM,IAAI,WAAW,KAAK,aAAa,CAAC,kBAAkB,EAAE,CAAC;YAC5D,IAAI,GAAG,MAAM,CAAC;QAChB,CAAC;aAAM,CAAC;YACN,eAAe;YACf,OAAO;QACT,CAAC;QAED,iBAAiB;QACjB,MAAM,QAAQ,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAY,CAAC;QAC9D,MAAM,gBAAgB,GAAG,GAAG,GAAI,aAAa,CAAC,MAAuB,CAAC,SAAS,CAAC;QAEhF,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACzC,oBAAoB;YACpB,OAAO;QACT,CAAC;QAED,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;QAEnD,MAAM,UAAU,GAAe;YAC7B,IAAI;YACJ,GAAG;YACH,OAAO,EAAE,IAAI;SACd,CAAC;QAEF,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,UAAU,CAAC,OAAO,GAAG,IAAI,CAAC;QAC5B,CAAC;aAAM,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YAChC,UAAU,CAAC,OAAO,GAAG,IAAI,CAAC;QAC5B,CAAC;aAAM,CAAC;YACN,UAAU,CAAC,OAAO,GAAG,IAAI,CAAC;QAC5B,CAAC;QAED,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@featurevisor/core",
3
- "version": "2.7.0",
3
+ "version": "2.9.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",
@@ -44,14 +44,10 @@
44
44
  "@featurevisor/site": "2.7.0",
45
45
  "@featurevisor/types": "2.7.0",
46
46
  "axios": "^1.3.4",
47
- "js-yaml": "^4.1.0",
48
- "tar": "^6.1.13",
47
+ "tar": "^7.5.7",
48
+ "yaml": "^1.10.2",
49
49
  "yargs": "^17.7.2",
50
50
  "zod": "^3.22.4"
51
51
  },
52
- "devDependencies": {
53
- "@types/js-yaml": "^4.0.5",
54
- "@types/tar": "^6.1.4"
55
- },
56
- "gitHead": "aebf65e5be80d1f8a67453e45b4609af2490103e"
52
+ "gitHead": "2cb1e557e83348b80b15fc5c5362b8445349d045"
57
53
  }
@@ -1,2 +1 @@
1
1
  export * from "./projectConfig";
2
- export * from "./parsers";
@@ -2,7 +2,7 @@ import * as path from "path";
2
2
 
3
3
  import type { BucketBy, Context, Tag } from "@featurevisor/types";
4
4
 
5
- import { Parser, parsers } from "./parsers";
5
+ import { Parser, parsers } from "../parsers";
6
6
  import { FilesystemAdapter } from "../datasource/filesystemAdapter";
7
7
  import type { Plugin } from "../cli";
8
8
  import type { BuildTags } from "../builder/buildDatafile";
@@ -13,7 +13,8 @@ import type {
13
13
  EntityType,
14
14
  } from "@featurevisor/types";
15
15
 
16
- import { ProjectConfig, CustomParser } from "../config";
16
+ import { ProjectConfig } from "../config";
17
+ import { CustomParser } from "../parsers";
17
18
 
18
19
  import { Adapter, DatafileOptions } from "./adapter";
19
20
 
@@ -14,7 +14,8 @@ import type {
14
14
  } from "@featurevisor/types";
15
15
 
16
16
  import { Adapter, DatafileOptions } from "./adapter";
17
- import { ProjectConfig, CustomParser } from "../config";
17
+ import { ProjectConfig } from "../config";
18
+ import { CustomParser } from "../parsers";
18
19
  import { getCommit } from "../utils/git";
19
20
 
20
21
  export function getExistingStateFilePath(
@@ -128,7 +129,7 @@ export class FilesystemAdapter extends Adapter {
128
129
  fs.mkdirSync(this.getEntityDirectoryPath(entityType), { recursive: true });
129
130
  }
130
131
 
131
- fs.writeFileSync(filePath, this.parser.stringify(entity));
132
+ fs.writeFileSync(filePath, this.parser.stringify(entity, filePath));
132
133
 
133
134
  return entity;
134
135
  }
package/src/index.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from "./config";
2
+ export * from "./parsers";
2
3
  export * from "./linter";
3
4
  export * from "./builder";
4
5
  export * from "./tester";
@@ -25,6 +25,12 @@ const arrayOperators = ["in", "notIn"];
25
25
  const regexOperators = ["matches", "notMatches"];
26
26
  const operatorsWithoutValue = ["exists", "notExists"];
27
27
 
28
+ const isoDateRegex = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|([+\-]\d{2}:\d{2})))?$/;
29
+
30
+ function isIsoDateString(value: string): boolean {
31
+ return isoDateRegex.test(value);
32
+ }
33
+
28
34
  export function getConditionsZodSchema(
29
35
  projectConfig: ProjectConfig,
30
36
  availableAttributeKeys: [string, ...string[]],
@@ -114,12 +120,43 @@ export function getConditionsZodSchema(
114
120
  }
115
121
 
116
122
  // date
117
- if (dateOperators.includes(data.operator) && !(data.value instanceof Date)) {
118
- context.addIssue({
119
- code: z.ZodIssueCode.custom,
120
- message: `when operator is "${data.operator}", value must be a date`,
121
- path: ["value"],
122
- });
123
+ if (dateOperators.includes(data.operator)) {
124
+ // Value is required and must not be undefined or null
125
+ if (typeof data.value === "undefined" || data.value === null || data.value === "") {
126
+ context.addIssue({
127
+ code: z.ZodIssueCode.custom,
128
+ message: `when operator is "${data.operator}", value must be provided`,
129
+ path: ["value"],
130
+ });
131
+ } else if (typeof data.value === "string") {
132
+ // If it's a string, must be valid ISO 8601
133
+ if (!isIsoDateString(data.value)) {
134
+ context.addIssue({
135
+ code: z.ZodIssueCode.custom,
136
+ message: `when operator is "${data.operator}", value must be a stringified date in ISO 8601 format`,
137
+ path: ["value"],
138
+ });
139
+ } else {
140
+ // valid ISO 8601 string -- no issue
141
+ }
142
+ } else if (data.value instanceof Date) {
143
+ // If it's a Date, must be valid
144
+ if (isNaN(data.value.getTime())) {
145
+ context.addIssue({
146
+ code: z.ZodIssueCode.custom,
147
+ message: `when operator is "${data.operator}", value is a Date but invalid`,
148
+ path: ["value"],
149
+ });
150
+ }
151
+ // Valid JS Date -- no issue
152
+ } else {
153
+ // NOT a string, NOT a Date
154
+ context.addIssue({
155
+ code: z.ZodIssueCode.custom,
156
+ message: `when operator is "${data.operator}", value must be a stringified date in ISO 8601 format or a valid Date object`,
157
+ path: ["value"],
158
+ });
159
+ }
123
160
  }
124
161
 
125
162
  // array
@@ -0,0 +1,22 @@
1
+ import { jsonParser } from "./json";
2
+ import { ymlParser } from "./yml";
3
+
4
+ export interface CustomParser {
5
+ extension: string;
6
+ parse: <T>(content: string, filePath?: string) => T;
7
+ stringify: (content: any, filePath?: string) => string;
8
+ }
9
+
10
+ /**
11
+ * If we want to add more built-in parsers,
12
+ * add them to this object with new file extension as the key,
13
+ * and a function that takes file content as string and returns parsed object as the value.
14
+ */
15
+ export const parsers: { [key: string]: CustomParser } = {
16
+ yml: ymlParser,
17
+ json: jsonParser,
18
+ };
19
+
20
+ export type BuiltInParser = keyof typeof parsers; // keys of parsers object
21
+
22
+ export type Parser = BuiltInParser | CustomParser;
@@ -0,0 +1,36 @@
1
+ import { jsonParser } from "./json";
2
+
3
+ describe("core :: parser :: jsonParser", () => {
4
+ it("should parse JSON string into object", () => {
5
+ const jsonString = '{"foo":1,"bar":"baz","arr":[1,2]}';
6
+ const result = jsonParser.parse<{ foo: number; bar: string; arr: number[] }>(jsonString);
7
+ expect(result).toEqual({ foo: 1, bar: "baz", arr: [1, 2] });
8
+ });
9
+
10
+ it("should stringify object into JSON string (pretty-printed)", () => {
11
+ const obj = { foo: 1, bar: "baz", arr: [1, 2] };
12
+ const jsonString = jsonParser.stringify(obj);
13
+ const expectedString = `{
14
+ "foo": 1,
15
+ "bar": "baz",
16
+ "arr": [
17
+ 1,
18
+ 2
19
+ ]
20
+ }`;
21
+ expect(jsonString).toBe(expectedString);
22
+ });
23
+
24
+ it("should parse and then stringify to preserve content", () => {
25
+ const original = { alpha: "a", num: 42, bool: true, nullish: null, nested: { z: "x" } };
26
+ const str = jsonParser.stringify(original);
27
+ const reparsed = jsonParser.parse<typeof original>(str);
28
+ expect(reparsed).toEqual(original);
29
+ });
30
+
31
+ it("should throw if invalid JSON string is provided to parse", () => {
32
+ expect(() => {
33
+ jsonParser.parse("this is not json");
34
+ }).toThrow();
35
+ });
36
+ });
@@ -0,0 +1,11 @@
1
+ import type { CustomParser } from "./index";
2
+
3
+ export const jsonParser: CustomParser = {
4
+ extension: "json",
5
+ parse: function <T>(content: string): T {
6
+ return JSON.parse(content) as T;
7
+ },
8
+ stringify: function (content: any) {
9
+ return JSON.stringify(content, null, 2);
10
+ },
11
+ };