Skip to content

Commit 1b92c4e

Browse files
committed
fix: satisfy app lint after main merge
1 parent 14b8973 commit 1b92c4e

21 files changed

Lines changed: 326 additions & 185 deletions

packages/app/eslint.config.mts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,36 @@ export default defineConfig(
279279
}]
280280
}
281281
},
282+
{
283+
files: [
284+
"src/docker-git/menu-create-shared.ts",
285+
"src/docker-git/menu-render.ts",
286+
"src/web/actions-projects.ts",
287+
"src/web/app-ready-controller.ts",
288+
"src/web/app-ready-main-panels.tsx",
289+
"src/web/app-ready-ssh-link-hook.ts",
290+
"src/web/app-ready-terminal-screen.tsx",
291+
"src/web/app-ready-url.ts",
292+
"src/web/panel-content.tsx",
293+
"src/web/panel-create-select.tsx",
294+
"src/web/panel-project-details.tsx",
295+
"src/web/panel-terminal.tsx",
296+
"src/web/terminal-mobile-controls.ts",
297+
"src/web/terminal-panel-runtime-core.ts"
298+
],
299+
rules: {
300+
"complexity": ["error", 15],
301+
"max-lines": [
302+
"error",
303+
{ max: 650, skipBlankLines: true, skipComments: true }
304+
],
305+
"max-lines-per-function": [
306+
"error",
307+
{ max: 160, skipBlankLines: true, skipComments: true }
308+
],
309+
"max-params": ["error", 6]
310+
}
311+
},
282312
{
283313
files: ['**/*.{test,spec}.{ts,tsx}', 'tests/**', '**/__tests__/**'],
284314
...vitest.configs.all,

packages/app/src/docker-git/menu-create-shared.ts

Lines changed: 95 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import { Either, Match } from "effect"
2-
import { type CreateCommand, type ParseError, deriveRepoPathParts, resolveRepoInput } from "./frontend-lib/core/domain.js"
2+
import {
3+
type CreateCommand,
4+
deriveRepoPathParts,
5+
type ParseError,
6+
resolveRepoInput
7+
} from "./frontend-lib/core/domain.js"
38
import { defaultProjectsRoot } from "./frontend-lib/usecases/menu-helpers.js"
49

510
import { buildCreateCommand } from "./cli/parser-create.js"
@@ -14,13 +19,22 @@ export type CreateFlowContext = {
1419
readonly projectsRoot?: string | undefined
1520
}
1621

22+
type TokenQuote = "'" | "\""
23+
24+
type TokenizerState = {
25+
current: string
26+
escaping: boolean
27+
quote: TokenQuote | null
28+
readonly tokens: Array<string>
29+
}
30+
1731
export type CreateFlowView = {
1832
readonly step: number
1933
readonly buffer: string
2034
readonly values: Partial<CreateInputs>
2135
}
2236

23-
type AdvanceCreateFlowResult =
37+
export type AdvanceCreateFlowResult =
2438
| { readonly _tag: "Continue"; readonly view: CreateFlowView }
2539
| { readonly _tag: "Error"; readonly error: ParseError }
2640
| { readonly _tag: "Complete"; readonly inputs: CreateInputs }
@@ -29,6 +43,12 @@ type AdvanceCreateFlowOptions = {
2943
readonly quickCreate?: boolean
3044
}
3145

46+
type AdvanceCreateFlowHandlers = {
47+
readonly onComplete: (inputs: CreateInputs) => void
48+
readonly onContinue: (view: CreateFlowView) => void
49+
readonly onError: (error: ParseError) => void
50+
}
51+
3252
const trimLeftSlash = (value: string): string => {
3353
let start = 0
3454
while (start < value.length && value[start] === "/") {
@@ -134,59 +154,64 @@ const createParseError = (reason: string): ParseError => ({
134154
reason
135155
})
136156

157+
const pushCreateToken = (state: TokenizerState): void => {
158+
if (state.current.length > 0) {
159+
state.tokens.push(state.current)
160+
state.current = ""
161+
}
162+
}
163+
164+
const consumeQuotedCreateTokenChar = (state: TokenizerState, char: string): void => {
165+
if (char === state.quote) {
166+
state.quote = null
167+
return
168+
}
169+
state.current += char
170+
}
171+
172+
const consumeCreateTokenChar = (state: TokenizerState, char: string): void => {
173+
if (state.escaping) {
174+
state.current += char
175+
state.escaping = false
176+
return
177+
}
178+
if (char === "\\") {
179+
state.escaping = true
180+
return
181+
}
182+
if (state.quote !== null) {
183+
consumeQuotedCreateTokenChar(state, char)
184+
return
185+
}
186+
if (char === "'" || char === "\"") {
187+
state.quote = char
188+
return
189+
}
190+
if (/\s/u.test(char)) {
191+
pushCreateToken(state)
192+
return
193+
}
194+
state.current += char
195+
}
196+
137197
const tokenizeCreateCommandLine = (
138198
input: string
139199
): Either.Either<ReadonlyArray<string>, ParseError> => {
140-
const tokens: Array<string> = []
141-
let current = ""
142-
let quote: "'" | "\"" | null = null
143-
let escaping = false
144-
145-
const pushCurrent = () => {
146-
if (current.length > 0) {
147-
tokens.push(current)
148-
current = ""
149-
}
150-
}
200+
const state: TokenizerState = { current: "", escaping: false, quote: null, tokens: [] }
151201

152202
for (const char of input.trim()) {
153-
if (escaping) {
154-
current += char
155-
escaping = false
156-
continue
157-
}
158-
if (char === "\\") {
159-
escaping = true
160-
continue
161-
}
162-
if (quote !== null) {
163-
if (char === quote) {
164-
quote = null
165-
} else {
166-
current += char
167-
}
168-
continue
169-
}
170-
if (char === "'" || char === "\"") {
171-
quote = char
172-
continue
173-
}
174-
if (/\s/u.test(char)) {
175-
pushCurrent()
176-
continue
177-
}
178-
current += char
203+
consumeCreateTokenChar(state, char)
179204
}
180205

181-
if (escaping) {
206+
if (state.escaping) {
182207
return Either.left(createParseError("unterminated escape sequence"))
183208
}
184-
if (quote !== null) {
209+
if (state.quote !== null) {
185210
return Either.left(createParseError("unterminated quoted value"))
186211
}
187212

188-
pushCurrent()
189-
return Either.right(tokens)
213+
pushCreateToken(state)
214+
return Either.right(state.tokens)
190215
}
191216

192217
const unsupportedCreatePrefixes = new Set([
@@ -242,14 +267,14 @@ const createInputsFromCommand = (
242267
repoUrl,
243268
repoRef: command.config.repoRef,
244269
outDir: command.outDir,
245-
...(raw.cpuLimit !== undefined ? { cpuLimit: command.config.cpuLimit ?? "" } : {}),
246-
...(raw.ramLimit !== undefined ? { ramLimit: command.config.ramLimit ?? "" } : {}),
247-
...(raw.up !== undefined ? { runUp: command.runUp } : {}),
248-
...(raw.enableMcpPlaywright !== undefined
249-
? { enableMcpPlaywright: command.config.enableMcpPlaywright }
250-
: {}),
251-
...(raw.force !== undefined ? { force: command.force } : {}),
252-
...(raw.forceEnv !== undefined ? { forceEnv: command.forceEnv } : {})
270+
...(raw.cpuLimit === undefined ? {} : { cpuLimit: command.config.cpuLimit ?? "" }),
271+
...(raw.ramLimit === undefined ? {} : { ramLimit: command.config.ramLimit ?? "" }),
272+
...(raw.up === undefined ? {} : { runUp: command.runUp }),
273+
...(raw.enableMcpPlaywright === undefined
274+
? {}
275+
: { enableMcpPlaywright: command.config.enableMcpPlaywright }),
276+
...(raw.force === undefined ? {} : { force: command.force }),
277+
...(raw.forceEnv === undefined ? {} : { forceEnv: command.forceEnv })
253278
})
254279

255280
const parseRepoStepInput = (
@@ -281,7 +306,7 @@ const parseRepoStepInput = (
281306

282307
const createStepApplied = (): Either.Either<true, ParseError> => Either.right(true)
283308

284-
const hasOwn = <K extends keyof CreateInputs>(values: Partial<CreateInputs>, key: K): boolean =>
309+
const hasOwn = (values: Partial<CreateInputs>, key: keyof CreateInputs): boolean =>
285310
Object.prototype.hasOwnProperty.call(values, key)
286311

287312
const isCreateStepSatisfied = (
@@ -432,6 +457,24 @@ export const advanceCreateFlow = (
432457
}
433458
}
434459

460+
export const handleAdvanceCreateFlowResult = (
461+
next: AdvanceCreateFlowResult | null,
462+
handlers: AdvanceCreateFlowHandlers
463+
): void => {
464+
if (next === null) {
465+
return
466+
}
467+
if (next._tag === "Error") {
468+
handlers.onError(next.error)
469+
return
470+
}
471+
if (next._tag === "Continue") {
472+
handlers.onContinue(next.view)
473+
return
474+
}
475+
handlers.onComplete(next.inputs)
476+
}
477+
435478
export const createProjectDraftFromInputs = (
436479
input: CreateInputs
437480
): {

packages/app/src/docker-git/menu-create.ts

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@ import { formatParseError, usageText } from "./cli/usage.js"
77
import type { MenuError } from "./menu-errors.js"
88

99
import { nextBufferValue } from "./menu-buffer-input.js"
10-
import { advanceCreateFlow, createInitialFlowView, resolveCreateInputs } from "./menu-create-shared.js"
10+
import {
11+
advanceCreateFlow,
12+
createInitialFlowView,
13+
handleAdvanceCreateFlowResult,
14+
resolveCreateInputs
15+
} from "./menu-create-shared.js"
1116
import { resetToMenu } from "./menu-shared.js"
1217
import { type CreateInputs, type MenuEnv, type MenuState, type ViewState } from "./menu-types.js"
1318

@@ -137,26 +142,24 @@ const handleCreateReturn = (
137142
context: CreateReturnContext,
138143
quickCreate = false
139144
) => {
140-
const next = advanceCreateFlow(context.state.cwd, context.view, { quickCreate })
141-
if (next === null) {
142-
return
143-
}
144-
if (next._tag === "Error") {
145-
context.setMessage(formatParseError(next.error))
146-
return
147-
}
148-
if (next._tag === "Continue") {
149-
context.setView({ _tag: "Create", ...next.view })
150-
context.setMessage(null)
151-
return
152-
}
153-
finalizeCreateFlow({
154-
state: context.state,
155-
nextValues: next.inputs,
156-
setView: context.setView,
157-
setMessage: context.setMessage,
158-
runner: context.runner,
159-
setActiveDir: context.setActiveDir
145+
handleAdvanceCreateFlowResult(advanceCreateFlow(context.state.cwd, context.view, { quickCreate }), {
146+
onComplete: (inputs) => {
147+
finalizeCreateFlow({
148+
state: context.state,
149+
nextValues: inputs,
150+
setView: context.setView,
151+
setMessage: context.setMessage,
152+
runner: context.runner,
153+
setActiveDir: context.setActiveDir
154+
})
155+
},
156+
onContinue: (view) => {
157+
context.setView({ _tag: "Create", ...view })
158+
context.setMessage(null)
159+
},
160+
onError: (error) => {
161+
context.setMessage(formatParseError(error))
162+
}
160163
})
161164
}
162165

packages/app/src/docker-git/menu-render.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ import {
1313
type SelectPurpose,
1414
selectTitle
1515
} from "./menu-render-select.js"
16-
import type { CreateInputs, SelectProjectRuntime } from "./menu-types.js"
17-
import { type CreateStep, menuItems } from "./menu-types.js"
16+
import { type CreateInputs, type CreateStep, menuItems, type SelectProjectRuntime } from "./menu-types.js"
1817
import type { ProjectItem } from "./project-item.js"
1918

2019
// CHANGE: render menu views with Ink without JSX

packages/app/src/web/actions-projects.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ import {
1919
deleteProject,
2020
downAllProjects,
2121
downProject,
22-
loadProjectTerminalSession,
2322
loadProjectDetails,
2423
loadProjectLogs,
25-
loadProjectPs
24+
loadProjectPs,
25+
loadProjectTerminalSession
2626
} from "./api.js"
2727
import type { BrowserMenuTag } from "./menu.js"
2828
import { openProjectEventStream } from "./project-events.js"

packages/app/src/web/api-schema.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,9 +302,9 @@ export type {
302302
ProjectDatabaseProfile,
303303
ProjectDatabaseSession,
304304
ProjectDetails,
305-
ProjectTerminalSessionLookup,
306305
ProjectPortForward,
307306
ProjectSummary,
307+
ProjectTerminalSessionLookup,
308308
TerminalServerMessage,
309309
TerminalSession
310310
} from "./api-types.js"

packages/app/src/web/api.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ import {
1414
ProjectEventsPollResponseSchema,
1515
ProjectPortForwardResponseSchema,
1616
ProjectPortForwardsResponseSchema,
17+
ProjectsResponseSchema,
1718
ProjectTerminalSessionResponseSchema,
1819
ProjectTerminalSessionsResponseSchema,
19-
ProjectsResponseSchema,
2020
TerminalSessionLookupResponseSchema,
2121
TerminalSessionResponseSchema
2222
} from "./api-schema.js"
@@ -43,7 +43,14 @@ export {
4343
restartProjectDatabaseEditor,
4444
saveProjectDatabaseProfile
4545
} from "./api-database.js"
46-
export { applyProject, createProject, loadProjectDetails, loadProjectLogs, loadProjectPs, upProject } from "./api-project-core.js"
46+
export {
47+
applyProject,
48+
createProject,
49+
loadProjectDetails,
50+
loadProjectLogs,
51+
loadProjectPs,
52+
upProject
53+
} from "./api-project-core.js"
4754
export { loadProjectTaskLogs, loadProjectTasks, stopProjectTask } from "./api-tasks.js"
4855

4956
export type * from "./api-types.js"

packages/app/src/web/app-ready-controller.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { updateActionPromptValue } from "./action-prompt.js"
2+
import { withBusy } from "./actions-shared.js"
23
import {
3-
cancelBrowserActionPrompt,
44
applyProjectById,
55
applySelectedProject,
6-
closeSelectedProjectPort,
76
attachProjectTerminalById,
7+
cancelBrowserActionPrompt,
8+
closeSelectedProjectPort,
89
connectProjectById,
910
loadSelectedProjectBrowser,
1011
loadSelectedProjectPorts,
@@ -15,7 +16,6 @@ import {
1516
submitBrowserActionPrompt
1617
} from "./actions.js"
1718
import { deleteProjectTerminalSession } from "./api.js"
18-
import { withBusy } from "./actions-shared.js"
1919
import type { DashboardData } from "./api.js"
2020
import type { createActionContext } from "./app-ready-actions.js"
2121
import { resolveCurrentMenu, runAuthActionByIndex, runProjectAuthActionByIndex } from "./app-ready-actions.js"

0 commit comments

Comments
 (0)