@sonde/packs 0.0.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 (153) hide show
  1. package/dist/docker/index.d.ts +3 -0
  2. package/dist/docker/index.d.ts.map +1 -0
  3. package/dist/docker/index.js +15 -0
  4. package/dist/docker/index.js.map +1 -0
  5. package/dist/docker/manifest.d.ts +3 -0
  6. package/dist/docker/manifest.d.ts.map +1 -0
  7. package/dist/docker/manifest.js +54 -0
  8. package/dist/docker/manifest.js.map +1 -0
  9. package/dist/docker/probes/containers-list.d.ts +19 -0
  10. package/dist/docker/probes/containers-list.d.ts.map +1 -0
  11. package/dist/docker/probes/containers-list.js +25 -0
  12. package/dist/docker/probes/containers-list.js.map +1 -0
  13. package/dist/docker/probes/containers-list.test.d.ts +2 -0
  14. package/dist/docker/probes/containers-list.test.d.ts.map +1 -0
  15. package/dist/docker/probes/containers-list.test.js +43 -0
  16. package/dist/docker/probes/containers-list.test.js.map +1 -0
  17. package/dist/docker/probes/daemon-info.d.ts +16 -0
  18. package/dist/docker/probes/daemon-info.d.ts.map +1 -0
  19. package/dist/docker/probes/daemon-info.js +20 -0
  20. package/dist/docker/probes/daemon-info.js.map +1 -0
  21. package/dist/docker/probes/daemon-info.test.d.ts +2 -0
  22. package/dist/docker/probes/daemon-info.test.d.ts.map +1 -0
  23. package/dist/docker/probes/daemon-info.test.js +42 -0
  24. package/dist/docker/probes/daemon-info.test.js.map +1 -0
  25. package/dist/docker/probes/images-list.d.ts +17 -0
  26. package/dist/docker/probes/images-list.d.ts.map +1 -0
  27. package/dist/docker/probes/images-list.js +23 -0
  28. package/dist/docker/probes/images-list.js.map +1 -0
  29. package/dist/docker/probes/images-list.test.d.ts +2 -0
  30. package/dist/docker/probes/images-list.test.d.ts.map +1 -0
  31. package/dist/docker/probes/images-list.test.js +41 -0
  32. package/dist/docker/probes/images-list.test.js.map +1 -0
  33. package/dist/docker/probes/logs-tail.d.ts +12 -0
  34. package/dist/docker/probes/logs-tail.d.ts.map +1 -0
  35. package/dist/docker/probes/logs-tail.js +22 -0
  36. package/dist/docker/probes/logs-tail.js.map +1 -0
  37. package/dist/docker/probes/logs-tail.test.d.ts +2 -0
  38. package/dist/docker/probes/logs-tail.test.d.ts.map +1 -0
  39. package/dist/docker/probes/logs-tail.test.js +42 -0
  40. package/dist/docker/probes/logs-tail.test.js.map +1 -0
  41. package/dist/index.d.ts +9 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +15 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/system/index.d.ts +3 -0
  46. package/dist/system/index.d.ts.map +1 -0
  47. package/dist/system/index.js +13 -0
  48. package/dist/system/index.js.map +1 -0
  49. package/dist/system/manifest.d.ts +3 -0
  50. package/dist/system/manifest.d.ts.map +1 -0
  51. package/dist/system/manifest.js +39 -0
  52. package/dist/system/manifest.js.map +1 -0
  53. package/dist/system/probes/cpu-usage.d.ts +14 -0
  54. package/dist/system/probes/cpu-usage.d.ts.map +1 -0
  55. package/dist/system/probes/cpu-usage.js +20 -0
  56. package/dist/system/probes/cpu-usage.js.map +1 -0
  57. package/dist/system/probes/cpu-usage.test.d.ts +2 -0
  58. package/dist/system/probes/cpu-usage.test.d.ts.map +1 -0
  59. package/dist/system/probes/cpu-usage.test.js +45 -0
  60. package/dist/system/probes/cpu-usage.test.js.map +1 -0
  61. package/dist/system/probes/disk-usage.d.ts +19 -0
  62. package/dist/system/probes/disk-usage.d.ts.map +1 -0
  63. package/dist/system/probes/disk-usage.js +34 -0
  64. package/dist/system/probes/disk-usage.js.map +1 -0
  65. package/dist/system/probes/disk-usage.test.d.ts +2 -0
  66. package/dist/system/probes/disk-usage.test.d.ts.map +1 -0
  67. package/dist/system/probes/disk-usage.test.js +62 -0
  68. package/dist/system/probes/disk-usage.test.js.map +1 -0
  69. package/dist/system/probes/memory-usage.d.ts +19 -0
  70. package/dist/system/probes/memory-usage.d.ts.map +1 -0
  71. package/dist/system/probes/memory-usage.js +46 -0
  72. package/dist/system/probes/memory-usage.js.map +1 -0
  73. package/dist/system/probes/memory-usage.test.d.ts +2 -0
  74. package/dist/system/probes/memory-usage.test.d.ts.map +1 -0
  75. package/dist/system/probes/memory-usage.test.js +50 -0
  76. package/dist/system/probes/memory-usage.test.js.map +1 -0
  77. package/dist/systemd/index.d.ts +3 -0
  78. package/dist/systemd/index.d.ts.map +1 -0
  79. package/dist/systemd/index.js +13 -0
  80. package/dist/systemd/index.js.map +1 -0
  81. package/dist/systemd/manifest.d.ts +3 -0
  82. package/dist/systemd/manifest.d.ts.map +1 -0
  83. package/dist/systemd/manifest.js +51 -0
  84. package/dist/systemd/manifest.js.map +1 -0
  85. package/dist/systemd/probes/journal-query.d.ts +19 -0
  86. package/dist/systemd/probes/journal-query.d.ts.map +1 -0
  87. package/dist/systemd/probes/journal-query.js +37 -0
  88. package/dist/systemd/probes/journal-query.js.map +1 -0
  89. package/dist/systemd/probes/journal-query.test.d.ts +2 -0
  90. package/dist/systemd/probes/journal-query.test.d.ts.map +1 -0
  91. package/dist/systemd/probes/journal-query.test.js +50 -0
  92. package/dist/systemd/probes/journal-query.test.js.map +1 -0
  93. package/dist/systemd/probes/service-status.d.ts +16 -0
  94. package/dist/systemd/probes/service-status.d.ts.map +1 -0
  95. package/dist/systemd/probes/service-status.js +29 -0
  96. package/dist/systemd/probes/service-status.js.map +1 -0
  97. package/dist/systemd/probes/service-status.test.d.ts +2 -0
  98. package/dist/systemd/probes/service-status.test.d.ts.map +1 -0
  99. package/dist/systemd/probes/service-status.test.js +48 -0
  100. package/dist/systemd/probes/service-status.test.js.map +1 -0
  101. package/dist/systemd/probes/services-list.d.ts +18 -0
  102. package/dist/systemd/probes/services-list.d.ts.map +1 -0
  103. package/dist/systemd/probes/services-list.js +29 -0
  104. package/dist/systemd/probes/services-list.js.map +1 -0
  105. package/dist/systemd/probes/services-list.test.d.ts +2 -0
  106. package/dist/systemd/probes/services-list.test.d.ts.map +1 -0
  107. package/dist/systemd/probes/services-list.test.js +61 -0
  108. package/dist/systemd/probes/services-list.test.js.map +1 -0
  109. package/dist/types.d.ts +11 -0
  110. package/dist/types.d.ts.map +1 -0
  111. package/dist/types.js +2 -0
  112. package/dist/types.js.map +1 -0
  113. package/dist/validation.d.ts +16 -0
  114. package/dist/validation.d.ts.map +1 -0
  115. package/dist/validation.js +44 -0
  116. package/dist/validation.js.map +1 -0
  117. package/dist/validation.test.d.ts +2 -0
  118. package/dist/validation.test.d.ts.map +1 -0
  119. package/dist/validation.test.js +76 -0
  120. package/dist/validation.test.js.map +1 -0
  121. package/package.json +26 -0
  122. package/src/docker/index.ts +16 -0
  123. package/src/docker/manifest.ts +55 -0
  124. package/src/docker/probes/containers-list.test.ts +50 -0
  125. package/src/docker/probes/containers-list.ts +42 -0
  126. package/src/docker/probes/daemon-info.test.ts +48 -0
  127. package/src/docker/probes/daemon-info.ts +33 -0
  128. package/src/docker/probes/images-list.test.ts +48 -0
  129. package/src/docker/probes/images-list.ts +39 -0
  130. package/src/docker/probes/logs-tail.test.ts +51 -0
  131. package/src/docker/probes/logs-tail.ts +32 -0
  132. package/src/index.ts +18 -0
  133. package/src/system/index.ts +14 -0
  134. package/src/system/manifest.ts +40 -0
  135. package/src/system/probes/cpu-usage.test.ts +55 -0
  136. package/src/system/probes/cpu-usage.ts +30 -0
  137. package/src/system/probes/disk-usage.test.ts +73 -0
  138. package/src/system/probes/disk-usage.ts +53 -0
  139. package/src/system/probes/memory-usage.test.ts +58 -0
  140. package/src/system/probes/memory-usage.ts +63 -0
  141. package/src/systemd/index.ts +14 -0
  142. package/src/systemd/manifest.ts +52 -0
  143. package/src/systemd/probes/journal-query.test.ts +64 -0
  144. package/src/systemd/probes/journal-query.ts +56 -0
  145. package/src/systemd/probes/service-status.test.ts +59 -0
  146. package/src/systemd/probes/service-status.ts +42 -0
  147. package/src/systemd/probes/services-list.test.ts +68 -0
  148. package/src/systemd/probes/services-list.ts +45 -0
  149. package/src/types.ts +16 -0
  150. package/src/validation.test.ts +86 -0
  151. package/src/validation.ts +52 -0
  152. package/tsconfig.json +11 -0
  153. package/vitest.config.ts +8 -0
@@ -0,0 +1,50 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { journalQuery, parseJournalQuery } from './journal-query.js';
3
+ const SAMPLE_OUTPUT = `{"__REALTIME_TIMESTAMP":"1705312200000000","PRIORITY":"6","MESSAGE":"Starting nginx...","_PID":"1234","_UID":"0","_SYSTEMD_UNIT":"nginx.service"}
4
+ {"__REALTIME_TIMESTAMP":"1705312201000000","PRIORITY":"6","MESSAGE":"Started nginx.","_PID":"1234","_UID":"0","_SYSTEMD_UNIT":"nginx.service"}
5
+ {"__REALTIME_TIMESTAMP":"1705312205000000","PRIORITY":"4","MESSAGE":"worker process exited on signal 15","_PID":"1235","_UID":"33","_SYSTEMD_UNIT":"nginx.service"}`;
6
+ describe('parseJournalQuery', () => {
7
+ it('parses journalctl JSON output into structured data', () => {
8
+ const result = parseJournalQuery('nginx.service', SAMPLE_OUTPUT);
9
+ expect(result.unit).toBe('nginx.service');
10
+ expect(result.entries).toHaveLength(3);
11
+ expect(result.entryCount).toBe(3);
12
+ expect(result.entries[0]).toEqual({
13
+ timestamp: '1705312200000000',
14
+ priority: 6,
15
+ message: 'Starting nginx...',
16
+ pid: '1234',
17
+ uid: '0',
18
+ });
19
+ expect(result.entries[2]?.priority).toBe(4);
20
+ expect(result.entries[2]?.message).toBe('worker process exited on signal 15');
21
+ });
22
+ it('handles empty output', () => {
23
+ const result = parseJournalQuery('nginx.service', '');
24
+ expect(result.entries).toHaveLength(0);
25
+ expect(result.entryCount).toBe(0);
26
+ });
27
+ });
28
+ describe('journalQuery handler', () => {
29
+ it('calls journalctl with default lines and returns parsed result', async () => {
30
+ const mockExec = async (cmd, args) => {
31
+ expect(cmd).toBe('journalctl');
32
+ expect(args).toEqual(['-u', 'nginx.service', '-n', '50', '--no-pager', '-o', 'json']);
33
+ return SAMPLE_OUTPUT;
34
+ };
35
+ const result = (await journalQuery({ unit: 'nginx.service' }, mockExec));
36
+ expect(result.unit).toBe('nginx.service');
37
+ expect(result.entryCount).toBe(3);
38
+ });
39
+ it('uses custom lines param', async () => {
40
+ const mockExec = async (cmd, args) => {
41
+ expect(cmd).toBe('journalctl');
42
+ expect(args).toEqual(['-u', 'sshd.service', '-n', '20', '--no-pager', '-o', 'json']);
43
+ return '{}';
44
+ };
45
+ // Single-line JSON object, not an array — parses as one entry
46
+ const result = (await journalQuery({ unit: 'sshd.service', lines: 20 }, mockExec));
47
+ expect(result.unit).toBe('sshd.service');
48
+ });
49
+ });
50
+ //# sourceMappingURL=journal-query.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"journal-query.test.js","sourceRoot":"","sources":["../../../src/systemd/probes/journal-query.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { ProbeHandler } from '../../types.js';
2
+ export interface ServiceStatusResult {
3
+ name: string;
4
+ loadState: string;
5
+ activeState: string;
6
+ subState: string;
7
+ mainPid: number;
8
+ memoryBytes: number;
9
+ restartCount: number;
10
+ }
11
+ /**
12
+ * Runs `systemctl show <service> --no-pager` and parses key=value output.
13
+ */
14
+ export declare const serviceStatus: ProbeHandler;
15
+ export declare function parseServiceStatus(stdout: string): ServiceStatusResult;
16
+ //# sourceMappingURL=service-status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-status.d.ts","sourceRoot":"","sources":["../../../src/systemd/probes/service-status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,YAI3B,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAoBtE"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Runs `systemctl show <service> --no-pager` and parses key=value output.
3
+ */
4
+ export const serviceStatus = async (params, exec) => {
5
+ const service = params?.service;
6
+ const stdout = await exec('systemctl', ['show', service, '--no-pager']);
7
+ return parseServiceStatus(stdout);
8
+ };
9
+ export function parseServiceStatus(stdout) {
10
+ const props = new Map();
11
+ for (const line of stdout.trim().split('\n')) {
12
+ const idx = line.indexOf('=');
13
+ if (idx === -1)
14
+ continue;
15
+ const key = line.slice(0, idx);
16
+ const value = line.slice(idx + 1);
17
+ props.set(key, value);
18
+ }
19
+ return {
20
+ name: props.get('Id') ?? '',
21
+ loadState: props.get('LoadState') ?? '',
22
+ activeState: props.get('ActiveState') ?? '',
23
+ subState: props.get('SubState') ?? '',
24
+ mainPid: Number(props.get('MainPID') ?? '0'),
25
+ memoryBytes: Number(props.get('MemoryCurrent') ?? '0'),
26
+ restartCount: Number(props.get('NRestarts') ?? '0'),
27
+ };
28
+ }
29
+ //# sourceMappingURL=service-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-status.js","sourceRoot":"","sources":["../../../src/systemd/probes/service-status.ts"],"names":[],"mappings":"AAYA;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAiB,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;IAChE,MAAM,OAAO,GAAG,MAAM,EAAE,OAAiB,CAAC;IAC1C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC;IACxE,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC;AACpC,CAAC,CAAC;AAEF,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAC/C,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IAExC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,GAAG,KAAK,CAAC,CAAC;YAAE,SAAS;QACzB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;QAClC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACxB,CAAC;IAED,OAAO;QACL,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE;QAC3B,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE;QACvC,WAAW,EAAE,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,EAAE;QAC3C,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE;QACrC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC;QAC5C,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,GAAG,CAAC;QACtD,YAAY,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,GAAG,CAAC;KACpD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=service-status.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-status.test.d.ts","sourceRoot":"","sources":["../../../src/systemd/probes/service-status.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,48 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { parseServiceStatus, serviceStatus } from './service-status.js';
3
+ const SAMPLE_OUTPUT = `Type=notify
4
+ Restart=on-failure
5
+ Id=nginx.service
6
+ LoadState=loaded
7
+ ActiveState=active
8
+ SubState=running
9
+ MainPID=1234
10
+ MemoryCurrent=52428800
11
+ NRestarts=2
12
+ ExecMainStartTimestamp=Mon 2024-01-15 10:30:00 UTC`;
13
+ describe('parseServiceStatus', () => {
14
+ it('parses systemctl show output into structured data', () => {
15
+ const result = parseServiceStatus(SAMPLE_OUTPUT);
16
+ expect(result).toEqual({
17
+ name: 'nginx.service',
18
+ loadState: 'loaded',
19
+ activeState: 'active',
20
+ subState: 'running',
21
+ mainPid: 1234,
22
+ memoryBytes: 52428800,
23
+ restartCount: 2,
24
+ });
25
+ });
26
+ it('handles missing fields with defaults', () => {
27
+ const result = parseServiceStatus('Id=unknown.service\nLoadState=not-found');
28
+ expect(result.name).toBe('unknown.service');
29
+ expect(result.loadState).toBe('not-found');
30
+ expect(result.activeState).toBe('');
31
+ expect(result.mainPid).toBe(0);
32
+ expect(result.memoryBytes).toBe(0);
33
+ expect(result.restartCount).toBe(0);
34
+ });
35
+ });
36
+ describe('serviceStatus handler', () => {
37
+ it('calls systemctl show with correct args and returns parsed result', async () => {
38
+ const mockExec = async (cmd, args) => {
39
+ expect(cmd).toBe('systemctl');
40
+ expect(args).toEqual(['show', 'nginx.service', '--no-pager']);
41
+ return SAMPLE_OUTPUT;
42
+ };
43
+ const result = (await serviceStatus({ service: 'nginx.service' }, mockExec));
44
+ expect(result.name).toBe('nginx.service');
45
+ expect(result.mainPid).toBe(1234);
46
+ });
47
+ });
48
+ //# sourceMappingURL=service-status.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-status.test.js","sourceRoot":"","sources":["../../../src/systemd/probes/service-status.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAG9C,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAExE,MAAM,aAAa,GAAG;;;;;;;;;mDAS6B,CAAC;AAEpD,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,MAAM,GAAG,kBAAkB,CAAC,aAAa,CAAC,CAAC;QAEjD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACrB,IAAI,EAAE,eAAe;YACrB,SAAS,EAAE,QAAQ;YACnB,WAAW,EAAE,QAAQ;YACrB,QAAQ,EAAE,SAAS;YACnB,OAAO,EAAE,IAAI;YACb,WAAW,EAAE,QAAQ;YACrB,YAAY,EAAE,CAAC;SAChB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,MAAM,GAAG,kBAAkB,CAAC,yCAAyC,CAAC,CAAC;QAE7E,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACpC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACnC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,QAAQ,GAAW,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;YAC3C,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,eAAe,EAAE,YAAY,CAAC,CAAC,CAAC;YAC9D,OAAO,aAAa,CAAC;QACvB,CAAC,CAAC;QAEF,MAAM,MAAM,GAAG,CAAC,MAAM,aAAa,CACjC,EAAE,OAAO,EAAE,eAAe,EAAE,EAC5B,QAAQ,CACT,CAAwB,CAAC;QAC1B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { ProbeHandler } from '../../types.js';
2
+ export interface ServiceInfo {
3
+ unit: string;
4
+ load: string;
5
+ active: string;
6
+ sub: string;
7
+ description: string;
8
+ }
9
+ export interface ServicesListResult {
10
+ services: ServiceInfo[];
11
+ }
12
+ /**
13
+ * Runs `systemctl list-units --type=service --all --no-pager --output=json`
14
+ * and parses the JSON output.
15
+ */
16
+ export declare const servicesList: ProbeHandler;
17
+ export declare function parseServicesList(stdout: string): ServicesListResult;
18
+ //# sourceMappingURL=services-list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"services-list.d.ts","sourceRoot":"","sources":["../../../src/systemd/probes/services-list.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,WAAW,EAAE,CAAC;CACzB;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,YAS1B,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,kBAAkB,CAepE"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Runs `systemctl list-units --type=service --all --no-pager --output=json`
3
+ * and parses the JSON output.
4
+ */
5
+ export const servicesList = async (_params, exec) => {
6
+ const stdout = await exec('systemctl', [
7
+ 'list-units',
8
+ '--type=service',
9
+ '--all',
10
+ '--no-pager',
11
+ '--output=json',
12
+ ]);
13
+ return parseServicesList(stdout);
14
+ };
15
+ export function parseServicesList(stdout) {
16
+ const raw = JSON.parse(stdout);
17
+ const services = [];
18
+ for (const entry of raw) {
19
+ services.push({
20
+ unit: entry.unit ?? '',
21
+ load: entry.load ?? '',
22
+ active: entry.active ?? '',
23
+ sub: entry.sub ?? '',
24
+ description: entry.description ?? '',
25
+ });
26
+ }
27
+ return { services };
28
+ }
29
+ //# sourceMappingURL=services-list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"services-list.js","sourceRoot":"","sources":["../../../src/systemd/probes/services-list.ts"],"names":[],"mappings":"AAcA;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAiB,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;IAChE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE;QACrC,YAAY;QACZ,gBAAgB;QAChB,OAAO;QACP,YAAY;QACZ,eAAe;KAChB,CAAC,CAAC;IACH,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAC;AACnC,CAAC,CAAC;AAEF,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/B,MAAM,QAAQ,GAAkB,EAAE,CAAC;IAEnC,KAAK,MAAM,KAAK,IAAI,GAAG,EAAE,CAAC;QACxB,QAAQ,CAAC,IAAI,CAAC;YACZ,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE;YACtB,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE;YACtB,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,EAAE;YAC1B,GAAG,EAAE,KAAK,CAAC,GAAG,IAAI,EAAE;YACpB,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,EAAE;SACrC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,CAAC;AACtB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=services-list.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"services-list.test.d.ts","sourceRoot":"","sources":["../../../src/systemd/probes/services-list.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,61 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { parseServicesList, servicesList } from './services-list.js';
3
+ const SAMPLE_OUTPUT = JSON.stringify([
4
+ {
5
+ unit: 'nginx.service',
6
+ load: 'loaded',
7
+ active: 'active',
8
+ sub: 'running',
9
+ description: 'A high performance web server',
10
+ },
11
+ {
12
+ unit: 'postgresql.service',
13
+ load: 'loaded',
14
+ active: 'inactive',
15
+ sub: 'dead',
16
+ description: 'PostgreSQL RDBMS',
17
+ },
18
+ ]);
19
+ describe('parseServicesList', () => {
20
+ it('parses systemctl JSON output into structured data', () => {
21
+ const result = parseServicesList(SAMPLE_OUTPUT);
22
+ expect(result.services).toHaveLength(2);
23
+ expect(result.services[0]).toEqual({
24
+ unit: 'nginx.service',
25
+ load: 'loaded',
26
+ active: 'active',
27
+ sub: 'running',
28
+ description: 'A high performance web server',
29
+ });
30
+ expect(result.services[1]).toEqual({
31
+ unit: 'postgresql.service',
32
+ load: 'loaded',
33
+ active: 'inactive',
34
+ sub: 'dead',
35
+ description: 'PostgreSQL RDBMS',
36
+ });
37
+ });
38
+ it('handles empty array', () => {
39
+ const result = parseServicesList('[]');
40
+ expect(result.services).toHaveLength(0);
41
+ });
42
+ });
43
+ describe('servicesList handler', () => {
44
+ it('calls systemctl with correct args and returns parsed result', async () => {
45
+ const mockExec = async (cmd, args) => {
46
+ expect(cmd).toBe('systemctl');
47
+ expect(args).toEqual([
48
+ 'list-units',
49
+ '--type=service',
50
+ '--all',
51
+ '--no-pager',
52
+ '--output=json',
53
+ ]);
54
+ return SAMPLE_OUTPUT;
55
+ };
56
+ const result = (await servicesList(undefined, mockExec));
57
+ expect(result.services).toHaveLength(2);
58
+ expect(result.services[0]?.unit).toBe('nginx.service');
59
+ });
60
+ });
61
+ //# sourceMappingURL=services-list.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"services-list.test.js","sourceRoot":"","sources":["../../../src/systemd/probes/services-list.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAG9C,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAErE,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC;IACnC;QACE,IAAI,EAAE,eAAe;QACrB,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,QAAQ;QAChB,GAAG,EAAE,SAAS;QACd,WAAW,EAAE,+BAA+B;KAC7C;IACD;QACE,IAAI,EAAE,oBAAoB;QAC1B,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,UAAU;QAClB,GAAG,EAAE,MAAM;QACX,WAAW,EAAE,kBAAkB;KAChC;CACF,CAAC,CAAC;AAEH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,MAAM,GAAG,iBAAiB,CAAC,aAAa,CAAC,CAAC;QAEhD,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YACjC,IAAI,EAAE,eAAe;YACrB,IAAI,EAAE,QAAQ;YACd,MAAM,EAAE,QAAQ;YAChB,GAAG,EAAE,SAAS;YACd,WAAW,EAAE,+BAA+B;SAC7C,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YACjC,IAAI,EAAE,oBAAoB;YAC1B,IAAI,EAAE,QAAQ;YACd,MAAM,EAAE,UAAU;YAClB,GAAG,EAAE,MAAM;YACX,WAAW,EAAE,kBAAkB;SAChC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;QACvC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;QAC3E,MAAM,QAAQ,GAAW,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;YAC3C,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC;gBACnB,YAAY;gBACZ,gBAAgB;gBAChB,OAAO;gBACP,YAAY;gBACZ,eAAe;aAChB,CAAC,CAAC;YACH,OAAO,aAAa,CAAC;QACvB,CAAC,CAAC;QAEF,MAAM,MAAM,GAAG,CAAC,MAAM,YAAY,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAuB,CAAC;QAC/E,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { PackManifest } from '@sonde/shared';
2
+ /** Function that executes a command and returns stdout */
3
+ export type ExecFn = (command: string, args: string[]) => Promise<string>;
4
+ /** Probe handler: takes params + exec helper, returns structured data */
5
+ export type ProbeHandler = (params: Record<string, unknown> | undefined, exec: ExecFn) => Promise<unknown>;
6
+ /** A loaded pack with its manifest and probe handlers */
7
+ export interface Pack {
8
+ manifest: PackManifest;
9
+ handlers: Record<string, ProbeHandler>;
10
+ }
11
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,0DAA0D;AAC1D,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAE1E,yEAAyE;AACzE,MAAM,MAAM,YAAY,GAAG,CACzB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC3C,IAAI,EAAE,MAAM,KACT,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB,yDAAyD;AACzD,MAAM,WAAW,IAAI;IACnB,QAAQ,EAAE,YAAY,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CACxC"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,16 @@
1
+ import type { Pack } from './types.js';
2
+ export declare class PackValidationError extends Error {
3
+ constructor(message: string);
4
+ }
5
+ /**
6
+ * Validates that a pack's handlers match its manifest probes exactly.
7
+ * - Every probe in manifest must have a handler keyed as `{packName}.{probeName}`
8
+ * - No extra handlers may exist beyond what the manifest declares
9
+ */
10
+ export declare function validatePack(pack: Pack): void;
11
+ /**
12
+ * Validates all packs and builds a frozen registry map.
13
+ * Throws on duplicate pack names or invalid packs.
14
+ */
15
+ export declare function createPackRegistry(packs: Pack[]): ReadonlyMap<string, Pack>;
16
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;CAI5B;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAkB7C;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,CAa3E"}
@@ -0,0 +1,44 @@
1
+ export class PackValidationError extends Error {
2
+ constructor(message) {
3
+ super(message);
4
+ this.name = 'PackValidationError';
5
+ }
6
+ }
7
+ /**
8
+ * Validates that a pack's handlers match its manifest probes exactly.
9
+ * - Every probe in manifest must have a handler keyed as `{packName}.{probeName}`
10
+ * - No extra handlers may exist beyond what the manifest declares
11
+ */
12
+ export function validatePack(pack) {
13
+ const packName = pack.manifest.name;
14
+ const expectedKeys = new Set(pack.manifest.probes.map((p) => `${packName}.${p.name}`));
15
+ const actualKeys = new Set(Object.keys(pack.handlers));
16
+ // Check for missing handlers
17
+ for (const key of expectedKeys) {
18
+ if (!actualKeys.has(key)) {
19
+ throw new PackValidationError(`Pack "${packName}": missing handler for probe "${key}"`);
20
+ }
21
+ }
22
+ // Check for extra handlers
23
+ for (const key of actualKeys) {
24
+ if (!expectedKeys.has(key)) {
25
+ throw new PackValidationError(`Pack "${packName}": extra handler "${key}" not in manifest`);
26
+ }
27
+ }
28
+ }
29
+ /**
30
+ * Validates all packs and builds a frozen registry map.
31
+ * Throws on duplicate pack names or invalid packs.
32
+ */
33
+ export function createPackRegistry(packs) {
34
+ const registry = new Map();
35
+ for (const pack of packs) {
36
+ validatePack(pack);
37
+ if (registry.has(pack.manifest.name)) {
38
+ throw new PackValidationError(`Duplicate pack name: "${pack.manifest.name}"`);
39
+ }
40
+ registry.set(pack.manifest.name, pack);
41
+ }
42
+ return registry;
43
+ }
44
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,IAAU;IACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;IACpC,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACvF,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEvD,6BAA6B;IAC7B,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;QAC/B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,mBAAmB,CAAC,SAAS,QAAQ,iCAAiC,GAAG,GAAG,CAAC,CAAC;QAC1F,CAAC;IACH,CAAC;IAED,2BAA2B;IAC3B,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,mBAAmB,CAAC,SAAS,QAAQ,qBAAqB,GAAG,mBAAmB,CAAC,CAAC;QAC9F,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAC9C,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAgB,CAAC;IAEzC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,YAAY,CAAC,IAAI,CAAC,CAAC;QAEnB,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACrC,MAAM,IAAI,mBAAmB,CAAC,yBAAyB,IAAI,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,CAAC;QAChF,CAAC;QACD,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=validation.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.test.d.ts","sourceRoot":"","sources":["../src/validation.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,76 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { PackValidationError, createPackRegistry, validatePack } from './validation.js';
3
+ function makePack(overrides) {
4
+ return {
5
+ manifest: {
6
+ name: 'test',
7
+ version: '0.1.0',
8
+ description: 'Test pack',
9
+ requires: { groups: [], files: [], commands: [] },
10
+ probes: [
11
+ { name: 'foo', description: 'Foo probe', capability: 'observe', timeout: 10_000 },
12
+ { name: 'bar', description: 'Bar probe', capability: 'observe', timeout: 10_000 },
13
+ ],
14
+ },
15
+ handlers: {
16
+ 'test.foo': async () => ({}),
17
+ 'test.bar': async () => ({}),
18
+ },
19
+ ...overrides,
20
+ };
21
+ }
22
+ describe('validatePack', () => {
23
+ it('passes for a valid pack', () => {
24
+ expect(() => validatePack(makePack())).not.toThrow();
25
+ });
26
+ it('throws on missing handler', () => {
27
+ const pack = makePack({
28
+ handlers: {
29
+ 'test.foo': async () => ({}),
30
+ // missing test.bar
31
+ },
32
+ });
33
+ expect(() => validatePack(pack)).toThrow(PackValidationError);
34
+ expect(() => validatePack(pack)).toThrow('missing handler for probe "test.bar"');
35
+ });
36
+ it('throws on extra handler', () => {
37
+ const pack = makePack({
38
+ handlers: {
39
+ 'test.foo': async () => ({}),
40
+ 'test.bar': async () => ({}),
41
+ 'test.baz': async () => ({}),
42
+ },
43
+ });
44
+ expect(() => validatePack(pack)).toThrow(PackValidationError);
45
+ expect(() => validatePack(pack)).toThrow('extra handler "test.baz" not in manifest');
46
+ });
47
+ });
48
+ describe('createPackRegistry', () => {
49
+ it('returns a map of validated packs', () => {
50
+ const pack = makePack();
51
+ const registry = createPackRegistry([pack]);
52
+ expect(registry.size).toBe(1);
53
+ expect(registry.get('test')).toBe(pack);
54
+ });
55
+ it('throws on duplicate pack names', () => {
56
+ const pack1 = makePack();
57
+ const pack2 = makePack();
58
+ expect(() => createPackRegistry([pack1, pack2])).toThrow(PackValidationError);
59
+ expect(() => createPackRegistry([pack1, pack2])).toThrow('Duplicate pack name: "test"');
60
+ });
61
+ it('throws if any pack is invalid', () => {
62
+ const validPack = makePack();
63
+ const invalidPack = makePack({
64
+ manifest: {
65
+ name: 'broken',
66
+ version: '0.1.0',
67
+ description: 'Broken pack',
68
+ requires: { groups: [], files: [], commands: [] },
69
+ probes: [{ name: 'x', description: 'X', capability: 'observe', timeout: 10_000 }],
70
+ },
71
+ handlers: {}, // missing handler
72
+ });
73
+ expect(() => createPackRegistry([validPack, invalidPack])).toThrow(PackValidationError);
74
+ });
75
+ });
76
+ //# sourceMappingURL=validation.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.test.js","sourceRoot":"","sources":["../src/validation.test.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "@sonde/packs",
3
+ "version": "0.0.0",
4
+ "private": false,
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "dev": "tsc --watch",
17
+ "test": "vitest run",
18
+ "typecheck": "tsc --noEmit"
19
+ },
20
+ "dependencies": {
21
+ "@sonde/shared": "*"
22
+ },
23
+ "devDependencies": {
24
+ "vitest": "^2.1.8"
25
+ }
26
+ }
@@ -0,0 +1,16 @@
1
+ import type { Pack } from '../types.js';
2
+ import { dockerManifest } from './manifest.js';
3
+ import { containersList } from './probes/containers-list.js';
4
+ import { daemonInfo } from './probes/daemon-info.js';
5
+ import { imagesList } from './probes/images-list.js';
6
+ import { logsTail } from './probes/logs-tail.js';
7
+
8
+ export const dockerPack: Pack = {
9
+ manifest: dockerManifest,
10
+ handlers: {
11
+ 'docker.containers.list': containersList,
12
+ 'docker.logs.tail': logsTail,
13
+ 'docker.images.list': imagesList,
14
+ 'docker.daemon.info': daemonInfo,
15
+ },
16
+ };
@@ -0,0 +1,55 @@
1
+ import type { PackManifest } from '@sonde/shared';
2
+
3
+ export const dockerManifest: PackManifest = {
4
+ name: 'docker',
5
+ version: '0.1.0',
6
+ description: 'Docker container and image management probes',
7
+ requires: {
8
+ groups: [],
9
+ files: [],
10
+ commands: ['docker'],
11
+ },
12
+ probes: [
13
+ {
14
+ name: 'containers.list',
15
+ description: 'List all Docker containers with status',
16
+ capability: 'observe',
17
+ timeout: 10_000,
18
+ },
19
+ {
20
+ name: 'logs.tail',
21
+ description: 'Tail recent logs from a container',
22
+ capability: 'observe',
23
+ params: {
24
+ container: { type: 'string', description: 'Container name or ID', required: true },
25
+ lines: {
26
+ type: 'number',
27
+ description: 'Number of lines to tail',
28
+ required: false,
29
+ default: 100,
30
+ },
31
+ },
32
+ timeout: 15_000,
33
+ },
34
+ {
35
+ name: 'images.list',
36
+ description: 'List all Docker images',
37
+ capability: 'observe',
38
+ timeout: 10_000,
39
+ },
40
+ {
41
+ name: 'daemon.info',
42
+ description: 'Docker daemon information and resource summary',
43
+ capability: 'observe',
44
+ timeout: 10_000,
45
+ },
46
+ ],
47
+ runbook: {
48
+ category: 'docker',
49
+ probes: ['containers.list', 'images.list', 'daemon.info'],
50
+ parallel: true,
51
+ },
52
+ detect: {
53
+ commands: ['docker'],
54
+ },
55
+ };