Skip to content
Open
1 change: 1 addition & 0 deletions packages/source-control-cursor-origin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
},
"devDependencies": {
"@effect/vitest": "catalog:",
"@t3tools/source-control-testing": "workspace:*",
"@types/node": "catalog:",
"vite-plus": "catalog:"
}
Expand Down
10 changes: 9 additions & 1 deletion packages/source-control-cursor-origin/src/server/OriginCli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ const OriginAuthStatusSchema = Schema.Struct({
});
type OriginAuthStatus = typeof OriginAuthStatusSchema.Type;

/** `origin` exits 1 on a bare `--json`, so this names the fields `OriginAuthStatusSchema` reads. */
export const ORIGIN_AUTH_STATUS_ARGS = [
"auth",
"status",
"--json",
"authenticated,tokenValid,account",
] as const;

export function parseOriginAuthStatus(raw: string): OriginAuthStatus | null {
const decoded = decodeJsonResult(OriginAuthStatusSchema)(raw);
return Result.isSuccess(decoded) ? decoded.success : null;
Expand Down Expand Up @@ -382,7 +390,7 @@ const make = Effect.gen(function* () {
});

const authStatus = (cwd: string) =>
run({ cwd, operation: "authStatus", args: ["auth", "status", "--json"] }).pipe(
run({ cwd, operation: "authStatus", args: ORIGIN_AUTH_STATUS_ARGS }).pipe(
Effect.flatMap((result) => {
const status = parseOriginAuthStatus(result.stdout);
if (status !== null) return Effect.succeed(status);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { assert, it } from "@effect/vitest";
import * as Effect from "effect/Effect";
import * as Layer from "effect/Layer";
import * as Option from "effect/Option";
import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner";
import * as TestSourceControlHost from "@t3tools/source-control-testing/TestSourceControlHost";

import * as OriginCli from "./OriginCli.ts";
import * as OriginSourceControlProvider from "./OriginSourceControlProvider.ts";

const signedIn: Record<string, unknown> = {
authenticated: true,
authMethod: "oauth",
tokenValid: true,
account: { email: "dev@example.test" },
};

// As the real CLI does, this exits 1 on a bare `--json` and prints only the fields it is asked for.
const origin = (args: ReadonlyArray<string>) => {
if (args[0] === "--version") return TestSourceControlHost.processOutput("2026.11.03");
const fields = args[args.indexOf("--json") + 1]?.split(",") ?? [];
return fields.length === 0
? TestSourceControlHost.processOutput("", {
stderr: "Error: Specify one or more comma-separated fields for `--json`:\n authenticated",
exitCode: ChildProcessSpawner.ExitCode(1),
})
: TestSourceControlHost.processOutput(
JSON.stringify(Object.fromEntries(fields.map((field) => [field, signedIn[field]]))),
);
};

it.effect("reads the sign-in from an Origin CLI that wants its --json fields named", () =>
Effect.gen(function* () {
const discovery = yield* OriginSourceControlProvider.makeDiscovery.pipe(
Effect.provide(
Layer.mergeAll(
Layer.mock(OriginCli.OriginCli)({ personalNamespace: () => Effect.succeed("acme") }),
TestSourceControlHost.layer({
process: { run: (input) => Effect.succeed(origin(input.args)) },
}),
),
),
);
const item = yield* discovery.probe("/repo");
assert.strictEqual(item.auth.status, "authenticated");
assert.deepStrictEqual(item.auth.account, Option.some("acme"));
}),
);
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const discovery = {
label: "Cursor Origin",
executable: OriginCli.ORIGIN_COMMAND,
versionArgs: ["--version"],
authArgs: ["auth", "status", "--json"],
authArgs: OriginCli.ORIGIN_AUTH_STATUS_ARGS,
parseAuth: (input) => {
const status = OriginCli.parseOriginAuthStatus(input.stdout);
const account = OriginCli.originAccount(status);
Expand Down
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading