@prover-coder-ai/docker-git 1.0.10 → 1.0.12
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.release.bak +1 -1
- package/CHANGELOG.md +12 -0
- package/README.md +5 -1
- package/dist/main.js +165 -165
- package/dist/main.js.map +1 -1
- package/dist/src/docker-git/cli/parser-clone.js +2 -1
- package/dist/src/docker-git/cli/parser-mcp-playwright.js +18 -0
- package/dist/src/docker-git/cli/parser-options.js +2 -0
- package/dist/src/docker-git/cli/parser.js +3 -2
- package/dist/src/docker-git/cli/usage.js +3 -0
- package/dist/src/docker-git/program.js +2 -1
- package/package.json +1 -1
- package/src/docker-git/cli/parser-clone.ts +2 -1
- package/src/docker-git/cli/parser-mcp-playwright.ts +25 -0
- package/src/docker-git/cli/parser-options.ts +2 -0
- package/src/docker-git/cli/parser.ts +7 -3
- package/src/docker-git/cli/usage.ts +3 -0
- package/src/docker-git/program.ts +5 -1
- package/tests/docker-git/parser.test.ts +44 -0
|
@@ -34,7 +34,8 @@ export const parseClone = (args) => {
|
|
|
34
34
|
const withRef = resolvedRepo.repoRef !== undefined && raw.repoRef === undefined
|
|
35
35
|
? { ...withDefaults, repoRef: resolvedRepo.repoRef }
|
|
36
36
|
: withDefaults;
|
|
37
|
+
const openSsh = raw.openSsh ?? true;
|
|
37
38
|
const create = yield* _(buildCreateCommand(withRef));
|
|
38
|
-
return { ...create, waitForClone: true };
|
|
39
|
+
return { ...create, waitForClone: true, openSsh };
|
|
39
40
|
});
|
|
40
41
|
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Either } from "effect";
|
|
2
|
+
import {} from "@effect-template/lib/core/domain";
|
|
3
|
+
import { parseProjectDirWithOptions } from "./parser-shared.js";
|
|
4
|
+
// CHANGE: parse "mcp-playwright" command for existing docker-git projects
|
|
5
|
+
// WHY: allow enabling Playwright MCP in an already created container/project dir
|
|
6
|
+
// QUOTE(ТЗ): "Добавить возможность поднимать MCP Playrgiht в контейнере который уже создан"
|
|
7
|
+
// REF: issue-29
|
|
8
|
+
// SOURCE: n/a
|
|
9
|
+
// FORMAT THEOREM: forall argv: parseMcpPlaywright(argv) = cmd -> deterministic(cmd)
|
|
10
|
+
// PURITY: CORE
|
|
11
|
+
// EFFECT: Effect<McpPlaywrightUpCommand, ParseError, never>
|
|
12
|
+
// INVARIANT: projectDir is never empty
|
|
13
|
+
// COMPLEXITY: O(n) where n = |argv|
|
|
14
|
+
export const parseMcpPlaywright = (args) => Either.map(parseProjectDirWithOptions(args), ({ projectDir, raw }) => ({
|
|
15
|
+
_tag: "McpPlaywrightUp",
|
|
16
|
+
projectDir,
|
|
17
|
+
runUp: raw.up ?? true
|
|
18
|
+
}));
|
|
@@ -31,6 +31,8 @@ const valueOptionSpecByFlag = new Map(valueOptionSpecs.map((spec) => [spec.flag,
|
|
|
31
31
|
const booleanFlagUpdaters = {
|
|
32
32
|
"--up": (raw) => ({ ...raw, up: true }),
|
|
33
33
|
"--no-up": (raw) => ({ ...raw, up: false }),
|
|
34
|
+
"--ssh": (raw) => ({ ...raw, openSsh: true }),
|
|
35
|
+
"--no-ssh": (raw) => ({ ...raw, openSsh: false }),
|
|
34
36
|
"--force": (raw) => ({ ...raw, force: true }),
|
|
35
37
|
"--force-env": (raw) => ({ ...raw, forceEnv: true }),
|
|
36
38
|
"--mcp-playwright": (raw) => ({ ...raw, enableMcpPlaywright: true }),
|
|
@@ -4,6 +4,7 @@ import { parseAttach } from "./parser-attach.js";
|
|
|
4
4
|
import { parseAuth } from "./parser-auth.js";
|
|
5
5
|
import { parseClone } from "./parser-clone.js";
|
|
6
6
|
import { buildCreateCommand } from "./parser-create.js";
|
|
7
|
+
import { parseMcpPlaywright } from "./parser-mcp-playwright.js";
|
|
7
8
|
import { parseRawOptions } from "./parser-options.js";
|
|
8
9
|
import { parsePanes } from "./parser-panes.js";
|
|
9
10
|
import { parseScrap } from "./parser-scrap.js";
|
|
@@ -40,6 +41,6 @@ export const parseArgs = (args) => {
|
|
|
40
41
|
command: command ?? ""
|
|
41
42
|
};
|
|
42
43
|
return Match.value(command)
|
|
43
|
-
.pipe(Match.when("create", () => parseCreate(rest)), Match.when("init", () => parseCreate(rest)), Match.when("clone", () => parseClone(rest)), Match.when("attach", () => parseAttach(rest)), Match.when("tmux", () => parseAttach(rest)), Match.when("panes", () => parsePanes(rest)), Match.when("terms", () => parsePanes(rest)), Match.when("terminals", () => parsePanes(rest)), Match.when("sessions", () => parseSessions(rest)), Match.when("scrap", () => parseScrap(rest)), Match.when("help", () => Either.right(helpCommand)), Match.when("ps", () => Either.right(statusCommand)), Match.when("status", () => Either.right(statusCommand)), Match.when("down-all", () => Either.right(downAllCommand)), Match.when("stop-all", () => Either.right(downAllCommand)), Match.when("kill-all", () => Either.right(downAllCommand)), Match.when("menu", () => Either.right(menuCommand)), Match.when("ui", () => Either.right(menuCommand)), Match.when("auth", () => parseAuth(rest))
|
|
44
|
-
.pipe(Match.orElse(() => Either.left(unknownCommandError)));
|
|
44
|
+
.pipe(Match.when("create", () => parseCreate(rest)), Match.when("init", () => parseCreate(rest)), Match.when("clone", () => parseClone(rest)), Match.when("attach", () => parseAttach(rest)), Match.when("tmux", () => parseAttach(rest)), Match.when("panes", () => parsePanes(rest)), Match.when("terms", () => parsePanes(rest)), Match.when("terminals", () => parsePanes(rest)), Match.when("sessions", () => parseSessions(rest)), Match.when("scrap", () => parseScrap(rest)), Match.when("mcp-playwright", () => parseMcpPlaywright(rest)), Match.when("help", () => Either.right(helpCommand)), Match.when("ps", () => Either.right(statusCommand)), Match.when("status", () => Either.right(statusCommand)), Match.when("down-all", () => Either.right(downAllCommand)), Match.when("stop-all", () => Either.right(downAllCommand)), Match.when("kill-all", () => Either.right(downAllCommand)), Match.when("menu", () => Either.right(menuCommand)), Match.when("ui", () => Either.right(menuCommand)), Match.when("auth", () => parseAuth(rest)))
|
|
45
|
+
.pipe(Match.when("state", () => parseState(rest)), Match.orElse(() => Either.left(unknownCommandError)));
|
|
45
46
|
};
|
|
@@ -2,6 +2,7 @@ import { Match } from "effect";
|
|
|
2
2
|
export const usageText = `docker-git menu
|
|
3
3
|
docker-git create --repo-url <url> [options]
|
|
4
4
|
docker-git clone <url> [options]
|
|
5
|
+
docker-git mcp-playwright [<url>] [options]
|
|
5
6
|
docker-git attach [<url>] [options]
|
|
6
7
|
docker-git panes [<url>] [options]
|
|
7
8
|
docker-git scrap <action> [<url>] [options]
|
|
@@ -17,6 +18,7 @@ Commands:
|
|
|
17
18
|
menu Interactive menu (default when no args)
|
|
18
19
|
create, init Generate docker development environment
|
|
19
20
|
clone Create + run container and clone repo
|
|
21
|
+
mcp-playwright Enable Playwright MCP + Chromium sidecar for an existing project dir
|
|
20
22
|
attach, tmux Open tmux workspace for a docker-git project
|
|
21
23
|
panes, terms List tmux panes for a docker-git project
|
|
22
24
|
scrap Export/import project scrap (session snapshot + rebuildable deps)
|
|
@@ -49,6 +51,7 @@ Options:
|
|
|
49
51
|
--lines <n> Tail last N lines for sessions logs (default: 200)
|
|
50
52
|
--include-default Show default/system processes in sessions list
|
|
51
53
|
--up | --no-up Run docker compose up after init (default: --up)
|
|
54
|
+
--ssh | --no-ssh Auto-open SSH after create/clone (default: clone=--ssh, create=--no-ssh)
|
|
52
55
|
--mcp-playwright | --no-mcp-playwright Enable Playwright MCP + Chromium sidecar (default: --no-mcp-playwright)
|
|
53
56
|
--force Overwrite existing files and wipe compose volumes (docker compose down -v)
|
|
54
57
|
--force-env Reset project env defaults only (keep workspace volume/data)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createProject } from "@effect-template/lib/usecases/actions";
|
|
2
2
|
import { authCodexLogin, authCodexLogout, authCodexStatus, authGithubLogin, authGithubLogout, authGithubStatus } from "@effect-template/lib/usecases/auth";
|
|
3
3
|
import { renderError } from "@effect-template/lib/usecases/errors";
|
|
4
|
+
import { mcpPlaywrightUp } from "@effect-template/lib/usecases/mcp-playwright";
|
|
4
5
|
import { downAllDockerGitProjects, listProjectStatus } from "@effect-template/lib/usecases/projects";
|
|
5
6
|
import { exportScrap, importScrap } from "@effect-template/lib/usecases/scrap";
|
|
6
7
|
import { stateCommit, stateInit, statePath, statePull, statePush, stateStatus, stateSync } from "@effect-template/lib/usecases/state-repo";
|
|
@@ -22,7 +23,7 @@ const logWarningAndExit = (error) => pipe(Effect.logWarning(renderError(error)),
|
|
|
22
23
|
const logErrorAndExit = (error) => pipe(Effect.logError(renderError(error)), Effect.tap(() => setExitCode(1)), Effect.asVoid);
|
|
23
24
|
const handleNonBaseCommand = (command) => Match.value(command)
|
|
24
25
|
.pipe(Match.when({ _tag: "StatePath" }, () => statePath), Match.when({ _tag: "StateInit" }, (cmd) => stateInit(cmd)), Match.when({ _tag: "StateStatus" }, () => stateStatus), Match.when({ _tag: "StatePull" }, () => statePull), Match.when({ _tag: "StateCommit" }, (cmd) => stateCommit(cmd.message)), Match.when({ _tag: "StatePush" }, () => statePush), Match.when({ _tag: "StateSync" }, (cmd) => stateSync(cmd.message)), Match.when({ _tag: "AuthGithubLogin" }, (cmd) => authGithubLogin(cmd)), Match.when({ _tag: "AuthGithubStatus" }, (cmd) => authGithubStatus(cmd)), Match.when({ _tag: "AuthGithubLogout" }, (cmd) => authGithubLogout(cmd)), Match.when({ _tag: "AuthCodexLogin" }, (cmd) => authCodexLogin(cmd)), Match.when({ _tag: "AuthCodexStatus" }, (cmd) => authCodexStatus(cmd)), Match.when({ _tag: "AuthCodexLogout" }, (cmd) => authCodexLogout(cmd)), Match.when({ _tag: "Attach" }, (cmd) => attachTmux(cmd)), Match.when({ _tag: "Panes" }, (cmd) => listTmuxPanes(cmd)), Match.when({ _tag: "SessionsList" }, (cmd) => listTerminalSessions(cmd)), Match.when({ _tag: "SessionsKill" }, (cmd) => killTerminalProcess(cmd)), Match.when({ _tag: "SessionsLogs" }, (cmd) => tailTerminalLogs(cmd)), Match.when({ _tag: "ScrapExport" }, (cmd) => exportScrap(cmd)), Match.when({ _tag: "ScrapImport" }, (cmd) => importScrap(cmd)))
|
|
25
|
-
.pipe(Match.exhaustive);
|
|
26
|
+
.pipe(Match.when({ _tag: "McpPlaywrightUp" }, (cmd) => mcpPlaywrightUp(cmd)), Match.exhaustive);
|
|
26
27
|
// CHANGE: compose CLI program with typed errors and shell effects
|
|
27
28
|
// WHY: keep a thin entry layer over pure parsing and template generation
|
|
28
29
|
// QUOTE(ТЗ): "CLI команду... создавать докер образы"
|
package/package.json
CHANGED
|
@@ -49,7 +49,8 @@ export const parseClone = (args: ReadonlyArray<string>): Either.Either<Command,
|
|
|
49
49
|
const withRef = resolvedRepo.repoRef !== undefined && raw.repoRef === undefined
|
|
50
50
|
? { ...withDefaults, repoRef: resolvedRepo.repoRef }
|
|
51
51
|
: withDefaults
|
|
52
|
+
const openSsh = raw.openSsh ?? true
|
|
52
53
|
const create = yield* _(buildCreateCommand(withRef))
|
|
53
|
-
return { ...create, waitForClone: true }
|
|
54
|
+
return { ...create, waitForClone: true, openSsh }
|
|
54
55
|
})
|
|
55
56
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Either } from "effect"
|
|
2
|
+
|
|
3
|
+
import { type McpPlaywrightUpCommand, type ParseError } from "@effect-template/lib/core/domain"
|
|
4
|
+
|
|
5
|
+
import { parseProjectDirWithOptions } from "./parser-shared.js"
|
|
6
|
+
|
|
7
|
+
// CHANGE: parse "mcp-playwright" command for existing docker-git projects
|
|
8
|
+
// WHY: allow enabling Playwright MCP in an already created container/project dir
|
|
9
|
+
// QUOTE(ТЗ): "Добавить возможность поднимать MCP Playrgiht в контейнере который уже создан"
|
|
10
|
+
// REF: issue-29
|
|
11
|
+
// SOURCE: n/a
|
|
12
|
+
// FORMAT THEOREM: forall argv: parseMcpPlaywright(argv) = cmd -> deterministic(cmd)
|
|
13
|
+
// PURITY: CORE
|
|
14
|
+
// EFFECT: Effect<McpPlaywrightUpCommand, ParseError, never>
|
|
15
|
+
// INVARIANT: projectDir is never empty
|
|
16
|
+
// COMPLEXITY: O(n) where n = |argv|
|
|
17
|
+
export const parseMcpPlaywright = (
|
|
18
|
+
args: ReadonlyArray<string>
|
|
19
|
+
): Either.Either<McpPlaywrightUpCommand, ParseError> =>
|
|
20
|
+
Either.map(parseProjectDirWithOptions(args), ({ projectDir, raw }) => ({
|
|
21
|
+
_tag: "McpPlaywrightUp",
|
|
22
|
+
projectDir,
|
|
23
|
+
runUp: raw.up ?? true
|
|
24
|
+
}))
|
|
25
|
+
|
|
@@ -69,6 +69,8 @@ type ValueKey = ValueOptionSpec["key"]
|
|
|
69
69
|
const booleanFlagUpdaters: Readonly<Record<string, (raw: RawOptions) => RawOptions>> = {
|
|
70
70
|
"--up": (raw) => ({ ...raw, up: true }),
|
|
71
71
|
"--no-up": (raw) => ({ ...raw, up: false }),
|
|
72
|
+
"--ssh": (raw) => ({ ...raw, openSsh: true }),
|
|
73
|
+
"--no-ssh": (raw) => ({ ...raw, openSsh: false }),
|
|
72
74
|
"--force": (raw) => ({ ...raw, force: true }),
|
|
73
75
|
"--force-env": (raw) => ({ ...raw, forceEnv: true }),
|
|
74
76
|
"--mcp-playwright": (raw) => ({ ...raw, enableMcpPlaywright: true }),
|
|
@@ -6,6 +6,7 @@ import { parseAttach } from "./parser-attach.js"
|
|
|
6
6
|
import { parseAuth } from "./parser-auth.js"
|
|
7
7
|
import { parseClone } from "./parser-clone.js"
|
|
8
8
|
import { buildCreateCommand } from "./parser-create.js"
|
|
9
|
+
import { parseMcpPlaywright } from "./parser-mcp-playwright.js"
|
|
9
10
|
import { parseRawOptions } from "./parser-options.js"
|
|
10
11
|
import { parsePanes } from "./parser-panes.js"
|
|
11
12
|
import { parseScrap } from "./parser-scrap.js"
|
|
@@ -61,6 +62,7 @@ export const parseArgs = (args: ReadonlyArray<string>): Either.Either<Command, P
|
|
|
61
62
|
Match.when("terminals", () => parsePanes(rest)),
|
|
62
63
|
Match.when("sessions", () => parseSessions(rest)),
|
|
63
64
|
Match.when("scrap", () => parseScrap(rest)),
|
|
65
|
+
Match.when("mcp-playwright", () => parseMcpPlaywright(rest)),
|
|
64
66
|
Match.when("help", () => Either.right(helpCommand)),
|
|
65
67
|
Match.when("ps", () => Either.right(statusCommand)),
|
|
66
68
|
Match.when("status", () => Either.right(statusCommand)),
|
|
@@ -69,8 +71,10 @@ export const parseArgs = (args: ReadonlyArray<string>): Either.Either<Command, P
|
|
|
69
71
|
Match.when("kill-all", () => Either.right(downAllCommand)),
|
|
70
72
|
Match.when("menu", () => Either.right(menuCommand)),
|
|
71
73
|
Match.when("ui", () => Either.right(menuCommand)),
|
|
72
|
-
Match.when("auth", () => parseAuth(rest))
|
|
73
|
-
|
|
74
|
+
Match.when("auth", () => parseAuth(rest))
|
|
75
|
+
)
|
|
76
|
+
.pipe(
|
|
77
|
+
Match.when("state", () => parseState(rest)),
|
|
78
|
+
Match.orElse(() => Either.left(unknownCommandError))
|
|
74
79
|
)
|
|
75
|
-
.pipe(Match.orElse(() => Either.left(unknownCommandError)))
|
|
76
80
|
}
|
|
@@ -5,6 +5,7 @@ import type { ParseError } from "@effect-template/lib/core/domain"
|
|
|
5
5
|
export const usageText = `docker-git menu
|
|
6
6
|
docker-git create --repo-url <url> [options]
|
|
7
7
|
docker-git clone <url> [options]
|
|
8
|
+
docker-git mcp-playwright [<url>] [options]
|
|
8
9
|
docker-git attach [<url>] [options]
|
|
9
10
|
docker-git panes [<url>] [options]
|
|
10
11
|
docker-git scrap <action> [<url>] [options]
|
|
@@ -20,6 +21,7 @@ Commands:
|
|
|
20
21
|
menu Interactive menu (default when no args)
|
|
21
22
|
create, init Generate docker development environment
|
|
22
23
|
clone Create + run container and clone repo
|
|
24
|
+
mcp-playwright Enable Playwright MCP + Chromium sidecar for an existing project dir
|
|
23
25
|
attach, tmux Open tmux workspace for a docker-git project
|
|
24
26
|
panes, terms List tmux panes for a docker-git project
|
|
25
27
|
scrap Export/import project scrap (session snapshot + rebuildable deps)
|
|
@@ -52,6 +54,7 @@ Options:
|
|
|
52
54
|
--lines <n> Tail last N lines for sessions logs (default: 200)
|
|
53
55
|
--include-default Show default/system processes in sessions list
|
|
54
56
|
--up | --no-up Run docker compose up after init (default: --up)
|
|
57
|
+
--ssh | --no-ssh Auto-open SSH after create/clone (default: clone=--ssh, create=--no-ssh)
|
|
55
58
|
--mcp-playwright | --no-mcp-playwright Enable Playwright MCP + Chromium sidecar (default: --no-mcp-playwright)
|
|
56
59
|
--force Overwrite existing files and wipe compose volumes (docker compose down -v)
|
|
57
60
|
--force-env Reset project env defaults only (keep workspace volume/data)
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
} from "@effect-template/lib/usecases/auth"
|
|
11
11
|
import type { AppError } from "@effect-template/lib/usecases/errors"
|
|
12
12
|
import { renderError } from "@effect-template/lib/usecases/errors"
|
|
13
|
+
import { mcpPlaywrightUp } from "@effect-template/lib/usecases/mcp-playwright"
|
|
13
14
|
import { downAllDockerGitProjects, listProjectStatus } from "@effect-template/lib/usecases/projects"
|
|
14
15
|
import { exportScrap, importScrap } from "@effect-template/lib/usecases/scrap"
|
|
15
16
|
import {
|
|
@@ -92,7 +93,10 @@ const handleNonBaseCommand = (command: NonBaseCommand) =>
|
|
|
92
93
|
Match.when({ _tag: "ScrapExport" }, (cmd) => exportScrap(cmd)),
|
|
93
94
|
Match.when({ _tag: "ScrapImport" }, (cmd) => importScrap(cmd))
|
|
94
95
|
)
|
|
95
|
-
.pipe(
|
|
96
|
+
.pipe(
|
|
97
|
+
Match.when({ _tag: "McpPlaywrightUp" }, (cmd) => mcpPlaywrightUp(cmd)),
|
|
98
|
+
Match.exhaustive
|
|
99
|
+
)
|
|
96
100
|
|
|
97
101
|
// CHANGE: compose CLI program with typed errors and shell effects
|
|
98
102
|
// WHY: keep a thin entry layer over pure parsing and template generation
|
|
@@ -56,6 +56,8 @@ describe("parseArgs", () => {
|
|
|
56
56
|
it.effect("parses create command with defaults", () =>
|
|
57
57
|
expectCreateCommand(["create", "--repo-url", "https://github.com/org/repo.git"], (command) => {
|
|
58
58
|
expectCreateDefaults(command)
|
|
59
|
+
expect(command.openSsh).toBe(false)
|
|
60
|
+
expect(command.waitForClone).toBe(false)
|
|
59
61
|
expect(command.config.containerName).toBe("dg-repo")
|
|
60
62
|
expect(command.config.serviceName).toBe("dg-repo")
|
|
61
63
|
expect(command.config.volumeName).toBe("dg-repo-home")
|
|
@@ -67,6 +69,8 @@ describe("parseArgs", () => {
|
|
|
67
69
|
expect(command.config.repoUrl).toBe("https://github.com/org/repo.git")
|
|
68
70
|
expect(command.config.repoRef).toBe("issue-9")
|
|
69
71
|
expect(command.outDir).toBe(".docker-git/org/repo/issue-9")
|
|
72
|
+
expect(command.openSsh).toBe(false)
|
|
73
|
+
expect(command.waitForClone).toBe(false)
|
|
70
74
|
expect(command.config.containerName).toBe("dg-repo-issue-9")
|
|
71
75
|
expect(command.config.serviceName).toBe("dg-repo-issue-9")
|
|
72
76
|
expect(command.config.volumeName).toBe("dg-repo-issue-9-home")
|
|
@@ -77,6 +81,8 @@ describe("parseArgs", () => {
|
|
|
77
81
|
it.effect("parses clone command with positional repo url", () =>
|
|
78
82
|
expectCreateCommand(["clone", "https://github.com/org/repo.git"], (command) => {
|
|
79
83
|
expectCreateDefaults(command)
|
|
84
|
+
expect(command.openSsh).toBe(true)
|
|
85
|
+
expect(command.waitForClone).toBe(true)
|
|
80
86
|
expect(command.config.targetDir).toBe("/home/dev/org/repo")
|
|
81
87
|
}))
|
|
82
88
|
|
|
@@ -85,6 +91,16 @@ describe("parseArgs", () => {
|
|
|
85
91
|
expect(command.config.repoRef).toBe("feature-x")
|
|
86
92
|
}))
|
|
87
93
|
|
|
94
|
+
it.effect("supports disabling SSH auto-open for clone", () =>
|
|
95
|
+
expectCreateCommand(["clone", "https://github.com/org/repo.git", "--no-ssh"], (command) => {
|
|
96
|
+
expect(command.openSsh).toBe(false)
|
|
97
|
+
}))
|
|
98
|
+
|
|
99
|
+
it.effect("supports enabling SSH auto-open for create", () =>
|
|
100
|
+
expectCreateCommand(["create", "--repo-url", "https://github.com/org/repo.git", "--ssh"], (command) => {
|
|
101
|
+
expect(command.openSsh).toBe(true)
|
|
102
|
+
}))
|
|
103
|
+
|
|
88
104
|
it.effect("parses force-env flag for clone", () =>
|
|
89
105
|
expectCreateCommand(["clone", "https://github.com/org/repo.git", "--force-env"], (command) => {
|
|
90
106
|
expect(command.force).toBe(false)
|
|
@@ -136,6 +152,34 @@ describe("parseArgs", () => {
|
|
|
136
152
|
expect(command.projectDir).toBe(".docker-git/org/repo/issue-7")
|
|
137
153
|
}))
|
|
138
154
|
|
|
155
|
+
it.effect("parses mcp-playwright command in current directory", () =>
|
|
156
|
+
Effect.sync(() => {
|
|
157
|
+
const command = parseOrThrow(["mcp-playwright"])
|
|
158
|
+
if (command._tag !== "McpPlaywrightUp") {
|
|
159
|
+
throw new Error("expected McpPlaywrightUp command")
|
|
160
|
+
}
|
|
161
|
+
expect(command.projectDir).toBe(".")
|
|
162
|
+
expect(command.runUp).toBe(true)
|
|
163
|
+
}))
|
|
164
|
+
|
|
165
|
+
it.effect("parses mcp-playwright command with --no-up", () =>
|
|
166
|
+
Effect.sync(() => {
|
|
167
|
+
const command = parseOrThrow(["mcp-playwright", "--no-up"])
|
|
168
|
+
if (command._tag !== "McpPlaywrightUp") {
|
|
169
|
+
throw new Error("expected McpPlaywrightUp command")
|
|
170
|
+
}
|
|
171
|
+
expect(command.runUp).toBe(false)
|
|
172
|
+
}))
|
|
173
|
+
|
|
174
|
+
it.effect("parses mcp-playwright with positional repo url into project dir", () =>
|
|
175
|
+
Effect.sync(() => {
|
|
176
|
+
const command = parseOrThrow(["mcp-playwright", "https://github.com/org/repo.git"])
|
|
177
|
+
if (command._tag !== "McpPlaywrightUp") {
|
|
178
|
+
throw new Error("expected McpPlaywrightUp command")
|
|
179
|
+
}
|
|
180
|
+
expect(command.projectDir).toBe(".docker-git/org/repo")
|
|
181
|
+
}))
|
|
182
|
+
|
|
139
183
|
it.effect("parses down-all command", () =>
|
|
140
184
|
Effect.sync(() => {
|
|
141
185
|
const command = parseOrThrow(["down-all"])
|