Skip to content

Commit 3ab1ade

Browse files
committed
fix(docker-git): satisfy effect lint
1 parent 6192c77 commit 3ab1ade

2 files changed

Lines changed: 79 additions & 40 deletions

File tree

packages/app/src/docker-git/browser-frontend-state.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,14 +112,21 @@ export const readBrowserFrontendState = (
112112
): Effect.Effect<BrowserFrontendStateFile | null, never, FileSystem.FileSystem> =>
113113
Effect.gen(function*(_) {
114114
const fs = yield* _(FileSystem.FileSystem)
115-
const exists = yield* _(fs.exists(statePath))
116-
if (!exists) {
115+
const exists = yield* _(Effect.either(fs.exists(statePath)))
116+
const fileExists = Either.match(exists, {
117+
onLeft: () => false,
118+
onRight: (value) => value
119+
})
120+
if (!fileExists) {
117121
return null
118122
}
119123

120-
const contents = yield* _(fs.readFileString(statePath))
121-
return decodeBrowserFrontendStateFile(contents)
122-
}).pipe(Effect.catchAll(() => Effect.succeed(null)))
124+
const contents = yield* _(Effect.either(fs.readFileString(statePath)))
125+
return Either.match(contents, {
126+
onLeft: () => null,
127+
onRight: decodeBrowserFrontendStateFile
128+
})
129+
})
123130

124131
// CHANGE: make web reuse a pure predicate over durable state and observed listening pids
125132
// WHY: reruns should restart only the changed browser runtime, not the whole stack

packages/app/tests/docker-git/browser-frontend.test.ts

Lines changed: 67 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"
2-
import { tmpdir } from "node:os"
3-
import path from "node:path"
4-
51
import { NodeContext as BrowserFrontendTestNodeContext } from "@effect/platform-node"
2+
import type { PlatformError } from "@effect/platform/Error"
3+
import * as FileSystem from "@effect/platform/FileSystem"
4+
import * as Path from "@effect/platform/Path"
65
import { describe, expect, it } from "@effect/vitest"
76
import { Effect } from "effect"
87
import { afterEach, beforeEach, vi } from "vitest"
@@ -67,39 +66,72 @@ const requireEnvValue = (
6766
const writeWebStateFile = (
6867
statePath: string,
6968
state: Readonly<Record<string, string | number>>
70-
): void => {
71-
mkdirSync(path.dirname(statePath), { recursive: true })
72-
writeFileSync(statePath, `${JSON.stringify(state, null, 2)}\n`)
73-
}
69+
): Effect.Effect<void, PlatformError> =>
70+
Effect.gen(function*(_) {
71+
const fs = yield* _(FileSystem.FileSystem)
72+
const path = yield* _(Path.Path)
73+
yield* _(fs.makeDirectory(path.dirname(statePath), { recursive: true }))
74+
yield* _(fs.writeFileString(statePath, `${JSON.stringify(state, null, 2)}\n`))
75+
}).pipe(Effect.provide(BrowserFrontendTestNodeContext.layer))
76+
77+
const makeProjectsRoot = (): Effect.Effect<string, PlatformError> =>
78+
Effect.gen(function*(_) {
79+
const fs = yield* _(FileSystem.FileSystem)
80+
return yield* _(fs.makeTempDirectory({ prefix: "docker-git-browser-test-" }))
81+
}).pipe(Effect.provide(BrowserFrontendTestNodeContext.layer))
82+
83+
const removeProjectsRoot = (root: string): Effect.Effect<void, PlatformError> =>
84+
Effect.gen(function*(_) {
85+
const fs = yield* _(FileSystem.FileSystem)
86+
yield* _(fs.remove(root, { force: true, recursive: true }))
87+
}).pipe(Effect.provide(BrowserFrontendTestNodeContext.layer))
7488

7589
describe("browser frontend command", () => {
7690
let projectsRoot: string | null = null
7791

78-
beforeEach(() => {
79-
vi.resetModules()
80-
projectsRoot = mkdtempSync(path.join(tmpdir(), "docker-git-browser-test-"))
81-
process.env["DOCKER_GIT_PROJECTS_ROOT"] = projectsRoot
82-
makeNonInteractive()
83-
ensureControllerReadyMock.mockReset()
84-
ensureControllerReadyMock.mockImplementation(() => Effect.void)
85-
runCommandCaptureMock.mockReset()
86-
runCommandCaptureMock.mockImplementation(() => Effect.succeed(""))
87-
runCommandExitCodeMock.mockReset()
88-
runCommandExitCodeMock.mockImplementation(() => Effect.succeed(0))
89-
runCommandExitCodeStreamingMock.mockReset()
90-
runCommandExitCodeStreamingMock.mockImplementation(() => Effect.succeed(0))
91-
})
92-
93-
afterEach(() => {
94-
restoreTty()
95-
delete process.env["DOCKER_GIT_WEB_PORT"]
96-
delete process.env["DOCKER_GIT_WEB_HOST"]
97-
delete process.env["DOCKER_GIT_PROJECTS_ROOT"]
98-
if (projectsRoot !== null) {
99-
rmSync(projectsRoot, { force: true, recursive: true })
100-
projectsRoot = null
101-
}
102-
})
92+
beforeEach(() =>
93+
Effect.runPromise(
94+
makeProjectsRoot().pipe(
95+
Effect.tap((root) =>
96+
Effect.sync(() => {
97+
vi.resetModules()
98+
projectsRoot = root
99+
process.env["DOCKER_GIT_PROJECTS_ROOT"] = root
100+
makeNonInteractive()
101+
ensureControllerReadyMock.mockReset()
102+
ensureControllerReadyMock.mockImplementation(() => Effect.void)
103+
runCommandCaptureMock.mockReset()
104+
runCommandCaptureMock.mockImplementation(() => Effect.succeed(""))
105+
runCommandExitCodeMock.mockReset()
106+
runCommandExitCodeMock.mockImplementation(() => Effect.succeed(0))
107+
runCommandExitCodeStreamingMock.mockReset()
108+
runCommandExitCodeStreamingMock.mockImplementation(() => Effect.succeed(0))
109+
})
110+
),
111+
Effect.asVoid
112+
)
113+
)
114+
)
115+
116+
afterEach(() =>
117+
Effect.runPromise(
118+
Effect.gen(function*(_) {
119+
const root = projectsRoot
120+
yield* _(
121+
Effect.sync(() => {
122+
restoreTty()
123+
delete process.env["DOCKER_GIT_WEB_PORT"]
124+
delete process.env["DOCKER_GIT_WEB_HOST"]
125+
delete process.env["DOCKER_GIT_PROJECTS_ROOT"]
126+
projectsRoot = null
127+
})
128+
)
129+
if (root !== null) {
130+
yield* _(removeProjectsRoot(root))
131+
}
132+
})
133+
)
134+
)
103135

104136
it.effect("starts controller and web when nothing is running", () =>
105137
Effect.gen(function*(_) {
@@ -172,15 +204,15 @@ describe("browser frontend command", () => {
172204
const revision = requireEnvValue(serveEnv, "DOCKER_GIT_WEB_REVISION")
173205
const statePath = requireEnvValue(serveEnv, "DOCKER_GIT_WEB_STATE_PATH")
174206

175-
writeWebStateFile(statePath, {
207+
yield* _(writeWebStateFile(statePath, {
176208
schemaVersion: 1,
177209
revision,
178210
pid: "123",
179211
host: "0.0.0.0",
180212
port: "4174",
181213
apiBaseUrl: "http://127.0.0.1:3334",
182214
startedAtIso: "2026-04-21T00:00:00.000Z"
183-
})
215+
}))
184216

185217
ensureControllerReadyMock.mockClear()
186218
runCommandExitCodeMock.mockClear()

0 commit comments

Comments
 (0)