@prover-coder-ai/docker-git 1.0.23 → 1.0.24
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 +4 -1
- package/.jscpd.json +0 -16
- package/.package.json.release.bak +0 -111
- package/CHANGELOG.md +0 -139
- package/biome.json +0 -34
- package/eslint.config.mts +0 -305
- package/eslint.effect-ts-check.config.mjs +0 -220
- package/linter.config.json +0 -33
- package/src/app/main.ts +0 -18
- package/src/app/program.ts +0 -78
- package/src/docker-git/cli/input.ts +0 -29
- package/src/docker-git/cli/parser-apply.ts +0 -28
- package/src/docker-git/cli/parser-attach.ts +0 -22
- package/src/docker-git/cli/parser-auth.ts +0 -154
- package/src/docker-git/cli/parser-clone.ts +0 -50
- package/src/docker-git/cli/parser-create.ts +0 -3
- package/src/docker-git/cli/parser-mcp-playwright.ts +0 -24
- package/src/docker-git/cli/parser-options.ts +0 -211
- package/src/docker-git/cli/parser-panes.ts +0 -22
- package/src/docker-git/cli/parser-scrap.ts +0 -106
- package/src/docker-git/cli/parser-sessions.ts +0 -101
- package/src/docker-git/cli/parser-shared.ts +0 -51
- package/src/docker-git/cli/parser-state.ts +0 -86
- package/src/docker-git/cli/parser.ts +0 -83
- package/src/docker-git/cli/read-command.ts +0 -26
- package/src/docker-git/cli/usage.ts +0 -131
- package/src/docker-git/main.ts +0 -18
- package/src/docker-git/menu-actions.ts +0 -273
- package/src/docker-git/menu-auth-data.ts +0 -184
- package/src/docker-git/menu-auth-helpers.ts +0 -30
- package/src/docker-git/menu-auth.ts +0 -311
- package/src/docker-git/menu-buffer-input.ts +0 -18
- package/src/docker-git/menu-create.ts +0 -310
- package/src/docker-git/menu-input-handler.ts +0 -183
- package/src/docker-git/menu-input-utils.ts +0 -85
- package/src/docker-git/menu-input.ts +0 -2
- package/src/docker-git/menu-labeled-env.ts +0 -37
- package/src/docker-git/menu-menu.ts +0 -58
- package/src/docker-git/menu-project-auth-claude.ts +0 -70
- package/src/docker-git/menu-project-auth-data.ts +0 -292
- package/src/docker-git/menu-project-auth.ts +0 -271
- package/src/docker-git/menu-render-auth.ts +0 -65
- package/src/docker-git/menu-render-common.ts +0 -67
- package/src/docker-git/menu-render-layout.ts +0 -30
- package/src/docker-git/menu-render-project-auth.ts +0 -70
- package/src/docker-git/menu-render-select.ts +0 -250
- package/src/docker-git/menu-render.ts +0 -292
- package/src/docker-git/menu-select-actions.ts +0 -150
- package/src/docker-git/menu-select-connect.ts +0 -27
- package/src/docker-git/menu-select-load.ts +0 -33
- package/src/docker-git/menu-select-order.ts +0 -37
- package/src/docker-git/menu-select-runtime.ts +0 -143
- package/src/docker-git/menu-select-view.ts +0 -25
- package/src/docker-git/menu-select.ts +0 -145
- package/src/docker-git/menu-shared.ts +0 -256
- package/src/docker-git/menu-startup.ts +0 -83
- package/src/docker-git/menu-types.ts +0 -170
- package/src/docker-git/menu.ts +0 -303
- package/src/docker-git/program.ts +0 -154
- package/src/docker-git/tmux.ts +0 -292
- package/tests/app/main.test.ts +0 -65
- package/tests/docker-git/entrypoint-auth.test.ts +0 -40
- package/tests/docker-git/fixtures/project-item.ts +0 -24
- package/tests/docker-git/menu-select-connect.test.ts +0 -55
- package/tests/docker-git/menu-select-order.test.ts +0 -84
- package/tests/docker-git/menu-startup.test.ts +0 -51
- package/tests/docker-git/parser-helpers.ts +0 -76
- package/tests/docker-git/parser-network-options.test.ts +0 -47
- package/tests/docker-git/parser.test.ts +0 -284
- package/tsconfig.build.json +0 -8
- package/tsconfig.json +0 -20
- package/vite.config.ts +0 -32
- package/vite.docker-git.config.ts +0 -34
- package/vitest.config.ts +0 -85
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { expect } from "@effect/vitest"
|
|
2
|
-
import { Effect, Either } from "effect"
|
|
3
|
-
|
|
4
|
-
import type { Command } from "@effect-template/lib/core/domain"
|
|
5
|
-
import { parseArgs } from "../../src/docker-git/cli/parser.js"
|
|
6
|
-
|
|
7
|
-
export type CreateCommand = Extract<Command, { _tag: "Create" }>
|
|
8
|
-
type ProjectDirRunUpCommand = Extract<Command, { readonly projectDir: string; readonly runUp: boolean }>
|
|
9
|
-
|
|
10
|
-
export const expectParseErrorTag = (
|
|
11
|
-
args: ReadonlyArray<string>,
|
|
12
|
-
expectedTag: string
|
|
13
|
-
) =>
|
|
14
|
-
Effect.sync(() => {
|
|
15
|
-
const parsed = parseArgs(args)
|
|
16
|
-
Either.match(parsed, {
|
|
17
|
-
onLeft: (error) => {
|
|
18
|
-
expect(error._tag).toBe(expectedTag)
|
|
19
|
-
},
|
|
20
|
-
onRight: () => {
|
|
21
|
-
throw new Error("expected parse error")
|
|
22
|
-
}
|
|
23
|
-
})
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
export const parseOrThrow = (args: ReadonlyArray<string>): Command => {
|
|
27
|
-
const parsed = parseArgs(args)
|
|
28
|
-
return Either.match(parsed, {
|
|
29
|
-
onLeft: (error) => {
|
|
30
|
-
throw new Error(`unexpected error ${error._tag}`)
|
|
31
|
-
},
|
|
32
|
-
onRight: (command) => command
|
|
33
|
-
})
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export const expectProjectDirRunUpCommand = (
|
|
37
|
-
args: ReadonlyArray<string>,
|
|
38
|
-
expectedTag: ProjectDirRunUpCommand["_tag"],
|
|
39
|
-
expectedProjectDir: string,
|
|
40
|
-
expectedRunUp: boolean
|
|
41
|
-
) =>
|
|
42
|
-
Effect.sync(() => {
|
|
43
|
-
const command = parseOrThrow(args)
|
|
44
|
-
if (command._tag !== expectedTag) {
|
|
45
|
-
throw new Error(`expected ${expectedTag} command`)
|
|
46
|
-
}
|
|
47
|
-
if (!("projectDir" in command) || !("runUp" in command)) {
|
|
48
|
-
throw new Error("expected command with projectDir and runUp")
|
|
49
|
-
}
|
|
50
|
-
expect(command.projectDir).toBe(expectedProjectDir)
|
|
51
|
-
expect(command.runUp).toBe(expectedRunUp)
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
export const expectAttachProjectDirCommand = (
|
|
55
|
-
args: ReadonlyArray<string>,
|
|
56
|
-
expectedProjectDir: string
|
|
57
|
-
) =>
|
|
58
|
-
Effect.sync(() => {
|
|
59
|
-
const command = parseOrThrow(args)
|
|
60
|
-
if (command._tag !== "Attach") {
|
|
61
|
-
throw new Error("expected Attach command")
|
|
62
|
-
}
|
|
63
|
-
expect(command.projectDir).toBe(expectedProjectDir)
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
export const expectCreateCommand = (
|
|
67
|
-
args: ReadonlyArray<string>,
|
|
68
|
-
onRight: (command: CreateCommand) => void
|
|
69
|
-
) =>
|
|
70
|
-
Effect.sync(() => {
|
|
71
|
-
const command = parseOrThrow(args)
|
|
72
|
-
if (command._tag !== "Create") {
|
|
73
|
-
throw new Error("expected Create command")
|
|
74
|
-
}
|
|
75
|
-
onRight(command)
|
|
76
|
-
})
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "@effect/vitest"
|
|
2
|
-
import { Effect, Either } from "effect"
|
|
3
|
-
|
|
4
|
-
import { parseArgs } from "../../src/docker-git/cli/parser.js"
|
|
5
|
-
|
|
6
|
-
describe("parseArgs network options", () => {
|
|
7
|
-
it.effect("parses create network mode options", () =>
|
|
8
|
-
Effect.sync(() => {
|
|
9
|
-
const parsed = parseArgs([
|
|
10
|
-
"create",
|
|
11
|
-
"--repo-url",
|
|
12
|
-
"https://github.com/org/repo.git",
|
|
13
|
-
"--network-mode",
|
|
14
|
-
"project",
|
|
15
|
-
"--shared-network",
|
|
16
|
-
"ignored-shared-network"
|
|
17
|
-
])
|
|
18
|
-
if (Either.isLeft(parsed)) {
|
|
19
|
-
throw new Error(`unexpected parse error: ${parsed.left._tag}`)
|
|
20
|
-
}
|
|
21
|
-
const command = parsed.right
|
|
22
|
-
if (command._tag !== "Create") {
|
|
23
|
-
throw new Error("expected Create command")
|
|
24
|
-
}
|
|
25
|
-
expect(command.config.dockerNetworkMode).toBe("project")
|
|
26
|
-
expect(command.config.dockerSharedNetworkName).toBe("ignored-shared-network")
|
|
27
|
-
}))
|
|
28
|
-
|
|
29
|
-
it.effect("fails on invalid network mode", () =>
|
|
30
|
-
Effect.sync(() => {
|
|
31
|
-
const command = parseArgs([
|
|
32
|
-
"create",
|
|
33
|
-
"--repo-url",
|
|
34
|
-
"https://github.com/org/repo.git",
|
|
35
|
-
"--network-mode",
|
|
36
|
-
"invalid"
|
|
37
|
-
])
|
|
38
|
-
Either.match(command, {
|
|
39
|
-
onLeft: (error) => {
|
|
40
|
-
expect(error._tag).toBe("InvalidOption")
|
|
41
|
-
},
|
|
42
|
-
onRight: () => {
|
|
43
|
-
throw new Error("expected parse error")
|
|
44
|
-
}
|
|
45
|
-
})
|
|
46
|
-
}))
|
|
47
|
-
})
|
|
@@ -1,284 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "@effect/vitest"
|
|
2
|
-
import { Effect } from "effect"
|
|
3
|
-
|
|
4
|
-
import { defaultTemplateConfig } from "@effect-template/lib/core/domain"
|
|
5
|
-
import { expandContainerHome } from "@effect-template/lib/usecases/scrap-path"
|
|
6
|
-
import {
|
|
7
|
-
type CreateCommand,
|
|
8
|
-
expectAttachProjectDirCommand,
|
|
9
|
-
expectCreateCommand,
|
|
10
|
-
expectParseErrorTag,
|
|
11
|
-
expectProjectDirRunUpCommand,
|
|
12
|
-
parseOrThrow
|
|
13
|
-
} from "./parser-helpers.js"
|
|
14
|
-
|
|
15
|
-
const expectCreateDefaults = (command: CreateCommand) => {
|
|
16
|
-
expect(command.config.repoUrl).toBe("https://github.com/org/repo.git")
|
|
17
|
-
expect(command.config.repoRef).toBe(defaultTemplateConfig.repoRef)
|
|
18
|
-
expect(command.outDir).toBe(".docker-git/org/repo")
|
|
19
|
-
expect(command.runUp).toBe(true)
|
|
20
|
-
expect(command.forceEnv).toBe(false)
|
|
21
|
-
expect(command.config.dockerNetworkMode).toBe("shared")
|
|
22
|
-
expect(command.config.dockerSharedNetworkName).toBe("docker-git-shared")
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const expandDefaultTargetDir = (path: string): string => expandContainerHome(defaultTemplateConfig.sshUser, path)
|
|
26
|
-
|
|
27
|
-
describe("parseArgs", () => {
|
|
28
|
-
it.effect("parses create command with defaults", () =>
|
|
29
|
-
expectCreateCommand(["create", "--repo-url", "https://github.com/org/repo.git"], (command) => {
|
|
30
|
-
expectCreateDefaults(command)
|
|
31
|
-
expect(command.openSsh).toBe(false)
|
|
32
|
-
expect(command.waitForClone).toBe(false)
|
|
33
|
-
expect(command.config.containerName).toBe("dg-repo")
|
|
34
|
-
expect(command.config.serviceName).toBe("dg-repo")
|
|
35
|
-
expect(command.config.volumeName).toBe("dg-repo-home")
|
|
36
|
-
expect(command.config.sshPort).toBe(defaultTemplateConfig.sshPort)
|
|
37
|
-
}))
|
|
38
|
-
|
|
39
|
-
it.effect("parses create command with issue url into isolated defaults", () =>
|
|
40
|
-
expectCreateCommand(["create", "--repo-url", "https://github.com/org/repo/issues/9"], (command) => {
|
|
41
|
-
expect(command.config.repoUrl).toBe("https://github.com/org/repo.git")
|
|
42
|
-
expect(command.config.repoRef).toBe("issue-9")
|
|
43
|
-
expect(command.outDir).toBe(".docker-git/org/repo/issue-9")
|
|
44
|
-
expect(command.openSsh).toBe(false)
|
|
45
|
-
expect(command.waitForClone).toBe(false)
|
|
46
|
-
expect(command.config.containerName).toBe("dg-repo-issue-9")
|
|
47
|
-
expect(command.config.serviceName).toBe("dg-repo-issue-9")
|
|
48
|
-
expect(command.config.volumeName).toBe("dg-repo-issue-9-home")
|
|
49
|
-
}))
|
|
50
|
-
|
|
51
|
-
it.effect("parses create command without repo url into empty workspace defaults", () =>
|
|
52
|
-
expectCreateCommand(["create"], (command) => {
|
|
53
|
-
expect(command.config.repoUrl).toBe("")
|
|
54
|
-
expect(command.config.repoRef).toBe(defaultTemplateConfig.repoRef)
|
|
55
|
-
expect(command.outDir).toBe(".docker-git/app")
|
|
56
|
-
expect(command.openSsh).toBe(false)
|
|
57
|
-
expect(command.waitForClone).toBe(false)
|
|
58
|
-
expect(command.config.containerName).toBe("dg-app")
|
|
59
|
-
expect(command.config.serviceName).toBe("dg-app")
|
|
60
|
-
expect(command.config.volumeName).toBe("dg-app-home")
|
|
61
|
-
expect(command.config.targetDir).toBe(expandDefaultTargetDir(defaultTemplateConfig.targetDir))
|
|
62
|
-
}))
|
|
63
|
-
|
|
64
|
-
it.effect("fails clone when repo url is missing", () => expectParseErrorTag(["clone"], "MissingRequiredOption"))
|
|
65
|
-
|
|
66
|
-
it.effect("parses clone command with positional repo url", () =>
|
|
67
|
-
expectCreateCommand(["clone", "https://github.com/org/repo.git"], (command) => {
|
|
68
|
-
expectCreateDefaults(command)
|
|
69
|
-
expect(command.openSsh).toBe(true)
|
|
70
|
-
expect(command.waitForClone).toBe(true)
|
|
71
|
-
expect(command.config.targetDir).toBe(
|
|
72
|
-
expandDefaultTargetDir("~/workspaces/org/repo")
|
|
73
|
-
)
|
|
74
|
-
}))
|
|
75
|
-
|
|
76
|
-
it.effect("parses clone branch alias", () =>
|
|
77
|
-
expectCreateCommand(["clone", "https://github.com/org/repo.git", "--branch", "feature-x"], (command) => {
|
|
78
|
-
expect(command.config.repoRef).toBe("feature-x")
|
|
79
|
-
}))
|
|
80
|
-
|
|
81
|
-
it.effect("supports disabling SSH auto-open for clone", () =>
|
|
82
|
-
expectCreateCommand(["clone", "https://github.com/org/repo.git", "--no-ssh"], (command) => {
|
|
83
|
-
expect(command.openSsh).toBe(false)
|
|
84
|
-
}))
|
|
85
|
-
|
|
86
|
-
it.effect("parses clone git token label from inline option and normalizes it", () =>
|
|
87
|
-
expectCreateCommand(["clone", "https://github.com/org/repo.git", "--git-token=#agiens"], (command) => {
|
|
88
|
-
expect(command.config.gitTokenLabel).toBe("AGIENS")
|
|
89
|
-
}))
|
|
90
|
-
|
|
91
|
-
it.effect("parses clone codex/claude token labels from inline options and normalizes them", () =>
|
|
92
|
-
expectCreateCommand(
|
|
93
|
-
[
|
|
94
|
-
"clone",
|
|
95
|
-
"https://github.com/org/repo.git",
|
|
96
|
-
"--codex-token= Team A ",
|
|
97
|
-
"--claude-token=---AGIENS:::Claude---"
|
|
98
|
-
],
|
|
99
|
-
(command) => {
|
|
100
|
-
expect(command.config.codexAuthLabel).toBe("team-a")
|
|
101
|
-
expect(command.config.claudeAuthLabel).toBe("agiens-claude")
|
|
102
|
-
}
|
|
103
|
-
))
|
|
104
|
-
|
|
105
|
-
it.effect("supports enabling SSH auto-open for create", () =>
|
|
106
|
-
expectCreateCommand(["create", "--repo-url", "https://github.com/org/repo.git", "--ssh"], (command) => {
|
|
107
|
-
expect(command.openSsh).toBe(true)
|
|
108
|
-
}))
|
|
109
|
-
|
|
110
|
-
it.effect("parses force-env flag for clone", () =>
|
|
111
|
-
expectCreateCommand(["clone", "https://github.com/org/repo.git", "--force-env"], (command) => {
|
|
112
|
-
expect(command.force).toBe(false)
|
|
113
|
-
expect(command.forceEnv).toBe(true)
|
|
114
|
-
}))
|
|
115
|
-
|
|
116
|
-
it.effect("supports force + force-env together", () =>
|
|
117
|
-
expectCreateCommand(["clone", "https://github.com/org/repo.git", "--force", "--force-env"], (command) => {
|
|
118
|
-
expect(command.force).toBe(true)
|
|
119
|
-
expect(command.forceEnv).toBe(true)
|
|
120
|
-
}))
|
|
121
|
-
|
|
122
|
-
it.effect("parses GitHub tree url as repo + ref", () =>
|
|
123
|
-
expectCreateCommand(["clone", "https://github.com/agiens/crm/tree/vova-fork"], (command) => {
|
|
124
|
-
expect(command.config.repoUrl).toBe("https://github.com/agiens/crm.git")
|
|
125
|
-
expect(command.config.repoRef).toBe("vova-fork")
|
|
126
|
-
expect(command.outDir).toBe(".docker-git/agiens/crm")
|
|
127
|
-
expect(command.config.targetDir).toBe(
|
|
128
|
-
expandDefaultTargetDir("~/workspaces/agiens/crm")
|
|
129
|
-
)
|
|
130
|
-
}))
|
|
131
|
-
|
|
132
|
-
it.effect("parses GitHub issue url as isolated project + issue branch", () =>
|
|
133
|
-
expectCreateCommand(["clone", "https://github.com/org/repo/issues/5"], (command) => {
|
|
134
|
-
expect(command.config.repoUrl).toBe("https://github.com/org/repo.git")
|
|
135
|
-
expect(command.config.repoRef).toBe("issue-5")
|
|
136
|
-
expect(command.outDir).toBe(".docker-git/org/repo/issue-5")
|
|
137
|
-
expect(command.config.targetDir).toBe(
|
|
138
|
-
expandDefaultTargetDir("~/workspaces/org/repo/issue-5")
|
|
139
|
-
)
|
|
140
|
-
expect(command.config.containerName).toBe("dg-repo-issue-5")
|
|
141
|
-
expect(command.config.serviceName).toBe("dg-repo-issue-5")
|
|
142
|
-
expect(command.config.volumeName).toBe("dg-repo-issue-5-home")
|
|
143
|
-
}))
|
|
144
|
-
|
|
145
|
-
it.effect("parses GitHub PR url as isolated project", () =>
|
|
146
|
-
expectCreateCommand(["clone", "https://github.com/org/repo/pull/42"], (command) => {
|
|
147
|
-
expect(command.config.repoUrl).toBe("https://github.com/org/repo.git")
|
|
148
|
-
expect(command.config.repoRef).toBe("refs/pull/42/head")
|
|
149
|
-
expect(command.outDir).toBe(".docker-git/org/repo/pr-42")
|
|
150
|
-
expect(command.config.targetDir).toBe(
|
|
151
|
-
expandDefaultTargetDir("~/workspaces/org/repo/pr-42")
|
|
152
|
-
)
|
|
153
|
-
expect(command.config.containerName).toBe("dg-repo-pr-42")
|
|
154
|
-
expect(command.config.serviceName).toBe("dg-repo-pr-42")
|
|
155
|
-
expect(command.config.volumeName).toBe("dg-repo-pr-42-home")
|
|
156
|
-
}))
|
|
157
|
-
|
|
158
|
-
it.effect("parses attach with GitHub issue url into issue workspace", () =>
|
|
159
|
-
expectAttachProjectDirCommand(["attach", "https://github.com/org/repo/issues/7"], ".docker-git/org/repo/issue-7"))
|
|
160
|
-
|
|
161
|
-
it.effect("parses open with GitHub issue url into issue workspace", () =>
|
|
162
|
-
expectAttachProjectDirCommand(["open", "https://github.com/org/repo/issues/7"], ".docker-git/org/repo/issue-7"))
|
|
163
|
-
|
|
164
|
-
it.effect("parses mcp-playwright command in current directory", () =>
|
|
165
|
-
expectProjectDirRunUpCommand(["mcp-playwright"], "McpPlaywrightUp", ".", true))
|
|
166
|
-
|
|
167
|
-
it.effect("parses mcp-playwright command with --no-up", () =>
|
|
168
|
-
expectProjectDirRunUpCommand(["mcp-playwright", "--no-up"], "McpPlaywrightUp", ".", false))
|
|
169
|
-
|
|
170
|
-
it.effect("parses mcp-playwright with positional repo url into project dir", () =>
|
|
171
|
-
Effect.sync(() => {
|
|
172
|
-
const command = parseOrThrow(["mcp-playwright", "https://github.com/org/repo.git"])
|
|
173
|
-
if (command._tag !== "McpPlaywrightUp") {
|
|
174
|
-
throw new Error("expected McpPlaywrightUp command")
|
|
175
|
-
}
|
|
176
|
-
expect(command.projectDir).toBe(".docker-git/org/repo")
|
|
177
|
-
}))
|
|
178
|
-
|
|
179
|
-
it.effect("parses apply command in current directory", () =>
|
|
180
|
-
expectProjectDirRunUpCommand(["apply"], "Apply", ".", true))
|
|
181
|
-
|
|
182
|
-
it.effect("parses apply command with --no-up", () =>
|
|
183
|
-
expectProjectDirRunUpCommand(["apply", "--no-up"], "Apply", ".", false))
|
|
184
|
-
|
|
185
|
-
it.effect("parses apply with positional repo url into project dir", () =>
|
|
186
|
-
Effect.sync(() => {
|
|
187
|
-
const command = parseOrThrow(["apply", "https://github.com/org/repo.git"])
|
|
188
|
-
if (command._tag !== "Apply") {
|
|
189
|
-
throw new Error("expected Apply command")
|
|
190
|
-
}
|
|
191
|
-
expect(command.projectDir).toBe(".docker-git/org/repo")
|
|
192
|
-
}))
|
|
193
|
-
|
|
194
|
-
it.effect("parses apply token and mcp overrides", () =>
|
|
195
|
-
Effect.sync(() => {
|
|
196
|
-
const command = parseOrThrow([
|
|
197
|
-
"apply",
|
|
198
|
-
"--git-token=agien_main",
|
|
199
|
-
"--codex-token=Team A",
|
|
200
|
-
"--claude-token=Team B",
|
|
201
|
-
"--mcp-playwright",
|
|
202
|
-
"--no-up"
|
|
203
|
-
])
|
|
204
|
-
if (command._tag !== "Apply") {
|
|
205
|
-
throw new Error("expected Apply command")
|
|
206
|
-
}
|
|
207
|
-
expect(command.runUp).toBe(false)
|
|
208
|
-
expect(command.gitTokenLabel).toBe("agien_main")
|
|
209
|
-
expect(command.codexTokenLabel).toBe("Team A")
|
|
210
|
-
expect(command.claudeTokenLabel).toBe("Team B")
|
|
211
|
-
expect(command.enableMcpPlaywright).toBe(true)
|
|
212
|
-
}))
|
|
213
|
-
|
|
214
|
-
it.effect("parses down-all command", () =>
|
|
215
|
-
Effect.sync(() => {
|
|
216
|
-
const command = parseOrThrow(["down-all"])
|
|
217
|
-
expect(command._tag).toBe("DownAll")
|
|
218
|
-
}))
|
|
219
|
-
|
|
220
|
-
it.effect("parses state path command", () =>
|
|
221
|
-
Effect.sync(() => {
|
|
222
|
-
const command = parseOrThrow(["state", "path"])
|
|
223
|
-
expect(command._tag).toBe("StatePath")
|
|
224
|
-
}))
|
|
225
|
-
|
|
226
|
-
it.effect("parses state init command", () =>
|
|
227
|
-
Effect.sync(() => {
|
|
228
|
-
const command = parseOrThrow(["state", "init", "--repo-url", "https://github.com/org/state.git"])
|
|
229
|
-
if (command._tag !== "StateInit") {
|
|
230
|
-
throw new Error("expected StateInit command")
|
|
231
|
-
}
|
|
232
|
-
expect(command.repoUrl).toBe("https://github.com/org/state.git")
|
|
233
|
-
expect(command.repoRef).toBe("main")
|
|
234
|
-
}))
|
|
235
|
-
|
|
236
|
-
it.effect("parses state commit command", () =>
|
|
237
|
-
Effect.sync(() => {
|
|
238
|
-
const command = parseOrThrow(["state", "commit", "-m", "sync state"])
|
|
239
|
-
if (command._tag !== "StateCommit") {
|
|
240
|
-
throw new Error("expected StateCommit command")
|
|
241
|
-
}
|
|
242
|
-
expect(command.message).toBe("sync state")
|
|
243
|
-
}))
|
|
244
|
-
|
|
245
|
-
it.effect("parses state sync command", () =>
|
|
246
|
-
Effect.sync(() => {
|
|
247
|
-
const command = parseOrThrow(["state", "sync", "-m", "sync state"])
|
|
248
|
-
if (command._tag !== "StateSync") {
|
|
249
|
-
throw new Error("expected StateSync command")
|
|
250
|
-
}
|
|
251
|
-
expect(command.message).toBe("sync state")
|
|
252
|
-
}))
|
|
253
|
-
|
|
254
|
-
it.effect("parses scrap export with defaults", () =>
|
|
255
|
-
Effect.sync(() => {
|
|
256
|
-
const command = parseOrThrow(["scrap", "export"])
|
|
257
|
-
if (command._tag !== "ScrapExport") {
|
|
258
|
-
throw new Error("expected ScrapExport command")
|
|
259
|
-
}
|
|
260
|
-
expect(command.projectDir).toBe(".")
|
|
261
|
-
expect(command.archivePath).toBe(".orch/scrap/session")
|
|
262
|
-
}))
|
|
263
|
-
|
|
264
|
-
it.effect("fails scrap import without archive", () =>
|
|
265
|
-
expectParseErrorTag(["scrap", "import"], "MissingRequiredOption"))
|
|
266
|
-
|
|
267
|
-
it.effect("parses scrap import wipe defaults", () =>
|
|
268
|
-
Effect.sync(() => {
|
|
269
|
-
const command = parseOrThrow(["scrap", "import", "--archive", "workspace.tar.gz"])
|
|
270
|
-
if (command._tag !== "ScrapImport") {
|
|
271
|
-
throw new Error("expected ScrapImport command")
|
|
272
|
-
}
|
|
273
|
-
expect(command.wipe).toBe(true)
|
|
274
|
-
}))
|
|
275
|
-
|
|
276
|
-
it.effect("parses scrap import --no-wipe", () =>
|
|
277
|
-
Effect.sync(() => {
|
|
278
|
-
const command = parseOrThrow(["scrap", "import", "--archive", "workspace.tar.gz", "--no-wipe"])
|
|
279
|
-
if (command._tag !== "ScrapImport") {
|
|
280
|
-
throw new Error("expected ScrapImport command")
|
|
281
|
-
}
|
|
282
|
-
expect(command.wipe).toBe(false)
|
|
283
|
-
}))
|
|
284
|
-
})
|
package/tsconfig.build.json
DELETED
package/tsconfig.json
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "../../tsconfig.base.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"rootDir": ".",
|
|
5
|
-
"outDir": "dist",
|
|
6
|
-
"types": ["vitest"],
|
|
7
|
-
"jsx": "react-jsx",
|
|
8
|
-
"baseUrl": ".",
|
|
9
|
-
"paths": {
|
|
10
|
-
"@/*": ["src/*"]
|
|
11
|
-
}
|
|
12
|
-
},
|
|
13
|
-
"include": [
|
|
14
|
-
"src/**/*",
|
|
15
|
-
"tests/**/*",
|
|
16
|
-
"vite.config.ts",
|
|
17
|
-
"vitest.config.ts"
|
|
18
|
-
],
|
|
19
|
-
"exclude": ["dist", "node_modules"]
|
|
20
|
-
}
|
package/vite.config.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import path from "node:path"
|
|
2
|
-
import { fileURLToPath } from "node:url"
|
|
3
|
-
import { defineConfig } from "vite"
|
|
4
|
-
import tsconfigPaths from "vite-tsconfig-paths"
|
|
5
|
-
|
|
6
|
-
const __filename = fileURLToPath(import.meta.url)
|
|
7
|
-
const __dirname = path.dirname(__filename)
|
|
8
|
-
|
|
9
|
-
export default defineConfig({
|
|
10
|
-
plugins: [tsconfigPaths()],
|
|
11
|
-
publicDir: false,
|
|
12
|
-
resolve: {
|
|
13
|
-
alias: {
|
|
14
|
-
"@": path.resolve(__dirname, "src")
|
|
15
|
-
}
|
|
16
|
-
},
|
|
17
|
-
build: {
|
|
18
|
-
target: "node20",
|
|
19
|
-
outDir: "dist",
|
|
20
|
-
sourcemap: true,
|
|
21
|
-
ssr: "src/app/main.ts",
|
|
22
|
-
rollupOptions: {
|
|
23
|
-
output: {
|
|
24
|
-
format: "es",
|
|
25
|
-
entryFileNames: "main.js"
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
ssr: {
|
|
30
|
-
target: "node"
|
|
31
|
-
}
|
|
32
|
-
})
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import path from "node:path"
|
|
2
|
-
import { fileURLToPath } from "node:url"
|
|
3
|
-
import { defineConfig } from "vite"
|
|
4
|
-
import tsconfigPaths from "vite-tsconfig-paths"
|
|
5
|
-
|
|
6
|
-
const __filename = fileURLToPath(import.meta.url)
|
|
7
|
-
const __dirname = path.dirname(__filename)
|
|
8
|
-
|
|
9
|
-
export default defineConfig({
|
|
10
|
-
plugins: [tsconfigPaths()],
|
|
11
|
-
publicDir: false,
|
|
12
|
-
resolve: {
|
|
13
|
-
alias: {
|
|
14
|
-
"@": path.resolve(__dirname, "src"),
|
|
15
|
-
"@effect-template/lib": path.resolve(__dirname, "../lib/src")
|
|
16
|
-
}
|
|
17
|
-
},
|
|
18
|
-
build: {
|
|
19
|
-
target: "node20",
|
|
20
|
-
outDir: "dist",
|
|
21
|
-
sourcemap: true,
|
|
22
|
-
ssr: "src/docker-git/main.ts",
|
|
23
|
-
rollupOptions: {
|
|
24
|
-
output: {
|
|
25
|
-
format: "es",
|
|
26
|
-
entryFileNames: "src/docker-git/main.js",
|
|
27
|
-
inlineDynamicImports: true
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
},
|
|
31
|
-
ssr: {
|
|
32
|
-
target: "node"
|
|
33
|
-
}
|
|
34
|
-
})
|
package/vitest.config.ts
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
// CHANGE: Migrate from Jest to Vitest with mathematical equivalence
|
|
2
|
-
// WHY: Faster execution, native ESM, Effect integration via @effect/vitest
|
|
3
|
-
// QUOTE(ТЗ): "Проект использует Effect + функциональную парадигму"
|
|
4
|
-
// REF: Migration from jest.config.mjs
|
|
5
|
-
// PURITY: SHELL (configuration only)
|
|
6
|
-
// INVARIANT: ∀ test: behavior_jest ≡ behavior_vitest
|
|
7
|
-
// EFFECT: Effect<TestReport, never, TestEnvironment>
|
|
8
|
-
// COMPLEXITY: O(n) test execution where n = |test_files|
|
|
9
|
-
|
|
10
|
-
import path from "node:path"
|
|
11
|
-
import { fileURLToPath } from "node:url"
|
|
12
|
-
import tsconfigPaths from "vite-tsconfig-paths"
|
|
13
|
-
import { defineConfig } from "vitest/config"
|
|
14
|
-
|
|
15
|
-
const __filename = fileURLToPath(import.meta.url)
|
|
16
|
-
const __dirname = path.dirname(__filename)
|
|
17
|
-
|
|
18
|
-
export default defineConfig({
|
|
19
|
-
plugins: [tsconfigPaths()], // Resolves @/* paths from tsconfig
|
|
20
|
-
test: {
|
|
21
|
-
// CHANGE: Native ESM support without experimental flags
|
|
22
|
-
// WHY: Vitest designed for ESM, no need for --experimental-vm-modules
|
|
23
|
-
// INVARIANT: Deterministic test execution without side effects
|
|
24
|
-
globals: false, // IMPORTANT: Use explicit imports for type safety
|
|
25
|
-
environment: "node",
|
|
26
|
-
|
|
27
|
-
// CHANGE: Match Jest's test file patterns
|
|
28
|
-
// INVARIANT: Same test discovery as Jest
|
|
29
|
-
include: ["tests/**/*.{test,spec}.ts"],
|
|
30
|
-
exclude: ["node_modules", "dist", "dist-test"],
|
|
31
|
-
|
|
32
|
-
// CHANGE: Coverage with 100% threshold for CORE (same as Jest)
|
|
33
|
-
// WHY: CORE must maintain mathematical guarantees via complete coverage
|
|
34
|
-
// INVARIANT: coverage_vitest ≥ coverage_jest ∧ ∀ f ∈ CORE: coverage(f) = 100%
|
|
35
|
-
coverage: {
|
|
36
|
-
provider: "v8", // Faster than babel (istanbul), native V8 coverage
|
|
37
|
-
reporter: ["text", "json", "html"],
|
|
38
|
-
include: ["src/**/*.ts"],
|
|
39
|
-
exclude: [
|
|
40
|
-
"src/**/*.test.ts",
|
|
41
|
-
"src/**/*.spec.ts",
|
|
42
|
-
"src/**/__tests__/**",
|
|
43
|
-
"scripts/**/*.ts"
|
|
44
|
-
],
|
|
45
|
-
// CHANGE: Maintain exact same thresholds as Jest
|
|
46
|
-
// WHY: Enforce 100% coverage for CORE, 10% minimum for SHELL
|
|
47
|
-
// INVARIANT: ∀ f ∈ src/core/**/*.ts: all_metrics(f) = 100%
|
|
48
|
-
// NOTE: Vitest v8 provider collects coverage for all matched files by default
|
|
49
|
-
thresholds: {
|
|
50
|
-
"src/core/**/*.ts": {
|
|
51
|
-
branches: 100,
|
|
52
|
-
functions: 100,
|
|
53
|
-
lines: 100,
|
|
54
|
-
statements: 100
|
|
55
|
-
},
|
|
56
|
-
global: {
|
|
57
|
-
branches: 10,
|
|
58
|
-
functions: 10,
|
|
59
|
-
lines: 10,
|
|
60
|
-
statements: 10
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
},
|
|
64
|
-
|
|
65
|
-
// CHANGE: Faster test execution via thread pooling
|
|
66
|
-
// WHY: Vitest uses worker threads by default (faster than Jest's processes)
|
|
67
|
-
// COMPLEXITY: O(n/k) where n = tests, k = worker_count
|
|
68
|
-
// NOTE: Vitest runs tests in parallel by default, no additional config needed
|
|
69
|
-
|
|
70
|
-
// CHANGE: Clear mocks between tests (Jest equivalence)
|
|
71
|
-
// WHY: Prevent test contamination, ensure test independence
|
|
72
|
-
// INVARIANT: ∀ test_i, test_j: independent(test_i, test_j) ⇒ no_shared_state
|
|
73
|
-
clearMocks: true,
|
|
74
|
-
mockReset: true,
|
|
75
|
-
restoreMocks: true
|
|
76
|
-
// CHANGE: Disable globals to enforce explicit imports
|
|
77
|
-
// WHY: Type safety, explicit dependencies, functional purity
|
|
78
|
-
// NOTE: Tests must import { describe, it, expect } from "vitest"
|
|
79
|
-
},
|
|
80
|
-
resolve: {
|
|
81
|
-
alias: {
|
|
82
|
-
"@": path.resolve(__dirname, "src")
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
})
|