@ozyman42/ozy-cli 0.4.8 → 0.4.9-darwin-x64.0
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/multi-call-binary +0 -0
- package/package.json +11 -52
- package/bin/ozy +0 -191
- package/bin/ozy-signing-agent +0 -191
- package/bin/ozy-ssh-keygen +0 -191
- package/bin/ozy-virtual-security-key +0 -191
- package/dist/commands/git/hosts.js +0 -18
- package/dist/commands/git/hosts.js.map +0 -1
- package/dist/commands/git/index.js +0 -8
- package/dist/commands/git/index.js.map +0 -1
- package/dist/commands/git/setup.js +0 -145
- package/dist/commands/git/setup.js.map +0 -1
- package/dist/commands/index.js +0 -13
- package/dist/commands/index.js.map +0 -1
- package/dist/commands/npm/index.js +0 -7
- package/dist/commands/npm/index.js.map +0 -1
- package/dist/commands/npm/setup/git-remote.js +0 -66
- package/dist/commands/npm/setup/git-remote.js.map +0 -1
- package/dist/commands/npm/setup/index.js +0 -168
- package/dist/commands/npm/setup/index.js.map +0 -1
- package/dist/commands/npm/setup/npm-auth.js +0 -62
- package/dist/commands/npm/setup/npm-auth.js.map +0 -1
- package/dist/commands/npm/setup/package-json-validate.js +0 -47
- package/dist/commands/npm/setup/package-json-validate.js.map +0 -1
- package/dist/commands/npm/setup/package-registry.js +0 -20
- package/dist/commands/npm/setup/package-registry.js.map +0 -1
- package/dist/commands/npm/setup/setup.test.js +0 -95
- package/dist/commands/npm/setup/setup.test.js.map +0 -1
- package/dist/commands/npm/setup/trusted-publishing.js +0 -84
- package/dist/commands/npm/setup/trusted-publishing.js.map +0 -1
- package/dist/commands/npm/setup/workflow.js +0 -19
- package/dist/commands/npm/setup/workflow.js.map +0 -1
- package/dist/commands/ssh/get-sk-credential.js +0 -104
- package/dist/commands/ssh/get-sk-credential.js.map +0 -1
- package/dist/commands/ssh/index.js +0 -7
- package/dist/commands/ssh/index.js.map +0 -1
- package/dist/commands/upgrade.js +0 -199
- package/dist/commands/upgrade.js.map +0 -1
- package/dist/common/command.js +0 -15
- package/dist/common/command.js.map +0 -1
- package/dist/common/constants.js +0 -25
- package/dist/common/constants.js.map +0 -1
- package/dist/common/effective-modules-extensions.js +0 -13
- package/dist/common/effective-modules-extensions.js.map +0 -1
- package/dist/common/log.js +0 -4
- package/dist/common/log.js.map +0 -1
- package/dist/common/render-caller-tree.js +0 -20
- package/dist/common/render-caller-tree.js.map +0 -1
- package/dist/entrypoints/ozy-signing-agent.js +0 -48
- package/dist/entrypoints/ozy-signing-agent.js.map +0 -1
- package/dist/entrypoints/ozy-ssh-keygen.js +0 -9
- package/dist/entrypoints/ozy-ssh-keygen.js.map +0 -1
- package/dist/entrypoints/ozy-virtual-security-key.js +0 -18
- package/dist/entrypoints/ozy-virtual-security-key.js.map +0 -1
- package/dist/entrypoints/ozy.js +0 -3
- package/dist/entrypoints/ozy.js.map +0 -1
- package/dist/index.js +0 -2
- package/dist/index.js.map +0 -1
- package/dist/internal/thing.js +0 -4
- package/dist/internal/thing.js.map +0 -1
- package/dist/modules/cli/agent-client/impl.js +0 -109
- package/dist/modules/cli/agent-client/impl.js.map +0 -1
- package/dist/modules/cli/agent-client/interface.js +0 -11
- package/dist/modules/cli/agent-client/interface.js.map +0 -1
- package/dist/modules/cli/git/impl.js +0 -124
- package/dist/modules/cli/git/impl.js.map +0 -1
- package/dist/modules/cli/git/interface.js +0 -3
- package/dist/modules/cli/git/interface.js.map +0 -1
- package/dist/modules/cli/git/submodule/fix.js +0 -257
- package/dist/modules/cli/git/submodule/fix.js.map +0 -1
- package/dist/modules/cli/git/submodule/git-state.js +0 -154
- package/dist/modules/cli/git/submodule/git-state.js.map +0 -1
- package/dist/modules/cli/git/submodule/gitmodules.js +0 -113
- package/dist/modules/cli/git/submodule/gitmodules.js.map +0 -1
- package/dist/modules/cli/git/submodule/printer.js +0 -232
- package/dist/modules/cli/git/submodule/printer.js.map +0 -1
- package/dist/modules/cli/git/submodule/resolve-git-dir.js +0 -16
- package/dist/modules/cli/git/submodule/resolve-git-dir.js.map +0 -1
- package/dist/modules/cli/github/impl.js +0 -137
- package/dist/modules/cli/github/impl.js.map +0 -1
- package/dist/modules/cli/github/interface.js +0 -2
- package/dist/modules/cli/github/interface.js.map +0 -1
- package/dist/modules/cli/index.js +0 -9
- package/dist/modules/cli/index.js.map +0 -1
- package/dist/modules/common/crypto/impl.js +0 -133
- package/dist/modules/common/crypto/impl.js.map +0 -1
- package/dist/modules/common/crypto/interface.js +0 -2
- package/dist/modules/common/crypto/interface.js.map +0 -1
- package/dist/modules/common/index.js +0 -10
- package/dist/modules/common/index.js.map +0 -1
- package/dist/modules/common/kep-map-store/impl.js +0 -42
- package/dist/modules/common/kep-map-store/impl.js.map +0 -1
- package/dist/modules/common/kep-map-store/interface.js +0 -2
- package/dist/modules/common/kep-map-store/interface.js.map +0 -1
- package/dist/modules/common/os-platform/caller-info.js +0 -132
- package/dist/modules/common/os-platform/caller-info.js.map +0 -1
- package/dist/modules/common/os-platform/impl.js +0 -95
- package/dist/modules/common/os-platform/impl.js.map +0 -1
- package/dist/modules/common/os-platform/interface.js +0 -2
- package/dist/modules/common/os-platform/interface.js.map +0 -1
- package/dist/modules/common/os-platform/virtual-hid/index.js +0 -12
- package/dist/modules/common/os-platform/virtual-hid/index.js.map +0 -1
- package/dist/modules/common/os-platform/virtual-hid/linux.js +0 -5
- package/dist/modules/common/os-platform/virtual-hid/linux.js.map +0 -1
- package/dist/modules/common/os-platform/virtual-hid/mac.js +0 -119
- package/dist/modules/common/os-platform/virtual-hid/mac.js.map +0 -1
- package/dist/modules/common/os-platform/virtual-hid/windows.js +0 -5
- package/dist/modules/common/os-platform/virtual-hid/windows.js.map +0 -1
- package/dist/modules/common/ssh-config/impl.js +0 -116
- package/dist/modules/common/ssh-config/impl.js.map +0 -1
- package/dist/modules/common/ssh-config/interface.js +0 -10
- package/dist/modules/common/ssh-config/interface.js.map +0 -1
- package/dist/modules/ssh-agent/index.js +0 -8
- package/dist/modules/ssh-agent/index.js.map +0 -1
- package/dist/modules/ssh-agent/session/impl.js +0 -265
- package/dist/modules/ssh-agent/session/impl.js.map +0 -1
- package/dist/modules/ssh-agent/session/interface-rpc.js +0 -20
- package/dist/modules/ssh-agent/session/interface-rpc.js.map +0 -1
- package/dist/modules/ssh-agent/session/interface.js +0 -32
- package/dist/modules/ssh-agent/session/interface.js.map +0 -1
- package/dist/modules/ssh-agent/session/passkey-prf-page.js +0 -204
- package/dist/modules/ssh-agent/session/passkey-prf-page.js.map +0 -1
- package/dist/modules/ssh-agent/session/prf-flow.js +0 -103
- package/dist/modules/ssh-agent/session/prf-flow.js.map +0 -1
- package/dist/modules/ssh-agent/ssh-agent/impl.js +0 -117
- package/dist/modules/ssh-agent/ssh-agent/impl.js.map +0 -1
- package/dist/modules/ssh-agent/ssh-agent/interface.js +0 -2
- package/dist/modules/ssh-agent/ssh-agent/interface.js.map +0 -1
- package/dist/scripts/build.js +0 -410
- package/dist/scripts/build.js.map +0 -1
- package/dist/scripts/check-npm-version.js +0 -8
- package/dist/scripts/check-npm-version.js.map +0 -1
- package/dist/scripts/kill-existing-agent.js +0 -21
- package/dist/scripts/kill-existing-agent.js.map +0 -1
- package/dist/scripts/publish.js +0 -46
- package/dist/scripts/publish.js.map +0 -1
- package/src/commands/git/hosts.ts +0 -20
- package/src/commands/git/index.ts +0 -9
- package/src/commands/git/setup.ts +0 -182
- package/src/commands/index.ts +0 -15
- package/src/commands/npm/index.ts +0 -8
- package/src/commands/npm/setup/git-remote.ts +0 -78
- package/src/commands/npm/setup/index.ts +0 -189
- package/src/commands/npm/setup/npm-auth.ts +0 -58
- package/src/commands/npm/setup/package-json-validate.ts +0 -68
- package/src/commands/npm/setup/package-registry.ts +0 -24
- package/src/commands/npm/setup/publish-workflow.yml +0 -35
- package/src/commands/npm/setup/setup.test.ts +0 -117
- package/src/commands/npm/setup/trusted-publishing.ts +0 -106
- package/src/commands/npm/setup/workflow.ts +0 -20
- package/src/commands/ssh/get-sk-credential.ts +0 -110
- package/src/commands/ssh/index.ts +0 -8
- package/src/commands/upgrade.ts +0 -220
- package/src/common/command.ts +0 -16
- package/src/common/constants.ts +0 -26
- package/src/common/effective-modules-extensions.ts +0 -24
- package/src/common/log.ts +0 -3
- package/src/common/render-caller-tree.ts +0 -22
- package/src/entrypoints/ozy-signing-agent.ts +0 -48
- package/src/entrypoints/ozy-ssh-keygen.ts +0 -10
- package/src/entrypoints/ozy-virtual-security-key.ts +0 -21
- package/src/entrypoints/ozy.ts +0 -2
- package/src/index.ts +0 -1
- package/src/internal/thing.ts +0 -3
- package/src/modules/cli/agent-client/impl.ts +0 -152
- package/src/modules/cli/agent-client/interface.ts +0 -17
- package/src/modules/cli/git/impl.ts +0 -133
- package/src/modules/cli/git/interface.ts +0 -23
- package/src/modules/cli/git/submodule/fix.ts +0 -298
- package/src/modules/cli/git/submodule/git-state.ts +0 -217
- package/src/modules/cli/git/submodule/gitmodules.ts +0 -126
- package/src/modules/cli/git/submodule/printer.ts +0 -256
- package/src/modules/cli/git/submodule/resolve-git-dir.ts +0 -14
- package/src/modules/cli/github/impl.ts +0 -169
- package/src/modules/cli/github/interface.ts +0 -29
- package/src/modules/cli/index.ts +0 -16
- package/src/modules/common/crypto/impl.ts +0 -173
- package/src/modules/common/crypto/interface.ts +0 -20
- package/src/modules/common/index.ts +0 -19
- package/src/modules/common/kep-map-store/impl.ts +0 -47
- package/src/modules/common/kep-map-store/interface.ts +0 -9
- package/src/modules/common/os-platform/caller-info.ts +0 -152
- package/src/modules/common/os-platform/impl.ts +0 -91
- package/src/modules/common/os-platform/interface.ts +0 -16
- package/src/modules/common/os-platform/virtual-hid/index.ts +0 -12
- package/src/modules/common/os-platform/virtual-hid/linux.ts +0 -7
- package/src/modules/common/os-platform/virtual-hid/mac.ts +0 -150
- package/src/modules/common/os-platform/virtual-hid/windows.ts +0 -7
- package/src/modules/common/ssh-config/impl.ts +0 -130
- package/src/modules/common/ssh-config/interface.ts +0 -33
- package/src/modules/ssh-agent/index.ts +0 -13
- package/src/modules/ssh-agent/session/agent-notes.md +0 -210
- package/src/modules/ssh-agent/session/design.md +0 -2
- package/src/modules/ssh-agent/session/html-refactor.md +0 -23
- package/src/modules/ssh-agent/session/impl.ts +0 -328
- package/src/modules/ssh-agent/session/interface-rpc.ts +0 -24
- package/src/modules/ssh-agent/session/interface.ts +0 -62
- package/src/modules/ssh-agent/session/passkey-prf-page.ts +0 -224
- package/src/modules/ssh-agent/session/prf-flow.ts +0 -152
- package/src/modules/ssh-agent/ssh-agent/impl.ts +0 -136
- package/src/modules/ssh-agent/ssh-agent/interface.ts +0 -9
- package/src/scripts/build.ts +0 -504
- package/src/scripts/check-npm-version.ts +0 -7
- package/src/scripts/command-launcher.js.ejs +0 -168
- package/src/scripts/kill-existing-agent.ts +0 -22
- package/src/scripts/publish.ts +0 -47
- package/src/scripts/windows-bin-shims.md +0 -1104
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { appendFileSync } from "node:fs";
|
|
2
|
-
import { Effect, Layer, pipe } from "effect";
|
|
3
|
-
import { OSPlatformImpl } from "@/modules/common/os-platform/impl";
|
|
4
|
-
import { CryptoImpl } from "@/modules/common/crypto/impl";
|
|
5
|
-
import { KeyMapStoreImpl } from "@/modules/common/kep-map-store/impl";
|
|
6
|
-
import { SSHConfigImpl } from "@/modules/common/ssh-config/impl";
|
|
7
|
-
import { SSHAgentImpl } from "@/modules/ssh-agent/ssh-agent/impl";
|
|
8
|
-
import { SessionImpl } from "@/modules/ssh-agent/session/impl";
|
|
9
|
-
import { AGENT_LOG_FILE_PATH, AGENT_PID_FILE_PATH, AGENT_PORT_FILE_PATH, AGENT_SOCK_FILE_PATH } from "@/common/constants";
|
|
10
|
-
import { rmSync } from "node:fs";
|
|
11
|
-
|
|
12
|
-
const origLog = console.log.bind(console);
|
|
13
|
-
const origError = console.error.bind(console);
|
|
14
|
-
const origWarn = console.warn.bind(console);
|
|
15
|
-
|
|
16
|
-
function logToFile(...args: any[]) {
|
|
17
|
-
try {
|
|
18
|
-
appendFileSync(AGENT_LOG_FILE_PATH, args.map(arg => {
|
|
19
|
-
try { return JSON.stringify(arg) }
|
|
20
|
-
catch(e) { return String(e); }
|
|
21
|
-
}).join(' ') + '\n');
|
|
22
|
-
} catch {}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
console.log = (...args: any[]) => { logToFile(...args); origLog(...args); };
|
|
26
|
-
console.error = (...args: any[]) => { logToFile(...args); origError(...args); };
|
|
27
|
-
console.warn = (...args: any[]) => { logToFile(...args); origWarn(...args); };
|
|
28
|
-
|
|
29
|
-
function cleanup() {
|
|
30
|
-
try { rmSync(AGENT_PID_FILE_PATH); } catch {}
|
|
31
|
-
try { rmSync(AGENT_PORT_FILE_PATH); } catch {}
|
|
32
|
-
try { rmSync(AGENT_SOCK_FILE_PATH); } catch {}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
process.on("exit", cleanup);
|
|
36
|
-
process.on("SIGTERM", () => { cleanup(); process.exit(0); });
|
|
37
|
-
process.on("SIGINT", () => { cleanup(); process.exit(0); });
|
|
38
|
-
|
|
39
|
-
pipe(
|
|
40
|
-
SSHAgentImpl.ServiceLayer,
|
|
41
|
-
Layer.provideMerge(SessionImpl.makeRpcLayer()),
|
|
42
|
-
Layer.provideMerge(KeyMapStoreImpl.Layer),
|
|
43
|
-
Layer.provideMerge(SSHConfigImpl.Layer),
|
|
44
|
-
Layer.provideMerge(CryptoImpl.Layer),
|
|
45
|
-
Layer.provideMerge(OSPlatformImpl.Layer),
|
|
46
|
-
Layer.launch,
|
|
47
|
-
Effect.runPromise
|
|
48
|
-
);
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { AGENT_SOCK_FILE_PATH } from "@/common/constants";
|
|
2
|
-
|
|
3
|
-
const result = Bun.spawnSync(["ssh-keygen", ...Bun.argv.slice(2)], {
|
|
4
|
-
stdin: "inherit",
|
|
5
|
-
stdout: "inherit",
|
|
6
|
-
stderr: "inherit",
|
|
7
|
-
env: { ...process.env, SSH_AUTH_SOCK: AGENT_SOCK_FILE_PATH },
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
process.exit(result.exitCode ?? 1);
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { Effect } from "effect";
|
|
2
|
-
import { appendFileSync } from "node:fs";
|
|
3
|
-
import { commonModules } from "@/modules/common";
|
|
4
|
-
import { OSPlatformImpl } from "@/modules/common/os-platform/impl";
|
|
5
|
-
import { VIRTUAL_KEY_LOG_FILE_PATH } from "@/common/constants";
|
|
6
|
-
|
|
7
|
-
const program = Effect.gen(function* () {
|
|
8
|
-
const platform = yield* commonModules.OSPlatform;
|
|
9
|
-
yield* platform.registerVirtualHID((data) =>
|
|
10
|
-
Effect.sync(() => {
|
|
11
|
-
appendFileSync(VIRTUAL_KEY_LOG_FILE_PATH, `[vhid] received ${data.length} bytes: ${data.toString('hex')}\n`);
|
|
12
|
-
return Buffer.alloc(64);
|
|
13
|
-
})
|
|
14
|
-
);
|
|
15
|
-
yield* Effect.never;
|
|
16
|
-
}).pipe(Effect.provide(OSPlatformImpl.Layer));
|
|
17
|
-
|
|
18
|
-
Effect.runPromise(program).catch(e => {
|
|
19
|
-
console.error('Virtual security key failed:', e);
|
|
20
|
-
process.exit(1);
|
|
21
|
-
});
|
package/src/entrypoints/ozy.ts
DELETED
package/src/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/src/internal/thing.ts
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
import { Effect, Layer, Match, Option, pipe, Data, FileSystem, Schedule, Result } from "effect";
|
|
2
|
-
import { effunct, implementing, type EffectGen } from "effective-modules";
|
|
3
|
-
import { FetchHttpClient } from "effect/unstable/http";
|
|
4
|
-
import { RpcClient, RpcSerialization } from "effect/unstable/rpc";
|
|
5
|
-
import { AgentRpcGroup } from "@/modules/ssh-agent/session/interface-rpc";
|
|
6
|
-
import { cliModules } from "..";
|
|
7
|
-
import { type AgentRpcClient, type IAgentClient, AgentClientError } from "./interface";
|
|
8
|
-
import { AGENT_CMD_PATH, AGENT_PID_FILE_PATH, AGENT_PORT_FILE_PATH, AGENT_SOCK_FILE_PATH, CURRENT_VERSION } from "@/common/constants";
|
|
9
|
-
import { readFileSync, rmSync } from "node:fs";
|
|
10
|
-
import { log } from "@/common/log";
|
|
11
|
-
|
|
12
|
-
function makeAgentClientLayer(port: number) {
|
|
13
|
-
return pipe(
|
|
14
|
-
RpcClient.layerProtocolHttp({ url: `http://localhost:${port}/rpc` }),
|
|
15
|
-
Layer.provideMerge(RpcSerialization.layerJson),
|
|
16
|
-
Layer.provideMerge(FetchHttpClient.layer)
|
|
17
|
-
);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
class NoResponseError extends Data.TaggedError("NoResponseError")<{}> {
|
|
21
|
-
public toString() { return "No response from agent."; }
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
class NonMatchingVersionError extends Data.TaggedError("NonMatchingVersionError")<{
|
|
25
|
-
cliVersion: string;
|
|
26
|
-
agentVersion: string;
|
|
27
|
-
}> {
|
|
28
|
-
public toString() {
|
|
29
|
-
return `Agent running but with mismatched version ${this.agentVersion} compared to CLI version ${this.cliVersion}`;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
type PingError = NoResponseError | NonMatchingVersionError;
|
|
34
|
-
|
|
35
|
-
export class AgentClientImpl extends implementing(cliModules.AgentClient).uses(FileSystem.FileSystem) implements IAgentClient {
|
|
36
|
-
private *readPortFromFile(): EffectGen<Option.Option<number>, never> {
|
|
37
|
-
const result = yield* pipe(
|
|
38
|
-
this.getDependency(FileSystem.FileSystem).readFileString(AGENT_PORT_FILE_PATH),
|
|
39
|
-
Effect.result
|
|
40
|
-
);
|
|
41
|
-
if (Result.isFailure(result)) return Option.none();
|
|
42
|
-
const port = parseInt(result.success.trim());
|
|
43
|
-
if (isNaN(port) || port <= 0 || port > 65535) {
|
|
44
|
-
log(`Read out of bounds port ${port}`);
|
|
45
|
-
return Option.none();
|
|
46
|
-
}
|
|
47
|
-
return Option.some(port);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
private *pingAtPort(port: number): EffectGen<void, PingError> {
|
|
51
|
-
yield* Effect.scoped(
|
|
52
|
-
Effect.gen(function* () {
|
|
53
|
-
const client = yield* RpcClient.make(AgentRpcGroup);
|
|
54
|
-
const { version } = yield* pipe(
|
|
55
|
-
client.GetVersion({}),
|
|
56
|
-
Effect.catchTag("RpcClientError", () => new NoResponseError())
|
|
57
|
-
);
|
|
58
|
-
if (version !== CURRENT_VERSION)
|
|
59
|
-
yield* new NonMatchingVersionError({ cliVersion: CURRENT_VERSION, agentVersion: version });
|
|
60
|
-
})
|
|
61
|
-
).pipe(Effect.provide(makeAgentClientLayer(port)));
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
private *ping(): EffectGen<{ port: number }, PingError> {
|
|
65
|
-
const portOption = yield* effunct(this.readPortFromFile)();
|
|
66
|
-
if (Option.isNone(portOption)) return yield* new NoResponseError();
|
|
67
|
-
const port = portOption.value;
|
|
68
|
-
yield* effunct(this.pingAtPort)(port);
|
|
69
|
-
return { port };
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
private *waitForPidFile(expectedPid: number): EffectGen<void, string> {
|
|
73
|
-
const fs = this.getDependency(FileSystem.FileSystem);
|
|
74
|
-
yield* pipe(
|
|
75
|
-
Effect.retry(
|
|
76
|
-
pipe(
|
|
77
|
-
fs.readFileString(AGENT_PID_FILE_PATH),
|
|
78
|
-
Effect.catchTag("PlatformError", () => Effect.fail("pid file not yet written")),
|
|
79
|
-
Effect.flatMap(content => {
|
|
80
|
-
const pid = parseInt(content.trim());
|
|
81
|
-
return pid === expectedPid
|
|
82
|
-
? Effect.void
|
|
83
|
-
: Effect.fail(`PID mismatch: expected ${expectedPid}, got ${pid}`);
|
|
84
|
-
})
|
|
85
|
-
),
|
|
86
|
-
Schedule.spaced("50 millis")
|
|
87
|
-
),
|
|
88
|
-
Effect.timeout("5 seconds"),
|
|
89
|
-
Effect.mapError(() => "Agent did not start within 5 seconds")
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
private *startAgent(): EffectGen<{ pid: number; port: number }, string | PingError> {
|
|
94
|
-
const proc = Bun.spawn([AGENT_CMD_PATH], { stdout: "ignore", stderr: "ignore" });
|
|
95
|
-
yield* effunct(this.waitForPidFile)(proc.pid);
|
|
96
|
-
const { port } = yield* effunct(this.ping)();
|
|
97
|
-
log(`Started agent at PID ${proc.pid}`);
|
|
98
|
-
return { pid: proc.pid, port };
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
*killIfRunning(): EffectGen<void, string> {
|
|
102
|
-
try {
|
|
103
|
-
// Throws if file missing
|
|
104
|
-
const pidFileContent = readFileSync(AGENT_PID_FILE_PATH, "utf-8");
|
|
105
|
-
const PID = parseInt(pidFileContent.trim());
|
|
106
|
-
// If doesn't exist, below line throws
|
|
107
|
-
process.kill(PID, 0);
|
|
108
|
-
log(`Killing agent on PID ${PID}`);
|
|
109
|
-
process.kill(PID, "SIGTERM");
|
|
110
|
-
yield* Effect.sleep(500);
|
|
111
|
-
} catch { }
|
|
112
|
-
try { rmSync(AGENT_PID_FILE_PATH); } catch {}
|
|
113
|
-
try { rmSync(AGENT_PORT_FILE_PATH); } catch {}
|
|
114
|
-
try { rmSync(AGENT_SOCK_FILE_PATH); } catch {}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
private *ensureRunning(): EffectGen<{ port: number }, string> {
|
|
118
|
-
const pingResult = yield* pipe(effunct(this.ping)(), Effect.result);
|
|
119
|
-
if (Result.isSuccess(pingResult)) return pingResult.success;
|
|
120
|
-
log(pingResult.failure.toString());
|
|
121
|
-
yield* Match.value(pingResult.failure).pipe(
|
|
122
|
-
Match.tag("NonMatchingVersionError", () => effunct(this.killIfRunning)()),
|
|
123
|
-
Match.tag("NoResponseError", () => effunct(this.killIfRunning)()),
|
|
124
|
-
Match.exhaustive
|
|
125
|
-
);
|
|
126
|
-
return yield* pipe(
|
|
127
|
-
effunct(this.startAgent)(),
|
|
128
|
-
Effect.mapError(err =>
|
|
129
|
-
typeof err === "string" ?
|
|
130
|
-
err :
|
|
131
|
-
`Failed to start agent due to ${err.name}: ${err.toString()}`
|
|
132
|
-
)
|
|
133
|
-
);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
*usingClient<A, E>(use: (client: AgentRpcClient) => EffectGen<A, E>): EffectGen<A, AgentClientError<E>> {
|
|
137
|
-
const { port } = yield* pipe(
|
|
138
|
-
effunct(this.ensureRunning)(),
|
|
139
|
-
Effect.mapError(reason => new AgentClientError.ClientError({ reason }))
|
|
140
|
-
);
|
|
141
|
-
return yield* pipe(
|
|
142
|
-
Effect.scoped(
|
|
143
|
-
Effect.gen(function* () {
|
|
144
|
-
const client = yield* RpcClient.make(AgentRpcGroup);
|
|
145
|
-
return yield* use(client);
|
|
146
|
-
})
|
|
147
|
-
),
|
|
148
|
-
Effect.provide(makeAgentClientLayer(port)),
|
|
149
|
-
Effect.mapError(e => new AgentClientError.UsageError({ cause: e }))
|
|
150
|
-
);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { EffectGen } from "effective-modules";
|
|
2
|
-
import type { AgentRpcGroup } from "@/modules/ssh-agent/session/interface-rpc";
|
|
3
|
-
import type { RpcClient, RpcClientError as RpcClientErrorModule, RpcGroup } from "effect/unstable/rpc";
|
|
4
|
-
import { Data } from "effect";
|
|
5
|
-
|
|
6
|
-
export type AgentRpcClient = RpcClient.RpcClient<RpcGroup.Rpcs<AgentRpcGroup>, RpcClientErrorModule.RpcClientError>;
|
|
7
|
-
|
|
8
|
-
export namespace AgentClientError {
|
|
9
|
-
export class UsageError<E> extends Data.TaggedError("AgentClientUsageError")<{ readonly cause: E }> {}
|
|
10
|
-
export class ClientError extends Data.TaggedError("AgentClientError")<{ readonly reason: string }> {}
|
|
11
|
-
}
|
|
12
|
-
export type AgentClientError<E> = AgentClientError.UsageError<E> | AgentClientError.ClientError;
|
|
13
|
-
|
|
14
|
-
export interface IAgentClient {
|
|
15
|
-
killIfRunning(): EffectGen<void, string>;
|
|
16
|
-
usingClient<A, E>(use: (client: AgentRpcClient) => EffectGen<A, E>): EffectGen<A, AgentClientError<E>>;
|
|
17
|
-
}
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import { implementing, type EffectGen } from "effective-modules";
|
|
2
|
-
import { cliModules } from "..";
|
|
3
|
-
import { commonModules } from "@/modules/common";
|
|
4
|
-
import { $ } from 'bun';
|
|
5
|
-
import type { IGit, SetupRepoInput } from "./interface";
|
|
6
|
-
import { Effect, Option, pipe } from "effect";
|
|
7
|
-
import { existsSync } from "node:fs";
|
|
8
|
-
import { resolve } from "node:path";
|
|
9
|
-
import { SSH_KEYGEN_CMD_PATH, STANDARD_REMOTE_PREFIX } from "@/common/constants";
|
|
10
|
-
import { Gitmodules } from "./submodule/gitmodules";
|
|
11
|
-
import { readGitState } from "./submodule/git-state";
|
|
12
|
-
import { fixGitConfig, fixModuleDirs, fixIndexGitlinks } from "./submodule/fix";
|
|
13
|
-
import { printSyncState, printFixes } from "./submodule/printer";
|
|
14
|
-
|
|
15
|
-
export class GitImpl extends implementing(cliModules.Git).uses(commonModules.OSPlatform, commonModules.SSHConfig) implements IGit {
|
|
16
|
-
private parseOwnerRepo(remote: string): Effect.Effect<{ owner: string; repo: string }, string> {
|
|
17
|
-
const sshMatch = remote.match(/^git@[^:]+:([^/]+)\/(.+?)(?:\.git)?$/);
|
|
18
|
-
if (sshMatch) return Effect.succeed({ owner: sshMatch[1]!, repo: sshMatch[2]! });
|
|
19
|
-
const httpsMatch = remote.match(/^https?:\/\/[^/]+\/([^/]+)\/(.+?)(?:\.git)?$/);
|
|
20
|
-
if (httpsMatch) return Effect.succeed({ owner: httpsMatch[1]!, repo: httpsMatch[2]! });
|
|
21
|
-
return Effect.fail(`Cannot parse owner/repo from remote: ${remote}`);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
*resolveOwnerAndRepo(maybeOwnerAndRepo: Option.Option<string>): EffectGen<{ owner: string; repo: string; }, string> {
|
|
25
|
-
if (Option.isSome(maybeOwnerAndRepo)) {
|
|
26
|
-
const parts = maybeOwnerAndRepo.value.split('/');
|
|
27
|
-
const [owner, repo] = parts;
|
|
28
|
-
if (parts.length !== 2 || !owner || !repo)
|
|
29
|
-
return yield* Effect.fail(`Cannot parse remote error: Expected "owner/repo", got "${maybeOwnerAndRepo.value}"`);
|
|
30
|
-
return { owner, repo };
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if (!(yield* this.isGitRepository())) {
|
|
34
|
-
yield* Effect.fail(`not in git repo: Current directory is not a git repository`);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const remoteOption = yield* this.getRemoteOrigin();
|
|
38
|
-
if (Option.isNone(remoteOption)) {
|
|
39
|
-
return yield* Effect.fail(`no remote origin: No remote.origin.url — pass owner/repo as argument to clone instead`);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return yield* this.parseOwnerRepo(remoteOption.value);
|
|
43
|
-
}
|
|
44
|
-
*isGitRepository(): EffectGen<boolean> {
|
|
45
|
-
return yield* pipe(
|
|
46
|
-
Effect.tryPromise(async () => {
|
|
47
|
-
await $`git rev-parse --is-inside-work-tree`.quiet();
|
|
48
|
-
return true;
|
|
49
|
-
}),
|
|
50
|
-
Effect.catchTag("UnknownError", () => Effect.succeed(false))
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
*getRemoteOrigin(): EffectGen<Option.Option<string>> {
|
|
54
|
-
return yield* pipe(
|
|
55
|
-
Effect.tryPromise(async() => {
|
|
56
|
-
return Option.some((await $`git config --get remote.origin.url`.quiet()).text().trim());
|
|
57
|
-
}),
|
|
58
|
-
Effect.catchTag("UnknownError", () => Effect.succeed(Option.none()))
|
|
59
|
-
)
|
|
60
|
-
}
|
|
61
|
-
*clone(owner: string, repo: string): EffectGen<void, string> {
|
|
62
|
-
const result = Bun.spawnSync(['git', 'clone', '--recurse-submodules', `${STANDARD_REMOTE_PREFIX}${owner}/${repo}.git`], { stdout: 'inherit', stderr: 'inherit' });
|
|
63
|
-
if (result.exitCode !== 0)
|
|
64
|
-
return yield* Effect.fail(`git clone failed with exit code ${result.exitCode}`);
|
|
65
|
-
process.chdir(`./${repo}`);
|
|
66
|
-
}
|
|
67
|
-
*setLocalConfig(key: string, value: string): EffectGen<void, string> {
|
|
68
|
-
yield* Effect.tryPromise({
|
|
69
|
-
try: async () => { await $`git config --local ${key} ${value}`.quiet(); },
|
|
70
|
-
catch: (e) => `git config ${key}: ${e instanceof Error ? e.message : String(e)}`,
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
private *configureRepo({ dir, remoteURL, user, pubkeyPath }: SetupRepoInput): EffectGen<void, string> {
|
|
74
|
-
yield* Effect.log(`Configuring ${dir}`);
|
|
75
|
-
yield* Effect.tryPromise({
|
|
76
|
-
try: async () => {
|
|
77
|
-
const configs: [string, string][] = [
|
|
78
|
-
['remote.origin.url', remoteURL],
|
|
79
|
-
['user.name', user.name],
|
|
80
|
-
['user.email', user.email],
|
|
81
|
-
['user.signingkey', pubkeyPath],
|
|
82
|
-
['gpg.format', 'ssh'],
|
|
83
|
-
['gpg.ssh.program', SSH_KEYGEN_CMD_PATH],
|
|
84
|
-
['commit.gpgsign', 'true'],
|
|
85
|
-
['tag.gpgsign', 'true'],
|
|
86
|
-
];
|
|
87
|
-
for (const [k, v] of configs) {
|
|
88
|
-
const r = Bun.spawnSync(['git', 'config', '--local', k, v], { cwd: dir, stdout: 'pipe', stderr: 'pipe' });
|
|
89
|
-
if (r.exitCode !== 0) {
|
|
90
|
-
const err = new TextDecoder().decode(r.stderr);
|
|
91
|
-
throw new Error(`git config ${k} failed: ${err.trim()}`);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
},
|
|
95
|
-
catch: (e) => e instanceof Error ? e.message : String(e),
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
private *syncSubmoduleState(repoRoot: string, topLevelRoot: string): EffectGen<Gitmodules, string> {
|
|
99
|
-
const gitmodules = yield* Gitmodules.fromRepoRoot(repoRoot);
|
|
100
|
-
if (gitmodules.list.length === 0) return gitmodules;
|
|
101
|
-
const submodulePaths = gitmodules.list.map(m => m.path);
|
|
102
|
-
const state = yield* readGitState(repoRoot, submodulePaths);
|
|
103
|
-
printSyncState(gitmodules, state);
|
|
104
|
-
const fixResults = yield* Effect.all(
|
|
105
|
-
[
|
|
106
|
-
fixGitConfig(repoRoot, gitmodules),
|
|
107
|
-
fixModuleDirs(repoRoot, gitmodules, state.moduleDirs, state.orphanModuleDirs, topLevelRoot),
|
|
108
|
-
fixIndexGitlinks(repoRoot, gitmodules, state.index),
|
|
109
|
-
],
|
|
110
|
-
{ concurrency: "unbounded" },
|
|
111
|
-
);
|
|
112
|
-
printFixes(fixResults.flat());
|
|
113
|
-
return gitmodules;
|
|
114
|
-
}
|
|
115
|
-
*setupRepo(input: SetupRepoInput): EffectGen<void, string> {
|
|
116
|
-
yield* this.setupRepoAt(input, input.dir);
|
|
117
|
-
}
|
|
118
|
-
private *setupRepoAt(input: SetupRepoInput, topLevelRoot: string): EffectGen<void, string> {
|
|
119
|
-
yield* this.configureRepo(input);
|
|
120
|
-
if (!existsSync(resolve(input.dir, '.gitmodules'))) return;
|
|
121
|
-
const gitmodules = yield* this.syncSubmoduleState(input.dir, topLevelRoot);
|
|
122
|
-
for (const m of gitmodules.list) {
|
|
123
|
-
const subDir = resolve(input.dir, m.path);
|
|
124
|
-
if (!existsSync(subDir)) continue;
|
|
125
|
-
yield* this.setupRepoAt({
|
|
126
|
-
dir: subDir,
|
|
127
|
-
remoteURL: m.url,
|
|
128
|
-
user: input.user,
|
|
129
|
-
pubkeyPath: input.pubkeyPath
|
|
130
|
-
}, topLevelRoot);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { type EffectGen} from "effective-modules";
|
|
2
|
-
import { Option } from "effect";
|
|
3
|
-
|
|
4
|
-
export interface GitUser {
|
|
5
|
-
name: string;
|
|
6
|
-
email: string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export interface SetupRepoInput {
|
|
10
|
-
dir: string;
|
|
11
|
-
user: GitUser;
|
|
12
|
-
pubkeyPath: string;
|
|
13
|
-
remoteURL: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface IGit {
|
|
17
|
-
isGitRepository(): EffectGen<boolean>;
|
|
18
|
-
getRemoteOrigin(): EffectGen<Option.Option<string>>;
|
|
19
|
-
resolveOwnerAndRepo(maybeOwnerAndRepo: Option.Option<string>): EffectGen<{owner: string; repo: string;}, string>;
|
|
20
|
-
clone(owner: string, repo: string): EffectGen<void, string>;
|
|
21
|
-
setLocalConfig(key: string, value: string): EffectGen<void, string>;
|
|
22
|
-
setupRepo(params: SetupRepoInput): EffectGen<void, string>;
|
|
23
|
-
}
|