mirror of
https://github.com/schpet/linear-cli.git
synced 2026-09-14 14:26:50 +08:00
3a00cc7604
Every command that takes a team now accepts its key, name, or UUID through
one shared resolver (findTeam / resolveTeam / resolveTeams), replacing the
key-only getTeamIdByKey and the ad-hoc uppercasing spread across commands.
One aliased ResolveTeam operation looks up key, name, and (for UUID-shaped
input) id in a single round trip; precedence is key, then id, then name,
applied client-side so a reference that equals one team's key and another
team's name always means the key. Keys stay the canonical downstream form:
filters that matched on team.key still do, with the server's uppercase key,
and callers that need a UUID take it from the same resolved object. An
unknown team now errors with the list of valid keys instead of an empty
result or a raw "Entity not found" from the API.
Only explicit input goes through the resolver. The configured default team
is already a normalized key, and resolving it would add a round trip to
every default-team invocation of the most-used commands for no gain. In
issue create, the interactive substring picker survives only for that
default; an explicit --team that matches nothing errors like everywhere
else.
issue query --state and issue mine --state take a workflow state name or
ID as well as the six type tokens. Names and IDs are resolved within the
queried scope (the team, the teams, or the whole workspace under
--all-teams, where a name matches every team's same-named state), so a
state from another team errors instead of silently matching nothing, and
the error lists the scope's states. Type-only input still sends the same
{ type: { in } } filter with no extra request; a mix of types and names
becomes an or-filter.
The MCP server already describes these parameters as "key, name, or ID"
and "type, name, or ID"; this brings the CLI to parity so an agent does
not need a preliminary team list to translate a name into a key.
Claude-Session: https://claude.ai/code/session_01A9qEGri4p2HZMQSuYsBmub
62 lines
1.7 KiB
TypeScript
62 lines
1.7 KiB
TypeScript
import { MockLinearServer } from "./mock_linear_server.ts"
|
|
|
|
// Common Deno args for permissions used across all tests
|
|
export const commonDenoArgs = ["--allow-all", "--quiet"]
|
|
|
|
// Helper function to set up mock Linear server with common environment
|
|
export async function setupMockLinearServer(
|
|
mockResponses: Array<{
|
|
queryName: string
|
|
queryIncludes?: string
|
|
variables?: Record<string, unknown>
|
|
response: Record<string, unknown>
|
|
}>,
|
|
envVars?: Record<string, string>,
|
|
): Promise<{ server: MockLinearServer; cleanup: () => Promise<void> }> {
|
|
const server = new MockLinearServer(mockResponses)
|
|
await server.start()
|
|
|
|
Deno.env.set("LINEAR_GRAPHQL_ENDPOINT", server.getEndpoint())
|
|
Deno.env.set("LINEAR_API_KEY", "Bearer test-token")
|
|
|
|
// Set any additional environment variables
|
|
if (envVars) {
|
|
for (const [key, value] of Object.entries(envVars)) {
|
|
Deno.env.set(key, value)
|
|
}
|
|
}
|
|
|
|
const cleanup = async () => {
|
|
await server.stop()
|
|
Deno.env.delete("LINEAR_GRAPHQL_ENDPOINT")
|
|
Deno.env.delete("LINEAR_API_KEY")
|
|
|
|
// Clean up additional environment variables
|
|
if (envVars) {
|
|
for (const key of Object.keys(envVars)) {
|
|
Deno.env.delete(key)
|
|
}
|
|
}
|
|
}
|
|
|
|
return { server, cleanup }
|
|
}
|
|
|
|
export const ENG_TEAM = { id: "team-eng-id", key: "ENG", name: "Engineering" }
|
|
|
|
/**
|
|
* Mock for the shared team resolver's key/name lookup. The server matches
|
|
* keys and names case-insensitively, so pass the exact reference the test
|
|
* sends and the team it should resolve to.
|
|
*/
|
|
export function resolveTeamMock(
|
|
reference: string,
|
|
team: { id: string; key: string; name: string } = ENG_TEAM,
|
|
) {
|
|
return {
|
|
queryName: "ResolveTeam",
|
|
variables: { reference },
|
|
response: { data: { teams: { nodes: [team] } } },
|
|
}
|
|
}
|