resend-cli 1.2.1 → 1.2.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 (191) hide show
  1. package/biome.json +1 -1
  2. package/bun.lock +0 -3
  3. package/package.json +2 -3
  4. package/src/cli.ts +11 -1
  5. package/src/commands/auth/login.ts +35 -8
  6. package/src/commands/doctor.ts +33 -115
  7. package/src/commands/teams/remove.ts +5 -2
  8. package/src/commands/teams/switch.ts +3 -0
  9. package/src/lib/config.ts +37 -31
  10. package/src/lib/spinner.ts +17 -10
  11. package/src/lib/update-check.ts +172 -0
  12. package/tests/commands/auth/login.test.ts +37 -0
  13. package/tests/lib/config.test.ts +38 -7
  14. package/tests/lib/update-check.test.ts +169 -0
  15. package/.claude/worktrees/emails-list/.claude/settings.local.json +0 -5
  16. package/.claude/worktrees/emails-list/.github/scripts/pr-title-check.js +0 -34
  17. package/.claude/worktrees/emails-list/.github/workflows/ci.yml +0 -32
  18. package/.claude/worktrees/emails-list/.github/workflows/pr-title-check.yml +0 -13
  19. package/.claude/worktrees/emails-list/.github/workflows/release.yml +0 -93
  20. package/.claude/worktrees/emails-list/CHANGELOG.md +0 -31
  21. package/.claude/worktrees/emails-list/LICENSE +0 -21
  22. package/.claude/worktrees/emails-list/README.md +0 -424
  23. package/.claude/worktrees/emails-list/biome.json +0 -36
  24. package/.claude/worktrees/emails-list/bun.lock +0 -76
  25. package/.claude/worktrees/emails-list/bunfig.toml +0 -2
  26. package/.claude/worktrees/emails-list/install.ps1 +0 -140
  27. package/.claude/worktrees/emails-list/install.sh +0 -301
  28. package/.claude/worktrees/emails-list/package.json +0 -43
  29. package/.claude/worktrees/emails-list/renovate.json +0 -6
  30. package/.claude/worktrees/emails-list/src/cli.ts +0 -74
  31. package/.claude/worktrees/emails-list/src/commands/api-keys/create.ts +0 -114
  32. package/.claude/worktrees/emails-list/src/commands/api-keys/delete.ts +0 -47
  33. package/.claude/worktrees/emails-list/src/commands/api-keys/index.ts +0 -26
  34. package/.claude/worktrees/emails-list/src/commands/api-keys/list.ts +0 -35
  35. package/.claude/worktrees/emails-list/src/commands/api-keys/utils.ts +0 -8
  36. package/.claude/worktrees/emails-list/src/commands/auth/index.ts +0 -20
  37. package/.claude/worktrees/emails-list/src/commands/auth/login.ts +0 -207
  38. package/.claude/worktrees/emails-list/src/commands/auth/logout.ts +0 -105
  39. package/.claude/worktrees/emails-list/src/commands/broadcasts/create.ts +0 -196
  40. package/.claude/worktrees/emails-list/src/commands/broadcasts/delete.ts +0 -46
  41. package/.claude/worktrees/emails-list/src/commands/broadcasts/get.ts +0 -59
  42. package/.claude/worktrees/emails-list/src/commands/broadcasts/index.ts +0 -43
  43. package/.claude/worktrees/emails-list/src/commands/broadcasts/list.ts +0 -60
  44. package/.claude/worktrees/emails-list/src/commands/broadcasts/send.ts +0 -56
  45. package/.claude/worktrees/emails-list/src/commands/broadcasts/update.ts +0 -95
  46. package/.claude/worktrees/emails-list/src/commands/broadcasts/utils.ts +0 -35
  47. package/.claude/worktrees/emails-list/src/commands/contact-properties/create.ts +0 -118
  48. package/.claude/worktrees/emails-list/src/commands/contact-properties/delete.ts +0 -48
  49. package/.claude/worktrees/emails-list/src/commands/contact-properties/get.ts +0 -46
  50. package/.claude/worktrees/emails-list/src/commands/contact-properties/index.ts +0 -48
  51. package/.claude/worktrees/emails-list/src/commands/contact-properties/list.ts +0 -68
  52. package/.claude/worktrees/emails-list/src/commands/contact-properties/update.ts +0 -88
  53. package/.claude/worktrees/emails-list/src/commands/contact-properties/utils.ts +0 -17
  54. package/.claude/worktrees/emails-list/src/commands/contacts/add-segment.ts +0 -78
  55. package/.claude/worktrees/emails-list/src/commands/contacts/create.ts +0 -122
  56. package/.claude/worktrees/emails-list/src/commands/contacts/delete.ts +0 -49
  57. package/.claude/worktrees/emails-list/src/commands/contacts/get.ts +0 -53
  58. package/.claude/worktrees/emails-list/src/commands/contacts/index.ts +0 -58
  59. package/.claude/worktrees/emails-list/src/commands/contacts/list.ts +0 -57
  60. package/.claude/worktrees/emails-list/src/commands/contacts/remove-segment.ts +0 -48
  61. package/.claude/worktrees/emails-list/src/commands/contacts/segments.ts +0 -39
  62. package/.claude/worktrees/emails-list/src/commands/contacts/topics.ts +0 -45
  63. package/.claude/worktrees/emails-list/src/commands/contacts/update-topics.ts +0 -90
  64. package/.claude/worktrees/emails-list/src/commands/contacts/update.ts +0 -77
  65. package/.claude/worktrees/emails-list/src/commands/contacts/utils.ts +0 -119
  66. package/.claude/worktrees/emails-list/src/commands/doctor.ts +0 -298
  67. package/.claude/worktrees/emails-list/src/commands/domains/create.ts +0 -83
  68. package/.claude/worktrees/emails-list/src/commands/domains/delete.ts +0 -42
  69. package/.claude/worktrees/emails-list/src/commands/domains/get.ts +0 -47
  70. package/.claude/worktrees/emails-list/src/commands/domains/index.ts +0 -35
  71. package/.claude/worktrees/emails-list/src/commands/domains/list.ts +0 -53
  72. package/.claude/worktrees/emails-list/src/commands/domains/update.ts +0 -75
  73. package/.claude/worktrees/emails-list/src/commands/domains/utils.ts +0 -44
  74. package/.claude/worktrees/emails-list/src/commands/domains/verify.ts +0 -38
  75. package/.claude/worktrees/emails-list/src/commands/emails/batch.ts +0 -140
  76. package/.claude/worktrees/emails-list/src/commands/emails/index.ts +0 -28
  77. package/.claude/worktrees/emails-list/src/commands/emails/list.ts +0 -73
  78. package/.claude/worktrees/emails-list/src/commands/emails/receiving/attachment.ts +0 -55
  79. package/.claude/worktrees/emails-list/src/commands/emails/receiving/attachments.ts +0 -68
  80. package/.claude/worktrees/emails-list/src/commands/emails/receiving/get.ts +0 -58
  81. package/.claude/worktrees/emails-list/src/commands/emails/receiving/index.ts +0 -28
  82. package/.claude/worktrees/emails-list/src/commands/emails/receiving/list.ts +0 -59
  83. package/.claude/worktrees/emails-list/src/commands/emails/receiving/utils.ts +0 -38
  84. package/.claude/worktrees/emails-list/src/commands/emails/send.ts +0 -189
  85. package/.claude/worktrees/emails-list/src/commands/open.ts +0 -24
  86. package/.claude/worktrees/emails-list/src/commands/segments/create.ts +0 -50
  87. package/.claude/worktrees/emails-list/src/commands/segments/delete.ts +0 -47
  88. package/.claude/worktrees/emails-list/src/commands/segments/get.ts +0 -38
  89. package/.claude/worktrees/emails-list/src/commands/segments/index.ts +0 -36
  90. package/.claude/worktrees/emails-list/src/commands/segments/list.ts +0 -58
  91. package/.claude/worktrees/emails-list/src/commands/segments/utils.ts +0 -7
  92. package/.claude/worktrees/emails-list/src/commands/teams/index.ts +0 -10
  93. package/.claude/worktrees/emails-list/src/commands/teams/list.ts +0 -35
  94. package/.claude/worktrees/emails-list/src/commands/teams/remove.ts +0 -83
  95. package/.claude/worktrees/emails-list/src/commands/teams/switch.ts +0 -73
  96. package/.claude/worktrees/emails-list/src/commands/topics/create.ts +0 -73
  97. package/.claude/worktrees/emails-list/src/commands/topics/delete.ts +0 -47
  98. package/.claude/worktrees/emails-list/src/commands/topics/get.ts +0 -42
  99. package/.claude/worktrees/emails-list/src/commands/topics/index.ts +0 -42
  100. package/.claude/worktrees/emails-list/src/commands/topics/list.ts +0 -34
  101. package/.claude/worktrees/emails-list/src/commands/topics/update.ts +0 -59
  102. package/.claude/worktrees/emails-list/src/commands/topics/utils.ts +0 -16
  103. package/.claude/worktrees/emails-list/src/commands/webhooks/create.ts +0 -128
  104. package/.claude/worktrees/emails-list/src/commands/webhooks/delete.ts +0 -49
  105. package/.claude/worktrees/emails-list/src/commands/webhooks/get.ts +0 -42
  106. package/.claude/worktrees/emails-list/src/commands/webhooks/index.ts +0 -44
  107. package/.claude/worktrees/emails-list/src/commands/webhooks/list.ts +0 -55
  108. package/.claude/worktrees/emails-list/src/commands/webhooks/update.ts +0 -83
  109. package/.claude/worktrees/emails-list/src/commands/webhooks/utils.ts +0 -36
  110. package/.claude/worktrees/emails-list/src/commands/whoami.ts +0 -71
  111. package/.claude/worktrees/emails-list/src/lib/actions.ts +0 -157
  112. package/.claude/worktrees/emails-list/src/lib/client.ts +0 -34
  113. package/.claude/worktrees/emails-list/src/lib/config.ts +0 -211
  114. package/.claude/worktrees/emails-list/src/lib/files.ts +0 -15
  115. package/.claude/worktrees/emails-list/src/lib/help-text.ts +0 -38
  116. package/.claude/worktrees/emails-list/src/lib/output.ts +0 -54
  117. package/.claude/worktrees/emails-list/src/lib/pagination.ts +0 -36
  118. package/.claude/worktrees/emails-list/src/lib/prompts.ts +0 -149
  119. package/.claude/worktrees/emails-list/src/lib/spinner.ts +0 -93
  120. package/.claude/worktrees/emails-list/src/lib/table.ts +0 -57
  121. package/.claude/worktrees/emails-list/src/lib/tty.ts +0 -28
  122. package/.claude/worktrees/emails-list/src/lib/version.ts +0 -4
  123. package/.claude/worktrees/emails-list/tests/commands/api-keys/create.test.ts +0 -195
  124. package/.claude/worktrees/emails-list/tests/commands/api-keys/delete.test.ts +0 -156
  125. package/.claude/worktrees/emails-list/tests/commands/api-keys/list.test.ts +0 -133
  126. package/.claude/worktrees/emails-list/tests/commands/auth/login.test.ts +0 -119
  127. package/.claude/worktrees/emails-list/tests/commands/auth/logout.test.ts +0 -146
  128. package/.claude/worktrees/emails-list/tests/commands/broadcasts/create.test.ts +0 -447
  129. package/.claude/worktrees/emails-list/tests/commands/broadcasts/delete.test.ts +0 -182
  130. package/.claude/worktrees/emails-list/tests/commands/broadcasts/get.test.ts +0 -146
  131. package/.claude/worktrees/emails-list/tests/commands/broadcasts/list.test.ts +0 -196
  132. package/.claude/worktrees/emails-list/tests/commands/broadcasts/send.test.ts +0 -161
  133. package/.claude/worktrees/emails-list/tests/commands/broadcasts/update.test.ts +0 -283
  134. package/.claude/worktrees/emails-list/tests/commands/contact-properties/create.test.ts +0 -250
  135. package/.claude/worktrees/emails-list/tests/commands/contact-properties/delete.test.ts +0 -183
  136. package/.claude/worktrees/emails-list/tests/commands/contact-properties/get.test.ts +0 -144
  137. package/.claude/worktrees/emails-list/tests/commands/contact-properties/list.test.ts +0 -180
  138. package/.claude/worktrees/emails-list/tests/commands/contact-properties/update.test.ts +0 -216
  139. package/.claude/worktrees/emails-list/tests/commands/contacts/add-segment.test.ts +0 -188
  140. package/.claude/worktrees/emails-list/tests/commands/contacts/create.test.ts +0 -270
  141. package/.claude/worktrees/emails-list/tests/commands/contacts/delete.test.ts +0 -192
  142. package/.claude/worktrees/emails-list/tests/commands/contacts/get.test.ts +0 -148
  143. package/.claude/worktrees/emails-list/tests/commands/contacts/list.test.ts +0 -175
  144. package/.claude/worktrees/emails-list/tests/commands/contacts/remove-segment.test.ts +0 -166
  145. package/.claude/worktrees/emails-list/tests/commands/contacts/segments.test.ts +0 -167
  146. package/.claude/worktrees/emails-list/tests/commands/contacts/topics.test.ts +0 -163
  147. package/.claude/worktrees/emails-list/tests/commands/contacts/update-topics.test.ts +0 -247
  148. package/.claude/worktrees/emails-list/tests/commands/contacts/update.test.ts +0 -205
  149. package/.claude/worktrees/emails-list/tests/commands/doctor.test.ts +0 -165
  150. package/.claude/worktrees/emails-list/tests/commands/domains/create.test.ts +0 -192
  151. package/.claude/worktrees/emails-list/tests/commands/domains/delete.test.ts +0 -156
  152. package/.claude/worktrees/emails-list/tests/commands/domains/get.test.ts +0 -137
  153. package/.claude/worktrees/emails-list/tests/commands/domains/list.test.ts +0 -164
  154. package/.claude/worktrees/emails-list/tests/commands/domains/update.test.ts +0 -223
  155. package/.claude/worktrees/emails-list/tests/commands/domains/verify.test.ts +0 -117
  156. package/.claude/worktrees/emails-list/tests/commands/emails/batch.test.ts +0 -313
  157. package/.claude/worktrees/emails-list/tests/commands/emails/list.test.ts +0 -196
  158. package/.claude/worktrees/emails-list/tests/commands/emails/receiving/attachment.test.ts +0 -140
  159. package/.claude/worktrees/emails-list/tests/commands/emails/receiving/attachments.test.ts +0 -168
  160. package/.claude/worktrees/emails-list/tests/commands/emails/receiving/get.test.ts +0 -140
  161. package/.claude/worktrees/emails-list/tests/commands/emails/receiving/list.test.ts +0 -181
  162. package/.claude/worktrees/emails-list/tests/commands/emails/send.test.ts +0 -309
  163. package/.claude/worktrees/emails-list/tests/commands/segments/create.test.ts +0 -163
  164. package/.claude/worktrees/emails-list/tests/commands/segments/delete.test.ts +0 -182
  165. package/.claude/worktrees/emails-list/tests/commands/segments/get.test.ts +0 -137
  166. package/.claude/worktrees/emails-list/tests/commands/segments/list.test.ts +0 -173
  167. package/.claude/worktrees/emails-list/tests/commands/teams/list.test.ts +0 -63
  168. package/.claude/worktrees/emails-list/tests/commands/teams/remove.test.ts +0 -103
  169. package/.claude/worktrees/emails-list/tests/commands/teams/switch.test.ts +0 -96
  170. package/.claude/worktrees/emails-list/tests/commands/topics/create.test.ts +0 -191
  171. package/.claude/worktrees/emails-list/tests/commands/topics/delete.test.ts +0 -156
  172. package/.claude/worktrees/emails-list/tests/commands/topics/get.test.ts +0 -125
  173. package/.claude/worktrees/emails-list/tests/commands/topics/list.test.ts +0 -124
  174. package/.claude/worktrees/emails-list/tests/commands/topics/update.test.ts +0 -177
  175. package/.claude/worktrees/emails-list/tests/commands/webhooks/create.test.ts +0 -224
  176. package/.claude/worktrees/emails-list/tests/commands/webhooks/delete.test.ts +0 -156
  177. package/.claude/worktrees/emails-list/tests/commands/webhooks/get.test.ts +0 -125
  178. package/.claude/worktrees/emails-list/tests/commands/webhooks/list.test.ts +0 -177
  179. package/.claude/worktrees/emails-list/tests/commands/webhooks/update.test.ts +0 -206
  180. package/.claude/worktrees/emails-list/tests/commands/whoami.test.ts +0 -99
  181. package/.claude/worktrees/emails-list/tests/helpers.ts +0 -93
  182. package/.claude/worktrees/emails-list/tests/lib/client.test.ts +0 -71
  183. package/.claude/worktrees/emails-list/tests/lib/config.test.ts +0 -414
  184. package/.claude/worktrees/emails-list/tests/lib/files.test.ts +0 -65
  185. package/.claude/worktrees/emails-list/tests/lib/help-text.test.ts +0 -97
  186. package/.claude/worktrees/emails-list/tests/lib/output.test.ts +0 -127
  187. package/.claude/worktrees/emails-list/tests/lib/prompts.test.ts +0 -178
  188. package/.claude/worktrees/emails-list/tests/lib/spinner.test.ts +0 -146
  189. package/.claude/worktrees/emails-list/tests/lib/table.test.ts +0 -63
  190. package/.claude/worktrees/emails-list/tests/lib/tty.test.ts +0 -85
  191. package/.claude/worktrees/emails-list/tsconfig.json +0 -14
@@ -1,178 +0,0 @@
1
- import { afterEach, describe, expect, spyOn, test } from 'bun:test';
2
- import { expectExit1, mockExitThrow } from '../helpers';
3
-
4
- describe('promptForMissing', () => {
5
- const originalStdinIsTTY = process.stdin.isTTY;
6
- const originalStdoutIsTTY = process.stdout.isTTY;
7
- let errorSpy: ReturnType<typeof spyOn> | undefined;
8
- let exitSpy: ReturnType<typeof spyOn> | undefined;
9
-
10
- afterEach(() => {
11
- errorSpy?.mockRestore();
12
- exitSpy?.mockRestore();
13
- errorSpy = undefined;
14
- exitSpy = undefined;
15
- Object.defineProperty(process.stdin, 'isTTY', {
16
- value: originalStdinIsTTY,
17
- writable: true,
18
- });
19
- Object.defineProperty(process.stdout, 'isTTY', {
20
- value: originalStdoutIsTTY,
21
- writable: true,
22
- });
23
- });
24
-
25
- test('returns options unchanged when nothing is missing', async () => {
26
- const { promptForMissing } = require('../../src/lib/prompts');
27
- const opts = { from: 'a@b.com', to: 'c@d.com', subject: 'Hi' };
28
- const result = await promptForMissing(
29
- opts,
30
- [
31
- { flag: 'from', message: 'From' },
32
- { flag: 'to', message: 'To' },
33
- { flag: 'subject', message: 'Subject' },
34
- ],
35
- {},
36
- );
37
- expect(result).toEqual(opts);
38
- });
39
-
40
- test('exits with missing_flags error in non-interactive mode', async () => {
41
- Object.defineProperty(process.stdin, 'isTTY', {
42
- value: undefined,
43
- writable: true,
44
- });
45
- Object.defineProperty(process.stdout, 'isTTY', {
46
- value: undefined,
47
- writable: true,
48
- });
49
- errorSpy = spyOn(console, 'error').mockImplementation(() => {});
50
- exitSpy = mockExitThrow();
51
-
52
- const { promptForMissing } = require('../../src/lib/prompts');
53
-
54
- await expectExit1(() =>
55
- promptForMissing(
56
- { from: undefined, to: 'c@d.com', subject: undefined },
57
- [
58
- { flag: 'from', message: 'From' },
59
- { flag: 'to', message: 'To' },
60
- { flag: 'subject', message: 'Subject' },
61
- ],
62
- {},
63
- ),
64
- );
65
-
66
- const allErrors = errorSpy?.mock.calls.map((c) => c[0]).join(' ');
67
- expect(allErrors).toContain('--from');
68
- expect(allErrors).toContain('--subject');
69
- // --to should NOT be listed since it has a value
70
- expect(allErrors).not.toContain('--to,');
71
- });
72
-
73
- test('errors output includes missing_flags code', async () => {
74
- Object.defineProperty(process.stdin, 'isTTY', {
75
- value: undefined,
76
- writable: true,
77
- });
78
- Object.defineProperty(process.stdout, 'isTTY', {
79
- value: undefined,
80
- writable: true,
81
- });
82
- errorSpy = spyOn(console, 'error').mockImplementation(() => {});
83
- exitSpy = mockExitThrow();
84
-
85
- const { promptForMissing } = require('../../src/lib/prompts');
86
-
87
- await expectExit1(() =>
88
- promptForMissing(
89
- { from: undefined },
90
- [{ flag: 'from', message: 'From' }],
91
- {},
92
- ),
93
- );
94
-
95
- const allErrors = errorSpy?.mock.calls.map((c) => c[0]).join(' ');
96
- expect(allErrors).toContain('missing_flags');
97
- });
98
-
99
- test('skips fields marked as required=false', async () => {
100
- const { promptForMissing } = require('../../src/lib/prompts');
101
- const opts = { from: 'a@b.com', to: undefined };
102
- const result = await promptForMissing(
103
- opts,
104
- [
105
- { flag: 'from', message: 'From' },
106
- { flag: 'to', message: 'To', required: false },
107
- ],
108
- {},
109
- );
110
- expect(result).toEqual(opts);
111
- });
112
- });
113
-
114
- describe('confirmDelete', () => {
115
- const originalStdinIsTTY = process.stdin.isTTY;
116
- const originalStdoutIsTTY = process.stdout.isTTY;
117
- let errorSpy: ReturnType<typeof spyOn> | undefined;
118
- let exitSpy: ReturnType<typeof spyOn> | undefined;
119
-
120
- afterEach(() => {
121
- errorSpy?.mockRestore();
122
- exitSpy?.mockRestore();
123
- errorSpy = undefined;
124
- exitSpy = undefined;
125
- Object.defineProperty(process.stdin, 'isTTY', {
126
- value: originalStdinIsTTY,
127
- writable: true,
128
- });
129
- Object.defineProperty(process.stdout, 'isTTY', {
130
- value: originalStdoutIsTTY,
131
- writable: true,
132
- });
133
- });
134
-
135
- test('exits with confirmation_required when non-interactive', async () => {
136
- Object.defineProperty(process.stdin, 'isTTY', {
137
- value: undefined,
138
- writable: true,
139
- });
140
- Object.defineProperty(process.stdout, 'isTTY', {
141
- value: undefined,
142
- writable: true,
143
- });
144
- errorSpy = spyOn(console, 'error').mockImplementation(() => {});
145
- exitSpy = mockExitThrow();
146
-
147
- const { confirmDelete } = require('../../src/lib/prompts');
148
-
149
- await expectExit1(() =>
150
- confirmDelete('res_123', 'Delete resource res_123?', { json: false }),
151
- );
152
-
153
- const output = errorSpy?.mock.calls.map((c) => c[0]).join(' ');
154
- expect(output).toContain('confirmation_required');
155
- });
156
-
157
- test('outputs JSON confirmation_required error when json option is true', async () => {
158
- Object.defineProperty(process.stdin, 'isTTY', {
159
- value: undefined,
160
- writable: true,
161
- });
162
- Object.defineProperty(process.stdout, 'isTTY', {
163
- value: undefined,
164
- writable: true,
165
- });
166
- errorSpy = spyOn(console, 'error').mockImplementation(() => {});
167
- exitSpy = mockExitThrow();
168
-
169
- const { confirmDelete } = require('../../src/lib/prompts');
170
- await expectExit1(() =>
171
- confirmDelete('res_123', 'Delete?', { json: true }),
172
- );
173
-
174
- const raw = errorSpy?.mock.calls.map((c) => c[0]).join(' ');
175
- const parsed = JSON.parse(raw);
176
- expect(parsed.error.code).toBe('confirmation_required');
177
- });
178
- });
@@ -1,146 +0,0 @@
1
- import { afterEach, describe, expect, spyOn, test } from 'bun:test';
2
-
3
- describe('createSpinner', () => {
4
- const originalStdinIsTTY = process.stdin.isTTY;
5
- const originalStdoutIsTTY = process.stdout.isTTY;
6
- let stderrSpy: ReturnType<typeof spyOn>;
7
-
8
- afterEach(() => {
9
- stderrSpy?.mockRestore();
10
- Object.defineProperty(process.stdin, 'isTTY', {
11
- value: originalStdinIsTTY,
12
- writable: true,
13
- });
14
- Object.defineProperty(process.stdout, 'isTTY', {
15
- value: originalStdoutIsTTY,
16
- writable: true,
17
- });
18
- delete process.env.CI;
19
- });
20
-
21
- test('returns no-op spinner in non-interactive mode', () => {
22
- Object.defineProperty(process.stdin, 'isTTY', {
23
- value: undefined,
24
- writable: true,
25
- });
26
- Object.defineProperty(process.stdout, 'isTTY', {
27
- value: undefined,
28
- writable: true,
29
- });
30
-
31
- const { createSpinner } = require('../../src/lib/spinner');
32
- const spinner = createSpinner('test message');
33
-
34
- // Should not throw when calling any method
35
- expect(() => spinner.stop('done')).not.toThrow();
36
- expect(() => spinner.fail('error')).not.toThrow();
37
- expect(() => spinner.warn('warning')).not.toThrow();
38
- expect(() => spinner.update('updating')).not.toThrow();
39
- });
40
-
41
- test('returns functional spinner in interactive mode', () => {
42
- Object.defineProperty(process.stdin, 'isTTY', {
43
- value: true,
44
- writable: true,
45
- });
46
- Object.defineProperty(process.stdout, 'isTTY', {
47
- value: true,
48
- writable: true,
49
- });
50
- delete process.env.CI;
51
- delete process.env.GITHUB_ACTIONS;
52
- delete process.env.TERM;
53
-
54
- stderrSpy = spyOn(process.stderr, 'write').mockImplementation(() => true);
55
-
56
- const { createSpinner } = require('../../src/lib/spinner');
57
- const spinner = createSpinner('loading...');
58
-
59
- expect(spinner).toHaveProperty('stop');
60
- expect(spinner).toHaveProperty('fail');
61
- expect(spinner).toHaveProperty('warn');
62
- expect(spinner).toHaveProperty('update');
63
-
64
- // Stop to clean up the interval
65
- spinner.stop('done');
66
- expect(stderrSpy).toHaveBeenCalled();
67
- });
68
-
69
- test('stop writes checkmark to stderr', () => {
70
- Object.defineProperty(process.stdin, 'isTTY', {
71
- value: true,
72
- writable: true,
73
- });
74
- Object.defineProperty(process.stdout, 'isTTY', {
75
- value: true,
76
- writable: true,
77
- });
78
- delete process.env.CI;
79
- delete process.env.GITHUB_ACTIONS;
80
- delete process.env.TERM;
81
-
82
- stderrSpy = spyOn(process.stderr, 'write').mockImplementation(() => true);
83
-
84
- const { createSpinner } = require('../../src/lib/spinner');
85
- const spinner = createSpinner('loading...');
86
- spinner.stop('completed');
87
-
88
- const lastCall = stderrSpy.mock.calls[
89
- stderrSpy.mock.calls.length - 1
90
- ][0] as string;
91
- expect(lastCall).toContain('✔');
92
- expect(lastCall).toContain('completed');
93
- });
94
-
95
- test('fail writes cross mark to stderr', () => {
96
- Object.defineProperty(process.stdin, 'isTTY', {
97
- value: true,
98
- writable: true,
99
- });
100
- Object.defineProperty(process.stdout, 'isTTY', {
101
- value: true,
102
- writable: true,
103
- });
104
- delete process.env.CI;
105
- delete process.env.GITHUB_ACTIONS;
106
- delete process.env.TERM;
107
-
108
- stderrSpy = spyOn(process.stderr, 'write').mockImplementation(() => true);
109
-
110
- const { createSpinner } = require('../../src/lib/spinner');
111
- const spinner = createSpinner('loading...');
112
- spinner.fail('error occurred');
113
-
114
- const lastCall = stderrSpy.mock.calls[
115
- stderrSpy.mock.calls.length - 1
116
- ][0] as string;
117
- expect(lastCall).toContain('✗');
118
- expect(lastCall).toContain('error occurred');
119
- });
120
-
121
- test('warn writes warning icon to stderr', () => {
122
- Object.defineProperty(process.stdin, 'isTTY', {
123
- value: true,
124
- writable: true,
125
- });
126
- Object.defineProperty(process.stdout, 'isTTY', {
127
- value: true,
128
- writable: true,
129
- });
130
- delete process.env.CI;
131
- delete process.env.GITHUB_ACTIONS;
132
- delete process.env.TERM;
133
-
134
- stderrSpy = spyOn(process.stderr, 'write').mockImplementation(() => true);
135
-
136
- const { createSpinner } = require('../../src/lib/spinner');
137
- const spinner = createSpinner('loading...');
138
- spinner.warn('watch out');
139
-
140
- const lastCall = stderrSpy.mock.calls[
141
- stderrSpy.mock.calls.length - 1
142
- ][0] as string;
143
- expect(lastCall).toContain('⚠');
144
- expect(lastCall).toContain('watch out');
145
- });
146
- });
@@ -1,63 +0,0 @@
1
- import { describe, expect, test } from 'bun:test';
2
- import { renderTable } from '../../src/lib/table';
3
-
4
- describe('renderTable', () => {
5
- test('renders a table with correct border characters', () => {
6
- const output = renderTable(['Name', 'ID'], [['Alice', 'abc-123']]);
7
- expect(output).toContain('┌');
8
- expect(output).toContain('┐');
9
- expect(output).toContain('└');
10
- expect(output).toContain('┘');
11
- expect(output).toContain('│');
12
- });
13
-
14
- test('includes headers in output', () => {
15
- const output = renderTable(
16
- ['Name', 'Status'],
17
- [['my-domain.com', 'verified']],
18
- );
19
- expect(output).toContain('Name');
20
- expect(output).toContain('Status');
21
- });
22
-
23
- test('includes row data in output', () => {
24
- const output = renderTable(
25
- ['Name', 'Status'],
26
- [['my-domain.com', 'verified']],
27
- );
28
- expect(output).toContain('my-domain.com');
29
- expect(output).toContain('verified');
30
- });
31
-
32
- test('pads columns to the widest cell in each column', () => {
33
- const output = renderTable(
34
- ['Key', 'Value'],
35
- [
36
- ['short', 'a very long value here'],
37
- ['much longer key', 'v'],
38
- ],
39
- );
40
- // All rows should have the same line length
41
- const lines = output.split('\n');
42
- const lengths = lines.map((l) => l.length);
43
- expect(new Set(lengths).size).toBe(1);
44
- });
45
-
46
- test('renders multiple rows', () => {
47
- const output = renderTable(
48
- ['A', 'B'],
49
- [
50
- ['row1a', 'row1b'],
51
- ['row2a', 'row2b'],
52
- ],
53
- );
54
- expect(output).toContain('row1a');
55
- expect(output).toContain('row2a');
56
- });
57
-
58
- test('contains a separator row between header and data', () => {
59
- const output = renderTable(['Col'], [['val']]);
60
- expect(output).toContain('├');
61
- expect(output).toContain('┤');
62
- });
63
- });
@@ -1,85 +0,0 @@
1
- import { afterEach, describe, expect, test } from 'bun:test';
2
- import { captureTestEnv } from '../helpers';
3
-
4
- // We need to import the module fresh per test to pick up env changes,
5
- // so we use dynamic imports.
6
-
7
- describe('isInteractive', () => {
8
- const restoreEnv = captureTestEnv();
9
-
10
- afterEach(() => {
11
- restoreEnv();
12
- });
13
-
14
- function setTTY(stdin: boolean, stdout: boolean) {
15
- Object.defineProperty(process.stdin, 'isTTY', {
16
- value: stdin ? true : undefined,
17
- writable: true,
18
- });
19
- Object.defineProperty(process.stdout, 'isTTY', {
20
- value: stdout ? true : undefined,
21
- writable: true,
22
- });
23
- }
24
-
25
- test('returns true when stdin and stdout are TTY and no CI env', () => {
26
- setTTY(true, true);
27
- delete process.env.CI;
28
- delete process.env.GITHUB_ACTIONS;
29
- delete process.env.TERM;
30
-
31
- const { isInteractive } = require('../../src/lib/tty');
32
- expect(isInteractive()).toBe(true);
33
- });
34
-
35
- test('returns false when stdin is not TTY', () => {
36
- setTTY(false, true);
37
- delete process.env.CI;
38
-
39
- const { isInteractive } = require('../../src/lib/tty');
40
- expect(isInteractive()).toBe(false);
41
- });
42
-
43
- test('returns false when stdout is not TTY', () => {
44
- setTTY(true, false);
45
- delete process.env.CI;
46
-
47
- const { isInteractive } = require('../../src/lib/tty');
48
- expect(isInteractive()).toBe(false);
49
- });
50
-
51
- test('returns false when CI=true', () => {
52
- setTTY(true, true);
53
- process.env.CI = 'true';
54
-
55
- const { isInteractive } = require('../../src/lib/tty');
56
- expect(isInteractive()).toBe(false);
57
- });
58
-
59
- test('returns false when CI=1', () => {
60
- setTTY(true, true);
61
- process.env.CI = '1';
62
-
63
- const { isInteractive } = require('../../src/lib/tty');
64
- expect(isInteractive()).toBe(false);
65
- });
66
-
67
- test('returns false when GITHUB_ACTIONS is set', () => {
68
- setTTY(true, true);
69
- delete process.env.CI;
70
- process.env.GITHUB_ACTIONS = 'true';
71
-
72
- const { isInteractive } = require('../../src/lib/tty');
73
- expect(isInteractive()).toBe(false);
74
- });
75
-
76
- test('returns false when TERM=dumb', () => {
77
- setTTY(true, true);
78
- delete process.env.CI;
79
- delete process.env.GITHUB_ACTIONS;
80
- process.env.TERM = 'dumb';
81
-
82
- const { isInteractive } = require('../../src/lib/tty');
83
- expect(isInteractive()).toBe(false);
84
- });
85
- });
@@ -1,14 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ESNext",
4
- "module": "ESNext",
5
- "moduleResolution": "bundler",
6
- "esModuleInterop": true,
7
- "strict": true,
8
- "skipLibCheck": true,
9
- "outDir": "./dist",
10
- "rootDir": "./src",
11
- "types": ["bun"]
12
- },
13
- "include": ["src/**/*.ts"]
14
- }