@zigrivers/scaffold 3.13.0 → 3.14.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 (73) hide show
  1. package/README.md +1 -1
  2. package/dist/cli/commands/adopt.d.ts.map +1 -1
  3. package/dist/cli/commands/adopt.js +8 -7
  4. package/dist/cli/commands/adopt.js.map +1 -1
  5. package/dist/cli/commands/adopt.serialization.test.js +8 -0
  6. package/dist/cli/commands/adopt.serialization.test.js.map +1 -1
  7. package/dist/cli/commands/adopt.test.js +8 -0
  8. package/dist/cli/commands/adopt.test.js.map +1 -1
  9. package/dist/cli/commands/build.d.ts.map +1 -1
  10. package/dist/cli/commands/build.js +191 -180
  11. package/dist/cli/commands/build.js.map +1 -1
  12. package/dist/cli/commands/complete.d.ts.map +1 -1
  13. package/dist/cli/commands/complete.js +16 -12
  14. package/dist/cli/commands/complete.js.map +1 -1
  15. package/dist/cli/commands/complete.test.js +14 -5
  16. package/dist/cli/commands/complete.test.js.map +1 -1
  17. package/dist/cli/commands/init.d.ts.map +1 -1
  18. package/dist/cli/commands/init.js +43 -49
  19. package/dist/cli/commands/init.js.map +1 -1
  20. package/dist/cli/commands/init.test.js +33 -27
  21. package/dist/cli/commands/init.test.js.map +1 -1
  22. package/dist/cli/commands/reset.d.ts.map +1 -1
  23. package/dist/cli/commands/reset.js +44 -40
  24. package/dist/cli/commands/reset.js.map +1 -1
  25. package/dist/cli/commands/reset.test.js +42 -20
  26. package/dist/cli/commands/reset.test.js.map +1 -1
  27. package/dist/cli/commands/rework.d.ts.map +1 -1
  28. package/dist/cli/commands/rework.js +16 -12
  29. package/dist/cli/commands/rework.js.map +1 -1
  30. package/dist/cli/commands/rework.test.js +12 -3
  31. package/dist/cli/commands/rework.test.js.map +1 -1
  32. package/dist/cli/commands/run.d.ts.map +1 -1
  33. package/dist/cli/commands/run.js +318 -298
  34. package/dist/cli/commands/run.js.map +1 -1
  35. package/dist/cli/commands/run.test.js +92 -120
  36. package/dist/cli/commands/run.test.js.map +1 -1
  37. package/dist/cli/commands/skip.d.ts.map +1 -1
  38. package/dist/cli/commands/skip.js +19 -15
  39. package/dist/cli/commands/skip.js.map +1 -1
  40. package/dist/cli/commands/skip.test.js +22 -11
  41. package/dist/cli/commands/skip.test.js.map +1 -1
  42. package/dist/cli/commands/update.d.ts.map +1 -1
  43. package/dist/cli/commands/update.js +3 -1
  44. package/dist/cli/commands/update.js.map +1 -1
  45. package/dist/cli/commands/update.test.js +8 -4
  46. package/dist/cli/commands/update.test.js.map +1 -1
  47. package/dist/cli/commands/version.d.ts.map +1 -1
  48. package/dist/cli/commands/version.js +3 -1
  49. package/dist/cli/commands/version.js.map +1 -1
  50. package/dist/cli/commands/version.test.js +9 -5
  51. package/dist/cli/commands/version.test.js.map +1 -1
  52. package/dist/cli/index.d.ts.map +1 -1
  53. package/dist/cli/index.js +2 -0
  54. package/dist/cli/index.js.map +1 -1
  55. package/dist/cli/output/interactive.d.ts +1 -0
  56. package/dist/cli/output/interactive.d.ts.map +1 -1
  57. package/dist/cli/output/interactive.js +5 -0
  58. package/dist/cli/output/interactive.js.map +1 -1
  59. package/dist/cli/shutdown.d.ts +51 -0
  60. package/dist/cli/shutdown.d.ts.map +1 -0
  61. package/dist/cli/shutdown.js +199 -0
  62. package/dist/cli/shutdown.js.map +1 -0
  63. package/dist/cli/shutdown.test.d.ts +2 -0
  64. package/dist/cli/shutdown.test.d.ts.map +1 -0
  65. package/dist/cli/shutdown.test.js +316 -0
  66. package/dist/cli/shutdown.test.js.map +1 -0
  67. package/dist/e2e/init.test.js +5 -4
  68. package/dist/e2e/init.test.js.map +1 -1
  69. package/dist/state/lock-manager.d.ts +1 -0
  70. package/dist/state/lock-manager.d.ts.map +1 -1
  71. package/dist/state/lock-manager.js +1 -1
  72. package/dist/state/lock-manager.js.map +1 -1
  73. package/package.json +1 -1
@@ -0,0 +1,199 @@
1
+ import { AsyncLocalStorage } from 'node:async_hooks';
2
+ import { setMaxListeners } from 'node:events';
3
+ import * as fs from 'node:fs';
4
+ import { ExitCode } from '../types/enums.js';
5
+ export class ShutdownManager {
6
+ proc;
7
+ shuttingDown = false;
8
+ sigintState = 'idle';
9
+ triggeredBySigterm = false;
10
+ exitHandlerRan = false;
11
+ lockOwned = false;
12
+ lockPath = null;
13
+ registry = new Map();
14
+ controller;
15
+ contextStorage = new AsyncLocalStorage();
16
+ fallbackContext = 'Cancelled.';
17
+ constructor(proc) {
18
+ this.proc = proc ?? process;
19
+ this.controller = new AbortController();
20
+ setMaxListeners(0, this.controller.signal);
21
+ }
22
+ get isShuttingDown() {
23
+ return this.shuttingDown;
24
+ }
25
+ get signal() {
26
+ return this.controller.signal;
27
+ }
28
+ sigintHandler = () => {
29
+ if (!this.proc.stdout.isTTY) {
30
+ if (this.sigintState === 'idle') {
31
+ this.sigintState = 'cleaning';
32
+ this.shutdown(ExitCode.UserCancellation);
33
+ }
34
+ else {
35
+ this.proc.exit(ExitCode.UserCancellation);
36
+ }
37
+ return;
38
+ }
39
+ switch (this.sigintState) {
40
+ case 'idle':
41
+ this.sigintState = 'cleaning';
42
+ this.shutdown(ExitCode.UserCancellation);
43
+ break;
44
+ case 'cleaning':
45
+ this.proc.stderr.write('\nPress Ctrl+C again to force quit.\n');
46
+ this.sigintState = 'armed';
47
+ break;
48
+ case 'armed':
49
+ this.proc.stderr.write('\nForce quit.\n');
50
+ this.proc.exit(ExitCode.UserCancellation);
51
+ break;
52
+ }
53
+ };
54
+ sigtermHandler = () => {
55
+ this.triggeredBySigterm = true;
56
+ if (this.sigintState === 'idle') {
57
+ this.sigintState = 'cleaning';
58
+ this.shutdown(ExitCode.UserCancellation);
59
+ }
60
+ };
61
+ get currentContext() {
62
+ const ctx = this.contextStorage.getStore() ?? this.fallbackContext;
63
+ return typeof ctx === 'function' ? ctx() : ctx;
64
+ }
65
+ getTimeoutMs() {
66
+ const env = this.proc.env?.SCAFFOLD_SHUTDOWN_TIMEOUT_MS;
67
+ if (env) {
68
+ const n = Number(env);
69
+ if (!Number.isNaN(n) && n > 0)
70
+ return Math.max(500, Math.min(n, 10000));
71
+ }
72
+ return this.triggeredBySigterm ? 5000 : 2000;
73
+ }
74
+ install() {
75
+ this.proc.on('SIGINT', this.sigintHandler);
76
+ this.proc.on('SIGTERM', this.sigtermHandler);
77
+ this.installExitHandler();
78
+ }
79
+ installExitHandler() {
80
+ this.proc.on('exit', (() => {
81
+ if (this.exitHandlerRan)
82
+ return;
83
+ this.exitHandlerRan = true;
84
+ if (this.lockOwned && this.lockPath) {
85
+ try {
86
+ fs.unlinkSync(this.lockPath);
87
+ }
88
+ catch { /* ok */ }
89
+ }
90
+ if (this.proc.stderr?.writable) {
91
+ try {
92
+ this.proc.stderr.write('\x1b[?25h\n');
93
+ }
94
+ catch { /* ok */ }
95
+ }
96
+ }));
97
+ }
98
+ reset() {
99
+ this.shuttingDown = false;
100
+ this.sigintState = 'idle';
101
+ this.triggeredBySigterm = false;
102
+ this.exitHandlerRan = false;
103
+ this.lockOwned = false;
104
+ this.lockPath = null;
105
+ this.registry.clear();
106
+ this.controller = new AbortController();
107
+ setMaxListeners(0, this.controller.signal);
108
+ this.proc.removeListener('SIGINT', this.sigintHandler);
109
+ this.proc.removeListener('SIGTERM', this.sigtermHandler);
110
+ }
111
+ // Placeholder methods — implemented in subsequent tasks
112
+ register(name, cleanup, opts) {
113
+ if (this.shuttingDown) {
114
+ try {
115
+ Promise.resolve(cleanup()).catch(() => { });
116
+ }
117
+ catch { /* sync throw */ }
118
+ return () => { };
119
+ }
120
+ this.registry.set(name, { cleanup, priority: opts?.priority });
121
+ return () => { this.registry.delete(name); };
122
+ }
123
+ registerLockOwnership(lockFilePath) {
124
+ this.lockPath = lockFilePath;
125
+ this.lockOwned = true;
126
+ }
127
+ releaseLockOwnership() {
128
+ this.lockOwned = false;
129
+ this.lockPath = null;
130
+ }
131
+ async shutdown(exitCode = ExitCode.UserCancellation) {
132
+ if (this.shuttingDown) {
133
+ return new Promise(() => { });
134
+ }
135
+ this.shuttingDown = true;
136
+ this.controller.abort();
137
+ const msg = this.currentContext;
138
+ this.proc.stderr.write(`\n${msg}\n`);
139
+ const timeoutMs = this.getTimeoutMs();
140
+ const timeout = setTimeout(() => this.proc.exit(exitCode), timeoutMs);
141
+ const entries = Array.from(this.registry.entries());
142
+ const critical = entries
143
+ .filter(([, v]) => v.priority === 'critical').reverse();
144
+ for (const [, d] of critical) {
145
+ try {
146
+ await Promise.resolve(d.cleanup());
147
+ }
148
+ catch { /* continue */ }
149
+ }
150
+ const normal = entries
151
+ .filter(([, v]) => v.priority !== 'critical').reverse();
152
+ await Promise.allSettled(normal.map(([, d]) => {
153
+ try {
154
+ return Promise.resolve(d.cleanup());
155
+ }
156
+ catch {
157
+ return Promise.resolve();
158
+ }
159
+ }));
160
+ clearTimeout(timeout);
161
+ this.proc.exit(exitCode);
162
+ }
163
+ async withPrompt(fn) {
164
+ try {
165
+ return await fn();
166
+ }
167
+ catch (e) {
168
+ if (e instanceof Error && e.name === 'ExitPromptError') {
169
+ return this.shutdown(ExitCode.UserCancellation);
170
+ }
171
+ throw e;
172
+ }
173
+ }
174
+ async withResource(name, cleanup, fn) {
175
+ let cleaned = false;
176
+ const guardedCleanup = async () => {
177
+ if (cleaned)
178
+ return;
179
+ cleaned = true;
180
+ await cleanup();
181
+ };
182
+ const deregister = this.register(name, guardedCleanup);
183
+ try {
184
+ return await fn();
185
+ }
186
+ finally {
187
+ deregister();
188
+ try {
189
+ await guardedCleanup();
190
+ }
191
+ catch { /* best effort */ }
192
+ }
193
+ }
194
+ async withContext(message, fn) {
195
+ return this.contextStorage.run(message, () => Promise.resolve(fn()));
196
+ }
197
+ }
198
+ export const shutdown = new ShutdownManager();
199
+ //# sourceMappingURL=shutdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shutdown.js","sourceRoot":"","sources":["../../src/cli/shutdown.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=shutdown.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shutdown.test.d.ts","sourceRoot":"","sources":["../../src/cli/shutdown.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,316 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
3
+ import { EventEmitter } from 'node:events';
4
+ import { ShutdownManager } from './shutdown.js';
5
+ import { ExitCode } from '../types/enums.js';
6
+ class FakeProcess extends EventEmitter {
7
+ exit = vi.fn();
8
+ env = {};
9
+ stdout = { writable: true, isTTY: true, write: vi.fn(() => true) };
10
+ stderr = { writable: true, write: vi.fn(() => true) };
11
+ }
12
+ function createFakeProcess() {
13
+ return new FakeProcess();
14
+ }
15
+ describe('ShutdownManager', () => {
16
+ let proc;
17
+ let mgr;
18
+ beforeEach(() => {
19
+ proc = createFakeProcess();
20
+ mgr = new ShutdownManager(proc);
21
+ });
22
+ afterEach(() => {
23
+ mgr.reset();
24
+ });
25
+ describe('constructor', () => {
26
+ it('creates an instance without errors', () => {
27
+ expect(mgr).toBeInstanceOf(ShutdownManager);
28
+ });
29
+ it('is not shutting down initially', () => {
30
+ expect(mgr.isShuttingDown).toBe(false);
31
+ });
32
+ });
33
+ describe('install()', () => {
34
+ it('registers SIGINT and SIGTERM listeners', () => {
35
+ mgr.install();
36
+ expect(proc.listenerCount('SIGINT')).toBe(1);
37
+ expect(proc.listenerCount('SIGTERM')).toBe(1);
38
+ });
39
+ });
40
+ describe('reset()', () => {
41
+ it('removes signal listeners', () => {
42
+ mgr.install();
43
+ mgr.reset();
44
+ expect(proc.listenerCount('SIGINT')).toBe(0);
45
+ expect(proc.listenerCount('SIGTERM')).toBe(0);
46
+ });
47
+ it('clears shutting down state', async () => {
48
+ mgr.install();
49
+ mgr.shuttingDown = true;
50
+ expect(mgr.isShuttingDown).toBe(true);
51
+ mgr.reset();
52
+ expect(mgr.isShuttingDown).toBe(false);
53
+ });
54
+ });
55
+ describe('SIGINT handler (TTY)', () => {
56
+ beforeEach(() => {
57
+ proc.stdout.isTTY = true;
58
+ mgr.install();
59
+ });
60
+ it('first SIGINT calls shutdown (idle -> cleaning)', () => {
61
+ const shutdownSpy = vi.spyOn(mgr, 'shutdown').mockResolvedValue(undefined);
62
+ proc.emit('SIGINT');
63
+ expect(shutdownSpy).toHaveBeenCalledWith(ExitCode.UserCancellation);
64
+ });
65
+ it('second SIGINT prints warning (cleaning -> armed)', () => {
66
+ vi.spyOn(mgr, 'shutdown').mockResolvedValue(undefined);
67
+ proc.emit('SIGINT');
68
+ proc.emit('SIGINT');
69
+ expect(proc.stderr.write).toHaveBeenCalledWith('\nPress Ctrl+C again to force quit.\n');
70
+ });
71
+ it('third SIGINT force-quits (armed -> exit)', () => {
72
+ vi.spyOn(mgr, 'shutdown').mockResolvedValue(undefined);
73
+ proc.emit('SIGINT');
74
+ proc.emit('SIGINT');
75
+ proc.emit('SIGINT');
76
+ expect(proc.stderr.write).toHaveBeenCalledWith('\nForce quit.\n');
77
+ expect(proc.exit).toHaveBeenCalledWith(ExitCode.UserCancellation);
78
+ });
79
+ });
80
+ describe('SIGINT handler (non-TTY)', () => {
81
+ beforeEach(() => {
82
+ proc.stdout.isTTY = false;
83
+ mgr.install();
84
+ });
85
+ it('first SIGINT calls shutdown immediately', () => {
86
+ const shutdownSpy = vi.spyOn(mgr, 'shutdown').mockResolvedValue(undefined);
87
+ proc.emit('SIGINT');
88
+ expect(shutdownSpy).toHaveBeenCalledWith(ExitCode.UserCancellation);
89
+ });
90
+ it('second SIGINT force-exits without warning', () => {
91
+ vi.spyOn(mgr, 'shutdown').mockResolvedValue(undefined);
92
+ proc.emit('SIGINT');
93
+ proc.emit('SIGINT');
94
+ expect(proc.exit).toHaveBeenCalledWith(ExitCode.UserCancellation);
95
+ expect(proc.stderr.write).not.toHaveBeenCalledWith(expect.stringContaining('Press Ctrl+C'));
96
+ });
97
+ });
98
+ describe('SIGTERM handler', () => {
99
+ beforeEach(() => {
100
+ mgr.install();
101
+ });
102
+ it('calls shutdown on SIGTERM', () => {
103
+ const shutdownSpy = vi.spyOn(mgr, 'shutdown').mockResolvedValue(undefined);
104
+ proc.emit('SIGTERM');
105
+ expect(shutdownSpy).toHaveBeenCalledWith(ExitCode.UserCancellation);
106
+ });
107
+ it('prevents subsequent SIGINT from also triggering shutdown', () => {
108
+ const shutdownSpy = vi.spyOn(mgr, 'shutdown').mockResolvedValue(undefined);
109
+ proc.emit('SIGTERM');
110
+ proc.emit('SIGINT');
111
+ expect(shutdownSpy).toHaveBeenCalledTimes(1);
112
+ });
113
+ });
114
+ describe('shutdown()', () => {
115
+ it('sets isShuttingDown to true', async () => {
116
+ mgr.install();
117
+ mgr.shutdown();
118
+ expect(mgr.isShuttingDown).toBe(true);
119
+ await vi.waitFor(() => expect(proc.exit).toHaveBeenCalled());
120
+ });
121
+ it('calls process.exit with provided code', async () => {
122
+ mgr.install();
123
+ mgr.shutdown(ExitCode.ValidationError);
124
+ await vi.waitFor(() => expect(proc.exit).toHaveBeenCalledWith(ExitCode.ValidationError));
125
+ });
126
+ it('returns never-resolving promise on second call (idempotency)', async () => {
127
+ mgr.install();
128
+ mgr.shutdown();
129
+ await vi.waitFor(() => expect(proc.exit).toHaveBeenCalled());
130
+ const exitMock = proc.exit;
131
+ const exitCallCount = exitMock.mock.calls.length;
132
+ mgr.shutdown();
133
+ await new Promise(r => setTimeout(r, 10));
134
+ expect(exitMock.mock.calls.length).toBe(exitCallCount);
135
+ });
136
+ it('writes context message to stderr', async () => {
137
+ mgr.install();
138
+ mgr.shutdown();
139
+ await vi.waitFor(() => expect(proc.exit).toHaveBeenCalled());
140
+ expect(proc.stderr.write).toHaveBeenCalledWith('\nCancelled.\n');
141
+ });
142
+ it('aborts the AbortSignal', async () => {
143
+ mgr.install();
144
+ expect(mgr.signal.aborted).toBe(false);
145
+ mgr.shutdown();
146
+ expect(mgr.signal.aborted).toBe(true);
147
+ });
148
+ it('runs critical disposers sequentially before normal', async () => {
149
+ mgr.install();
150
+ const order = [];
151
+ mgr.register('normal-1', () => { order.push('normal-1'); });
152
+ mgr.register('critical-1', () => { order.push('critical-1'); }, { priority: 'critical' });
153
+ mgr.register('normal-2', () => { order.push('normal-2'); });
154
+ mgr.shutdown();
155
+ await vi.waitFor(() => expect(proc.exit).toHaveBeenCalled());
156
+ expect(order[0]).toBe('critical-1');
157
+ expect(order).toContain('normal-1');
158
+ expect(order).toContain('normal-2');
159
+ });
160
+ it('late registration during shutdown runs cleanup immediately', async () => {
161
+ mgr.install();
162
+ mgr.shutdown();
163
+ await vi.waitFor(() => expect(mgr.isShuttingDown).toBe(true));
164
+ const lateFn = vi.fn();
165
+ const deregister = mgr.register('late', lateFn);
166
+ await vi.waitFor(() => expect(lateFn).toHaveBeenCalled());
167
+ expect(typeof deregister).toBe('function');
168
+ });
169
+ it('continues cleanup if a disposer throws', async () => {
170
+ mgr.install();
171
+ const ran = [];
172
+ mgr.register('throws', () => { throw new Error('boom'); });
173
+ mgr.register('runs', () => { ran.push('ok'); });
174
+ mgr.shutdown();
175
+ await vi.waitFor(() => expect(proc.exit).toHaveBeenCalled());
176
+ expect(ran).toContain('ok');
177
+ });
178
+ it('uses 5000ms timeout for SIGTERM', async () => {
179
+ const setTimeoutSpy = vi.spyOn(globalThis, 'setTimeout');
180
+ mgr.install();
181
+ proc.emit('SIGTERM');
182
+ await vi.waitFor(() => expect(proc.exit).toHaveBeenCalled());
183
+ const timeoutCall = setTimeoutSpy.mock.calls.find(([, ms]) => ms === 5000 || ms === 2000);
184
+ expect(timeoutCall?.[1]).toBe(5000);
185
+ setTimeoutSpy.mockRestore();
186
+ });
187
+ });
188
+ describe('withResource()', () => {
189
+ beforeEach(() => {
190
+ mgr.install();
191
+ });
192
+ it('returns the value from the wrapped function', async () => {
193
+ const result = await mgr.withResource('test', () => { }, async () => 42);
194
+ expect(result).toBe(42);
195
+ });
196
+ it('runs cleanup on normal completion', async () => {
197
+ const cleanup = vi.fn();
198
+ await mgr.withResource('test', cleanup, async () => 'done');
199
+ expect(cleanup).toHaveBeenCalledOnce();
200
+ });
201
+ it('runs cleanup on error', async () => {
202
+ const cleanup = vi.fn();
203
+ await expect(mgr.withResource('test', cleanup, async () => { throw new Error('fail'); })).rejects.toThrow('fail');
204
+ expect(cleanup).toHaveBeenCalledOnce();
205
+ });
206
+ it('only runs cleanup once if shutdown also fires (idempotency)', async () => {
207
+ const cleanup = vi.fn();
208
+ const promise = mgr.withResource('test', cleanup, async () => {
209
+ // Simulate shutdown calling the registered cleanup
210
+ const entry = mgr.registry.get('test');
211
+ if (entry)
212
+ entry.cleanup();
213
+ return 'done';
214
+ });
215
+ await promise;
216
+ expect(cleanup).toHaveBeenCalledOnce();
217
+ });
218
+ it('deregisters from registry after completion', async () => {
219
+ await mgr.withResource('test', () => { }, async () => 'done');
220
+ expect(mgr.registry.has('test')).toBe(false);
221
+ });
222
+ });
223
+ describe('withContext()', () => {
224
+ beforeEach(() => {
225
+ mgr.install();
226
+ });
227
+ it('returns the value from the wrapped function', async () => {
228
+ const result = await mgr.withContext('msg', async () => 'value');
229
+ expect(result).toBe('value');
230
+ });
231
+ it('uses context message during shutdown', async () => {
232
+ await mgr.withContext('Custom cancel message.', async () => {
233
+ mgr.shutdown();
234
+ await vi.waitFor(() => expect(proc.exit).toHaveBeenCalled());
235
+ });
236
+ expect(proc.stderr.write).toHaveBeenCalledWith('\nCustom cancel message.\n');
237
+ });
238
+ it('supports thunk messages evaluated at shutdown time', async () => {
239
+ let phase = 'wizard';
240
+ await mgr.withContext(() => `Cancelled during ${phase}.`, async () => {
241
+ phase = 'build';
242
+ mgr.shutdown();
243
+ await vi.waitFor(() => expect(proc.exit).toHaveBeenCalled());
244
+ });
245
+ expect(proc.stderr.write).toHaveBeenCalledWith('\nCancelled during build.\n');
246
+ });
247
+ it('concurrent async scopes maintain independent contexts', async () => {
248
+ const contexts = [];
249
+ await Promise.all([
250
+ mgr.withContext('scope-A', async () => {
251
+ await new Promise(r => setTimeout(r, 10));
252
+ contexts.push(mgr.currentContext);
253
+ }),
254
+ mgr.withContext('scope-B', async () => {
255
+ await new Promise(r => setTimeout(r, 5));
256
+ contexts.push(mgr.currentContext);
257
+ }),
258
+ ]);
259
+ expect(contexts).toContain('scope-A');
260
+ expect(contexts).toContain('scope-B');
261
+ });
262
+ it('inner context overrides outer context', async () => {
263
+ await mgr.withContext('outer', async () => {
264
+ await mgr.withContext('inner', async () => {
265
+ mgr.shutdown();
266
+ await vi.waitFor(() => expect(proc.exit).toHaveBeenCalled());
267
+ });
268
+ });
269
+ expect(proc.stderr.write).toHaveBeenCalledWith('\ninner\n');
270
+ });
271
+ });
272
+ describe('lock ownership', () => {
273
+ it('registers and releases lock ownership', () => {
274
+ mgr.registerLockOwnership('/path/to/lock.json');
275
+ expect(mgr.lockOwned).toBe(true);
276
+ expect(mgr.lockPath).toBe('/path/to/lock.json');
277
+ mgr.releaseLockOwnership();
278
+ expect(mgr.lockOwned).toBe(false);
279
+ expect(mgr.lockPath).toBeNull();
280
+ });
281
+ });
282
+ describe('exit safety net', () => {
283
+ it('runs exit handler only once (reentrancy guard)', () => {
284
+ mgr.install();
285
+ proc.emit('exit', 0);
286
+ proc.emit('exit', 0);
287
+ const stderrCalls = proc.stderr.write.mock.calls;
288
+ const cursorRestores = stderrCalls.filter((args) => typeof args[0] === 'string' && args[0].includes('\x1b[?25h'));
289
+ expect(cursorRestores.length).toBe(1);
290
+ });
291
+ });
292
+ describe('withPrompt()', () => {
293
+ beforeEach(() => {
294
+ mgr.install();
295
+ });
296
+ it('returns the value from the wrapped function', async () => {
297
+ const result = await mgr.withPrompt(async () => 'hello');
298
+ expect(result).toBe('hello');
299
+ });
300
+ it('re-throws non-ExitPromptError errors', async () => {
301
+ await expect(mgr.withPrompt(async () => { throw new Error('oops'); })).rejects.toThrow('oops');
302
+ });
303
+ it('catches ExitPromptError by name and calls shutdown', async () => {
304
+ const shutdownSpy = vi.spyOn(mgr, 'shutdown').mockResolvedValue(undefined);
305
+ const err = new Error('User force closed the prompt with SIGINT');
306
+ err.name = 'ExitPromptError';
307
+ await mgr.withPrompt(async () => { throw err; });
308
+ expect(shutdownSpy).toHaveBeenCalledWith(ExitCode.UserCancellation);
309
+ });
310
+ it('does not catch errors where only message mentions ExitPromptError', async () => {
311
+ const err = new Error('ExitPromptError happened');
312
+ await expect(mgr.withPrompt(async () => { throw err; })).rejects.toThrow('ExitPromptError happened');
313
+ });
314
+ });
315
+ });
316
+ //# sourceMappingURL=shutdown.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shutdown.test.js","sourceRoot":"","sources":["../../src/cli/shutdown.test.ts"],"names":[],"mappings":"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"}
@@ -102,6 +102,7 @@ describe('scaffold init E2E', () => {
102
102
  afterEach(() => {
103
103
  fs.rmSync(tmpDir, { recursive: true, force: true });
104
104
  vi.restoreAllMocks();
105
+ process.exitCode = undefined;
105
106
  });
106
107
  // Test 1: Creates .scaffold/ directory structure
107
108
  it('creates .scaffold/ directory structure', async () => {
@@ -213,7 +214,7 @@ describe('scaffold init E2E', () => {
213
214
  });
214
215
  // Test 11: init command auto-runs build into hidden .scaffold/generated output
215
216
  it('init command creates hidden generated output and .gitignore without root commands', async () => {
216
- const exitSpy = vi.spyOn(process, 'exit').mockImplementation((() => { }));
217
+ vi.spyOn(process, 'exit').mockImplementation((() => { }));
217
218
  vi.spyOn(process.stdout, 'write').mockImplementation(() => true);
218
219
  vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
219
220
  await initCommand.handler({
@@ -227,7 +228,7 @@ describe('scaffold init E2E', () => {
227
228
  format: undefined,
228
229
  verbose: false,
229
230
  });
230
- expect(exitSpy).toHaveBeenCalledWith(0);
231
+ expect(process.exitCode ?? 0).toBe(0);
231
232
  expect(fs.existsSync(path.join(tmpDir, '.scaffold', 'generated', 'universal', 'prompts', 'README.md'))).toBe(true);
232
233
  expect(fs.existsSync(path.join(tmpDir, '.gitignore'))).toBe(true);
233
234
  expect(fs.readFileSync(path.join(tmpDir, '.gitignore'), 'utf8')).toContain('.scaffold/generated/');
@@ -235,7 +236,7 @@ describe('scaffold init E2E', () => {
235
236
  });
236
237
  // Test 12: init command still writes hidden generated output from the default build path
237
238
  it('init command creates hidden generated output in the temp project', async () => {
238
- const exitSpy = vi.spyOn(process, 'exit').mockImplementation((() => { }));
239
+ vi.spyOn(process, 'exit').mockImplementation((() => { }));
239
240
  vi.spyOn(process.stdout, 'write').mockImplementation(() => true);
240
241
  vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
241
242
  await initCommand.handler({
@@ -249,7 +250,7 @@ describe('scaffold init E2E', () => {
249
250
  format: undefined,
250
251
  verbose: false,
251
252
  });
252
- expect(exitSpy).toHaveBeenCalledWith(0);
253
+ expect(process.exitCode ?? 0).toBe(0);
253
254
  expect(fs.existsSync(path.join(tmpDir, '.scaffold', 'generated', 'universal', 'prompts', 'README.md'))).toBe(true);
254
255
  });
255
256
  // Test 13: real wizard + build path produces Gemini output with a tiny step fixture