@spotable/attio-sdk
Version:
Client for Attio REST API
119 lines (100 loc) • 4.18 kB
text/typescript
import { AttioObject } from "../../helpers/fetchAttioSchema";
import { writeGeneratedFile } from "../../helpers/fs";
import { generateFileHeader } from "../types/fileHeader";
const FILE_NAME = "attioClient.ts";
export function generateAttioClient(outputDir: string, objects: AttioObject[], includeStandardTypes: boolean): void {
const standardTypesImports = includeStandardTypes
? `import { AttioObjectFetcher } from "./fetchers/object";
import { AttioAttributeFetcher } from "./fetchers/attribute";
import { AttioListFetcher } from "./fetchers/list";
import { AttioListEntryFetcher } from "./fetchers/listEntry";
import { AttioNoteFetcher } from "./fetchers/note";
import { AttioTaskFetcher } from "./fetchers/task";
import { AttioWebhookFetcher } from "./fetchers/webhook";
import { AttioCommentFetcher } from "./fetchers/comment";
import { AttioWorkspaceMemberFetcher } from "./fetchers/workspaceMember";`
: "";
const standardTypes = includeStandardTypes
? `objects: AttioObjectFetcher;
attributes: AttioAttributeFetcher;
lists: AttioListFetcher;
listEntries: AttioListEntryFetcher;
notes: AttioNoteFetcher;
tasks: AttioTaskFetcher;
webhooks: AttioWebhookFetcher;
comments: AttioCommentFetcher;
workspaceMembers: AttioWorkspaceMemberFetcher;`
: "";
const content = `${generateFileHeader(FILE_NAME)}
import fetch, { RequestInit, Response } from "node-fetch";
${standardTypesImports}
// We always import the record fetcher because it is used for all objects
import { AttioRecordFetcher } from "./fetchers/record";
import { ${objects.map((object) => `${object.singular_noun}, ${object.singular_noun}Attributes, ${object.singular_noun}InputAttributes`).join(", ")} } from "./types";
const DEFAULT_ATTIO_API_URL = "https://api.attio.com/v2";
export interface AttioClientOptions {
/**
* The API key for authenticating with the Attio API.
*/
apiKey: string;
/**
* The base URL for the Attio API. Defaults to "https://api.attio.com/v2".
*/
apiUrl?: string;
}
type DoFetchOptions = Omit<RequestInit, "body"> & {
query?: object;
body?: Record<string, any>;
};
export class AttioClient {
private static options: AttioClientOptions;
constructor(options: AttioClientOptions) {
AttioClient.options = options;
AttioClient.options.apiUrl = AttioClient.options.apiUrl || DEFAULT_ATTIO_API_URL;
${
includeStandardTypes
? `
this.objects = new AttioObjectFetcher(this);
this.attributes = new AttioAttributeFetcher(this);
this.lists = new AttioListFetcher(this);
this.listEntries = new AttioListEntryFetcher(this);
this.notes = new AttioNoteFetcher(this);
this.tasks = new AttioTaskFetcher(this);
this.webhooks = new AttioWebhookFetcher(this);
this.comments = new AttioCommentFetcher(this);
this.workspaceMembers = new AttioWorkspaceMemberFetcher(this)`.trim()
: ""
}
${objects.map((object) => `this.${object.api_slug} = new AttioRecordFetcher<${object.singular_noun}, ${object.singular_noun}InputAttributes, ${object.singular_noun}Attributes>(this, "${object.api_slug}");`).join("\n ")}
}
public async doFetch(uri: string, opts?: DoFetchOptions): Promise<Response> {
const { query, body, ...init } = opts || {};
const queryString = query
? \`?$\{new URLSearchParams(
Object.fromEntries(
Object.entries(query)
.filter(([_, v]) => v !== undefined)
.map(([k, v]) => [k, String(v)])
)
).toString()}\`
: "";
const response = await fetch(\`$\{AttioClient.options.apiUrl}$\{uri}$\{queryString}\`, {
...init,
body: body ? JSON.stringify(body) : undefined,
headers: {
...init?.headers,
Authorization: \`Bearer $\{AttioClient.options.apiKey}\`,
"Content-Type": "application/json",
},
});
return response;
}
${standardTypes}
${objects
.map((object) => `${object.api_slug}: AttioRecordFetcher<${object.singular_noun}, ${object.singular_noun}InputAttributes, ${object.singular_noun}Attributes>;`)
.join("\n ")
.trim()}
}
`;
writeGeneratedFile(outputDir, FILE_NAME, content);
}