Skip to content

Commit 6bea8da

Browse files
committed
fix: satisfy lib lint constraints
1 parent 47d56a0 commit 6bea8da

8 files changed

Lines changed: 286 additions & 258 deletions

File tree

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { Either } from "effect"
2+
3+
import { type CreateCommand, defaultTemplateConfig, isDockerNetworkMode, type ParseError } from "./domain.js"
4+
5+
const parsePort = (value: string): Either.Either<number, ParseError> => {
6+
const parsed = Number(value)
7+
if (!Number.isInteger(parsed)) {
8+
return Either.left({
9+
_tag: "InvalidOption",
10+
option: "--ssh-port",
11+
reason: `expected integer, got: ${value}`
12+
})
13+
}
14+
if (parsed < 1 || parsed > 65_535) {
15+
return Either.left({
16+
_tag: "InvalidOption",
17+
option: "--ssh-port",
18+
reason: "must be between 1 and 65535"
19+
})
20+
}
21+
return Either.right(parsed)
22+
}
23+
24+
export const parseSshPort = (value: string): Either.Either<number, ParseError> => parsePort(value)
25+
26+
export const parseDockerNetworkMode = (
27+
value: string | undefined
28+
): Either.Either<CreateCommand["config"]["dockerNetworkMode"], ParseError> => {
29+
const candidate = value?.trim() ?? defaultTemplateConfig.dockerNetworkMode
30+
if (isDockerNetworkMode(candidate)) {
31+
return Either.right(candidate)
32+
}
33+
return Either.left({
34+
_tag: "InvalidOption",
35+
option: "--network-mode",
36+
reason: "expected one of: shared, project"
37+
})
38+
}
39+
40+
export const nonEmpty = (
41+
option: string,
42+
value: string | undefined,
43+
fallback?: string
44+
): Either.Either<string, ParseError> => {
45+
const candidate = value?.trim() ?? fallback
46+
if (candidate === undefined || candidate.length === 0) {
47+
return Either.left({
48+
_tag: "MissingRequiredOption",
49+
option
50+
})
51+
}
52+
return Either.right(candidate)
53+
}

packages/lib/src/core/command-builders.ts

Lines changed: 4 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Either } from "effect"
22

33
import { expandContainerHome } from "../usecases/scrap-path.js"
44
import { resolveAutoAgentFlags } from "./auto-agent-flags.js"
5+
import { nonEmpty, parseDockerNetworkMode, parseSshPort } from "./command-builders-shared.js"
56
import { type RawOptions } from "./command-options.js"
67
import {
78
type AgentMode,
@@ -11,61 +12,14 @@ import {
1112
defaultTemplateConfig,
1213
deriveRepoPathParts,
1314
deriveRepoSlug,
14-
isDockerNetworkMode,
1515
type ParseError,
1616
resolveRepoInput
1717
} from "./domain.js"
1818
import { normalizeCpuLimit, normalizeRamLimit } from "./resource-limits.js"
1919
import { trimRightChar } from "./strings.js"
2020
import { normalizeAuthLabel, normalizeGitTokenLabel } from "./token-labels.js"
2121

22-
const parsePort = (value: string): Either.Either<number, ParseError> => {
23-
const parsed = Number(value)
24-
if (!Number.isInteger(parsed)) {
25-
return Either.left({
26-
_tag: "InvalidOption",
27-
option: "--ssh-port",
28-
reason: `expected integer, got: ${value}`
29-
})
30-
}
31-
if (parsed < 1 || parsed > 65_535) {
32-
return Either.left({
33-
_tag: "InvalidOption",
34-
option: "--ssh-port",
35-
reason: "must be between 1 and 65535"
36-
})
37-
}
38-
return Either.right(parsed)
39-
}
40-
41-
const parseDockerNetworkMode = (
42-
value: string | undefined
43-
): Either.Either<CreateCommand["config"]["dockerNetworkMode"], ParseError> => {
44-
const candidate = value?.trim() ?? defaultTemplateConfig.dockerNetworkMode
45-
if (isDockerNetworkMode(candidate)) {
46-
return Either.right(candidate)
47-
}
48-
return Either.left({
49-
_tag: "InvalidOption",
50-
option: "--network-mode",
51-
reason: "expected one of: shared, project"
52-
})
53-
}
54-
55-
export const nonEmpty = (
56-
option: string,
57-
value: string | undefined,
58-
fallback?: string
59-
): Either.Either<string, ParseError> => {
60-
const candidate = value?.trim() ?? fallback
61-
if (candidate === undefined || candidate.length === 0) {
62-
return Either.left({
63-
_tag: "MissingRequiredOption",
64-
option
65-
})
66-
}
67-
return Either.right(candidate)
68-
}
22+
export { nonEmpty } from "./command-builders-shared.js"
6923

7024
const normalizeSecretsRoot = (value: string): string => trimRightChar(value, "/")
7125

@@ -98,7 +52,7 @@ const resolveRepoBasics = (raw: RawOptions): Either.Either<RepoBasics, ParseErro
9852
nonEmpty("--target-dir", raw.targetDir, defaultTemplateConfig.targetDir)
9953
)
10054
const targetDir = expandContainerHome(sshUser, rawTargetDir)
101-
const sshPort = yield* _(parsePort(raw.sshPort ?? String(defaultTemplateConfig.sshPort)))
55+
const sshPort = yield* _(parseSshPort(raw.sshPort ?? String(defaultTemplateConfig.sshPort)))
10256

10357
return { repoUrl, repoSlug, projectSlug, repoPath, repoRef, targetDir, sshUser, sshPort }
10458
})
@@ -243,13 +197,13 @@ const buildTemplateConfig = ({
243197
claudeAuthLabel,
244198
codexAuthLabel,
245199
cpuLimit,
246-
ramLimit,
247200
dockerNetworkMode,
248201
dockerSharedNetworkName,
249202
enableMcpPlaywright,
250203
gitTokenLabel,
251204
names,
252205
paths,
206+
ramLimit,
253207
repo
254208
}: BuildTemplateConfigInput): CreateCommand["config"] => ({
255209
containerName: names.containerName,

packages/lib/src/core/resource-limits.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ const cpuAbsolutePattern = /^\d+(?:\.\d+)?$/u
2121
const ramAbsolutePattern = /^\d+(?:\.\d+)?(?:b|k|kb|m|mb|g|gb|t|tb)$/iu
2222
const percentPattern = /^\d+(?:\.\d+)?%$/u
2323

24-
const normalizePrecision = (value: number): number =>
25-
Math.round(value * precisionScale) / precisionScale
24+
const normalizePrecision = (value: number): number => Math.round(value * precisionScale) / precisionScale
25+
26+
const missingLimit = (): string | undefined => undefined
2627

2728
const parsePercent = (candidate: string): number | null => {
2829
if (!percentPattern.test(candidate)) {
@@ -58,7 +59,7 @@ export const normalizeCpuLimit = (
5859
): Either.Either<string | undefined, ParseError> => {
5960
const candidate = value?.trim().toLowerCase() ?? ""
6061
if (candidate.length === 0) {
61-
return Either.right(undefined)
62+
return Either.right(missingLimit())
6263
}
6364
if (candidate.endsWith("%")) {
6465
return normalizePercent(candidate, "cpu")
@@ -87,7 +88,7 @@ export const normalizeRamLimit = (
8788
): Either.Either<string | undefined, ParseError> => {
8889
const candidate = value?.trim().toLowerCase() ?? ""
8990
if (candidate.length === 0) {
90-
return Either.right(undefined)
91+
return Either.right(missingLimit())
9192
}
9293
if (candidate.endsWith("%")) {
9394
return normalizePercent(candidate, "ram")

packages/lib/src/core/templates/docker-compose.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,9 @@ const buildPlaywrightFragments = (
8282
maybePlaywrightEnv:
8383
` MCP_PLAYWRIGHT_ENABLE: "1"\n MCP_PLAYWRIGHT_CDP_ENDPOINT: "${browserCdpEndpoint}"\n`,
8484
maybeBrowserService:
85-
`\n ${browserServiceName}:\n build:\n context: .\n dockerfile: ${browserDockerfile}\n container_name: ${browserContainerName}\n restart: unless-stopped\n${renderResourceLimits(resourceLimits)} environment:\n VNC_NOPW: "1"\n shm_size: "2gb"\n expose:\n - "9223"\n volumes:\n - ${browserVolumeName}:/data\n networks:\n - ${networkName}\n`,
85+
`\n ${browserServiceName}:\n build:\n context: .\n dockerfile: ${browserDockerfile}\n container_name: ${browserContainerName}\n restart: unless-stopped\n${
86+
renderResourceLimits(resourceLimits)
87+
} environment:\n VNC_NOPW: "1"\n shm_size: "2gb"\n expose:\n - "9223"\n volumes:\n - ${browserVolumeName}:/data\n networks:\n - ${networkName}\n`,
8688
maybeBrowserVolume: ` ${browserVolumeName}:\n`
8789
}
8890
}

packages/lib/src/shell/files.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { availableParallelism, totalmem } from "os"
1+
import { availableParallelism, totalmem } from "node:os"
22

33
import type { PlatformError } from "@effect/platform/Error"
44
import type * as FileSystem from "@effect/platform/FileSystem"

0 commit comments

Comments
 (0)