@markjaquith/agency 1.9.1 → 1.9.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.
- package/package.json +1 -1
- package/src/utils/spinner.test.ts +45 -0
- package/src/utils/spinner.ts +39 -26
package/package.json
CHANGED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test"
|
|
2
|
+
import { Effect } from "effect"
|
|
3
|
+
import { withSpinner } from "./spinner"
|
|
4
|
+
|
|
5
|
+
describe("withSpinner", () => {
|
|
6
|
+
test("clears and stops the spinner when an Effect failure has no fail text", async () => {
|
|
7
|
+
const originalNodeEnv = process.env.NODE_ENV
|
|
8
|
+
const originalBunEnv = process.env.BUN_ENV
|
|
9
|
+
delete process.env.NODE_ENV
|
|
10
|
+
delete process.env.BUN_ENV
|
|
11
|
+
|
|
12
|
+
const calls: string[] = []
|
|
13
|
+
const error = new Error("boom")
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
await expect(
|
|
17
|
+
Effect.runPromise(
|
|
18
|
+
withSpinner(Effect.fail(error), {
|
|
19
|
+
text: "Working",
|
|
20
|
+
createSpinner: () => ({
|
|
21
|
+
succeed: () => calls.push("succeed"),
|
|
22
|
+
fail: () => calls.push("fail"),
|
|
23
|
+
clear: () => calls.push("clear"),
|
|
24
|
+
stop: () => calls.push("stop"),
|
|
25
|
+
}),
|
|
26
|
+
}),
|
|
27
|
+
),
|
|
28
|
+
).rejects.toThrow("boom")
|
|
29
|
+
|
|
30
|
+
expect(calls).toEqual(["clear", "stop"])
|
|
31
|
+
} finally {
|
|
32
|
+
if (originalNodeEnv === undefined) {
|
|
33
|
+
delete process.env.NODE_ENV
|
|
34
|
+
} else {
|
|
35
|
+
process.env.NODE_ENV = originalNodeEnv
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (originalBunEnv === undefined) {
|
|
39
|
+
delete process.env.BUN_ENV
|
|
40
|
+
} else {
|
|
41
|
+
process.env.BUN_ENV = originalBunEnv
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
})
|
package/src/utils/spinner.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import ora from "ora"
|
|
2
|
-
import { Effect } from "effect"
|
|
2
|
+
import { Effect, Exit } from "effect"
|
|
3
|
+
|
|
4
|
+
interface Spinner {
|
|
5
|
+
succeed: (text?: string) => unknown
|
|
6
|
+
fail: (text?: string) => unknown
|
|
7
|
+
clear: () => unknown
|
|
8
|
+
stop: () => unknown
|
|
9
|
+
}
|
|
3
10
|
|
|
4
11
|
/**
|
|
5
12
|
* Check if we're running in a test environment
|
|
@@ -20,6 +27,8 @@ interface SpinnerConfig {
|
|
|
20
27
|
failText?: string
|
|
21
28
|
/** Whether the spinner is enabled (defaults to true) */
|
|
22
29
|
enabled?: boolean
|
|
30
|
+
/** Creates the spinner instance. Intended for tests. */
|
|
31
|
+
createSpinner?: (text: string) => Spinner
|
|
23
32
|
}
|
|
24
33
|
|
|
25
34
|
/**
|
|
@@ -53,31 +62,35 @@ export const withSpinner = <A, E, R>(
|
|
|
53
62
|
return effect
|
|
54
63
|
}
|
|
55
64
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const result = yield* effect
|
|
65
|
+
const createSpinner =
|
|
66
|
+
config.createSpinner ??
|
|
67
|
+
((text: string) =>
|
|
68
|
+
ora({
|
|
69
|
+
text,
|
|
70
|
+
spinner: "dots",
|
|
71
|
+
color: "cyan",
|
|
72
|
+
}).start())
|
|
65
73
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
74
|
+
return Effect.acquireUseRelease(
|
|
75
|
+
Effect.sync(() => createSpinner(text)),
|
|
76
|
+
() => effect,
|
|
77
|
+
(spinner, exit) =>
|
|
78
|
+
Effect.sync(() => {
|
|
79
|
+
if (Exit.isSuccess(exit)) {
|
|
80
|
+
if (successText) {
|
|
81
|
+
spinner.succeed(successText)
|
|
82
|
+
} else {
|
|
83
|
+
spinner.stop()
|
|
84
|
+
}
|
|
85
|
+
return
|
|
86
|
+
}
|
|
71
87
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
throw error
|
|
81
|
-
}
|
|
82
|
-
})
|
|
88
|
+
if (failText) {
|
|
89
|
+
spinner.fail(failText)
|
|
90
|
+
} else {
|
|
91
|
+
spinner.clear()
|
|
92
|
+
spinner.stop()
|
|
93
|
+
}
|
|
94
|
+
}),
|
|
95
|
+
)
|
|
83
96
|
}
|