@hartvig/developer-control-center 0.8.2

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 (193) hide show
  1. package/.developer-control-center/metrics.json +1 -0
  2. package/.developer-control-center/status.json +1 -0
  3. package/.developer-control-center/timings.jsonl +3 -0
  4. package/.github/workflows/ci.yml +47 -0
  5. package/AGENTS.md +51 -0
  6. package/PLUGINS.md +145 -0
  7. package/README.md +147 -0
  8. package/developer-control-center.config.example.js +91 -0
  9. package/developer-control-center.config.js +177 -0
  10. package/dist/cli.d.ts +3 -0
  11. package/dist/cli.d.ts.map +1 -0
  12. package/dist/cli.js +223 -0
  13. package/dist/cli.js.map +1 -0
  14. package/dist/config/index.d.ts +3 -0
  15. package/dist/config/index.d.ts.map +1 -0
  16. package/dist/config/index.js +2 -0
  17. package/dist/config/index.js.map +1 -0
  18. package/dist/config/loader.d.ts +4 -0
  19. package/dist/config/loader.d.ts.map +1 -0
  20. package/dist/config/loader.js +96 -0
  21. package/dist/config/loader.js.map +1 -0
  22. package/dist/config/loader.test.d.ts +2 -0
  23. package/dist/config/loader.test.d.ts.map +1 -0
  24. package/dist/config/loader.test.js +25 -0
  25. package/dist/config/loader.test.js.map +1 -0
  26. package/dist/config/presets/node.d.ts +10 -0
  27. package/dist/config/presets/node.d.ts.map +1 -0
  28. package/dist/config/presets/node.js +31 -0
  29. package/dist/config/presets/node.js.map +1 -0
  30. package/dist/config/presets/react.d.ts +10 -0
  31. package/dist/config/presets/react.d.ts.map +1 -0
  32. package/dist/config/presets/react.js +36 -0
  33. package/dist/config/presets/react.js.map +1 -0
  34. package/dist/config/types.d.ts +55 -0
  35. package/dist/config/types.d.ts.map +1 -0
  36. package/dist/config/types.js +2 -0
  37. package/dist/config/types.js.map +1 -0
  38. package/dist/config/types.test.d.ts +2 -0
  39. package/dist/config/types.test.d.ts.map +1 -0
  40. package/dist/config/types.test.js +23 -0
  41. package/dist/config/types.test.js.map +1 -0
  42. package/dist/core/ci.d.ts +6 -0
  43. package/dist/core/ci.d.ts.map +1 -0
  44. package/dist/core/ci.js +22 -0
  45. package/dist/core/ci.js.map +1 -0
  46. package/dist/core/ci.test.d.ts +2 -0
  47. package/dist/core/ci.test.d.ts.map +1 -0
  48. package/dist/core/ci.test.js +45 -0
  49. package/dist/core/ci.test.js.map +1 -0
  50. package/dist/core/event-bus.d.ts +18 -0
  51. package/dist/core/event-bus.d.ts.map +1 -0
  52. package/dist/core/event-bus.js +19 -0
  53. package/dist/core/event-bus.js.map +1 -0
  54. package/dist/core/event-bus.test.d.ts +2 -0
  55. package/dist/core/event-bus.test.d.ts.map +1 -0
  56. package/dist/core/event-bus.test.js +49 -0
  57. package/dist/core/event-bus.test.js.map +1 -0
  58. package/dist/core/index.d.ts +9 -0
  59. package/dist/core/index.d.ts.map +1 -0
  60. package/dist/core/index.js +7 -0
  61. package/dist/core/index.js.map +1 -0
  62. package/dist/core/notifier.d.ts +2 -0
  63. package/dist/core/notifier.d.ts.map +1 -0
  64. package/dist/core/notifier.js +28 -0
  65. package/dist/core/notifier.js.map +1 -0
  66. package/dist/core/notifier.test.d.ts +2 -0
  67. package/dist/core/notifier.test.d.ts.map +1 -0
  68. package/dist/core/notifier.test.js +25 -0
  69. package/dist/core/notifier.test.js.map +1 -0
  70. package/dist/core/runtime.d.ts +25 -0
  71. package/dist/core/runtime.d.ts.map +1 -0
  72. package/dist/core/runtime.js +85 -0
  73. package/dist/core/runtime.js.map +1 -0
  74. package/dist/core/task-runner.d.ts +26 -0
  75. package/dist/core/task-runner.d.ts.map +1 -0
  76. package/dist/core/task-runner.js +354 -0
  77. package/dist/core/task-runner.js.map +1 -0
  78. package/dist/core/timer-plugin.d.ts +3 -0
  79. package/dist/core/timer-plugin.d.ts.map +1 -0
  80. package/dist/core/timer-plugin.js +34 -0
  81. package/dist/core/timer-plugin.js.map +1 -0
  82. package/dist/core/workspaces.d.ts +6 -0
  83. package/dist/core/workspaces.d.ts.map +1 -0
  84. package/dist/core/workspaces.js +60 -0
  85. package/dist/core/workspaces.js.map +1 -0
  86. package/dist/core/workspaces.test.d.ts +2 -0
  87. package/dist/core/workspaces.test.d.ts.map +1 -0
  88. package/dist/core/workspaces.test.js +62 -0
  89. package/dist/core/workspaces.test.js.map +1 -0
  90. package/dist/index.d.ts +16 -0
  91. package/dist/index.d.ts.map +1 -0
  92. package/dist/index.js +11 -0
  93. package/dist/index.js.map +1 -0
  94. package/dist/plugins/index.d.ts +3 -0
  95. package/dist/plugins/index.d.ts.map +1 -0
  96. package/dist/plugins/index.js +2 -0
  97. package/dist/plugins/index.js.map +1 -0
  98. package/dist/plugins/manager.d.ts +13 -0
  99. package/dist/plugins/manager.d.ts.map +1 -0
  100. package/dist/plugins/manager.js +43 -0
  101. package/dist/plugins/manager.js.map +1 -0
  102. package/dist/plugins/manager.test.d.ts +2 -0
  103. package/dist/plugins/manager.test.d.ts.map +1 -0
  104. package/dist/plugins/manager.test.js +79 -0
  105. package/dist/plugins/manager.test.js.map +1 -0
  106. package/dist/plugins/types.d.ts +17 -0
  107. package/dist/plugins/types.d.ts.map +1 -0
  108. package/dist/plugins/types.js +2 -0
  109. package/dist/plugins/types.js.map +1 -0
  110. package/dist/status/index.d.ts +3 -0
  111. package/dist/status/index.d.ts.map +1 -0
  112. package/dist/status/index.js +2 -0
  113. package/dist/status/index.js.map +1 -0
  114. package/dist/status/store.d.ts +18 -0
  115. package/dist/status/store.d.ts.map +1 -0
  116. package/dist/status/store.js +76 -0
  117. package/dist/status/store.js.map +1 -0
  118. package/dist/status/store.test.d.ts +2 -0
  119. package/dist/status/store.test.d.ts.map +1 -0
  120. package/dist/status/store.test.js +107 -0
  121. package/dist/status/store.test.js.map +1 -0
  122. package/dist/status/types.d.ts +12 -0
  123. package/dist/status/types.d.ts.map +1 -0
  124. package/dist/status/types.js +2 -0
  125. package/dist/status/types.js.map +1 -0
  126. package/dist/ui/app.d.ts +10 -0
  127. package/dist/ui/app.d.ts.map +1 -0
  128. package/dist/ui/app.js +479 -0
  129. package/dist/ui/app.js.map +1 -0
  130. package/dist/ui/command-list.d.ts +30 -0
  131. package/dist/ui/command-list.d.ts.map +1 -0
  132. package/dist/ui/command-list.js +45 -0
  133. package/dist/ui/command-list.js.map +1 -0
  134. package/dist/ui/index.d.ts +4 -0
  135. package/dist/ui/index.d.ts.map +1 -0
  136. package/dist/ui/index.js +8 -0
  137. package/dist/ui/index.js.map +1 -0
  138. package/dist/ui/metrics-panel.d.ts +10 -0
  139. package/dist/ui/metrics-panel.d.ts.map +1 -0
  140. package/dist/ui/metrics-panel.js +139 -0
  141. package/dist/ui/metrics-panel.js.map +1 -0
  142. package/dist/ui/panel.d.ts +16 -0
  143. package/dist/ui/panel.d.ts.map +1 -0
  144. package/dist/ui/panel.js +16 -0
  145. package/dist/ui/panel.js.map +1 -0
  146. package/dist/ui/status-panel.d.ts +16 -0
  147. package/dist/ui/status-panel.d.ts.map +1 -0
  148. package/dist/ui/status-panel.js +52 -0
  149. package/dist/ui/status-panel.js.map +1 -0
  150. package/docs/architecture.md +29 -0
  151. package/docs/config.md +15 -0
  152. package/docs/mvp.md +17 -0
  153. package/docs/phases.md +49 -0
  154. package/docs/technical-decisions.md +19 -0
  155. package/docs/ui.md +14 -0
  156. package/package.json +30 -0
  157. package/src/cli.ts +242 -0
  158. package/src/config/index.ts +2 -0
  159. package/src/config/loader.test.ts +30 -0
  160. package/src/config/loader.ts +123 -0
  161. package/src/config/presets/node.ts +30 -0
  162. package/src/config/presets/react.ts +35 -0
  163. package/src/config/types.test.ts +24 -0
  164. package/src/config/types.ts +52 -0
  165. package/src/core/ci.test.ts +54 -0
  166. package/src/core/ci.ts +26 -0
  167. package/src/core/event-bus.test.ts +56 -0
  168. package/src/core/event-bus.ts +34 -0
  169. package/src/core/index.ts +8 -0
  170. package/src/core/notifier.test.ts +30 -0
  171. package/src/core/notifier.ts +34 -0
  172. package/src/core/runtime.ts +99 -0
  173. package/src/core/task-runner.ts +408 -0
  174. package/src/core/timer-plugin.ts +34 -0
  175. package/src/core/workspaces.test.ts +72 -0
  176. package/src/core/workspaces.ts +73 -0
  177. package/src/index.ts +15 -0
  178. package/src/plugins/index.ts +2 -0
  179. package/src/plugins/manager.test.ts +92 -0
  180. package/src/plugins/manager.ts +54 -0
  181. package/src/plugins/types.ts +18 -0
  182. package/src/status/index.ts +2 -0
  183. package/src/status/store.test.ts +122 -0
  184. package/src/status/store.ts +88 -0
  185. package/src/status/types.ts +12 -0
  186. package/src/ui/app.tsx +606 -0
  187. package/src/ui/command-list.tsx +163 -0
  188. package/src/ui/index.tsx +10 -0
  189. package/src/ui/metrics-panel.tsx +234 -0
  190. package/src/ui/panel.tsx +76 -0
  191. package/src/ui/status-panel.tsx +160 -0
  192. package/tsconfig.json +21 -0
  193. package/vitest.config.ts +8 -0
@@ -0,0 +1,13 @@
1
+ import { Plugin, PluginHooks } from './types.js';
2
+ type HookName = keyof PluginHooks;
3
+ export declare class PluginManager {
4
+ private plugins;
5
+ register(plugin: Plugin): void;
6
+ get(id: string): Plugin | undefined;
7
+ getAll(): Plugin[];
8
+ remove(id: string): boolean;
9
+ executeHook<K extends HookName>(hook: K, ...args: Parameters<NonNullable<PluginHooks[K]>>): Promise<void>;
10
+ loadFromConfig(pluginNames?: string[]): Promise<void>;
11
+ }
12
+ export {};
13
+ //# sourceMappingURL=manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/plugins/manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEjD,KAAK,QAAQ,GAAG,MAAM,WAAW,CAAC;AAElC,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAA6B;IAE5C,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI9B,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAInC,MAAM,IAAI,MAAM,EAAE;IAIlB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAIrB,WAAW,CAAC,CAAC,SAAS,QAAQ,EAClC,IAAI,EAAE,CAAC,EACP,GAAG,IAAI,EAAE,UAAU,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,GAC/C,OAAO,CAAC,IAAI,CAAC;IAeV,cAAc,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAY5D"}
@@ -0,0 +1,43 @@
1
+ export class PluginManager {
2
+ plugins = new Map();
3
+ register(plugin) {
4
+ this.plugins.set(plugin.id, plugin);
5
+ }
6
+ get(id) {
7
+ return this.plugins.get(id);
8
+ }
9
+ getAll() {
10
+ return Array.from(this.plugins.values());
11
+ }
12
+ remove(id) {
13
+ return this.plugins.delete(id);
14
+ }
15
+ async executeHook(hook, ...args) {
16
+ for (const plugin of this.plugins.values()) {
17
+ const fn = plugin.hooks?.[hook];
18
+ if (fn) {
19
+ try {
20
+ await Promise.resolve(fn(...args));
21
+ }
22
+ catch (e) {
23
+ console.error(`Plugin ${plugin.id} ${hook} error:`, e);
24
+ }
25
+ }
26
+ }
27
+ }
28
+ async loadFromConfig(pluginNames) {
29
+ if (!pluginNames?.length)
30
+ return;
31
+ for (const name of pluginNames) {
32
+ try {
33
+ const mod = await import(name);
34
+ const p = mod.default || mod;
35
+ this.register(p);
36
+ }
37
+ catch (e) {
38
+ console.error(`Failed to load plugin "${name}":`, e);
39
+ }
40
+ }
41
+ }
42
+ }
43
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/plugins/manager.ts"],"names":[],"mappings":"AAIA,MAAM,OAAO,aAAa;IAChB,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAE5C,QAAQ,CAAC,MAAc;QACrB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IACtC,CAAC;IAED,GAAG,CAAC,EAAU;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC9B,CAAC;IAED,MAAM;QACJ,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,CAAC,EAAU;QACf,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,WAAW,CACf,IAAO,EACP,GAAG,IAA6C;QAEhD,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YAC3C,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC,IAAI,CAEjB,CAAC;YACd,IAAI,EAAE,EAAE,CAAC;gBACP,IAAI,CAAC;oBACH,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;gBACrC,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,OAAO,CAAC,KAAK,CAAC,UAAU,MAAM,CAAC,EAAE,IAAI,IAAI,SAAS,EAAE,CAAC,CAAC,CAAC;gBACzD,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,WAAsB;QACzC,IAAI,CAAC,WAAW,EAAE,MAAM;YAAE,OAAO;QACjC,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;YAC/B,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;gBAC/B,MAAM,CAAC,GAAW,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC;gBACrC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YACnB,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,OAAO,CAAC,KAAK,CAAC,0BAA0B,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC;YACvD,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=manager.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.test.d.ts","sourceRoot":"","sources":["../../src/plugins/manager.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,79 @@
1
+ import { describe, it, expect, beforeEach, vi } from 'vitest';
2
+ import { PluginManager } from './manager.js';
3
+ describe('PluginManager', () => {
4
+ let pm;
5
+ beforeEach(() => {
6
+ pm = new PluginManager();
7
+ });
8
+ it('registers and retrieves a plugin', () => {
9
+ pm.register({ id: 'p1', name: 'Plugin 1' });
10
+ expect(pm.get('p1')?.name).toBe('Plugin 1');
11
+ });
12
+ it('returns all plugins', () => {
13
+ pm.register({ id: 'a', name: 'A' });
14
+ pm.register({ id: 'b', name: 'B' });
15
+ expect(pm.getAll().length).toBe(2);
16
+ });
17
+ it('removes a plugin', () => {
18
+ pm.register({ id: 'x', name: 'X' });
19
+ expect(pm.remove('x')).toBe(true);
20
+ expect(pm.get('x')).toBeUndefined();
21
+ });
22
+ it('returns false when removing nonexistent plugin', () => {
23
+ expect(pm.remove('nope')).toBe(false);
24
+ });
25
+ it('executes a hook on all registered plugins', async () => {
26
+ const calls = [];
27
+ pm.register({
28
+ id: 'a',
29
+ name: 'A',
30
+ hooks: { beforeRun: () => { calls.push('a-before'); } },
31
+ });
32
+ pm.register({
33
+ id: 'b',
34
+ name: 'B',
35
+ hooks: { beforeRun: () => { calls.push('b-before'); } },
36
+ });
37
+ await pm.executeHook('beforeRun', { id: 'test', label: 'T', command: 't' });
38
+ expect(calls).toEqual(['a-before', 'b-before']);
39
+ });
40
+ it('handles async hooks', async () => {
41
+ const order = [];
42
+ pm.register({
43
+ id: 'slow',
44
+ name: 'Slow',
45
+ hooks: {
46
+ beforeRun: async () => {
47
+ await new Promise((r) => setTimeout(r, 10));
48
+ order.push(1);
49
+ },
50
+ },
51
+ });
52
+ pm.register({
53
+ id: 'fast',
54
+ name: 'Fast',
55
+ hooks: { beforeRun: () => { order.push(2); } },
56
+ });
57
+ await pm.executeHook('beforeRun', { id: 'x', label: 'X', command: 'x' });
58
+ expect(order).toEqual([1, 2]);
59
+ });
60
+ it('does not throw when a hook fails', async () => {
61
+ vi.spyOn(console, 'error').mockImplementation(() => { });
62
+ pm.register({
63
+ id: 'bad',
64
+ name: 'Bad',
65
+ hooks: { beforeRun: () => { throw new Error('fail'); } },
66
+ });
67
+ await expect(pm.executeHook('beforeRun', { id: 'x', label: 'X', command: 'x' })).resolves.toBeUndefined();
68
+ });
69
+ it('skips plugin with no hooks for the requested hook', async () => {
70
+ pm.register({ id: 'none', name: 'None' });
71
+ await pm.executeHook('beforeRun', { id: 'x', label: 'X', command: 'x' });
72
+ });
73
+ it('loads nothing when pluginNames is empty', async () => {
74
+ await pm.loadFromConfig();
75
+ await pm.loadFromConfig([]);
76
+ expect(pm.getAll().length).toBe(0);
77
+ });
78
+ });
79
+ //# sourceMappingURL=manager.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.test.js","sourceRoot":"","sources":["../../src/plugins/manager.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { ProkomCommand } from '../config/types.js';
2
+ export interface PluginHooks {
3
+ beforeRun?: (command: ProkomCommand) => void | Promise<void>;
4
+ afterRun?: (command: ProkomCommand, result: {
5
+ exitCode?: number;
6
+ status: string;
7
+ }) => void | Promise<void>;
8
+ onOutput?: (commandId: string, text: string) => void | Promise<void>;
9
+ onError?: (commandId: string, error: Error) => void | Promise<void>;
10
+ }
11
+ export interface Plugin {
12
+ id: string;
13
+ name: string;
14
+ version?: string;
15
+ hooks?: PluginHooks;
16
+ }
17
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/plugins/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,MAAM,WAAW,WAAW;IAC1B,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D,QAAQ,CAAC,EAAE,CACT,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAC1C,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrE,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACrE;AAED,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/plugins/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ export { StatusStore } from './store.js';
2
+ export type { TaskState, TaskStatus } from './types.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/status/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { StatusStore } from './store.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/status/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { TaskState } from './types.js';
2
+ type Listener = (tasks: ReadonlyMap<string, TaskState>) => void;
3
+ export declare class StatusStore {
4
+ private tasks;
5
+ private listeners;
6
+ getTask(id: string): TaskState | undefined;
7
+ getAllTasks(): ReadonlyMap<string, TaskState>;
8
+ updateTask(id: string, update: Partial<TaskState>): void;
9
+ clear(): void;
10
+ removeTask(id: string): void;
11
+ pruneCompleted(): void;
12
+ subscribe(listener: Listener): () => void;
13
+ saveDir(dir: string): void;
14
+ loadDir(dir: string): void;
15
+ private notify;
16
+ }
17
+ export {};
18
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/status/store.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,KAAK,QAAQ,GAAG,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,KAAK,IAAI,CAAC;AAEhE,qBAAa,WAAW;IACtB,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,SAAS,CAAuB;IAExC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAI1C,WAAW,IAAI,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC;IAI7C,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,IAAI;IAUxD,KAAK,IAAI,IAAI;IAKb,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAK5B,cAAc,IAAI,IAAI;IAWtB,SAAS,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,IAAI;IAKzC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAO1B,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAqB1B,OAAO,CAAC,MAAM;CAKf"}
@@ -0,0 +1,76 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ export class StatusStore {
4
+ tasks = new Map();
5
+ listeners = new Set();
6
+ getTask(id) {
7
+ return this.tasks.get(id);
8
+ }
9
+ getAllTasks() {
10
+ return new Map(this.tasks);
11
+ }
12
+ updateTask(id, update) {
13
+ const existing = this.tasks.get(id) ?? {
14
+ id,
15
+ label: id,
16
+ status: 'idle',
17
+ };
18
+ this.tasks.set(id, { ...existing, ...update });
19
+ this.notify();
20
+ }
21
+ clear() {
22
+ this.tasks.clear();
23
+ this.notify();
24
+ }
25
+ removeTask(id) {
26
+ this.tasks.delete(id);
27
+ this.notify();
28
+ }
29
+ pruneCompleted() {
30
+ let changed = false;
31
+ for (const [id, task] of this.tasks) {
32
+ if (task.status !== 'running') {
33
+ this.tasks.delete(id);
34
+ changed = true;
35
+ }
36
+ }
37
+ if (changed)
38
+ this.notify();
39
+ }
40
+ subscribe(listener) {
41
+ this.listeners.add(listener);
42
+ return () => this.listeners.delete(listener);
43
+ }
44
+ saveDir(dir) {
45
+ const filePath = path.join(dir, 'status.json');
46
+ const data = JSON.stringify(Array.from(this.tasks.entries()));
47
+ fs.mkdirSync(dir, { recursive: true });
48
+ fs.writeFileSync(filePath, data, 'utf-8');
49
+ }
50
+ loadDir(dir) {
51
+ const filePath = path.join(dir, 'status.json');
52
+ if (fs.existsSync(filePath)) {
53
+ const raw = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
54
+ const tasks = new Map(raw);
55
+ let changed = false;
56
+ for (const [id] of tasks) {
57
+ const task = tasks.get(id);
58
+ if (task.status === 'running') {
59
+ tasks.set(id, { ...task, status: 'failure', endTime: Date.now() });
60
+ changed = true;
61
+ }
62
+ }
63
+ if (changed) {
64
+ fs.writeFileSync(filePath, JSON.stringify(Array.from(tasks.entries())), 'utf-8');
65
+ }
66
+ this.tasks = tasks;
67
+ this.notify();
68
+ }
69
+ }
70
+ notify() {
71
+ for (const listener of this.listeners) {
72
+ listener(new Map(this.tasks));
73
+ }
74
+ }
75
+ }
76
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/status/store.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/status/store.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,107 @@
1
+ import { describe, it, expect, beforeEach } from 'vitest';
2
+ import fs from 'fs';
3
+ import { StatusStore } from './store.js';
4
+ describe('StatusStore', () => {
5
+ let store;
6
+ beforeEach(() => {
7
+ store = new StatusStore();
8
+ });
9
+ it('starts empty', () => {
10
+ expect(store.getAllTasks().size).toBe(0);
11
+ });
12
+ it('stores and retrieves a task', () => {
13
+ store.updateTask('build', {
14
+ id: 'build',
15
+ label: 'Build',
16
+ status: 'running',
17
+ output: '',
18
+ });
19
+ const task = store.getTask('build');
20
+ expect(task?.label).toBe('Build');
21
+ expect(task?.status).toBe('running');
22
+ });
23
+ it('updates an existing task', () => {
24
+ store.updateTask('build', {
25
+ id: 'build',
26
+ label: 'Build',
27
+ status: 'running',
28
+ output: 'start',
29
+ });
30
+ store.updateTask('build', { output: 'start\nprogress' });
31
+ expect(store.getTask('build')?.output).toBe('start\nprogress');
32
+ });
33
+ it('clears all tasks', () => {
34
+ store.updateTask('a', { id: 'a', label: 'A', status: 'running' });
35
+ store.updateTask('b', { id: 'b', label: 'B', status: 'success' });
36
+ expect(store.getAllTasks().size).toBe(2);
37
+ store.clear();
38
+ expect(store.getAllTasks().size).toBe(0);
39
+ });
40
+ it('prunes completed tasks but keeps running ones', () => {
41
+ store.updateTask('running-task', { id: 'running-task', label: 'Running', status: 'running' });
42
+ store.updateTask('done-task', { id: 'done-task', label: 'Done', status: 'success' });
43
+ store.updateTask('failed-task', { id: 'failed-task', label: 'Failed', status: 'failure' });
44
+ expect(store.getAllTasks().size).toBe(3);
45
+ store.pruneCompleted();
46
+ expect(store.getAllTasks().size).toBe(1);
47
+ expect(store.getTask('running-task')).toBeDefined();
48
+ expect(store.getTask('done-task')).toBeUndefined();
49
+ expect(store.getTask('failed-task')).toBeUndefined();
50
+ });
51
+ it('pruneCompleted removes nothing when all tasks are running', () => {
52
+ store.updateTask('a', { id: 'a', label: 'A', status: 'running' });
53
+ store.updateTask('b', { id: 'b', label: 'B', status: 'running' });
54
+ store.pruneCompleted();
55
+ expect(store.getAllTasks().size).toBe(2);
56
+ });
57
+ it('notifies subscribers on update', () => {
58
+ const updates = [];
59
+ store.subscribe((tasks) => updates.push(tasks.size));
60
+ store.updateTask('x', { id: 'x', label: 'X', status: 'running' });
61
+ expect(updates).toEqual([1]);
62
+ });
63
+ it('unsubscribes correctly', () => {
64
+ const updates = [];
65
+ const unsub = store.subscribe((tasks) => updates.push(tasks.size));
66
+ unsub();
67
+ store.updateTask('x', { id: 'x', label: 'X', status: 'running' });
68
+ expect(updates).toEqual([]);
69
+ });
70
+ it('persists and loads from directory', () => {
71
+ const dir = '/tmp/dcc-test-store';
72
+ fs.mkdirSync(dir, { recursive: true });
73
+ store.updateTask('persist', {
74
+ id: 'persist',
75
+ label: 'Persist',
76
+ status: 'success',
77
+ exitCode: 0,
78
+ });
79
+ store.saveDir(dir);
80
+ const store2 = new StatusStore();
81
+ store2.loadDir(dir);
82
+ const task = store2.getTask('persist');
83
+ expect(task?.label).toBe('Persist');
84
+ expect(task?.status).toBe('success');
85
+ fs.rmSync(dir, { recursive: true, force: true });
86
+ });
87
+ it('resets stale running tasks to failure on load', () => {
88
+ const dir = '/tmp/dcc-test-stale-store';
89
+ fs.mkdirSync(dir, { recursive: true });
90
+ const store = new StatusStore();
91
+ store.updateTask('stale-run', {
92
+ id: 'stale-run',
93
+ label: 'Stale Run',
94
+ status: 'running',
95
+ startTime: Date.now(),
96
+ });
97
+ store.saveDir(dir);
98
+ const store2 = new StatusStore();
99
+ store2.loadDir(dir);
100
+ const task = store2.getTask('stale-run');
101
+ expect(task?.status).toBe('failure');
102
+ expect(task?.label).toBe('Stale Run');
103
+ expect(typeof task?.endTime).toBe('number');
104
+ fs.rmSync(dir, { recursive: true, force: true });
105
+ });
106
+ });
107
+ //# sourceMappingURL=store.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.test.js","sourceRoot":"","sources":["../../src/status/store.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export type TaskStatus = 'idle' | 'running' | 'success' | 'failure';
2
+ export interface TaskState {
3
+ id: string;
4
+ label: string;
5
+ status: TaskStatus;
6
+ output?: string;
7
+ exitCode?: number;
8
+ startTime?: number;
9
+ endTime?: number;
10
+ watchMode?: boolean;
11
+ }
12
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/status/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAEpE,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/status/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { Runtime } from '../core/index.js';
3
+ import { ProkomConfig } from '../config/index.js';
4
+ interface AppProps {
5
+ config: ProkomConfig;
6
+ runtime: Runtime;
7
+ }
8
+ export declare const App: React.FC<AppProps>;
9
+ export {};
10
+ //# sourceMappingURL=app.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/ui/app.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;AAEjF,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAgC,MAAM,oBAAoB,CAAC;AAOhF,UAAU,QAAQ;IAChB,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;CAClB;AAsCD,eAAO,MAAM,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC,QAAQ,CA0iBlC,CAAC"}