/** * Core Integration Entity Utilities * DO NOT MODIFY THIS FILE - You may break the integration entity functionality * * This module provides the IntegrationEntity base class for entities that are backed * by external integrations (HubSpot, GitHub, Salesforce, etc.) instead of local storage. * * IntegrationEntity implements the unified EntityClass interface with EntityContext. * All CRUD operations take ctx as the first parameter, matching the Entity class pattern. */ import type { EntityContext, ListOptions, PaginatedResult, EntityClass } from './core-entities'; import type { Env } from './core-utils'; export interface OperationConfig { /** API endpoint path (use :id for ID placeholder) */ endpoint: string; } export interface IntegrationEntityConfig { /** Integration identifier: "hubspot", "github", "salesforce", etc. */ integrationId: string; /** Nango provider config key: "hubspot", "github", etc. */ providerConfigKey: string; operations: { list?: OperationConfig; get?: OperationConfig; create?: OperationConfig; update?: OperationConfig; delete?: OperationConfig; }; } /** * Extract the entity data type from an IntegrationEntity constructor. * e.g., IntegrationEntityData = HubSpotContact */ type IntegrationEntityData = T extends abstract new (...args: unknown[]) => IntegrationEntity ? D : never; /** * Base constructor type for IntegrationEntity subclasses */ type IntegrationEntityCtor = abstract new (...args: unknown[]) => IntegrationEntity<{ id: string; }>; /** * Constructor with required static properties. * This ensures the calling class has entityName, config, etc. */ type IntegrationEntityCtorWithConfig = TCtor & { entityName: string; config: IntegrationEntityConfig; schema?: Record; getConnectionId(env: Env | Record): string | undefined; }; /** * IntegrationEntityClass type - for type checking integration entity classes */ export interface IntegrationEntityClass extends EntityClass { config: IntegrationEntityConfig; } /** * IntegrationEntity - Base class for entities backed by external integrations * * Implements the unified EntityClass interface with EntityContext as first parameter. * This makes IntegrationEntity and Entity have identical CRUD interfaces. * * Extend this class to define entities that proxy CRUD operations to external services * like HubSpot, GitHub, Salesforce, etc. via the IntegrationClient. * * @example * ```typescript * import { IntegrationEntity, IntegrationEntityConfig } from './core-integration-entities'; * * interface HubSpotContact { * id: string; * properties: { email: string; firstname: string; lastname: string }; * } * * export class ContactEntity extends IntegrationEntity { * static readonly entityName = 'hubspot_contact'; * static readonly config: IntegrationEntityConfig = { * integrationId: 'hubspot', * providerConfigKey: 'hubspot', * operations: { * list: { endpoint: '/crm/v3/objects/contacts' }, * get: { endpoint: '/crm/v3/objects/contacts/:id' }, * create: { endpoint: '/crm/v3/objects/contacts' }, * update: { endpoint: '/crm/v3/objects/contacts/:id' }, * delete: { endpoint: '/crm/v3/objects/contacts/:id' }, * }, * }; * static readonly schema = { fields: ['id', 'email', 'firstname', 'lastname'] }; * } * * // Usage (same pattern as Entity): * const ctx = { env, client }; * const contacts = await ContactEntity.list(ctx, { limit: 50 }); * // contacts is PaginatedResult - properly typed! * const contact = await ContactEntity.get(ctx, 'contact-123'); * // contact is HubSpotContact | null - properly typed! * ``` */ export declare abstract class IntegrationEntity { static readonly entityName: string; static readonly config: IntegrationEntityConfig; static readonly schema?: Record; /** * Get connection ID from env var if explicitly set. * Returns undefined when not set -- the proxy resolves connections * dynamically via workspaceId + provider, so this is optional. */ static getConnectionId(env: Env | Record): string | undefined; /** * Get the IntegrationClient from context * Throws if client is not available */ private static getClient; /** * List entities from the integration with optional filters * Filters are passed through as query parameters to the external API * Note: Entities needing POST-based filtering should override this method */ static list(this: IntegrationEntityCtorWithConfig, ctx: EntityContext, options?: ListOptions): Promise>>; /** * Get a single entity by ID from the integration */ static get(this: IntegrationEntityCtorWithConfig, ctx: EntityContext, id: string): Promise | null>; /** * Create a new entity in the integration */ static create(this: IntegrationEntityCtorWithConfig, ctx: EntityContext, data: Partial>): Promise>; /** * Update an entity in the integration */ static update(this: IntegrationEntityCtorWithConfig, ctx: EntityContext, id: string, data: Partial>): Promise>; /** * Delete an entity from the integration */ static delete(this: IntegrationEntityCtorWithConfig, ctx: EntityContext, id: string): Promise; } /** * Type guard to check if a class is an IntegrationEntity */ export declare function isIntegrationEntity(cls: unknown): cls is IntegrationEntityClass; export {};