Something went wrong. Try again.
CLI for Linear via GraphQL API
Something went wrong. Try again.
6.8 kB · 314 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315import { graphql } from "../api.ts";import { pad, printTable, requireToken, useJson } from "./shared.ts";
export interface ListDocumentsOptions { project?: string; limit?: number; json?: boolean;}
export async function listDocuments( options: ListDocumentsOptions,): Promise<void> { const token = await requireToken(); const limit = options.limit ?? 50;
const filter: Record<string, unknown> = {}; if (options.project) { filter.project = { id: { eq: options.project } }; }
const query = ` query Documents($first: Int, $filter: DocumentFilter) { documents(first: $first, filter: $filter) { nodes { id title icon color project { name } creator { name } createdAt updatedAt } } } `;
const data = await graphql<{ documents: { nodes: Array<{ id: string; title: string; icon: string | null; color: string | null; project: { name: string } | null; creator: { name: string }; createdAt: string; updatedAt: string; }>; }; }>(token, query, { first: limit, filter: Object.keys(filter).length > 0 ? filter : undefined, });
const documents = data.documents.nodes;
if (await useJson(options.json)) { console.log(JSON.stringify(documents, null, 2)); return; }
if (documents.length === 0) { console.log("No documents found."); return; }
const headers = ["TITLE", "PROJECT", "CREATOR", "CREATED"]; const rows = documents.map((d) => [ d.title, d.project?.name ?? "", d.creator.name, d.createdAt, ]);
printTable(headers, rows);}
export interface GetDocumentOptions { id: string; json?: boolean;}
export async function getDocument(options: GetDocumentOptions): Promise<void> { const token = await requireToken();
const query = ` query Document($id: String!) { document(id: $id) { id title content icon color project { name } creator { name email } createdAt updatedAt url } } `;
const data = await graphql<{ document: { id: string; title: string; content: string; icon: string | null; color: string | null; project: { name: string } | null; creator: { name: string; email: string }; createdAt: string; updatedAt: string; url: string; }; }>(token, query, { id: options.id });
const doc = data.document;
if (await useJson(options.json)) { console.log(JSON.stringify(doc, null, 2)); return; }
const fields: Array<[string, string]> = [ ["Title", doc.title], ["ID", doc.id], ["Icon", doc.icon ?? ""], ["Color", doc.color ?? ""], ["Project", doc.project?.name ?? ""], ["Creator", `${doc.creator.name} <${doc.creator.email}>`], ["Created", doc.createdAt], ["Updated", doc.updatedAt], ["URL", doc.url], ];
const maxKey = Math.max(...fields.map(([k]) => k.length)); for (const [key, value] of fields) { if (value) { console.log(`${pad(key, maxKey)} ${value}`); } }
if (doc.content) { console.log(`\nContent:\n${doc.content}`); }}
export interface CreateDocumentOptions { title: string; content: string; project?: string; json?: boolean;}
export async function createDocument( options: CreateDocumentOptions,): Promise<void> { const token = await requireToken(); const json = await useJson(options.json);
const input: Record<string, unknown> = { title: options.title, content: options.content, };
if (options.project) input.projectId = options.project;
const mutation = ` mutation DocumentCreate($input: DocumentCreateInput!) { documentCreate(input: $input) { success document { id title project { name } url } } } `;
const data = await graphql<{ documentCreate: { success: boolean; document: { id: string; title: string; project: { name: string } | null; url: string; }; }; }>(token, mutation, { input });
if (!data.documentCreate.success) { console.error("Error: Failed to create document."); process.exit(1); }
const doc = data.documentCreate.document;
if (json) { console.log(JSON.stringify(doc, null, 2)); return; }
console.log(`Created ${doc.title}`); if (doc.project) { console.log(`Project: ${doc.project.name}`); } console.log(`URL: ${doc.url}`);}
export interface UpdateDocumentOptions { id: string; title?: string; content?: string; json?: boolean;}
export async function updateDocument( options: UpdateDocumentOptions,): Promise<void> { const token = await requireToken(); const json = await useJson(options.json);
const input: Record<string, unknown> = {};
if (options.title) input.title = options.title; if (options.content) input.content = options.content;
if (Object.keys(input).length === 0) { console.error("Error: No update flags provided."); process.exit(1); }
const mutation = ` mutation DocumentUpdate($id: String!, $input: DocumentUpdateInput!) { documentUpdate(id: $id, input: $input) { success document { id title url } } } `;
const data = await graphql<{ documentUpdate: { success: boolean; document: { id: string; title: string; url: string; }; }; }>(token, mutation, { id: options.id, input });
if (!data.documentUpdate.success) { console.error("Error: Failed to update document."); process.exit(1); }
const doc = data.documentUpdate.document;
if (json) { console.log(JSON.stringify(doc, null, 2)); return; }
console.log(`Updated ${doc.title}`); console.log(`URL: ${doc.url}`);}
export interface DeleteDocumentOptions { id: string; json?: boolean;}
export async function deleteDocument( options: DeleteDocumentOptions,): Promise<void> { const token = await requireToken(); const json = await useJson(options.json);
const mutation = ` mutation DocumentDelete($id: String!) { documentDelete(id: $id) { success } } `;
const data = await graphql<{ documentDelete: { success: boolean; }; }>(token, mutation, { id: options.id });
if (!data.documentDelete.success) { console.error("Error: Failed to delete document."); process.exit(1); }
if (json) { console.log(JSON.stringify({ id: options.id, deleted: true }, null, 2)); return; }
console.log(`Deleted document ${options.id}`);}