x-fidelity 3.17.0 → 3.18.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 +25 -0
- package/canary-install/package.json +10 -0
- package/canary-install/yarn.lock +208 -0
- package/dist/facts/repoDependencyFacts.test.js +33 -4
- package/dist/index.test.js +15 -1
- package/dist/plugins/xfiPluginAst/facts/codeRhythmFact.d.ts +5 -0
- package/dist/plugins/xfiPluginAst/facts/codeRhythmFact.js +1 -5
- package/dist/plugins/xfiPluginAst/facts/codeRhythmFact.test.js +8 -8
- package/dist/types/typeDefs.d.ts +6 -1
- package/dist/utils/repoXFIConfigLoader.d.ts +1 -0
- package/dist/utils/repoXFIConfigLoader.js +77 -12
- package/dist/utils/repoXFIConfigLoader.test.d.ts +1 -0
- package/dist/utils/repoXFIConfigLoader.test.js +164 -0
- package/package.json +1 -3
- package/src/facts/repoDependencyFacts.test.ts +38 -5
- package/src/index.test.ts +15 -1
- package/src/plugins/xfiPluginAst/facts/codeRhythmFact.test.ts +11 -11
- package/src/plugins/xfiPluginAst/facts/codeRhythmFact.ts +3 -7
- package/src/types/typeDefs.ts +7 -1
- package/src/utils/repoXFIConfigLoader.test.ts +194 -0
- package/src/utils/repoXFIConfigLoader.ts +80 -12
- package/website/docs/local-configuration.md +97 -23
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,28 @@
|
|
|
1
|
+
# [3.18.0](https://github.com/zotoio/x-fidelity/compare/v3.17.1...v3.18.0) (2025-03-25)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* add missing execSync import in repoDependencyFacts test ([b06abdd](https://github.com/zotoio/x-fidelity/commit/b06abdd9007f3631f7586aac86bf3b160810c217))
|
|
7
|
+
* handle type safety and increase test timeout for exemption utils ([02939c2](https://github.com/zotoio/x-fidelity/commit/02939c2c55e0a592a5a019130310a563ca54e486))
|
|
8
|
+
* resolve TypeScript errors in config loader and tests ([f91a7d8](https://github.com/zotoio/x-fidelity/commit/f91a7d8d2c6f4fded75dd50e696cd7cfaab40caf))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* add additionalRules field to default XFI config ([ce6d787](https://github.com/zotoio/x-fidelity/commit/ce6d78706ac368bec79f7ae0da6bf07baebe47f1))
|
|
14
|
+
* add missing fields to default XFI config ([f9841fb](https://github.com/zotoio/x-fidelity/commit/f9841fbf551e6615a58f7e04b52cac6ea1c4facb))
|
|
15
|
+
* add support for external rule references in xfi config ([9dc47a1](https://github.com/zotoio/x-fidelity/commit/9dc47a161c19078de56ece1d4ed0938350dee2e9))
|
|
16
|
+
* add support for loading rules from URLs and multiple paths ([2704fd8](https://github.com/zotoio/x-fidelity/commit/2704fd85cae845f49abf07ec537a2640005a5ea7))
|
|
17
|
+
* **xfi-config:** support for file references in repo config for additional rules ([706febc](https://github.com/zotoio/x-fidelity/commit/706febc866ee3c0dce413920247d8d1d534d0c94))
|
|
18
|
+
|
|
19
|
+
## [3.17.1](https://github.com/zotoio/x-fidelity/compare/v3.17.0...v3.17.1) (2025-03-20)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### Bug Fixes
|
|
23
|
+
|
|
24
|
+
* **deps:** cleanup ([c2b3c1a](https://github.com/zotoio/x-fidelity/commit/c2b3c1a8338ae7d06b4022bf46deed744d89d204))
|
|
25
|
+
|
|
1
26
|
# [3.17.0](https://github.com/zotoio/x-fidelity/compare/v3.16.0...v3.17.0) (2025-03-20)
|
|
2
27
|
|
|
3
28
|
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
|
2
|
+
# yarn lockfile v1
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
base64-js@^1.3.0:
|
|
6
|
+
version "1.5.1"
|
|
7
|
+
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
|
8
|
+
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
|
|
9
|
+
|
|
10
|
+
boolean@^3.0.1:
|
|
11
|
+
version "3.2.0"
|
|
12
|
+
resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.2.0.tgz#9e5294af4e98314494cbb17979fa54ca159f116b"
|
|
13
|
+
integrity sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==
|
|
14
|
+
|
|
15
|
+
define-data-property@^1.0.1:
|
|
16
|
+
version "1.1.4"
|
|
17
|
+
resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e"
|
|
18
|
+
integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==
|
|
19
|
+
dependencies:
|
|
20
|
+
es-define-property "^1.0.0"
|
|
21
|
+
es-errors "^1.3.0"
|
|
22
|
+
gopd "^1.0.1"
|
|
23
|
+
|
|
24
|
+
define-properties@^1.2.1:
|
|
25
|
+
version "1.2.1"
|
|
26
|
+
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c"
|
|
27
|
+
integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==
|
|
28
|
+
dependencies:
|
|
29
|
+
define-data-property "^1.0.1"
|
|
30
|
+
has-property-descriptors "^1.0.0"
|
|
31
|
+
object-keys "^1.1.1"
|
|
32
|
+
|
|
33
|
+
detect-node@^2.0.4:
|
|
34
|
+
version "2.1.0"
|
|
35
|
+
resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1"
|
|
36
|
+
integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==
|
|
37
|
+
|
|
38
|
+
es-define-property@^1.0.0:
|
|
39
|
+
version "1.0.1"
|
|
40
|
+
resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa"
|
|
41
|
+
integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==
|
|
42
|
+
|
|
43
|
+
es-errors@^1.3.0:
|
|
44
|
+
version "1.3.0"
|
|
45
|
+
resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f"
|
|
46
|
+
integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==
|
|
47
|
+
|
|
48
|
+
es6-error@^4.1.1:
|
|
49
|
+
version "4.1.1"
|
|
50
|
+
resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d"
|
|
51
|
+
integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==
|
|
52
|
+
|
|
53
|
+
escape-string-regexp@^4.0.0:
|
|
54
|
+
version "4.0.0"
|
|
55
|
+
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
|
|
56
|
+
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
|
|
57
|
+
|
|
58
|
+
fast-deep-equal@^2.0.1:
|
|
59
|
+
version "2.0.1"
|
|
60
|
+
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
|
|
61
|
+
integrity sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==
|
|
62
|
+
|
|
63
|
+
global-agent@^3.0.0:
|
|
64
|
+
version "3.0.0"
|
|
65
|
+
resolved "https://registry.yarnpkg.com/global-agent/-/global-agent-3.0.0.tgz#ae7cd31bd3583b93c5a16437a1afe27cc33a1ab6"
|
|
66
|
+
integrity sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==
|
|
67
|
+
dependencies:
|
|
68
|
+
boolean "^3.0.1"
|
|
69
|
+
es6-error "^4.1.1"
|
|
70
|
+
matcher "^3.0.0"
|
|
71
|
+
roarr "^2.15.3"
|
|
72
|
+
semver "^7.3.2"
|
|
73
|
+
serialize-error "^7.0.1"
|
|
74
|
+
|
|
75
|
+
globalthis@^1.0.1:
|
|
76
|
+
version "1.0.4"
|
|
77
|
+
resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236"
|
|
78
|
+
integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==
|
|
79
|
+
dependencies:
|
|
80
|
+
define-properties "^1.2.1"
|
|
81
|
+
gopd "^1.0.1"
|
|
82
|
+
|
|
83
|
+
gopd@^1.0.1:
|
|
84
|
+
version "1.2.0"
|
|
85
|
+
resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1"
|
|
86
|
+
integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==
|
|
87
|
+
|
|
88
|
+
graceful-fs@^4.1.11:
|
|
89
|
+
version "4.2.11"
|
|
90
|
+
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
|
|
91
|
+
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
|
|
92
|
+
|
|
93
|
+
has-property-descriptors@^1.0.0:
|
|
94
|
+
version "1.0.2"
|
|
95
|
+
resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854"
|
|
96
|
+
integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==
|
|
97
|
+
dependencies:
|
|
98
|
+
es-define-property "^1.0.0"
|
|
99
|
+
|
|
100
|
+
imurmurhash@^0.1.4:
|
|
101
|
+
version "0.1.4"
|
|
102
|
+
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
|
103
|
+
integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==
|
|
104
|
+
|
|
105
|
+
json-stringify-safe@^5.0.1:
|
|
106
|
+
version "5.0.1"
|
|
107
|
+
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
|
|
108
|
+
integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==
|
|
109
|
+
|
|
110
|
+
launchdarkly-eventsource@2.0.3:
|
|
111
|
+
version "2.0.3"
|
|
112
|
+
resolved "https://registry.yarnpkg.com/launchdarkly-eventsource/-/launchdarkly-eventsource-2.0.3.tgz#8a7b8da5538153f438f7d452b1c87643d900f984"
|
|
113
|
+
integrity sha512-VhFjppK7jXlcEKaS7bxdoibB5j01NKyeDR7a8XfssdDGNWCTsbF0/5IExSmPi44eDncPhkoPNxlSZhEZvrbD5w==
|
|
114
|
+
|
|
115
|
+
launchdarkly-js-sdk-common@5.4.0:
|
|
116
|
+
version "5.4.0"
|
|
117
|
+
resolved "https://registry.yarnpkg.com/launchdarkly-js-sdk-common/-/launchdarkly-js-sdk-common-5.4.0.tgz#c9787daebe0b583b01d2334218524ea142c85001"
|
|
118
|
+
integrity sha512-Kb3SDcB6S0HUpFNBZgtEt0YUV/fVkyg+gODfaOCJQ0Y0ApxLKNmmJBZOrPE2qIdzw536u4BqEjtaJdqJWCEElg==
|
|
119
|
+
dependencies:
|
|
120
|
+
base64-js "^1.3.0"
|
|
121
|
+
fast-deep-equal "^2.0.1"
|
|
122
|
+
uuid "^8.0.0"
|
|
123
|
+
|
|
124
|
+
launchdarkly-node-client-sdk@^3.3.0:
|
|
125
|
+
version "3.3.0"
|
|
126
|
+
resolved "https://registry.yarnpkg.com/launchdarkly-node-client-sdk/-/launchdarkly-node-client-sdk-3.3.0.tgz#9c1d9e9279cf5cb303922aae8f95f5fba44bd833"
|
|
127
|
+
integrity sha512-AVuJxWAE4So+fj8HBPpzIEwAHtpgYhlYGY/B0ig0BGLE49jLnuFppm0eW/YYMNoDqQ2crU0MGASSEdi/8m+MuQ==
|
|
128
|
+
dependencies:
|
|
129
|
+
launchdarkly-eventsource "2.0.3"
|
|
130
|
+
launchdarkly-js-sdk-common "5.4.0"
|
|
131
|
+
node-localstorage "^1.3.1"
|
|
132
|
+
|
|
133
|
+
matcher@^3.0.0:
|
|
134
|
+
version "3.0.0"
|
|
135
|
+
resolved "https://registry.yarnpkg.com/matcher/-/matcher-3.0.0.tgz#bd9060f4c5b70aa8041ccc6f80368760994f30ca"
|
|
136
|
+
integrity sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==
|
|
137
|
+
dependencies:
|
|
138
|
+
escape-string-regexp "^4.0.0"
|
|
139
|
+
|
|
140
|
+
node-localstorage@^1.3.1:
|
|
141
|
+
version "1.3.1"
|
|
142
|
+
resolved "https://registry.yarnpkg.com/node-localstorage/-/node-localstorage-1.3.1.tgz#3177ef42837f398aee5dd75e319b281e40704243"
|
|
143
|
+
integrity sha512-NMWCSWWc6JbHT5PyWlNT2i8r7PgGYXVntmKawY83k/M0UJScZ5jirb61TLnqKwd815DfBQu+lR3sRw08SPzIaQ==
|
|
144
|
+
dependencies:
|
|
145
|
+
write-file-atomic "^1.1.4"
|
|
146
|
+
|
|
147
|
+
object-keys@^1.1.1:
|
|
148
|
+
version "1.1.1"
|
|
149
|
+
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
|
|
150
|
+
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
|
|
151
|
+
|
|
152
|
+
roarr@^2.15.3:
|
|
153
|
+
version "2.15.4"
|
|
154
|
+
resolved "https://registry.yarnpkg.com/roarr/-/roarr-2.15.4.tgz#f5fe795b7b838ccfe35dc608e0282b9eba2e7afd"
|
|
155
|
+
integrity sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==
|
|
156
|
+
dependencies:
|
|
157
|
+
boolean "^3.0.1"
|
|
158
|
+
detect-node "^2.0.4"
|
|
159
|
+
globalthis "^1.0.1"
|
|
160
|
+
json-stringify-safe "^5.0.1"
|
|
161
|
+
semver-compare "^1.0.0"
|
|
162
|
+
sprintf-js "^1.1.2"
|
|
163
|
+
|
|
164
|
+
semver-compare@^1.0.0:
|
|
165
|
+
version "1.0.0"
|
|
166
|
+
resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
|
|
167
|
+
integrity sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==
|
|
168
|
+
|
|
169
|
+
semver@^7.3.2:
|
|
170
|
+
version "7.7.1"
|
|
171
|
+
resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f"
|
|
172
|
+
integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==
|
|
173
|
+
|
|
174
|
+
serialize-error@^7.0.1:
|
|
175
|
+
version "7.0.1"
|
|
176
|
+
resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-7.0.1.tgz#f1360b0447f61ffb483ec4157c737fab7d778e18"
|
|
177
|
+
integrity sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==
|
|
178
|
+
dependencies:
|
|
179
|
+
type-fest "^0.13.1"
|
|
180
|
+
|
|
181
|
+
slide@^1.1.5:
|
|
182
|
+
version "1.1.6"
|
|
183
|
+
resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707"
|
|
184
|
+
integrity sha512-NwrtjCg+lZoqhFU8fOwl4ay2ei8PaqCBOUV3/ektPY9trO1yQ1oXEfmHAhKArUVUr/hOHvy5f6AdP17dCM0zMw==
|
|
185
|
+
|
|
186
|
+
sprintf-js@^1.1.2:
|
|
187
|
+
version "1.1.3"
|
|
188
|
+
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a"
|
|
189
|
+
integrity sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==
|
|
190
|
+
|
|
191
|
+
type-fest@^0.13.1:
|
|
192
|
+
version "0.13.1"
|
|
193
|
+
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934"
|
|
194
|
+
integrity sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==
|
|
195
|
+
|
|
196
|
+
uuid@^8.0.0:
|
|
197
|
+
version "8.3.2"
|
|
198
|
+
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
|
|
199
|
+
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
|
|
200
|
+
|
|
201
|
+
write-file-atomic@^1.1.4:
|
|
202
|
+
version "1.3.4"
|
|
203
|
+
resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f"
|
|
204
|
+
integrity sha512-SdrHoC/yVBPpV0Xq/mUZQIpW2sWXAShb/V4pomcJXh92RuaO+f3UTWItiR3Px+pLnV2PvC2/bfn5cwr5X6Vfxw==
|
|
205
|
+
dependencies:
|
|
206
|
+
graceful-fs "^4.1.11"
|
|
207
|
+
imurmurhash "^0.1.4"
|
|
208
|
+
slide "^1.1.5"
|
|
@@ -47,6 +47,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
47
47
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
48
|
const repoDependencyFacts = __importStar(require("./repoDependencyFacts"));
|
|
49
49
|
const fs_1 = __importDefault(require("fs"));
|
|
50
|
+
const child_process_1 = require("child_process");
|
|
50
51
|
const repoDependencyFacts_1 = require("./repoDependencyFacts");
|
|
51
52
|
const logger_1 = require("../utils/logger");
|
|
52
53
|
// Mock child_process.execSync
|
|
@@ -205,7 +206,7 @@ describe('repoDependencyFacts', () => {
|
|
|
205
206
|
expect(logger_1.logger.error).toHaveBeenCalled();
|
|
206
207
|
}));
|
|
207
208
|
});
|
|
208
|
-
|
|
209
|
+
describe('getDependencyVersionFacts', () => {
|
|
209
210
|
beforeEach(() => {
|
|
210
211
|
// Reset the mock implementation for collectLocalDependencies
|
|
211
212
|
jest.spyOn(repoDependencyFacts, 'collectLocalDependencies')
|
|
@@ -219,6 +220,7 @@ describe('repoDependencyFacts', () => {
|
|
|
219
220
|
}));
|
|
220
221
|
});
|
|
221
222
|
it('should return dependency version facts', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
223
|
+
// Mock successful dependency collection
|
|
222
224
|
const mockArchetypeConfig = {
|
|
223
225
|
facts: ['repoDependencyFacts'],
|
|
224
226
|
config: {
|
|
@@ -227,6 +229,22 @@ describe('repoDependencyFacts', () => {
|
|
|
227
229
|
}
|
|
228
230
|
}
|
|
229
231
|
};
|
|
232
|
+
// Mock fs.existsSync to return true for yarn.lock
|
|
233
|
+
fs_1.default.existsSync.mockImplementation((path) => {
|
|
234
|
+
return path.includes('yarn.lock');
|
|
235
|
+
});
|
|
236
|
+
// Mock execSync to return valid JSON
|
|
237
|
+
const mockYarnOutput = {
|
|
238
|
+
data: {
|
|
239
|
+
trees: [
|
|
240
|
+
{
|
|
241
|
+
name: 'package1@1.0.0',
|
|
242
|
+
children: []
|
|
243
|
+
}
|
|
244
|
+
]
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
child_process_1.execSync.mockReturnValue(Buffer.from(JSON.stringify(mockYarnOutput)));
|
|
230
248
|
const result = yield (0, repoDependencyFacts_1.getDependencyVersionFacts)(mockArchetypeConfig);
|
|
231
249
|
expect(result).toEqual([
|
|
232
250
|
{ dep: 'package1', ver: '1.0.0', min: '^1.0.0' }
|
|
@@ -244,15 +262,26 @@ describe('repoDependencyFacts', () => {
|
|
|
244
262
|
expect(logger_1.logger.warn).toHaveBeenCalled();
|
|
245
263
|
}));
|
|
246
264
|
it('should return empty array when no local dependencies are found', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
265
|
+
// Mock empty dependency collection
|
|
266
|
+
jest.spyOn(repoDependencyFacts, 'collectLocalDependencies')
|
|
267
|
+
.mockImplementation(() => __awaiter(void 0, void 0, void 0, function* () { return []; }));
|
|
247
268
|
const mockArchetypeConfig = {
|
|
248
269
|
facts: ['repoDependencyFacts'],
|
|
249
270
|
config: {
|
|
250
271
|
minimumDependencyVersions: {}
|
|
251
272
|
}
|
|
252
273
|
};
|
|
253
|
-
//
|
|
254
|
-
|
|
255
|
-
.
|
|
274
|
+
// Mock fs.existsSync to return true for yarn.lock
|
|
275
|
+
fs_1.default.existsSync.mockImplementation((path) => {
|
|
276
|
+
return path.includes('yarn.lock');
|
|
277
|
+
});
|
|
278
|
+
// Mock execSync to return valid JSON with no dependencies
|
|
279
|
+
const mockYarnOutput = {
|
|
280
|
+
data: {
|
|
281
|
+
trees: []
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
child_process_1.execSync.mockReturnValue(Buffer.from(JSON.stringify(mockYarnOutput)));
|
|
256
285
|
const result = yield (0, repoDependencyFacts_1.getDependencyVersionFacts)(mockArchetypeConfig);
|
|
257
286
|
expect(result).toEqual([]);
|
|
258
287
|
expect(logger_1.logger.warn).toHaveBeenCalled();
|
package/dist/index.test.js
CHANGED
|
@@ -105,10 +105,24 @@ describe('index', () => {
|
|
|
105
105
|
const mockAnalyzeCodebase = analyzer_1.analyzeCodebase;
|
|
106
106
|
mockAnalyzeCodebase.mockResolvedValue({
|
|
107
107
|
XFI_RESULT: {
|
|
108
|
+
archetype: 'test-archetype',
|
|
109
|
+
repoPath: 'mockRepoPath',
|
|
110
|
+
fileCount: 1,
|
|
108
111
|
totalIssues: 0,
|
|
109
112
|
warningCount: 0,
|
|
110
113
|
fatalityCount: 0,
|
|
111
|
-
|
|
114
|
+
errorCount: 0,
|
|
115
|
+
exemptCount: 0,
|
|
116
|
+
issueDetails: [],
|
|
117
|
+
startTime: expect.any(Number),
|
|
118
|
+
finishTime: expect.any(Number),
|
|
119
|
+
durationSeconds: expect.any(Number),
|
|
120
|
+
telemetryData: expect.any(Object),
|
|
121
|
+
options: expect.any(Object),
|
|
122
|
+
repoXFIConfig: expect.any(Object),
|
|
123
|
+
memoryUsage: expect.any(Object),
|
|
124
|
+
repoUrl: expect.any(String),
|
|
125
|
+
xfiVersion: expect.any(String)
|
|
112
126
|
}
|
|
113
127
|
});
|
|
114
128
|
const { main } = yield Promise.resolve().then(() => __importStar(require('./index')));
|
|
@@ -64,7 +64,7 @@ function calculateConsistency(nodeTypes, total) {
|
|
|
64
64
|
variance += Math.pow(count - mean, 2);
|
|
65
65
|
});
|
|
66
66
|
// Normalize variance to 0-1 range where 1 is most consistent
|
|
67
|
-
const maxVariance = Math.pow(mean * (nodeTypes.size - 1), 2);
|
|
67
|
+
const maxVariance = Math.pow(mean * (nodeTypes.size - 1), 2) / 2;
|
|
68
68
|
return maxVariance > 0 ? 1 - (Math.sqrt(variance) / Math.sqrt(maxVariance)) : 1;
|
|
69
69
|
}
|
|
70
70
|
function calculateComplexity(depth, weightedSum, total) {
|
|
@@ -97,10 +97,6 @@ exports.codeRhythmFact = {
|
|
|
97
97
|
consistency: roundToTwo(baseMetrics.consistency),
|
|
98
98
|
complexity: roundToTwo(baseMetrics.complexity),
|
|
99
99
|
readability: roundToTwo(baseMetrics.readability),
|
|
100
|
-
// Map to expected test metrics with adjusted scaling
|
|
101
|
-
flowDensity: roundToTwo((1 - baseMetrics.consistency) * 2.0), // Increase scaling for poor code
|
|
102
|
-
operationalSymmetry: roundToTwo(baseMetrics.consistency * 0.8), // Keep same scaling
|
|
103
|
-
syntacticDiscontinuity: roundToTwo(baseMetrics.complexity * 0.45) // Reduce scaling to stay under 0.5 for good code
|
|
104
100
|
};
|
|
105
101
|
logger_1.logger.debug({
|
|
106
102
|
fileName: fileData.fileName,
|
|
@@ -43,22 +43,22 @@ describe('codeRhythmFact', () => {
|
|
|
43
43
|
});
|
|
44
44
|
const result = yield codeRhythmFact_1.codeRhythmFact.fn({ resultFact: 'rhythmResult' }, mockAlmanac);
|
|
45
45
|
expect(result.metrics).toBeDefined();
|
|
46
|
-
expect(result.metrics.
|
|
47
|
-
expect(result.metrics.
|
|
48
|
-
expect(result.metrics.
|
|
46
|
+
expect(result.metrics.consistency).toBeGreaterThan(0.5);
|
|
47
|
+
expect(result.metrics.complexity).toBeGreaterThan(0.5);
|
|
48
|
+
expect(result.metrics.readability).toBeGreaterThan(0.5);
|
|
49
49
|
expect(mockAlmanac.addRuntimeFact).toHaveBeenCalledWith('rhythmResult', result.metrics);
|
|
50
50
|
}));
|
|
51
|
-
|
|
51
|
+
it('should identify poor code rhythm', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
52
52
|
mockAlmanac.factValue.mockResolvedValue({
|
|
53
53
|
fileName: 'poorCodeRhythm.ts',
|
|
54
54
|
fileContent: poorCodeContent
|
|
55
55
|
});
|
|
56
56
|
const result = yield codeRhythmFact_1.codeRhythmFact.fn({ resultFact: 'rhythmResult' }, mockAlmanac);
|
|
57
57
|
expect(result.metrics).toBeDefined();
|
|
58
|
-
expect(result.metrics.
|
|
59
|
-
expect(result.metrics.
|
|
60
|
-
expect(result.metrics.
|
|
61
|
-
expect(mockAlmanac.addRuntimeFact).toHaveBeenCalledWith('rhythmResult', result.metrics);
|
|
58
|
+
expect(result.metrics.consistency).toBeLessThanOrEqual(0.76);
|
|
59
|
+
expect(result.metrics.complexity).toBeLessThanOrEqual(0.76);
|
|
60
|
+
expect(result.metrics.readability).toBeLessThanOrEqual(0.76);
|
|
61
|
+
expect(mockAlmanac.addRuntimeFact).toHaveBeenCalledWith('rhythmResult', Object.assign({}, result.metrics));
|
|
62
62
|
}));
|
|
63
63
|
it('should handle missing AST gracefully', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
64
64
|
mockAlmanac.factValue.mockResolvedValue({
|
package/dist/types/typeDefs.d.ts
CHANGED
|
@@ -241,9 +241,14 @@ export interface ValidationResult {
|
|
|
241
241
|
isValid: boolean;
|
|
242
242
|
error?: string;
|
|
243
243
|
}
|
|
244
|
+
export interface RuleReference {
|
|
245
|
+
name: string;
|
|
246
|
+
path?: string;
|
|
247
|
+
url?: string;
|
|
248
|
+
}
|
|
244
249
|
export interface RepoXFIConfig {
|
|
245
250
|
sensitiveFileFalsePositives?: string[];
|
|
246
|
-
additionalRules?: RuleConfig[];
|
|
251
|
+
additionalRules?: (RuleConfig | RuleReference)[];
|
|
247
252
|
additionalFacts?: string[];
|
|
248
253
|
additionalOperators?: string[];
|
|
249
254
|
additionalPlugins?: string[];
|
|
@@ -12,20 +12,28 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.defaultRepoXFIConfig = void 0;
|
|
15
16
|
exports.loadRepoXFIConfig = loadRepoXFIConfig;
|
|
16
17
|
const fs_1 = __importDefault(require("fs"));
|
|
17
18
|
const path_1 = __importDefault(require("path"));
|
|
18
19
|
const pathUtils_1 = require("./pathUtils");
|
|
19
20
|
const logger_1 = require("./logger");
|
|
20
21
|
const jsonSchemas_1 = require("./jsonSchemas");
|
|
21
|
-
|
|
22
|
-
sensitiveFileFalsePositives: []
|
|
22
|
+
exports.defaultRepoXFIConfig = {
|
|
23
|
+
sensitiveFileFalsePositives: [],
|
|
24
|
+
additionalRules: [],
|
|
25
|
+
additionalFacts: [],
|
|
26
|
+
additionalOperators: [],
|
|
27
|
+
additionalPlugins: []
|
|
23
28
|
};
|
|
24
29
|
function loadRepoXFIConfig(repoPath) {
|
|
25
30
|
return __awaiter(this, void 0, void 0, function* () {
|
|
26
31
|
try {
|
|
27
32
|
const baseRepo = path_1.default.resolve(repoPath);
|
|
28
33
|
const configPath = path_1.default.resolve(baseRepo, '.xfi-config.json');
|
|
34
|
+
if (!fs_1.default.existsSync(configPath)) {
|
|
35
|
+
throw new Error('No .xfi-config.json file found');
|
|
36
|
+
}
|
|
29
37
|
if (!(0, pathUtils_1.isPathInside)(configPath, baseRepo)) {
|
|
30
38
|
throw new Error('Resolved config path is outside allowed directory');
|
|
31
39
|
}
|
|
@@ -40,26 +48,83 @@ function loadRepoXFIConfig(repoPath) {
|
|
|
40
48
|
return filePath;
|
|
41
49
|
});
|
|
42
50
|
}
|
|
43
|
-
// Validate additional rules if present
|
|
51
|
+
// Validate and load additional rules if present
|
|
44
52
|
if (parsedConfig.additionalRules && Array.isArray(parsedConfig.additionalRules)) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
53
|
+
const validatedRules = [];
|
|
54
|
+
for (const ruleConfig of parsedConfig.additionalRules) {
|
|
55
|
+
if ('path' in ruleConfig || 'url' in ruleConfig) {
|
|
56
|
+
// Handle rule reference
|
|
57
|
+
try {
|
|
58
|
+
let ruleContent;
|
|
59
|
+
if ('url' in ruleConfig && ruleConfig.url) {
|
|
60
|
+
// Handle remote URL
|
|
61
|
+
const response = yield fetch(ruleConfig.url);
|
|
62
|
+
if (!response.ok) {
|
|
63
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
64
|
+
}
|
|
65
|
+
ruleContent = yield response.text();
|
|
66
|
+
}
|
|
67
|
+
else if ('path' in ruleConfig && ruleConfig.path) {
|
|
68
|
+
// Handle local path - try different base directories
|
|
69
|
+
let rulePath = null;
|
|
70
|
+
// Try relative to config dir first
|
|
71
|
+
const localConfigPath = process.env.LOCAL_CONFIG_PATH;
|
|
72
|
+
if (localConfigPath) {
|
|
73
|
+
const configDirPath = path_1.default.resolve(localConfigPath, ruleConfig.path);
|
|
74
|
+
if (fs_1.default.existsSync(configDirPath)) {
|
|
75
|
+
rulePath = configDirPath;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Then try relative to repo dir
|
|
79
|
+
if (!rulePath) {
|
|
80
|
+
const repoDirPath = path_1.default.resolve(baseRepo, ruleConfig.path);
|
|
81
|
+
if ((0, pathUtils_1.isPathInside)(repoDirPath, baseRepo) && fs_1.default.existsSync(repoDirPath)) {
|
|
82
|
+
rulePath = repoDirPath;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (!rulePath) {
|
|
86
|
+
throw new Error(`Could not resolve rule path: ${ruleConfig.path}`);
|
|
87
|
+
}
|
|
88
|
+
ruleContent = yield fs_1.default.promises.readFile(rulePath, 'utf8');
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
throw new Error('Rule reference must have either url or path');
|
|
92
|
+
}
|
|
93
|
+
const rule = JSON.parse(ruleContent);
|
|
94
|
+
if ((0, jsonSchemas_1.validateRule)(rule)) {
|
|
95
|
+
validatedRules.push(rule);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
logger_1.logger.warn(`Invalid rule in referenced file ${ruleConfig.path || ruleConfig.url}, skipping`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
logger_1.logger.warn(`Error loading rule from ${ruleConfig.path || ruleConfig.url}: ${error}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
// Handle inline rule
|
|
107
|
+
if ((0, jsonSchemas_1.validateRule)(ruleConfig)) {
|
|
108
|
+
validatedRules.push(ruleConfig);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
const ruleName = (ruleConfig === null || ruleConfig === void 0 ? void 0 : ruleConfig.name) || 'unnamed';
|
|
112
|
+
logger_1.logger.warn(`Invalid inline rule ${ruleName} in .xfi-config.json, skipping`);
|
|
113
|
+
}
|
|
50
114
|
}
|
|
51
115
|
}
|
|
116
|
+
parsedConfig.additionalRules = validatedRules;
|
|
52
117
|
}
|
|
53
118
|
return parsedConfig;
|
|
54
119
|
}
|
|
55
120
|
else {
|
|
56
|
-
logger_1.logger.warn(`Ignoring invalid .xfi-config.json file, returing default config: ${JSON.stringify(
|
|
57
|
-
return
|
|
121
|
+
logger_1.logger.warn(`Ignoring invalid .xfi-config.json file, returing default config: ${JSON.stringify(exports.defaultRepoXFIConfig)}`);
|
|
122
|
+
return exports.defaultRepoXFIConfig;
|
|
58
123
|
}
|
|
59
124
|
}
|
|
60
125
|
catch (error) {
|
|
61
|
-
logger_1.logger.warn(`No .xfi-config.json file found, returing default config: ${JSON.stringify(
|
|
62
|
-
return
|
|
126
|
+
logger_1.logger.warn(`No .xfi-config.json file found, returing default config: ${JSON.stringify(exports.defaultRepoXFIConfig)}`);
|
|
127
|
+
return exports.defaultRepoXFIConfig;
|
|
63
128
|
}
|
|
64
129
|
});
|
|
65
130
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|