@opensip-tools/contracts 1.0.4

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 (86) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/.turbo/turbo-typecheck.log +4 -0
  3. package/LICENSE +21 -0
  4. package/dist/__tests__/dashboard.test.d.ts +2 -0
  5. package/dist/__tests__/dashboard.test.d.ts.map +1 -0
  6. package/dist/__tests__/dashboard.test.js +85 -0
  7. package/dist/__tests__/dashboard.test.js.map +1 -0
  8. package/dist/__tests__/exit-codes.test.d.ts +2 -0
  9. package/dist/__tests__/exit-codes.test.d.ts.map +1 -0
  10. package/dist/__tests__/exit-codes.test.js +73 -0
  11. package/dist/__tests__/exit-codes.test.js.map +1 -0
  12. package/dist/__tests__/store.test.d.ts +2 -0
  13. package/dist/__tests__/store.test.d.ts.map +1 -0
  14. package/dist/__tests__/store.test.js +169 -0
  15. package/dist/__tests__/store.test.js.map +1 -0
  16. package/dist/exit-codes.d.ts +14 -0
  17. package/dist/exit-codes.d.ts.map +1 -0
  18. package/dist/exit-codes.js +61 -0
  19. package/dist/exit-codes.js.map +1 -0
  20. package/dist/index.d.ts +21 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +20 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/persistence/dashboard/checks.d.ts +7 -0
  25. package/dist/persistence/dashboard/checks.d.ts.map +1 -0
  26. package/dist/persistence/dashboard/checks.js +279 -0
  27. package/dist/persistence/dashboard/checks.js.map +1 -0
  28. package/dist/persistence/dashboard/css.d.ts +6 -0
  29. package/dist/persistence/dashboard/css.d.ts.map +1 -0
  30. package/dist/persistence/dashboard/css.js +141 -0
  31. package/dist/persistence/dashboard/css.js.map +1 -0
  32. package/dist/persistence/dashboard/generator.d.ts +9 -0
  33. package/dist/persistence/dashboard/generator.d.ts.map +1 -0
  34. package/dist/persistence/dashboard/generator.js +79 -0
  35. package/dist/persistence/dashboard/generator.js.map +1 -0
  36. package/dist/persistence/dashboard/index.d.ts +5 -0
  37. package/dist/persistence/dashboard/index.d.ts.map +1 -0
  38. package/dist/persistence/dashboard/index.js +5 -0
  39. package/dist/persistence/dashboard/index.js.map +1 -0
  40. package/dist/persistence/dashboard/overview.d.ts +6 -0
  41. package/dist/persistence/dashboard/overview.d.ts.map +1 -0
  42. package/dist/persistence/dashboard/overview.js +65 -0
  43. package/dist/persistence/dashboard/overview.js.map +1 -0
  44. package/dist/persistence/dashboard/recipes.d.ts +6 -0
  45. package/dist/persistence/dashboard/recipes.d.ts.map +1 -0
  46. package/dist/persistence/dashboard/recipes.js +68 -0
  47. package/dist/persistence/dashboard/recipes.js.map +1 -0
  48. package/dist/persistence/dashboard/sessions.d.ts +6 -0
  49. package/dist/persistence/dashboard/sessions.d.ts.map +1 -0
  50. package/dist/persistence/dashboard/sessions.js +205 -0
  51. package/dist/persistence/dashboard/sessions.js.map +1 -0
  52. package/dist/persistence/dashboard/shared.d.ts +6 -0
  53. package/dist/persistence/dashboard/shared.d.ts.map +1 -0
  54. package/dist/persistence/dashboard/shared.js +211 -0
  55. package/dist/persistence/dashboard/shared.js.map +1 -0
  56. package/dist/persistence/dashboard/tool-tabs.d.ts +6 -0
  57. package/dist/persistence/dashboard/tool-tabs.d.ts.map +1 -0
  58. package/dist/persistence/dashboard/tool-tabs.js +102 -0
  59. package/dist/persistence/dashboard/tool-tabs.js.map +1 -0
  60. package/dist/persistence/store.d.ts +103 -0
  61. package/dist/persistence/store.d.ts.map +1 -0
  62. package/dist/persistence/store.js +156 -0
  63. package/dist/persistence/store.js.map +1 -0
  64. package/dist/types.d.ts +279 -0
  65. package/dist/types.d.ts.map +1 -0
  66. package/dist/types.js +2 -0
  67. package/dist/types.js.map +1 -0
  68. package/package.json +35 -0
  69. package/src/__tests__/dashboard.test.ts +102 -0
  70. package/src/__tests__/exit-codes.test.ts +87 -0
  71. package/src/__tests__/store.test.ts +213 -0
  72. package/src/exit-codes.ts +74 -0
  73. package/src/index.ts +71 -0
  74. package/src/persistence/dashboard/checks.ts +279 -0
  75. package/src/persistence/dashboard/css.ts +141 -0
  76. package/src/persistence/dashboard/generator.ts +89 -0
  77. package/src/persistence/dashboard/index.ts +5 -0
  78. package/src/persistence/dashboard/overview.ts +65 -0
  79. package/src/persistence/dashboard/recipes.ts +68 -0
  80. package/src/persistence/dashboard/sessions.ts +205 -0
  81. package/src/persistence/dashboard/shared.ts +211 -0
  82. package/src/persistence/dashboard/tool-tabs.ts +102 -0
  83. package/src/persistence/store.ts +233 -0
  84. package/src/types.ts +306 -0
  85. package/tsconfig.json +8 -0
  86. package/vitest.config.ts +16 -0
@@ -0,0 +1,4 @@
1
+
2
+ > @opensip-tools/contracts@1.0.4 build /Users/sb/Documents/Code/opensip-ai/opensip-tools/packages/contracts
3
+ > tsc
4
+
@@ -0,0 +1,4 @@
1
+
2
+ > @opensip-tools/contracts@1.0.4 typecheck /Users/sb/Documents/Code/opensip-ai/opensip-tools/packages/contracts
3
+ > tsc --noEmit
4
+
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 opensip-ai
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=dashboard.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/dashboard.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,85 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { generateDashboardHtml } from '../persistence/dashboard/generator.js';
3
+ function makeSession(overrides = {}) {
4
+ return {
5
+ id: 'sess-1',
6
+ tool: 'fit',
7
+ timestamp: new Date().toISOString(),
8
+ cwd: '/proj',
9
+ score: 92,
10
+ passed: true,
11
+ summary: { total: 10, passed: 9, failed: 1, errors: 0, warnings: 0 },
12
+ checks: [],
13
+ durationMs: 100,
14
+ ...overrides,
15
+ };
16
+ }
17
+ const checkCatalog = [
18
+ {
19
+ slug: 'no-console-log',
20
+ name: 'No console.log',
21
+ icon: '🚫',
22
+ description: 'Forbids console.log in production',
23
+ tags: ['quality'],
24
+ confidence: 'high',
25
+ source: 'built-in',
26
+ },
27
+ ];
28
+ const recipeCatalog = [
29
+ {
30
+ name: 'default',
31
+ displayName: 'Default',
32
+ description: 'All checks',
33
+ tags: [],
34
+ selectorType: 'all',
35
+ mode: 'parallel',
36
+ timeout: 30_000,
37
+ },
38
+ ];
39
+ describe('generateDashboardHtml', () => {
40
+ it('produces a complete HTML5 document', () => {
41
+ const html = generateDashboardHtml([makeSession()]);
42
+ expect(html).toContain('<!DOCTYPE html>');
43
+ expect(html).toContain('</html>');
44
+ });
45
+ it('inlines the latest session score in the document title', () => {
46
+ const html = generateDashboardHtml([makeSession({ score: 85 })]);
47
+ expect(html).toContain('Pass Rate: 85%');
48
+ });
49
+ it('omits the score from the title when there are no sessions', () => {
50
+ const html = generateDashboardHtml([]);
51
+ expect(html).toMatch(/<title>OpenSIP Tools<\/title>/);
52
+ });
53
+ it('inlines session, check catalog, and recipe catalog as JS data', () => {
54
+ const html = generateDashboardHtml([makeSession({ id: 'special-session-id' })], checkCatalog, recipeCatalog);
55
+ expect(html).toContain('special-session-id');
56
+ expect(html).toContain('no-console-log');
57
+ expect(html).toContain('default');
58
+ });
59
+ it('escapes < and > in inlined JSON to prevent script injection', () => {
60
+ // A session whose cwd contains a fake </script> tag must not break out
61
+ const evil = makeSession({ cwd: '</script><script>alert(1)</script>' });
62
+ const html = generateDashboardHtml([evil]);
63
+ expect(html).not.toMatch(/<\/script>\s*<script>alert\(1\)/);
64
+ expect(html).toContain(String.raw `</script>`);
65
+ });
66
+ it('renders all three tab panels (overview, fitness, simulation)', () => {
67
+ const html = generateDashboardHtml([]);
68
+ expect(html).toContain('id="panel-overview"');
69
+ expect(html).toContain('id="panel-fitness"');
70
+ expect(html).toContain('id="panel-simulation"');
71
+ });
72
+ it('includes inline CSS', () => {
73
+ const html = generateDashboardHtml([]);
74
+ expect(html).toMatch(/<style>[\s\S]+?<\/style>/);
75
+ });
76
+ it('partitions sessions into fit vs sim arrays in the page script', () => {
77
+ const html = generateDashboardHtml([
78
+ makeSession({ id: 'fit-1', tool: 'fit' }),
79
+ makeSession({ id: 'sim-1', tool: 'sim' }),
80
+ ]);
81
+ expect(html).toContain("sessions.filter(s => s.tool === 'fit')");
82
+ expect(html).toContain("sessions.filter(s => s.tool === 'sim')");
83
+ });
84
+ });
85
+ //# sourceMappingURL=dashboard.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.test.js","sourceRoot":"","sources":["../../src/__tests__/dashboard.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=exit-codes.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exit-codes.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/exit-codes.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,73 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { EXIT_CODES, getErrorSuggestion } from '../exit-codes.js';
3
+ describe('EXIT_CODES', () => {
4
+ it('exposes the documented set', () => {
5
+ expect(EXIT_CODES).toEqual({
6
+ SUCCESS: 0,
7
+ RUNTIME_ERROR: 1,
8
+ CONFIGURATION_ERROR: 2,
9
+ CHECK_NOT_FOUND: 3,
10
+ REPORT_FAILED: 4,
11
+ });
12
+ });
13
+ });
14
+ describe('getErrorSuggestion', () => {
15
+ it('returns null when no pattern matches', () => {
16
+ expect(getErrorSuggestion(new Error('something else entirely'))).toBeNull();
17
+ });
18
+ it('handles non-Error inputs', () => {
19
+ expect(getErrorSuggestion('just a string')).toBeNull();
20
+ expect(getErrorSuggestion(undefined)).toBeNull();
21
+ });
22
+ it('classifies "Check not found: <slug>" with the slug surfaced', () => {
23
+ const out = getErrorSuggestion(new Error('Check not found: foo-check'));
24
+ expect(out?.exitCode).toBe(EXIT_CODES.CHECK_NOT_FOUND);
25
+ expect(out?.message).toContain('foo-check');
26
+ });
27
+ it('classifies "not found: <slug>" without the "Check" prefix', () => {
28
+ const out = getErrorSuggestion(new Error('Recipe not found: my-recipe'));
29
+ expect(out?.exitCode).toBe(EXIT_CODES.CHECK_NOT_FOUND);
30
+ expect(out?.message).toContain('my-recipe');
31
+ });
32
+ it('falls back to "unknown" when slug cannot be extracted', () => {
33
+ const out = getErrorSuggestion(new Error('not found'));
34
+ expect(out?.message).toContain('unknown');
35
+ });
36
+ it('classifies "Unknown recipe ..." as configuration error', () => {
37
+ const out = getErrorSuggestion(new Error('Unknown recipe foo'));
38
+ expect(out?.exitCode).toBe(EXIT_CODES.CONFIGURATION_ERROR);
39
+ expect(out?.action).toContain('--recipes');
40
+ });
41
+ it('classifies opensip-tools.config.yml errors', () => {
42
+ const out = getErrorSuggestion(new Error('Failed to parse opensip-tools.config.yml'));
43
+ expect(out?.exitCode).toBe(EXIT_CODES.CONFIGURATION_ERROR);
44
+ });
45
+ it('classifies YAML errors as configuration', () => {
46
+ const out = getErrorSuggestion(new Error('Bad YAML at line 3'));
47
+ expect(out?.exitCode).toBe(EXIT_CODES.CONFIGURATION_ERROR);
48
+ });
49
+ it('classifies generic config errors', () => {
50
+ const out = getErrorSuggestion(new Error('config invalid'));
51
+ expect(out?.exitCode).toBe(EXIT_CODES.CONFIGURATION_ERROR);
52
+ });
53
+ it('classifies EACCES as a runtime permission error', () => {
54
+ const out = getErrorSuggestion(new Error('EACCES: permission denied reading /etc'));
55
+ expect(out?.exitCode).toBe(EXIT_CODES.RUNTIME_ERROR);
56
+ expect(out?.action).toContain('permissions');
57
+ });
58
+ it('classifies "No checks registered" as runtime error with check-pack guidance', () => {
59
+ const out = getErrorSuggestion(new Error('No checks registered'));
60
+ expect(out?.exitCode).toBe(EXIT_CODES.RUNTIME_ERROR);
61
+ expect(out?.action).toContain('checks-*');
62
+ });
63
+ it('classifies "No checks to run" similarly', () => {
64
+ const out = getErrorSuggestion(new Error('No checks to run'));
65
+ expect(out?.exitCode).toBe(EXIT_CODES.RUNTIME_ERROR);
66
+ });
67
+ it('classifies fetch/network errors as REPORT_FAILED', () => {
68
+ expect(getErrorSuggestion(new Error('fetch failed'))?.exitCode).toBe(EXIT_CODES.REPORT_FAILED);
69
+ expect(getErrorSuggestion(new Error('ECONNREFUSED'))?.exitCode).toBe(EXIT_CODES.REPORT_FAILED);
70
+ expect(getErrorSuggestion(new Error('network unreachable'))?.exitCode).toBe(EXIT_CODES.REPORT_FAILED);
71
+ });
72
+ });
73
+ //# sourceMappingURL=exit-codes.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exit-codes.test.js","sourceRoot":"","sources":["../../src/__tests__/exit-codes.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=store.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/store.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,169 @@
1
+ import { mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs';
2
+ import { tmpdir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
5
+ import { clearAllSessions, clearSessionsOlderThan, configurePersistencePaths, countSessions, generateSessionId, getReportsDir, getStoreDir, loadLatestSession, loadSessions, sanitizeForFilename, saveSession, } from '../persistence/store.js';
6
+ let testDir;
7
+ let sessionsDir;
8
+ let reportsDir;
9
+ function makeSession(overrides = {}) {
10
+ return {
11
+ id: 'sess-1',
12
+ tool: 'fit',
13
+ timestamp: new Date().toISOString(),
14
+ cwd: '/proj',
15
+ score: 100,
16
+ passed: true,
17
+ summary: { total: 1, passed: 1, failed: 0, errors: 0, warnings: 0 },
18
+ checks: [],
19
+ durationMs: 0,
20
+ ...overrides,
21
+ };
22
+ }
23
+ beforeEach(() => {
24
+ testDir = mkdtempSync(join(tmpdir(), 'contracts-store-'));
25
+ sessionsDir = join(testDir, 'sessions');
26
+ reportsDir = join(testDir, 'reports');
27
+ configurePersistencePaths({ sessionsDir, reportsDir });
28
+ });
29
+ afterEach(() => {
30
+ rmSync(testDir, { recursive: true, force: true });
31
+ });
32
+ describe('configurePersistencePaths', () => {
33
+ it('redirects getStoreDir / getReportsDir to the configured paths', () => {
34
+ expect(getStoreDir()).toBe(sessionsDir);
35
+ expect(getReportsDir()).toBe(reportsDir);
36
+ });
37
+ });
38
+ describe('sanitizeForFilename', () => {
39
+ it('strips path separators and special chars', () => {
40
+ expect(sanitizeForFilename(String.raw `a/b\c:d*e?f"g<h>i|j.k`)).not.toMatch(/[/\\:*?"<>|.]/);
41
+ });
42
+ it('collapses parent traversal', () => {
43
+ expect(sanitizeForFilename('../../etc/passwd')).not.toContain('..');
44
+ });
45
+ });
46
+ describe('saveSession', () => {
47
+ it('writes a json file under the sessions dir and returns its path', () => {
48
+ const path = saveSession(makeSession());
49
+ expect(path.startsWith(sessionsDir)).toBe(true);
50
+ expect(readdirSync(sessionsDir).length).toBe(1);
51
+ });
52
+ it('encodes the recipe in the filename, sanitized', () => {
53
+ const path = saveSession(makeSession({ recipe: 'foo/bar' }));
54
+ expect(path).toContain('-foo-bar');
55
+ });
56
+ it('does not include a recipe segment when recipe is absent', () => {
57
+ const path = saveSession(makeSession());
58
+ expect(path).not.toContain('-undefined');
59
+ });
60
+ });
61
+ describe('loadSessions / loadLatestSession', () => {
62
+ it('returns sessions in newest-first order', () => {
63
+ saveSession(makeSession({ id: 'first', timestamp: '2024-01-01T00:00:00.000Z' }));
64
+ saveSession(makeSession({ id: 'second', timestamp: '2024-06-01T00:00:00.000Z' }));
65
+ saveSession(makeSession({ id: 'third', timestamp: '2024-12-01T00:00:00.000Z' }));
66
+ const out = loadSessions();
67
+ expect(out.map((s) => s.id)).toEqual(['third', 'second', 'first']);
68
+ });
69
+ it('honors the limit parameter', () => {
70
+ saveSession(makeSession({ id: 'a', timestamp: '2024-01-01T00:00:00.000Z' }));
71
+ saveSession(makeSession({ id: 'b', timestamp: '2024-02-01T00:00:00.000Z' }));
72
+ saveSession(makeSession({ id: 'c', timestamp: '2024-03-01T00:00:00.000Z' }));
73
+ expect(loadSessions(2)).toHaveLength(2);
74
+ });
75
+ it('skips corrupted JSON files without crashing', () => {
76
+ saveSession(makeSession({ id: 'good' }));
77
+ mkdirSync(sessionsDir, { recursive: true });
78
+ writeFileSync(join(sessionsDir, '2024-99-99-fit.json'), '{not-json');
79
+ const out = loadSessions();
80
+ expect(out.map((s) => s.id)).toContain('good');
81
+ });
82
+ it('loadLatestSession returns null when no sessions exist', () => {
83
+ expect(loadLatestSession()).toBeNull();
84
+ });
85
+ it('loadLatestSession returns the newest session', () => {
86
+ saveSession(makeSession({ id: 'old', timestamp: '2024-01-01T00:00:00.000Z' }));
87
+ saveSession(makeSession({ id: 'new', timestamp: '2024-12-31T00:00:00.000Z' }));
88
+ expect(loadLatestSession()?.id).toBe('new');
89
+ });
90
+ });
91
+ describe('countSessions', () => {
92
+ it('returns 0 when the store is empty', () => {
93
+ expect(countSessions()).toBe(0);
94
+ });
95
+ it('counts only .json files', () => {
96
+ saveSession(makeSession());
97
+ writeFileSync(join(sessionsDir, 'note.txt'), 'ignored');
98
+ expect(countSessions()).toBe(1);
99
+ });
100
+ });
101
+ describe('clearAllSessions', () => {
102
+ it('removes every json file and returns the count', () => {
103
+ saveSession(makeSession({ id: 'a', timestamp: '2024-01-01T00:00:00.000Z' }));
104
+ saveSession(makeSession({ id: 'b', timestamp: '2024-02-01T00:00:00.000Z' }));
105
+ expect(clearAllSessions()).toBe(2);
106
+ expect(countSessions()).toBe(0);
107
+ });
108
+ it('returns 0 when the store is already empty', () => {
109
+ expect(clearAllSessions()).toBe(0);
110
+ });
111
+ });
112
+ describe('clearSessionsOlderThan', () => {
113
+ it('deletes sessions with timestamps older than the cutoff', () => {
114
+ const oldTs = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString();
115
+ const newTs = new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString();
116
+ saveSession(makeSession({ id: 'old', timestamp: oldTs }));
117
+ saveSession(makeSession({ id: 'new', timestamp: newTs }));
118
+ expect(clearSessionsOlderThan(7)).toBe(1);
119
+ expect(countSessions()).toBe(1);
120
+ expect(loadLatestSession()?.id).toBe('new');
121
+ });
122
+ it('skips files with unparseable timestamps', () => {
123
+ mkdirSync(sessionsDir, { recursive: true });
124
+ writeFileSync(join(sessionsDir, 'bad.json'), JSON.stringify({ timestamp: 'not-a-date' }));
125
+ saveSession(makeSession({ id: 'ok', timestamp: new Date().toISOString() }));
126
+ // bad.json has unparseable timestamp; 'ok' is recent. None deleted.
127
+ expect(clearSessionsOlderThan(7)).toBe(0);
128
+ });
129
+ it('skips files with no timestamp field', () => {
130
+ mkdirSync(sessionsDir, { recursive: true });
131
+ writeFileSync(join(sessionsDir, 'no-ts.json'), JSON.stringify({}));
132
+ expect(clearSessionsOlderThan(7)).toBe(0);
133
+ });
134
+ it('skips unparseable JSON', () => {
135
+ mkdirSync(sessionsDir, { recursive: true });
136
+ writeFileSync(join(sessionsDir, 'broken.json'), '{');
137
+ expect(clearSessionsOlderThan(7)).toBe(0);
138
+ });
139
+ });
140
+ describe('saveSession pruning', () => {
141
+ it('keeps at most 100 sessions, pruning oldest', () => {
142
+ // Create 105 sessions with monotonically increasing timestamps
143
+ for (let i = 0; i < 105; i++) {
144
+ const day = String(i + 1).padStart(2, '0');
145
+ saveSession(makeSession({ id: `s-${i}`, timestamp: `2024-01-${day}T00:00:00.000Z` }));
146
+ }
147
+ expect(countSessions()).toBeLessThanOrEqual(100);
148
+ });
149
+ });
150
+ describe('reports dir', () => {
151
+ it('getReportsDir creates the directory if missing', () => {
152
+ rmSync(reportsDir, { recursive: true, force: true });
153
+ expect(getReportsDir()).toBe(reportsDir);
154
+ // The act of calling should have ensured the dir
155
+ expect(readFileSync.length).toBeGreaterThan(0); // sanity: fs is available
156
+ });
157
+ });
158
+ describe('generateSessionId', () => {
159
+ it('returns a UUID-shaped string', () => {
160
+ const id = generateSessionId();
161
+ expect(id).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/);
162
+ });
163
+ it('generates unique IDs', () => {
164
+ const a = generateSessionId();
165
+ const b = generateSessionId();
166
+ expect(a).not.toBe(b);
167
+ });
168
+ });
169
+ //# sourceMappingURL=store.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.test.js","sourceRoot":"","sources":["../../src/__tests__/store.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export declare const EXIT_CODES: {
2
+ readonly SUCCESS: 0;
3
+ readonly RUNTIME_ERROR: 1;
4
+ readonly CONFIGURATION_ERROR: 2;
5
+ readonly CHECK_NOT_FOUND: 3;
6
+ readonly REPORT_FAILED: 4;
7
+ };
8
+ export interface ErrorSuggestion {
9
+ message: string;
10
+ action?: string;
11
+ exitCode: number;
12
+ }
13
+ export declare function getErrorSuggestion(err: unknown): ErrorSuggestion | null;
14
+ //# sourceMappingURL=exit-codes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exit-codes.d.ts","sourceRoot":"","sources":["../src/exit-codes.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU;;;;;;CAMb,CAAC;AAEX,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,eAAe,GAAG,IAAI,CA2DvE"}
@@ -0,0 +1,61 @@
1
+ export const EXIT_CODES = {
2
+ SUCCESS: 0,
3
+ RUNTIME_ERROR: 1,
4
+ CONFIGURATION_ERROR: 2,
5
+ CHECK_NOT_FOUND: 3,
6
+ REPORT_FAILED: 4,
7
+ };
8
+ export function getErrorSuggestion(err) {
9
+ const message = err instanceof Error ? err.message : String(err);
10
+ // Check not found
11
+ if (message.includes('Check not found:') || message.includes('not found')) {
12
+ const slug = (/Check not found: (.+)/.exec(message))?.[1] ?? (/not found: (.+)/.exec(message))?.[1];
13
+ return {
14
+ message: `Check '${slug ?? 'unknown'}' not found.`,
15
+ action: 'Run opensip-tools fit --list to see available checks.',
16
+ exitCode: EXIT_CODES.CHECK_NOT_FOUND,
17
+ };
18
+ }
19
+ // Recipe not found
20
+ if (message.includes('Unknown recipe')) {
21
+ return {
22
+ message: message,
23
+ action: 'Run opensip-tools fit --recipes to see available recipes.',
24
+ exitCode: EXIT_CODES.CONFIGURATION_ERROR,
25
+ };
26
+ }
27
+ // Config file error
28
+ if (message.includes('opensip-tools.config.yml') || message.includes('YAML') || message.includes('config')) {
29
+ return {
30
+ message: 'Configuration error.',
31
+ action: 'Check opensip-tools.config.yml for syntax errors.',
32
+ exitCode: EXIT_CODES.CONFIGURATION_ERROR,
33
+ };
34
+ }
35
+ // Permission denied
36
+ if (message.includes('EACCES') || message.includes('permission denied')) {
37
+ return {
38
+ message: 'Permission denied reading files.',
39
+ action: 'Check file permissions in the target directory.',
40
+ exitCode: EXIT_CODES.RUNTIME_ERROR,
41
+ };
42
+ }
43
+ // No files found
44
+ if (message.includes('No checks registered') || message.includes('No checks to run')) {
45
+ return {
46
+ message: 'No checks available to run.',
47
+ action: 'Install at least one @opensip-tools/checks-* package, or declare plugins.checkPackages in opensip-tools.config.yml.',
48
+ exitCode: EXIT_CODES.RUNTIME_ERROR,
49
+ };
50
+ }
51
+ // Network error (report-to)
52
+ if (message.includes('fetch') || message.includes('ECONNREFUSED') || message.includes('network')) {
53
+ return {
54
+ message: 'Network error sending report.',
55
+ action: 'Check the --report-to URL and your network connection.',
56
+ exitCode: EXIT_CODES.REPORT_FAILED,
57
+ };
58
+ }
59
+ return null;
60
+ }
61
+ //# sourceMappingURL=exit-codes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exit-codes.js","sourceRoot":"","sources":["../src/exit-codes.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,OAAO,EAAE,CAAC;IACV,aAAa,EAAE,CAAC;IAChB,mBAAmB,EAAE,CAAC;IACtB,eAAe,EAAE,CAAC;IAClB,aAAa,EAAE,CAAC;CACR,CAAC;AAQX,MAAM,UAAU,kBAAkB,CAAC,GAAY;IAC7C,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAEjE,kBAAkB;IAClB,IAAI,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QAC1E,MAAM,IAAI,GAAG,CAAC,uBAAuB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACpG,OAAO;YACL,OAAO,EAAE,UAAU,IAAI,IAAI,SAAS,cAAc;YAClD,MAAM,EAAE,uDAAuD;YAC/D,QAAQ,EAAE,UAAU,CAAC,eAAe;SACrC,CAAC;IACJ,CAAC;IAED,mBAAmB;IACnB,IAAI,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACvC,OAAO;YACL,OAAO,EAAE,OAAO;YAChB,MAAM,EAAE,2DAA2D;YACnE,QAAQ,EAAE,UAAU,CAAC,mBAAmB;SACzC,CAAC;IACJ,CAAC;IAED,oBAAoB;IACpB,IAAI,OAAO,CAAC,QAAQ,CAAC,0BAA0B,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3G,OAAO;YACL,OAAO,EAAE,sBAAsB;YAC/B,MAAM,EAAE,mDAAmD;YAC3D,QAAQ,EAAE,UAAU,CAAC,mBAAmB;SACzC,CAAC;IACJ,CAAC;IAED,oBAAoB;IACpB,IAAI,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;QACxE,OAAO;YACL,OAAO,EAAE,kCAAkC;YAC3C,MAAM,EAAE,iDAAiD;YACzD,QAAQ,EAAE,UAAU,CAAC,aAAa;SACnC,CAAC;IACJ,CAAC;IAED,iBAAiB;IACjB,IAAI,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;QACrF,OAAO;YACL,OAAO,EAAE,6BAA6B;YACtC,MAAM,EAAE,qHAAqH;YAC7H,QAAQ,EAAE,UAAU,CAAC,aAAa;SACnC,CAAC;IACJ,CAAC;IAED,4BAA4B;IAC5B,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACjG,OAAO;YACL,OAAO,EAAE,+BAA+B;YACxC,MAAM,EAAE,wDAAwD;YAChE,QAAQ,EAAE,UAAU,CAAC,aAAa;SACnC,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @opensip-tools/contracts — shared contract types.
3
+ *
4
+ * Tool packages (fitness, simulation) and the CLI entry-point both
5
+ * depend on this package for:
6
+ * - CLI option / output / result types
7
+ * - Exit code constants and error suggestions
8
+ * - Session persistence (saveSession, loadSessions, dashboard generator)
9
+ *
10
+ * contracts depends only on @opensip-tools/core. Tools depend on
11
+ * contracts. The CLI entry-point depends on contracts and on every
12
+ * tool package — the dependency graph stays acyclic.
13
+ */
14
+ export type { CliArgs, FitOptions, InitOptions, ToolOptions, } from './types.js';
15
+ export type { CliOutput, CheckOutput, FindingOutput, TableRow, SummaryOptions, CommandResult, ClearDoneResult, FitDoneResult, SimDoneResult, ListChecksResult, ListRecipesResult, HistoryResult, DashboardResult, InitResult, ExperimentalResult, PluginResult, HelpResult, ErrorResult, } from './types.js';
16
+ export { EXIT_CODES, getErrorSuggestion } from './exit-codes.js';
17
+ export type { ErrorSuggestion } from './exit-codes.js';
18
+ export { TOOLS_HOME, configurePersistencePaths, saveSession, loadSessions, loadLatestSession, countSessions, clearAllSessions, clearSessionsOlderThan, getStoreDir, getReportsDir, generateSessionId, sanitizeForFilename, } from './persistence/store.js';
19
+ export type { StoredSession, CheckCatalogEntry, RecipeCatalogEntry, } from './persistence/store.js';
20
+ export { generateDashboardHtml } from './persistence/dashboard/index.js';
21
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,YAAY,EACV,OAAO,EACP,UAAU,EACV,WAAW,EACX,WAAW,GACZ,MAAM,YAAY,CAAC;AAGpB,YAAY,EACV,SAAS,EACT,WAAW,EACX,aAAa,EACb,QAAQ,EACR,cAAc,EACd,aAAa,EACb,eAAe,EACf,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,UAAU,EACV,kBAAkB,EAClB,YAAY,EACZ,UAAU,EACV,WAAW,GACZ,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACjE,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGvD,OAAO,EACL,UAAU,EACV,yBAAyB,EACzB,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,sBAAsB,EACtB,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @opensip-tools/contracts — shared contract types.
3
+ *
4
+ * Tool packages (fitness, simulation) and the CLI entry-point both
5
+ * depend on this package for:
6
+ * - CLI option / output / result types
7
+ * - Exit code constants and error suggestions
8
+ * - Session persistence (saveSession, loadSessions, dashboard generator)
9
+ *
10
+ * contracts depends only on @opensip-tools/core. Tools depend on
11
+ * contracts. The CLI entry-point depends on contracts and on every
12
+ * tool package — the dependency graph stays acyclic.
13
+ */
14
+ // Exit codes + error suggestion helper
15
+ export { EXIT_CODES, getErrorSuggestion } from './exit-codes.js';
16
+ // Session persistence
17
+ export { TOOLS_HOME, configurePersistencePaths, saveSession, loadSessions, loadLatestSession, countSessions, clearAllSessions, clearSessionsOlderThan, getStoreDir, getReportsDir, generateSessionId, sanitizeForFilename, } from './persistence/store.js';
18
+ // Dashboard HTML generator
19
+ export { generateDashboardHtml } from './persistence/dashboard/index.js';
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAgCH,uCAAuC;AACvC,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAGjE,sBAAsB;AACtB,OAAO,EACL,UAAU,EACV,yBAAyB,EACzB,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,sBAAsB,EACtB,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,wBAAwB,CAAC;AAOhC,2BAA2B;AAC3B,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Checks catalog rendering — browsable catalog of checks with run stats.
3
+ * Reusable: renderChecksCatalog(container, catalogData) can be called from any panel.
4
+ * Returns JS code as a string.
5
+ */
6
+ export declare function dashboardChecksJs(): string;
7
+ //# sourceMappingURL=checks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../../../src/persistence/dashboard/checks.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,wBAAgB,iBAAiB,IAAI,MAAM,CAgR1C"}