@opensip-tools/fitness 1.0.8 → 1.0.10
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/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-test.log +40 -40
- package/.turbo/turbo-typecheck.log +1 -1
- package/dist/recipes/__tests__/check-config.test.js +21 -0
- package/dist/recipes/__tests__/check-config.test.js.map +1 -1
- package/dist/recipes/check-config.d.ts +3 -3
- package/dist/recipes/check-config.d.ts.map +1 -1
- package/dist/recipes/check-config.js +30 -13
- package/dist/recipes/check-config.js.map +1 -1
- package/package.json +3 -3
- package/src/recipes/__tests__/check-config.test.ts +22 -0
- package/src/recipes/check-config.ts +35 -13
package/.turbo/turbo-build.log
CHANGED
package/.turbo/turbo-test.log
CHANGED
|
@@ -1,49 +1,49 @@
|
|
|
1
1
|
|
|
2
|
-
> @opensip-tools/fitness@1.0.
|
|
2
|
+
> @opensip-tools/fitness@1.0.10 test /home/runner/work/opensip-tools/opensip-tools/packages/fitness/engine
|
|
3
3
|
> vitest run --passWithNoTests
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
[1m[7m[36m RUN [39m[27m[22m [36mv2.1.9 [39m[90m/home/runner/work/opensip-tools/opensip-tools/packages/fitness/engine[39m
|
|
7
7
|
|
|
8
|
-
[32m✓[39m src/__tests__/gate.test.ts [2m([22m[2m28 tests[22m[2m)[22m[
|
|
9
|
-
[32m✓[39m src/recipes/__tests__/service.test.ts [2m([22m[2m28 tests[22m[2m)[22m[33m
|
|
10
|
-
[32m✓[39m src/framework/__tests__/registry.test.ts [2m([22m[2m24 tests[22m[2m)[22m[90m
|
|
11
|
-
[32m✓[39m src/framework/__tests__/import-graph.test.ts [2m([22m[2m20 tests[22m[2m)[22m[33m
|
|
12
|
-
[33m[2m✓[22m[39m findStronglyConnectedComponents[2m > [22mhandles a deep graph without recursion blowing the stack [
|
|
13
|
-
[32m✓[39m src/plugins/__tests__/check-package-discovery.test.ts [2m([22m[2m16 tests[22m[2m)[22m[
|
|
14
|
-
[32m✓[39m src/recipes/__tests__/check-resolution.test.ts [2m([22m[2m14 tests[22m[2m)[22m[90m
|
|
15
|
-
[32m✓[39m src/__tests__/sarif.test.ts [2m([22m[2m15 tests[22m[2m)[22m[90m
|
|
16
|
-
[32m✓[39m src/plugins/__tests__/lang-domain.test.ts [2m([22m[2m8 tests[22m[2m)[22m[90m
|
|
17
|
-
[32m✓[39m src/framework/__tests__/result-builder.test.ts [2m([22m[2m25 tests[22m[2m)[22m[90m
|
|
18
|
-
[32m✓[39m src/framework/__tests__/scope-resolver.test.ts [2m([22m[2m8 tests[22m[2m)[22m[90m
|
|
19
|
-
[32m✓[39m src/plugins/__tests__/loader.test.ts [2m([22m[2m10 tests[22m[2m)[22m[33m
|
|
20
|
-
[33m[2m✓[22m[39m loadPlugin[2m > [22mregisters Check instances exported as named exports (no array wrapper) [
|
|
21
|
-
[32m✓[39m src/framework/__tests__/content-filter.test.ts [2m([22m[2m10 tests[22m[2m)[22m[90m
|
|
22
|
-
[32m✓[39m src/framework/__tests__/define-check.test.ts [2m([22m[2m17 tests[22m[2m)[22m[90m
|
|
23
|
-
[32m✓[39m src/framework/__tests__/file-cache.test.ts [2m([22m[2m15 tests[22m[2m)[22m[90m
|
|
24
|
-
[32m✓[39m src/framework/__tests__/path-matcher.test.ts [2m([22m[2m12 tests[22m[2m)[22m[90m
|
|
25
|
-
[32m✓[39m src/
|
|
26
|
-
[32m✓[39m src/
|
|
27
|
-
[32m✓[39m src/targets/__tests__/loader.test.ts [2m([22m[2m11 tests[22m[2m)[22m[90m
|
|
28
|
-
[32m✓[39m src/framework/__tests__/file-accessor.test.ts [2m([22m[2m11 tests[22m[2m)[22m[90m
|
|
29
|
-
[32m✓[39m src/framework/__tests__/strip-literals.test.ts [2m([22m[2m17 tests[22m[2m)[22m[90m
|
|
30
|
-
[32m✓[39m src/
|
|
31
|
-
[32m✓[39m src/
|
|
32
|
-
[32m✓[39m src/targets/__tests__/target-registry.test.ts [2m([22m[2m11 tests[22m[2m)[22m[90m
|
|
33
|
-
[32m✓[39m src/framework/__tests__/execution-context.test.ts [2m([22m[2m4 tests[22m[2m)[22m[90m
|
|
34
|
-
[32m✓[39m src/signalers/__tests__/loader.test.ts [2m([22m[2m8 tests[22m[2m)[22m[90m
|
|
35
|
-
[32m✓[39m src/recipes/__tests__/retry.test.ts [2m([22m[2m6 tests[22m[2m)[22m[90m
|
|
36
|
-
[32m✓[39m src/
|
|
37
|
-
[32m✓[39m src/
|
|
38
|
-
[32m✓[39m src/
|
|
39
|
-
[32m✓[39m src/framework/__tests__/
|
|
40
|
-
[32m✓[39m src/framework/__tests__/
|
|
41
|
-
[32m✓[39m src/framework/__tests__/
|
|
42
|
-
[32m✓[39m src/framework/__tests__/
|
|
43
|
-
[32m✓[39m src/
|
|
8
|
+
[32m✓[39m src/__tests__/gate.test.ts [2m([22m[2m28 tests[22m[2m)[22m[33m 354[2mms[22m[39m
|
|
9
|
+
[32m✓[39m src/recipes/__tests__/service.test.ts [2m([22m[2m28 tests[22m[2m)[22m[33m 666[2mms[22m[39m
|
|
10
|
+
[32m✓[39m src/framework/__tests__/registry.test.ts [2m([22m[2m24 tests[22m[2m)[22m[90m 99[2mms[22m[39m
|
|
11
|
+
[32m✓[39m src/framework/__tests__/import-graph.test.ts [2m([22m[2m20 tests[22m[2m)[22m[33m 745[2mms[22m[39m
|
|
12
|
+
[33m[2m✓[22m[39m findStronglyConnectedComponents[2m > [22mhandles a deep graph without recursion blowing the stack [33m557[2mms[22m[39m
|
|
13
|
+
[32m✓[39m src/plugins/__tests__/check-package-discovery.test.ts [2m([22m[2m16 tests[22m[2m)[22m[33m 327[2mms[22m[39m
|
|
14
|
+
[32m✓[39m src/recipes/__tests__/check-resolution.test.ts [2m([22m[2m14 tests[22m[2m)[22m[90m 145[2mms[22m[39m
|
|
15
|
+
[32m✓[39m src/__tests__/sarif.test.ts [2m([22m[2m15 tests[22m[2m)[22m[90m 101[2mms[22m[39m
|
|
16
|
+
[32m✓[39m src/plugins/__tests__/lang-domain.test.ts [2m([22m[2m8 tests[22m[2m)[22m[90m 84[2mms[22m[39m
|
|
17
|
+
[32m✓[39m src/framework/__tests__/result-builder.test.ts [2m([22m[2m25 tests[22m[2m)[22m[90m 124[2mms[22m[39m
|
|
18
|
+
[32m✓[39m src/framework/__tests__/scope-resolver.test.ts [2m([22m[2m8 tests[22m[2m)[22m[90m 181[2mms[22m[39m
|
|
19
|
+
[32m✓[39m src/plugins/__tests__/loader.test.ts [2m([22m[2m10 tests[22m[2m)[22m[33m 6479[2mms[22m[39m
|
|
20
|
+
[33m[2m✓[22m[39m loadPlugin[2m > [22mregisters Check instances exported as named exports (no array wrapper) [33m6108[2mms[22m[39m
|
|
21
|
+
[32m✓[39m src/framework/__tests__/content-filter.test.ts [2m([22m[2m10 tests[22m[2m)[22m[90m 111[2mms[22m[39m
|
|
22
|
+
[32m✓[39m src/framework/__tests__/define-check.test.ts [2m([22m[2m17 tests[22m[2m)[22m[90m 85[2mms[22m[39m
|
|
23
|
+
[32m✓[39m src/framework/__tests__/file-cache.test.ts [2m([22m[2m15 tests[22m[2m)[22m[90m 60[2mms[22m[39m
|
|
24
|
+
[32m✓[39m src/framework/__tests__/path-matcher.test.ts [2m([22m[2m12 tests[22m[2m)[22m[90m 150[2mms[22m[39m
|
|
25
|
+
[32m✓[39m src/recipes/__tests__/registry.test.ts [2m([22m[2m15 tests[22m[2m)[22m[90m 33[2mms[22m[39m
|
|
26
|
+
[32m✓[39m src/framework/__tests__/content-filter-dispatch.test.ts [2m([22m[2m6 tests[22m[2m)[22m[90m 67[2mms[22m[39m
|
|
27
|
+
[32m✓[39m src/targets/__tests__/loader.test.ts [2m([22m[2m11 tests[22m[2m)[22m[90m 71[2mms[22m[39m
|
|
28
|
+
[32m✓[39m src/framework/__tests__/file-accessor.test.ts [2m([22m[2m11 tests[22m[2m)[22m[90m 147[2mms[22m[39m
|
|
29
|
+
[32m✓[39m src/framework/__tests__/strip-literals.test.ts [2m([22m[2m17 tests[22m[2m)[22m[90m 38[2mms[22m[39m
|
|
30
|
+
[32m✓[39m src/recipes/__tests__/built-in-recipes.test.ts [2m([22m[2m14 tests[22m[2m)[22m[90m 64[2mms[22m[39m
|
|
31
|
+
[32m✓[39m src/framework/__tests__/ast-utilities.test.ts [2m([22m[2m19 tests[22m[2m)[22m[90m 88[2mms[22m[39m
|
|
32
|
+
[32m✓[39m src/targets/__tests__/target-registry.test.ts [2m([22m[2m11 tests[22m[2m)[22m[90m 30[2mms[22m[39m
|
|
33
|
+
[32m✓[39m src/framework/__tests__/execution-context.test.ts [2m([22m[2m4 tests[22m[2m)[22m[90m 150[2mms[22m[39m
|
|
34
|
+
[32m✓[39m src/signalers/__tests__/loader.test.ts [2m([22m[2m8 tests[22m[2m)[22m[90m 153[2mms[22m[39m
|
|
35
|
+
[32m✓[39m src/recipes/__tests__/retry.test.ts [2m([22m[2m6 tests[22m[2m)[22m[90m 25[2mms[22m[39m
|
|
36
|
+
[32m✓[39m src/recipes/__tests__/check-config.test.ts [2m([22m[2m5 tests[22m[2m)[22m[90m 20[2mms[22m[39m
|
|
37
|
+
[32m✓[39m src/framework/__tests__/directive-parsing.test.ts [2m([22m[2m8 tests[22m[2m)[22m[90m 16[2mms[22m[39m
|
|
38
|
+
[32m✓[39m src/targets/__tests__/resolver.test.ts [2m([22m[2m6 tests[22m[2m)[22m[90m 113[2mms[22m[39m
|
|
39
|
+
[32m✓[39m src/framework/__tests__/command-executor.test.ts [2m([22m[2m5 tests[22m[2m)[22m[90m 101[2mms[22m[39m
|
|
40
|
+
[32m✓[39m src/framework/__tests__/directive-inventory.test.ts [2m([22m[2m9 tests[22m[2m)[22m[90m 12[2mms[22m[39m
|
|
41
|
+
[32m✓[39m src/framework/__tests__/check-config.test.ts [2m([22m[2m6 tests[22m[2m)[22m[90m 47[2mms[22m[39m
|
|
42
|
+
[32m✓[39m src/framework/__tests__/severity-mapping.test.ts [2m([22m[2m13 tests[22m[2m)[22m[90m 18[2mms[22m[39m
|
|
43
|
+
[32m✓[39m src/framework/__tests__/register-helpers.test.ts [2m([22m[2m4 tests[22m[2m)[22m[90m 20[2mms[22m[39m
|
|
44
44
|
|
|
45
45
|
[2m Test Files [22m [1m[32m34 passed[39m[22m[90m (34)[39m
|
|
46
|
-
[2m Tests [22m [1m[
|
|
47
|
-
[2m Start at [22m
|
|
48
|
-
[2m Duration [22m
|
|
46
|
+
[2m Tests [22m [1m[32m428 passed[39m[22m[90m (428)[39m
|
|
47
|
+
[2m Start at [22m 00:26:54
|
|
48
|
+
[2m Duration [22m 25.75s[2m (transform 5.14s, setup 0ms, collect 22.49s, tests 10.92s, environment 43ms, prepare 14.54s)[22m
|
|
49
49
|
|
|
@@ -33,5 +33,26 @@ describe('getCheckConfig', () => {
|
|
|
33
33
|
const cfg = getCheckConfig('sample-check');
|
|
34
34
|
expect(cfg).toEqual({});
|
|
35
35
|
});
|
|
36
|
+
it('shares state with a separately-loaded copy of this module (multi-instance contract)', () => {
|
|
37
|
+
// Regression test for the multi-instance bug fixed in 1.0.9. The
|
|
38
|
+
// runtime frequently has TWO copies of `@opensip-tools/fitness`:
|
|
39
|
+
// the CLI's bundled copy (running the recipe service) and the
|
|
40
|
+
// plugin pack's resolved copy (running the check). Each copy has
|
|
41
|
+
// its own module-scope state; the prior `let currentRecipeCheckConfig`
|
|
42
|
+
// implementation made cross-copy state invisible. The fix moves
|
|
43
|
+
// the slot onto a `Symbol.for(...)` keyed `globalThis` entry so
|
|
44
|
+
// every copy reads + writes the same slot.
|
|
45
|
+
//
|
|
46
|
+
// Simulating "two copies" within one test: stash a value, look it
|
|
47
|
+
// up under the same well-known symbol from a separate import path
|
|
48
|
+
// (here: globalThis directly), and confirm the values match.
|
|
49
|
+
setCurrentRecipeCheckConfig({
|
|
50
|
+
'sample-check': { additionalEntries: ['cross-copy'] },
|
|
51
|
+
});
|
|
52
|
+
const KEY = Symbol.for('@opensip-tools/fitness/currentRecipeCheckConfig');
|
|
53
|
+
const slot = globalThis[KEY];
|
|
54
|
+
expect(slot).toBeDefined();
|
|
55
|
+
expect(slot['sample-check'].additionalEntries).toEqual(['cross-copy']);
|
|
56
|
+
});
|
|
36
57
|
});
|
|
37
58
|
//# sourceMappingURL=check-config.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check-config.test.js","sourceRoot":"","sources":["../../../src/recipes/__tests__/check-config.test.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAExD,OAAO,EACL,cAAc,EACd,2BAA2B,EAC3B,6BAA6B,GAC9B,MAAM,oBAAoB,CAAA;AAM3B,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,SAAS,CAAC,GAAG,EAAE;QACb,6BAA6B,EAAE,CAAA;IACjC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,GAAG,GAAG,cAAc,CAAe,UAAU,CAAC,CAAA;QACpD,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IACzB,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qEAAqE,EAAE,GAAG,EAAE;QAC7E,2BAA2B,CAAC;YAC1B,aAAa,EAAE,EAAE,iBAAiB,EAAE,CAAC,GAAG,CAAC,EAAE;SAC5C,CAAC,CAAA;QACF,MAAM,GAAG,GAAG,cAAc,CAAe,SAAS,CAAC,CAAA;QACnD,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IACzB,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,2BAA2B,CAAC;YAC1B,cAAc,EAAE,EAAE,iBAAiB,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE;SAClD,CAAC,CAAA;QACF,MAAM,GAAG,GAAG,cAAc,CAAe,cAAc,CAAC,CAAA;QACxD,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAA;IACnD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,uEAAuE,EAAE,GAAG,EAAE;QAC/E,2BAA2B,CAAC;YAC1B,cAAc,EAAE,EAAE,iBAAiB,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE;SAClD,CAAC,CAAA;QACF,6BAA6B,EAAE,CAAA;QAC/B,MAAM,GAAG,GAAG,cAAc,CAAe,cAAc,CAAC,CAAA;QACxD,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IACzB,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
|
1
|
+
{"version":3,"file":"check-config.test.js","sourceRoot":"","sources":["../../../src/recipes/__tests__/check-config.test.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAExD,OAAO,EACL,cAAc,EACd,2BAA2B,EAC3B,6BAA6B,GAC9B,MAAM,oBAAoB,CAAA;AAM3B,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,SAAS,CAAC,GAAG,EAAE;QACb,6BAA6B,EAAE,CAAA;IACjC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,GAAG,GAAG,cAAc,CAAe,UAAU,CAAC,CAAA;QACpD,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IACzB,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qEAAqE,EAAE,GAAG,EAAE;QAC7E,2BAA2B,CAAC;YAC1B,aAAa,EAAE,EAAE,iBAAiB,EAAE,CAAC,GAAG,CAAC,EAAE;SAC5C,CAAC,CAAA;QACF,MAAM,GAAG,GAAG,cAAc,CAAe,SAAS,CAAC,CAAA;QACnD,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IACzB,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,2BAA2B,CAAC;YAC1B,cAAc,EAAE,EAAE,iBAAiB,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE;SAClD,CAAC,CAAA;QACF,MAAM,GAAG,GAAG,cAAc,CAAe,cAAc,CAAC,CAAA;QACxD,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAA;IACnD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,uEAAuE,EAAE,GAAG,EAAE;QAC/E,2BAA2B,CAAC;YAC1B,cAAc,EAAE,EAAE,iBAAiB,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE;SAClD,CAAC,CAAA;QACF,6BAA6B,EAAE,CAAA;QAC/B,MAAM,GAAG,GAAG,cAAc,CAAe,cAAc,CAAC,CAAA;QACxD,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IACzB,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qFAAqF,EAAE,GAAG,EAAE;QAC7F,iEAAiE;QACjE,iEAAiE;QACjE,8DAA8D;QAC9D,iEAAiE;QACjE,uEAAuE;QACvE,gEAAgE;QAChE,gEAAgE;QAChE,2CAA2C;QAC3C,EAAE;QACF,kEAAkE;QAClE,kEAAkE;QAClE,6DAA6D;QAC7D,2BAA2B,CAAC;YAC1B,cAAc,EAAE,EAAE,iBAAiB,EAAE,CAAC,YAAY,CAAC,EAAE;SACtD,CAAC,CAAA;QACF,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAA;QACzE,MAAM,IAAI,GAAI,UAAiD,CAAC,GAAG,CAAC,CAAA;QACpE,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAA;QAC1B,MAAM,CAAE,IAA4D,CAAC,cAAc,CAAC,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAA;IACjI,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
|
@@ -28,13 +28,13 @@ import type { RecipeCheckConfigMap } from './types.js';
|
|
|
28
28
|
*/
|
|
29
29
|
export declare function getCheckConfig<T extends Record<string, unknown>>(slug: string): T;
|
|
30
30
|
/**
|
|
31
|
-
* Replace the
|
|
31
|
+
* Replace the global recipe config. Called by the recipe service at
|
|
32
32
|
* the start of a recipe run, before any check executes.
|
|
33
33
|
*/
|
|
34
34
|
export declare function setCurrentRecipeCheckConfig(config: RecipeCheckConfigMap | undefined): void;
|
|
35
35
|
/**
|
|
36
|
-
* Clear the
|
|
37
|
-
*
|
|
36
|
+
* Clear the global recipe config. Called by the recipe service at the end
|
|
37
|
+
* of a recipe run (success or failure).
|
|
38
38
|
*/
|
|
39
39
|
export declare function clearCurrentRecipeCheckConfig(): void;
|
|
40
40
|
//# sourceMappingURL=check-config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check-config.d.ts","sourceRoot":"","sources":["../../src/recipes/check-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"check-config.d.ts","sourceRoot":"","sources":["../../src/recipes/check-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAmCtD;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,CAMjF;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,oBAAoB,GAAG,SAAS,GAAG,IAAI,CAE1F;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,IAAI,IAAI,CAEpD"}
|
|
@@ -16,16 +16,32 @@
|
|
|
16
16
|
* extend the safe-lists with project-specific names.
|
|
17
17
|
*/
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
19
|
+
* Process-shared current-recipe config. Populated by the recipe service at
|
|
20
20
|
* the start of a run and cleared at the end. Checks read from it lazily via
|
|
21
21
|
* {@link getCheckConfig}.
|
|
22
22
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
23
|
+
* `globalThis` (not module-local `let`) is load-bearing — the runtime
|
|
24
|
+
* frequently has TWO copies of `@opensip-tools/fitness` loaded:
|
|
25
|
+
*
|
|
26
|
+
* 1. The CLI's bundled copy (running the recipe service).
|
|
27
|
+
* 2. The plugin pack's resolved copy (running the check, calling
|
|
28
|
+
* `getCheckConfig(slug)`).
|
|
29
|
+
*
|
|
30
|
+
* Each copy has its own module-scope state, so a module-local `let` here
|
|
31
|
+
* means `setCurrentRecipeCheckConfig(...)` in copy 1 is invisible to
|
|
32
|
+
* `getCheckConfig(...)` in copy 2 — the recipe's `additionalSyncFunctions`
|
|
33
|
+
* (and every other per-check allowlist) silently never reaches the checks
|
|
34
|
+
* that read it. Storing the map on `globalThis` under a single well-known
|
|
35
|
+
* symbol means every copy reads + writes the same slot.
|
|
36
|
+
*
|
|
37
|
+
* The single-session contract still holds (the recipe service throws
|
|
38
|
+
* SESSION_IN_PROGRESS otherwise); the only thing that changes vs the prior
|
|
39
|
+
* design is the storage location, not the lifecycle.
|
|
27
40
|
*/
|
|
28
|
-
|
|
41
|
+
const GLOBAL_KEY = Symbol.for('@opensip-tools/fitness/currentRecipeCheckConfig');
|
|
42
|
+
function slot() {
|
|
43
|
+
return globalThis;
|
|
44
|
+
}
|
|
29
45
|
/**
|
|
30
46
|
* Read the per-check config slice for the given slug.
|
|
31
47
|
*
|
|
@@ -37,25 +53,26 @@ let currentRecipeCheckConfig;
|
|
|
37
53
|
* its own config interface.
|
|
38
54
|
*/
|
|
39
55
|
export function getCheckConfig(slug) {
|
|
40
|
-
|
|
56
|
+
const current = slot()[GLOBAL_KEY];
|
|
57
|
+
if (!current)
|
|
41
58
|
return {};
|
|
42
|
-
const entry =
|
|
59
|
+
const entry = current[slug];
|
|
43
60
|
if (!entry)
|
|
44
61
|
return {};
|
|
45
62
|
return entry;
|
|
46
63
|
}
|
|
47
64
|
/**
|
|
48
|
-
* Replace the
|
|
65
|
+
* Replace the global recipe config. Called by the recipe service at
|
|
49
66
|
* the start of a recipe run, before any check executes.
|
|
50
67
|
*/
|
|
51
68
|
export function setCurrentRecipeCheckConfig(config) {
|
|
52
|
-
|
|
69
|
+
slot()[GLOBAL_KEY] = config;
|
|
53
70
|
}
|
|
54
71
|
/**
|
|
55
|
-
* Clear the
|
|
56
|
-
*
|
|
72
|
+
* Clear the global recipe config. Called by the recipe service at the end
|
|
73
|
+
* of a recipe run (success or failure).
|
|
57
74
|
*/
|
|
58
75
|
export function clearCurrentRecipeCheckConfig() {
|
|
59
|
-
|
|
76
|
+
slot()[GLOBAL_KEY] = undefined;
|
|
60
77
|
}
|
|
61
78
|
//# sourceMappingURL=check-config.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check-config.js","sourceRoot":"","sources":["../../src/recipes/check-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH
|
|
1
|
+
{"version":3,"file":"check-config.js","sourceRoot":"","sources":["../../src/recipes/check-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAA;AAMhF,SAAS,IAAI;IACX,OAAO,UAAmC,CAAA;AAC5C,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAAoC,IAAY;IAC5E,MAAM,OAAO,GAAG,IAAI,EAAE,CAAC,UAAU,CAAC,CAAA;IAClC,IAAI,CAAC,OAAO;QAAE,OAAO,EAAO,CAAA;IAC5B,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3B,IAAI,CAAC,KAAK;QAAE,OAAO,EAAO,CAAA;IAC1B,OAAO,KAAU,CAAA;AACnB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,2BAA2B,CAAC,MAAwC;IAClF,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,MAAM,CAAA;AAC7B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,6BAA6B;IAC3C,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,SAAS,CAAA;AAChC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opensip-tools/fitness",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.10",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Fitness checks engine for OpenSIP Tools",
|
|
6
6
|
"repository": {
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"minimatch": "^10.0.0",
|
|
29
29
|
"typescript": "~5.7.0",
|
|
30
30
|
"zod": "^3.24.0",
|
|
31
|
-
"@opensip-tools/
|
|
32
|
-
"@opensip-tools/
|
|
31
|
+
"@opensip-tools/contracts": "1.0.10",
|
|
32
|
+
"@opensip-tools/core": "1.0.10"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/js-yaml": "^4.0.0",
|
|
@@ -48,4 +48,26 @@ describe('getCheckConfig', () => {
|
|
|
48
48
|
const cfg = getCheckConfig<SampleConfig>('sample-check')
|
|
49
49
|
expect(cfg).toEqual({})
|
|
50
50
|
})
|
|
51
|
+
|
|
52
|
+
it('shares state with a separately-loaded copy of this module (multi-instance contract)', () => {
|
|
53
|
+
// Regression test for the multi-instance bug fixed in 1.0.9. The
|
|
54
|
+
// runtime frequently has TWO copies of `@opensip-tools/fitness`:
|
|
55
|
+
// the CLI's bundled copy (running the recipe service) and the
|
|
56
|
+
// plugin pack's resolved copy (running the check). Each copy has
|
|
57
|
+
// its own module-scope state; the prior `let currentRecipeCheckConfig`
|
|
58
|
+
// implementation made cross-copy state invisible. The fix moves
|
|
59
|
+
// the slot onto a `Symbol.for(...)` keyed `globalThis` entry so
|
|
60
|
+
// every copy reads + writes the same slot.
|
|
61
|
+
//
|
|
62
|
+
// Simulating "two copies" within one test: stash a value, look it
|
|
63
|
+
// up under the same well-known symbol from a separate import path
|
|
64
|
+
// (here: globalThis directly), and confirm the values match.
|
|
65
|
+
setCurrentRecipeCheckConfig({
|
|
66
|
+
'sample-check': { additionalEntries: ['cross-copy'] },
|
|
67
|
+
})
|
|
68
|
+
const KEY = Symbol.for('@opensip-tools/fitness/currentRecipeCheckConfig')
|
|
69
|
+
const slot = (globalThis as unknown as Record<symbol, unknown>)[KEY]
|
|
70
|
+
expect(slot).toBeDefined()
|
|
71
|
+
expect((slot as { 'sample-check': { additionalEntries: string[] } })['sample-check'].additionalEntries).toEqual(['cross-copy'])
|
|
72
|
+
})
|
|
51
73
|
})
|
|
@@ -19,16 +19,37 @@
|
|
|
19
19
|
import type { RecipeCheckConfigMap } from './types.js'
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
*
|
|
22
|
+
* Process-shared current-recipe config. Populated by the recipe service at
|
|
23
23
|
* the start of a run and cleared at the end. Checks read from it lazily via
|
|
24
24
|
* {@link getCheckConfig}.
|
|
25
25
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
26
|
+
* `globalThis` (not module-local `let`) is load-bearing — the runtime
|
|
27
|
+
* frequently has TWO copies of `@opensip-tools/fitness` loaded:
|
|
28
|
+
*
|
|
29
|
+
* 1. The CLI's bundled copy (running the recipe service).
|
|
30
|
+
* 2. The plugin pack's resolved copy (running the check, calling
|
|
31
|
+
* `getCheckConfig(slug)`).
|
|
32
|
+
*
|
|
33
|
+
* Each copy has its own module-scope state, so a module-local `let` here
|
|
34
|
+
* means `setCurrentRecipeCheckConfig(...)` in copy 1 is invisible to
|
|
35
|
+
* `getCheckConfig(...)` in copy 2 — the recipe's `additionalSyncFunctions`
|
|
36
|
+
* (and every other per-check allowlist) silently never reaches the checks
|
|
37
|
+
* that read it. Storing the map on `globalThis` under a single well-known
|
|
38
|
+
* symbol means every copy reads + writes the same slot.
|
|
39
|
+
*
|
|
40
|
+
* The single-session contract still holds (the recipe service throws
|
|
41
|
+
* SESSION_IN_PROGRESS otherwise); the only thing that changes vs the prior
|
|
42
|
+
* design is the storage location, not the lifecycle.
|
|
30
43
|
*/
|
|
31
|
-
|
|
44
|
+
const GLOBAL_KEY = Symbol.for('@opensip-tools/fitness/currentRecipeCheckConfig')
|
|
45
|
+
|
|
46
|
+
interface GlobalSlot {
|
|
47
|
+
[GLOBAL_KEY]?: RecipeCheckConfigMap | undefined
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function slot(): GlobalSlot {
|
|
51
|
+
return globalThis as unknown as GlobalSlot
|
|
52
|
+
}
|
|
32
53
|
|
|
33
54
|
/**
|
|
34
55
|
* Read the per-check config slice for the given slug.
|
|
@@ -41,24 +62,25 @@ let currentRecipeCheckConfig: RecipeCheckConfigMap | undefined
|
|
|
41
62
|
* its own config interface.
|
|
42
63
|
*/
|
|
43
64
|
export function getCheckConfig<T extends Record<string, unknown>>(slug: string): T {
|
|
44
|
-
|
|
45
|
-
|
|
65
|
+
const current = slot()[GLOBAL_KEY]
|
|
66
|
+
if (!current) return {} as T
|
|
67
|
+
const entry = current[slug]
|
|
46
68
|
if (!entry) return {} as T
|
|
47
69
|
return entry as T
|
|
48
70
|
}
|
|
49
71
|
|
|
50
72
|
/**
|
|
51
|
-
* Replace the
|
|
73
|
+
* Replace the global recipe config. Called by the recipe service at
|
|
52
74
|
* the start of a recipe run, before any check executes.
|
|
53
75
|
*/
|
|
54
76
|
export function setCurrentRecipeCheckConfig(config: RecipeCheckConfigMap | undefined): void {
|
|
55
|
-
|
|
77
|
+
slot()[GLOBAL_KEY] = config
|
|
56
78
|
}
|
|
57
79
|
|
|
58
80
|
/**
|
|
59
|
-
* Clear the
|
|
60
|
-
*
|
|
81
|
+
* Clear the global recipe config. Called by the recipe service at the end
|
|
82
|
+
* of a recipe run (success or failure).
|
|
61
83
|
*/
|
|
62
84
|
export function clearCurrentRecipeCheckConfig(): void {
|
|
63
|
-
|
|
85
|
+
slot()[GLOBAL_KEY] = undefined
|
|
64
86
|
}
|