@rawdash/connector-calendly 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +149 -0
- package/dist/index.d.ts +649 -0
- package/dist/index.js +567 -0
- package/dist/index.js.map +1 -0
- package/package.json +43 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../connector-shared/src/errors.ts","../../../connector-shared/src/retry.ts","../../../connector-shared/src/version.ts","../../../connector-shared/src/request.ts","../../../connector-shared/src/rate-limit.ts","../../../connector-shared/src/map-concurrent.ts","../../../connector-shared/src/sanitize.ts","../../../connector-shared/src/epoch.ts","../../../connector-shared/src/pagination.ts","../../../connector-shared/src/logger.ts","../src/calendly.ts","../src/index.ts"],"sourcesContent":["import type { HttpResponse } from './types';\n\nexport type HttpErrorKind =\n | 'transient'\n | 'rate_limit'\n | 'auth'\n | 'upstream_bug'\n | 'client_bug';\n\nexport abstract class HttpClientError extends Error {\n abstract readonly kind: HttpErrorKind;\n readonly response?: HttpResponse;\n\n constructor(message: string, response?: HttpResponse) {\n super(message);\n this.name = new.target.name;\n this.response = response;\n }\n}\n\nexport class TransientError extends HttpClientError {\n readonly kind = 'transient' as const;\n}\n\nexport class RateLimitError extends HttpClientError {\n readonly kind = 'rate_limit' as const;\n readonly retryAfter?: Date;\n\n constructor(message: string, response?: HttpResponse, retryAfter?: Date) {\n super(message, response);\n this.retryAfter = retryAfter;\n }\n}\n\nexport class AuthError extends HttpClientError {\n readonly kind = 'auth' as const;\n}\n\nexport class UpstreamBugError extends HttpClientError {\n readonly kind = 'upstream_bug' as const;\n}\n\nexport class ClientBugError extends HttpClientError {\n readonly kind = 'client_bug' as const;\n}\n\nexport function classifyStatus(status: number): HttpErrorKind {\n if (status === 429) {\n return 'rate_limit';\n }\n if (status === 401 || status === 403) {\n return 'auth';\n }\n if (status === 408) {\n return 'transient';\n }\n if (status >= 500) {\n return 'upstream_bug';\n }\n if (status >= 400) {\n return 'client_bug';\n }\n return 'client_bug';\n}\n\nexport function errorForStatus(\n message: string,\n response: HttpResponse,\n retryAfter?: Date,\n): HttpClientError {\n const kind = classifyStatus(response.status);\n switch (kind) {\n case 'rate_limit':\n return new RateLimitError(message, response, retryAfter);\n case 'auth':\n return new AuthError(message, response);\n case 'transient':\n return new TransientError(message, response);\n case 'upstream_bug':\n return new UpstreamBugError(message, response);\n case 'client_bug':\n return new ClientBugError(message, response);\n }\n}\n","import { HttpClientError, RateLimitError, TransientError } from './errors';\n\nexport interface RetryPolicy {\n maxAttempts?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n retryOn?: (status: number | null, err?: Error) => boolean;\n}\n\nexport const defaultRetryOn = (status: number | null, err?: Error): boolean => {\n if (err instanceof RateLimitError) {\n return true;\n }\n if (err instanceof TransientError) {\n return true;\n }\n if (status === null) {\n return err instanceof Error && !(err instanceof HttpClientError);\n }\n if (status === 408 || status === 429) {\n return true;\n }\n if (status >= 500) {\n return true;\n }\n return false;\n};\n\nexport function backoffDelayMs(\n attempt: number,\n policy: Required<Pick<RetryPolicy, 'initialDelayMs' | 'maxDelayMs'>>,\n): number {\n const base = policy.initialDelayMs * 2 ** attempt;\n const jitter = base * 0.25 * Math.random();\n return Math.min(base + jitter, policy.maxDelayMs);\n}\n\nexport function parseRetryAfter(\n headerValue: string | null,\n now: Date = new Date(),\n): Date | undefined {\n if (!headerValue) {\n return undefined;\n }\n const trimmed = headerValue.trim();\n if (/^\\d+$/.test(trimmed)) {\n return new Date(now.getTime() + Number(trimmed) * 1000);\n }\n const parsed = Date.parse(trimmed);\n if (Number.isNaN(parsed)) {\n return undefined;\n }\n return new Date(parsed);\n}\n\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) {\n return Promise.reject(signal.reason ?? new Error('Aborted'));\n }\n return new Promise<void>((resolve, reject) => {\n const onAbort = () => {\n clearTimeout(timer);\n reject(signal!.reason ?? new Error('Aborted'));\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n","export const HTTP_CLIENT_VERSION = '0.0.0';\n\nexport const DEFAULT_USER_AGENT = `rawdash-connector/${HTTP_CLIENT_VERSION} (+https://rawdash.dev)`;\n\nexport function connectorUserAgent(connectorId: string): string {\n return `rawdash-connector-${connectorId}/${HTTP_CLIENT_VERSION} (+https://rawdash.dev)`;\n}\n","import {\n AuthError,\n ClientBugError,\n HttpClientError,\n RateLimitError,\n TransientError,\n UpstreamBugError,\n errorForStatus,\n} from './errors';\nimport { defaultRetryOn, parseRetryAfter, sleep } from './retry';\nimport type { FetchLike, HttpMethod, HttpRequest, HttpResponse } from './types';\nimport { DEFAULT_USER_AGENT } from './version';\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\nconst DEFAULT_MAX_ATTEMPTS = 3;\nconst DEFAULT_INITIAL_DELAY_MS = 1000;\nconst DEFAULT_MAX_DELAY_MS = 60_000;\nconst OBSERVER_TIMEOUT_MS = 250;\n\nexport interface RequestObservation {\n url: string;\n method: HttpMethod;\n status: number;\n resource: string;\n requestId: string;\n body: unknown;\n}\n\nexport type RequestObserver = (\n event: RequestObservation,\n) => void | Promise<void>;\n\nexport interface RequestOptions {\n fetch?: FetchLike;\n observer?: RequestObserver;\n resource: string;\n requestId?: string;\n}\n\nasync function notifyObserver(\n observer: RequestObserver,\n event: RequestObservation,\n): Promise<void> {\n let result: void | Promise<void>;\n try {\n result = observer(event);\n } catch (err) {\n console.warn('[connector-shared] request observer threw:', err);\n return;\n }\n if (!(result instanceof Promise)) {\n return;\n }\n const guarded = result.catch((err) => {\n console.warn('[connector-shared] request observer rejected:', err);\n });\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<void>((resolve) => {\n timer = setTimeout(resolve, OBSERVER_TIMEOUT_MS);\n });\n try {\n await Promise.race([guarded, timeout]);\n } finally {\n if (timer) {\n clearTimeout(timer);\n }\n }\n}\n\nfunction newRequestId(): string {\n const c = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto;\n if (c?.randomUUID) {\n return c.randomUUID();\n }\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction mergeHeaders(\n defaults: Record<string, string>,\n overrides: Record<string, string> | undefined,\n): Record<string, string> {\n const merged: Record<string, string> = {};\n for (const [k, v] of Object.entries(defaults)) {\n merged[k.toLowerCase()] = v;\n }\n if (overrides) {\n for (const [k, v] of Object.entries(overrides)) {\n merged[k.toLowerCase()] = v;\n }\n }\n return merged;\n}\n\nfunction linkTimeoutSignal(\n parent: AbortSignal | undefined,\n timeoutMs: number,\n): { signal: AbortSignal; cancel: () => void } {\n const controller = new AbortController();\n const onParentAbort = () => {\n controller.abort(parent?.reason);\n };\n if (parent) {\n if (parent.aborted) {\n controller.abort(parent.reason);\n } else {\n parent.addEventListener('abort', onParentAbort, { once: true });\n }\n }\n const timer = setTimeout(() => {\n controller.abort(new Error(`Request timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n return {\n signal: controller.signal,\n cancel: () => {\n clearTimeout(timer);\n if (parent) {\n parent.removeEventListener('abort', onParentAbort);\n }\n },\n };\n}\n\nasync function readBody(\n res: Response,\n parseJson: boolean,\n binary: boolean,\n): Promise<unknown> {\n if (res.status === 204 || res.status === 205) {\n return null;\n }\n if (binary) {\n return new Uint8Array(await res.arrayBuffer());\n }\n const contentType = res.headers.get('content-type') ?? '';\n if (parseJson && contentType.includes('application/json')) {\n const text = await res.text();\n if (text.length === 0) {\n return null;\n }\n return JSON.parse(text);\n }\n return res.text();\n}\n\nexport async function request<T = unknown>(\n req: HttpRequest,\n options: RequestOptions,\n): Promise<HttpResponse<T>> {\n const fetchImpl: FetchLike = options.fetch ?? (globalThis.fetch as FetchLike);\n const retry = req.retry ?? {};\n const maxAttempts = retry.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;\n const initialDelayMs = retry.initialDelayMs ?? DEFAULT_INITIAL_DELAY_MS;\n const maxDelayMs = retry.maxDelayMs ?? DEFAULT_MAX_DELAY_MS;\n const retryOn = retry.retryOn ?? defaultRetryOn;\n const timeoutMs = req.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const parseJson = req.parseJson ?? true;\n const binary = req.binary ?? false;\n\n const headers = mergeHeaders(\n {\n 'User-Agent': DEFAULT_USER_AGENT,\n Accept: 'application/json',\n },\n req.headers,\n );\n\n let lastErr: Error | undefined;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n req.signal?.throwIfAborted();\n\n const { signal, cancel } = linkTimeoutSignal(req.signal, timeoutMs);\n let res: Response;\n try {\n res = await fetchImpl(req.url, {\n method: req.method ?? 'GET',\n headers,\n body: req.body as RequestInit['body'],\n signal,\n });\n } catch (err) {\n cancel();\n if (req.signal?.aborted) {\n throw req.signal.reason ?? err;\n }\n const error = err instanceof Error ? err : new Error(String(err));\n lastErr = error;\n if (attempt < maxAttempts - 1 && retryOn(null, error)) {\n const delay = computeDelay(attempt, initialDelayMs, maxDelayMs);\n await sleep(delay, req.signal);\n continue;\n }\n throw new TransientError(error.message);\n }\n cancel();\n\n const body = await readBody(res, parseJson, binary);\n const httpResponse: HttpResponse<T> = {\n status: res.status,\n headers: res.headers,\n body: body as T,\n };\n if (req.rateLimit) {\n const state = req.rateLimit.parse(res.headers);\n if (state) {\n httpResponse.rateLimitState = state;\n }\n }\n\n if (options.observer) {\n await notifyObserver(options.observer, {\n url: req.url,\n method: req.method ?? 'GET',\n status: res.status,\n resource: options.resource,\n requestId: options.requestId ?? newRequestId(),\n body,\n });\n }\n\n if (res.ok) {\n return httpResponse;\n }\n\n const retryAfter = parseRetryAfter(res.headers.get('retry-after'));\n const message = `HTTP ${res.status} ${res.statusText} for ${req.method ?? 'GET'} ${req.url}`;\n const err = errorForStatus(message, httpResponse, retryAfter);\n\n if (\n attempt < maxAttempts - 1 &&\n retryOn(res.status, err) &&\n !(err instanceof AuthError) &&\n !(err instanceof ClientBugError)\n ) {\n lastErr = err;\n let delay = computeDelay(attempt, initialDelayMs, maxDelayMs);\n if (err instanceof RateLimitError && retryAfter) {\n const wait = retryAfter.getTime() - Date.now();\n if (wait > 0) {\n delay = Math.min(wait, maxDelayMs);\n }\n }\n await sleep(delay, req.signal);\n continue;\n }\n\n throw err;\n }\n\n throw lastErr ?? new UpstreamBugError('Exhausted retry attempts');\n}\n\nfunction computeDelay(\n attempt: number,\n initialDelayMs: number,\n maxDelayMs: number,\n): number {\n const base = initialDelayMs * 2 ** attempt;\n const jitter = base * 0.25 * Math.random();\n return Math.min(base + jitter, maxDelayMs);\n}\n\nexport { HttpClientError };\n","export interface RateLimitState {\n remaining: number;\n resetAt: Date;\n}\n\nexport interface RateLimitPolicy {\n parse(headers: Headers): RateLimitState | null;\n}\n\nexport interface StandardRateLimitPolicyConfig {\n remainingHeader: string;\n resetHeader: string;\n resetUnit: 's' | 'ms';\n resetFallbackMs?: number;\n}\n\nexport function standardRateLimitPolicy(\n config: StandardRateLimitPolicyConfig,\n): RateLimitPolicy {\n const { remainingHeader, resetHeader, resetUnit, resetFallbackMs } = config;\n const multiplier = resetUnit === 's' ? 1000 : 1;\n return {\n parse(h) {\n const remainingRaw = h.get(remainingHeader);\n if (remainingRaw === null || remainingRaw.trim() === '') {\n return null;\n }\n const remaining = Number(remainingRaw);\n if (!Number.isFinite(remaining)) {\n return null;\n }\n const resetRaw = h.get(resetHeader);\n if (resetRaw === null) {\n if (resetFallbackMs === undefined) {\n return null;\n }\n return {\n remaining,\n resetAt: new Date(Date.now() + resetFallbackMs),\n };\n }\n if (resetRaw.trim() === '') {\n return null;\n }\n const reset = Number(resetRaw);\n if (!Number.isFinite(reset) || reset < 0) {\n return null;\n }\n const resetMs = reset * multiplier;\n if (!Number.isFinite(resetMs)) {\n return null;\n }\n return { remaining, resetAt: new Date(resetMs) };\n },\n };\n}\n","export async function mapWithConcurrency<T, R>(\n items: readonly T[],\n concurrency: number,\n fn: (item: T, index: number) => Promise<R>,\n): Promise<R[]> {\n const results = new Array<R>(items.length);\n if (items.length === 0) {\n return results;\n }\n const normalized = Number.isFinite(concurrency) ? Math.floor(concurrency) : 1;\n const limit = Math.max(1, Math.min(normalized, items.length));\n let next = 0;\n let failed = false;\n\n async function worker(): Promise<void> {\n while (!failed) {\n const i = next++;\n if (i >= items.length) {\n return;\n }\n try {\n results[i] = await fn(items[i]!, i);\n } catch (err) {\n failed = true;\n throw err;\n }\n }\n }\n\n const workers: Promise<void>[] = [];\n for (let w = 0; w < limit; w++) {\n workers.push(worker());\n }\n await Promise.all(workers);\n return results;\n}\n","export interface SanitizeAllowedUrlOptions {\n url: string | null;\n host: string;\n pathname: string;\n protocol?: 'https:' | 'http:';\n}\n\nexport function sanitizeAllowedUrl(\n options: SanitizeAllowedUrlOptions,\n): string | null {\n const { url, host, pathname, protocol = 'https:' } = options;\n if (url === null) {\n return null;\n }\n try {\n const u = new URL(url);\n if (u.protocol !== protocol || u.host !== host || u.pathname !== pathname) {\n return null;\n }\n return u.toString();\n } catch {\n return null;\n }\n}\n","export type EpochUnit = 'ms' | 's' | 'iso';\n\nexport function parseEpoch(\n value: number | string | null | undefined,\n unit: EpochUnit,\n): number | null {\n if (value === null || value === undefined) {\n return null;\n }\n if (unit === 'iso') {\n if (typeof value !== 'string') {\n return null;\n }\n const ms = new Date(value).getTime();\n return Number.isFinite(ms) ? ms : null;\n }\n if (typeof value === 'string' && value.trim() === '') {\n return null;\n }\n const n = typeof value === 'number' ? value : Number(value);\n if (!Number.isFinite(n)) {\n return null;\n }\n const result = unit === 's' ? n * 1000 : n;\n return Number.isFinite(result) ? result : null;\n}\n","import { request } from './request';\nimport type { HttpRequest } from './types';\n\nexport function parseLinkHeader(header: string | null): Record<string, string> {\n if (!header) {\n return {};\n }\n const result: Record<string, string> = {};\n for (const part of header.split(',')) {\n const match = part.match(/<([^>]+)>\\s*;\\s*rel=\"([^\"]+)\"/);\n if (match) {\n result[match[2]!] = match[1]!;\n }\n }\n return result;\n}\n\nexport async function* paginateLink<T>(\n initial: HttpRequest,\n parse: (body: unknown) => T[],\n options: { resource: string },\n): AsyncIterable<T> {\n let next: string | null = initial.url;\n while (next) {\n const res: Awaited<ReturnType<typeof request>> = await request(\n {\n ...initial,\n url: next,\n },\n { resource: options.resource },\n );\n for (const item of parse(res.body)) {\n yield item;\n }\n const links = parseLinkHeader(res.headers.get('link'));\n next = links['next'] ?? null;\n }\n}\n\nexport async function* paginateCursor<T>(\n initial: HttpRequest,\n parse: (body: unknown) => { items: T[]; nextCursor: string | null },\n buildNext: (req: HttpRequest, cursor: string) => HttpRequest,\n options: { resource: string },\n): AsyncIterable<T> {\n let req: HttpRequest = initial;\n while (true) {\n const res = await request(req, { resource: options.resource });\n const { items, nextCursor } = parse(res.body);\n for (const item of items) {\n yield item;\n }\n if (!nextCursor) {\n return;\n }\n req = buildNext(req, nextCursor);\n }\n}\n\nexport async function* paginatePage<T>(\n initial: HttpRequest,\n parse: (body: unknown) => { items: T[]; hasMore: boolean },\n buildPage: (req: HttpRequest, page: number) => HttpRequest,\n options: { resource: string },\n): AsyncIterable<T> {\n let page = 1;\n while (true) {\n const req = page === 1 ? initial : buildPage(initial, page);\n const res = await request(req, { resource: options.resource });\n const { items, hasMore } = parse(res.body);\n for (const item of items) {\n yield item;\n }\n if (!hasMore || items.length === 0) {\n return;\n }\n page++;\n }\n}\n","export type LogFields = Record<string, unknown>;\n\nexport interface ConnectorLogger {\n info(event: string, fields?: LogFields): void;\n warn(event: string, fields?: LogFields): void;\n}\n\nexport interface ConnectorLoggerOptions {\n scope: string;\n}\n\nconst MAX_VALUE_LEN = 120;\n\nfunction truncate(s: string, max = MAX_VALUE_LEN): string {\n if (s.length <= max) {\n return s;\n }\n return `${s.slice(0, max - 1)}…`;\n}\n\nfunction formatValue(value: unknown): string {\n if (value === null) {\n return 'null';\n }\n if (value === undefined) {\n return '';\n }\n if (typeof value === 'number' || typeof value === 'boolean') {\n return String(value);\n }\n if (typeof value === 'string') {\n const t = truncate(value);\n if (/[\\s\"=]/.test(t)) {\n return JSON.stringify(t);\n }\n return t;\n }\n if (typeof value === 'bigint') {\n return value.toString();\n }\n let json: string | undefined;\n try {\n json = JSON.stringify(value);\n } catch {\n json = undefined;\n }\n return truncate(json ?? String(value));\n}\n\nexport function formatLogFields(fields?: LogFields): string {\n if (!fields) {\n return '';\n }\n const parts: string[] = [];\n for (const [k, v] of Object.entries(fields)) {\n if (v === undefined) {\n continue;\n }\n parts.push(`${k}=${formatValue(v)}`);\n }\n return parts.length > 0 ? ` ${parts.join(' ')}` : '';\n}\n\nexport function formatLogLine(\n scope: string,\n event: string,\n fields?: LogFields,\n): string {\n return `[${scope}] ${event}${formatLogFields(fields)}`;\n}\n\nexport function createDefaultConnectorLogger(\n opts: ConnectorLoggerOptions,\n): ConnectorLogger {\n return {\n info(event, fields) {\n console.info(formatLogLine(opts.scope, event, fields));\n },\n warn(event, fields) {\n console.warn(formatLogLine(opts.scope, event, fields));\n },\n };\n}\n\nconst NOOP_LOGGER: ConnectorLogger = {\n info() {},\n warn() {},\n};\n\nexport function noopConnectorLogger(): ConnectorLogger {\n return NOOP_LOGGER;\n}\n","import {\n type HttpResponse,\n connectorUserAgent,\n parseEpoch,\n} from '@rawdash/connector-shared';\nimport {\n BaseConnector,\n type ConnectorContext,\n type ConnectorDoc,\n type CredentialsSchema,\n type JSONValue,\n type StorageHandle,\n type SyncOptions,\n type SyncResult,\n defineConfigFields,\n defineConnectorDoc,\n defineResources,\n makeChunkedCursorGuard,\n paginateChunked,\n schemasFromResources,\n selectActivePhases,\n} from '@rawdash/core';\nimport { z } from 'zod';\n\nexport const configFields = defineConfigFields(\n z.object({\n apiToken: z.object({ $secret: z.string() }).meta({\n label: 'Personal access token',\n description:\n 'Calendly personal access token with read access. Create one under Integrations -> API & Webhooks -> Personal Access Tokens.',\n placeholder: 'eyJraWQiOi...',\n secret: true,\n }),\n organizationUri: z\n .string()\n .url()\n .regex(\n /\\/organizations\\/[^/]+$/,\n 'Organization URI looks like https://api.calendly.com/organizations/AAAAAAAAAAAAAAAA.',\n )\n .meta({\n label: 'Organization URI',\n description:\n 'The full Calendly organization URI to sync. Fetch it from GET https://api.calendly.com/users/me (current_organization).',\n placeholder: 'https://api.calendly.com/organizations/AAAAAAAAAAAAAAAA',\n }),\n lookbackDays: z.number().int().positive().optional().meta({\n label: 'Lookback days',\n description:\n 'How many days of past scheduled events to sync. Defaults to 90. Events are synced over a rolling window and rewritten on every sync.',\n placeholder: '90',\n }),\n resources: z\n .array(z.enum(['event_types', 'scheduled_events', 'cancellations']))\n .nonempty()\n .optional()\n .meta({\n label: 'Resources',\n description:\n \"Which Calendly resources to sync. Omit to sync all of them. 'cancellations' is derived from the scheduled-events scan, so enabling it without 'scheduled_events' still walks scheduled events but only writes cancellation events.\",\n }),\n }),\n);\n\nexport const doc: ConnectorDoc = defineConnectorDoc({\n displayName: 'Calendly',\n category: 'sales',\n brandColor: '#006BFF',\n tagline:\n 'Sync Calendly event types, scheduled events, and cancellations for booking, no-show, and meeting-mix dashboards.',\n vendor: {\n name: 'Calendly',\n domain: 'calendly.com',\n apiDocs: 'https://developer.calendly.com/api-docs',\n website: 'https://calendly.com',\n },\n auth: {\n summary:\n 'Authenticates with a personal access token sent as a Bearer credential. The token inherits the permissions of the account that created it, so use an organization admin to sync organization-wide scheduled events.',\n setup: [\n 'Sign in to Calendly and open Integrations -> API & Webhooks -> Personal Access Tokens.',\n 'Create a token, give it a name, and copy the value (it is shown only once).',\n 'Store the token as a secret and reference it from the connector config as `apiToken: secret(\"CALENDLY_API_TOKEN\")`.',\n 'Fetch your organization URI from GET https://api.calendly.com/users/me (the `current_organization` field) and set it as `organizationUri`.',\n ],\n },\n rateLimit:\n 'Calendly enforces per-token rate limits and returns HTTP 429 with a Retry-After header when exceeded; the shared HTTP client honors it with backoff. Enabling scheduled events fetches invitees per event, which increases request volume on large windows.',\n limitations: [\n 'Scheduled events and cancellations are synced over a rolling window (lookbackDays back through 60 days ahead) and rewritten on every sync, so bookings outside the window age out.',\n 'No-show and invitee email are read from the per-event invitees endpoint, so they are only populated when the scheduled_events resource is enabled.',\n 'Cancellation events are derived from canceled scheduled events within the window; a cancellation of an event whose start time has aged out of the window is not retained.',\n ],\n});\n\nexport type CalendlyResource =\n | 'event_types'\n | 'scheduled_events'\n | 'cancellations';\n\nexport interface CalendlySettings {\n organizationUri: string;\n lookbackDays?: number;\n resources?: readonly CalendlyResource[];\n}\n\nconst calendlyCredentials = {\n apiToken: {\n description: 'Calendly personal access token',\n auth: 'required' as const,\n },\n} satisfies CredentialsSchema;\n\ntype CalendlyCredentials = typeof calendlyCredentials;\n\nconst PHASE_ORDER = ['event_types', 'scheduled_events'] as const;\n\ntype CalendlyPhase = (typeof PHASE_ORDER)[number];\n\nconst isCalendlySyncCursor = makeChunkedCursorGuard(PHASE_ORDER);\n\nconst iso = z.string();\nconst uri = z.string().min(1);\n\nconst paginationSchema = z.object({\n next_page_token: z.string().nullable().optional(),\n});\n\nconst eventTypesResponseSchema = z.object({\n collection: z.array(\n z.object({\n uri,\n name: z.string().nullable().optional(),\n active: z.boolean().nullable().optional(),\n slug: z.string().nullable().optional(),\n kind: z.string().nullable().optional(),\n pooling_type: z.string().nullable().optional(),\n duration: z.number().nullable().optional(),\n color: z.string().nullable().optional(),\n scheduling_url: z.string().nullable().optional(),\n created_at: iso.nullable().optional(),\n updated_at: iso,\n profile: z\n .object({\n type: z.string().nullable().optional(),\n name: z.string().nullable().optional(),\n owner: z.string().nullable().optional(),\n })\n .nullable()\n .optional(),\n }),\n ),\n pagination: paginationSchema,\n});\n\nconst cancellationSchema = z\n .object({\n canceled_by: z.string().nullable().optional(),\n canceler_type: z.string().nullable().optional(),\n reason: z.string().nullable().optional(),\n created_at: iso.nullable().optional(),\n })\n .nullable()\n .optional();\n\nconst scheduledEventsResponseSchema = z.object({\n collection: z.array(\n z.object({\n uri,\n name: z.string().nullable().optional(),\n status: z.string().nullable().optional(),\n start_time: iso,\n end_time: iso.nullable().optional(),\n created_at: iso.nullable().optional(),\n updated_at: iso.nullable().optional(),\n event_type: z.string().nullable().optional(),\n location: z\n .object({ type: z.string().nullable().optional() })\n .nullable()\n .optional(),\n invitees_counter: z\n .object({\n total: z.number().nullable().optional(),\n active: z.number().nullable().optional(),\n limit: z.number().nullable().optional(),\n })\n .nullable()\n .optional(),\n event_memberships: z\n .array(\n z.object({\n user: z.string().nullable().optional(),\n user_email: z.string().nullable().optional(),\n user_name: z.string().nullable().optional(),\n }),\n )\n .nullable()\n .optional(),\n cancellation: cancellationSchema,\n }),\n ),\n pagination: paginationSchema,\n});\n\nconst inviteesResponseSchema = z.object({\n collection: z.array(\n z.object({\n uri,\n email: z.string().nullable().optional(),\n name: z.string().nullable().optional(),\n status: z.string().nullable().optional(),\n created_at: iso.nullable().optional(),\n no_show: z\n .object({\n uri: z.string().nullable().optional(),\n created_at: iso.nullable().optional(),\n })\n .nullable()\n .optional(),\n }),\n ),\n pagination: paginationSchema,\n});\n\ntype EventTypeRecord = z.infer<\n typeof eventTypesResponseSchema\n>['collection'][number];\ntype ScheduledEventRecord = z.infer<\n typeof scheduledEventsResponseSchema\n>['collection'][number];\ntype InviteeRecord = z.infer<\n typeof inviteesResponseSchema\n>['collection'][number];\n\ninterface ScheduledEventWithContext {\n event: ScheduledEventRecord;\n invitees: InviteeRecord[];\n}\n\nexport const calendlyResources = defineResources({\n calendly_event_type: {\n shape: 'entity',\n filterable: [\n { field: 'active', ops: ['eq'] },\n { field: 'kind', ops: ['eq'] },\n ],\n description:\n 'Event types (meeting templates) in the organization with name, active state, duration, kind, and owner.',\n endpoint: 'GET /event_types?organization={organizationUri}',\n fields: [\n { name: 'name', description: 'Event type name.' },\n { name: 'active', description: 'Whether the event type is active.' },\n { name: 'slug', description: 'URL slug of the event type.' },\n { name: 'kind', description: 'Event type kind (e.g. solo, group).' },\n {\n name: 'poolingType',\n description: 'Pooling type for round-robin/collective types.',\n },\n { name: 'durationMinutes', description: 'Default duration in minutes.' },\n { name: 'color', description: 'Display color.' },\n { name: 'schedulingUrl', description: 'Public scheduling URL.' },\n { name: 'ownerUri', description: 'URI of the owning user or team.' },\n { name: 'ownerType', description: 'Owner type (user or team).' },\n { name: 'createdAt', description: 'Creation time (epoch ms).' },\n ],\n responses: { event_types: eventTypesResponseSchema },\n },\n calendly_scheduled_event: {\n shape: 'event',\n filterable: [],\n description:\n 'Scheduled events (bookings) timestamped at their start time, carrying status, event type, host, invitee, and no-show info.',\n endpoint: 'GET /scheduled_events?organization={organizationUri}',\n notes:\n 'start_ts is the meeting start time, end_ts the meeting end time. Invitee email and no-show counts come from the per-event invitees endpoint. Timestamps are Unix epoch milliseconds.',\n fields: [\n { name: 'uri', description: 'Calendly scheduled event URI.' },\n { name: 'name', description: 'Event name.' },\n { name: 'eventTypeUri', description: 'URI of the booked event type.' },\n {\n name: 'status',\n description: 'Event status (active or canceled).',\n },\n { name: 'canceled', description: 'Whether the event was canceled.' },\n {\n name: 'inviteeEmail',\n description: 'Email of the primary invitee, if available.',\n },\n { name: 'inviteeName', description: 'Name of the primary invitee.' },\n { name: 'inviteeCount', description: 'Total invitees on the event.' },\n {\n name: 'activeInviteeCount',\n description: 'Invitees that have not canceled.',\n },\n {\n name: 'noShowCount',\n description: 'Number of invitees marked as no-show.',\n },\n { name: 'hostEmail', description: 'Email of the first host.' },\n { name: 'hostName', description: 'Name of the first host.' },\n { name: 'locationType', description: 'Meeting location type.' },\n { name: 'createdAt', description: 'Booking creation time (epoch ms).' },\n { name: 'updatedAt', description: 'Last update time (epoch ms).' },\n ],\n responses: {\n scheduled_events: scheduledEventsResponseSchema,\n event_invitees: inviteesResponseSchema,\n },\n },\n calendly_cancellation: {\n shape: 'event',\n filterable: [],\n description:\n 'Cancellation events derived from canceled scheduled events, timestamped at cancellation time with reason and canceler.',\n endpoint: 'GET /scheduled_events?organization={organizationUri}',\n notes:\n 'Derived from the scheduled-events scan; one event per canceled scheduled event. start_ts is the cancellation time. Timestamps are Unix epoch milliseconds.',\n fields: [\n { name: 'eventUri', description: 'URI of the canceled scheduled event.' },\n { name: 'eventName', description: 'Name of the canceled event.' },\n { name: 'eventTypeUri', description: 'URI of the booked event type.' },\n { name: 'reason', description: 'Cancellation reason, if provided.' },\n { name: 'canceledBy', description: 'Name of who canceled.' },\n {\n name: 'cancelerType',\n description: 'Whether the host or invitee canceled.',\n },\n {\n name: 'eventStartTime',\n description: 'Start time of the canceled event (epoch ms).',\n },\n ],\n responses: { scheduled_event_cancellations: scheduledEventsResponseSchema },\n },\n});\n\nconst API_BASE = 'https://api.calendly.com';\nconst MS_PER_DAY = 24 * 60 * 60 * 1000;\nconst DEFAULT_LOOKBACK_DAYS = 90;\nconst FORWARD_HORIZON_DAYS = 60;\nconst EVENT_TYPES_PAGE_SIZE = 100;\nconst SCHEDULED_EVENTS_PAGE_SIZE = 100;\nconst INVITEES_PAGE_SIZE = 100;\n\ninterface StartWindow {\n minStartTime: string;\n maxStartTime: string;\n}\n\nexport function getStartWindow(\n lookbackDays: number,\n now: number = Date.now(),\n): StartWindow {\n return {\n minStartTime: new Date(now - lookbackDays * MS_PER_DAY).toISOString(),\n maxStartTime: new Date(\n now + FORWARD_HORIZON_DAYS * MS_PER_DAY,\n ).toISOString(),\n };\n}\n\nfunction eventUuid(uri: string): string {\n const trimmed = uri.replace(/\\/+$/, '');\n const idx = trimmed.lastIndexOf('/');\n return idx === -1 ? trimmed : trimmed.slice(idx + 1);\n}\n\nexport function eventTypeToEntity(record: EventTypeRecord, now: number) {\n return {\n type: 'calendly_event_type' as const,\n id: record.uri,\n attributes: {\n name: record.name ?? null,\n active: record.active ?? null,\n slug: record.slug ?? null,\n kind: record.kind ?? null,\n poolingType: record.pooling_type ?? null,\n durationMinutes: record.duration ?? null,\n color: record.color ?? null,\n schedulingUrl: record.scheduling_url ?? null,\n ownerUri: record.profile?.owner ?? null,\n ownerType: record.profile?.type ?? null,\n createdAt: parseEpoch(record.created_at ?? null, 'iso'),\n } satisfies Record<string, JSONValue>,\n updated_at: parseEpoch(record.updated_at, 'iso') ?? now,\n };\n}\n\nexport function scheduledEventToEvent(ctx: ScheduledEventWithContext) {\n const { event, invitees } = ctx;\n const startMs = parseEpoch(event.start_time, 'iso') ?? 0;\n const primary = invitees[0];\n const noShowCount = invitees.filter((i) => i.no_show != null).length;\n const host = event.event_memberships?.[0];\n const attributes: Record<string, JSONValue> = {\n uri: event.uri,\n name: event.name ?? null,\n eventTypeUri: event.event_type ?? null,\n status: event.status ?? null,\n canceled: event.status === 'canceled',\n inviteeEmail: primary?.email ?? null,\n inviteeName: primary?.name ?? null,\n inviteeCount: event.invitees_counter?.total ?? invitees.length,\n activeInviteeCount: event.invitees_counter?.active ?? null,\n noShowCount,\n hostEmail: host?.user_email ?? null,\n hostName: host?.user_name ?? null,\n locationType: event.location?.type ?? null,\n createdAt: parseEpoch(event.created_at ?? null, 'iso'),\n updatedAt: parseEpoch(event.updated_at ?? null, 'iso'),\n };\n return {\n name: 'calendly_scheduled_event' as const,\n start_ts: startMs,\n end_ts: parseEpoch(event.end_time ?? null, 'iso'),\n attributes,\n };\n}\n\nexport function cancellationToEvent(event: ScheduledEventRecord) {\n if (event.status !== 'canceled' || !event.cancellation) {\n return null;\n }\n const startMs = parseEpoch(event.start_time, 'iso');\n const canceledMs =\n parseEpoch(event.cancellation.created_at ?? null, 'iso') ?? startMs ?? 0;\n const attributes: Record<string, JSONValue> = {\n eventUri: event.uri,\n eventName: event.name ?? null,\n eventTypeUri: event.event_type ?? null,\n reason: event.cancellation.reason ?? null,\n canceledBy: event.cancellation.canceled_by ?? null,\n cancelerType: event.cancellation.canceler_type ?? null,\n eventStartTime: startMs,\n };\n return {\n name: 'calendly_cancellation' as const,\n start_ts: canceledMs,\n end_ts: null,\n attributes,\n };\n}\n\nexport const id = 'calendly';\n\nexport class CalendlyConnector extends BaseConnector<\n CalendlySettings,\n CalendlyCredentials\n> {\n static readonly id = id;\n\n static readonly resources = calendlyResources;\n\n static readonly schemas = schemasFromResources(calendlyResources);\n\n static create(input: unknown, ctx?: ConnectorContext): CalendlyConnector {\n const parsed = configFields.parse(input);\n return new CalendlyConnector(\n {\n organizationUri: parsed.organizationUri,\n lookbackDays: parsed.lookbackDays,\n resources: parsed.resources,\n },\n { apiToken: parsed.apiToken },\n ctx,\n );\n }\n\n readonly id = id;\n override readonly credentials = calendlyCredentials;\n\n private buildHeaders(): Record<string, string> {\n return {\n Authorization: `Bearer ${this.creds.apiToken}`,\n Accept: 'application/json',\n 'User-Agent': connectorUserAgent('calendly'),\n };\n }\n\n private fetch<T>(\n url: string,\n resource: string,\n signal?: AbortSignal,\n ): Promise<HttpResponse<T>> {\n return this.get<T>(url, {\n resource,\n headers: this.buildHeaders(),\n signal,\n });\n }\n\n private activePhases(): CalendlyPhase[] {\n return selectActivePhases<CalendlyResource, CalendlyPhase>(\n (r) => {\n switch (r) {\n case 'event_types':\n return 'event_types';\n case 'scheduled_events':\n case 'cancellations':\n return 'scheduled_events';\n }\n },\n PHASE_ORDER,\n this.settings.resources,\n );\n }\n\n private async fetchEventTypesPage(\n page: string | null,\n signal: AbortSignal | undefined,\n ): Promise<{ items: EventTypeRecord[]; next: string | null }> {\n const u = new URL(`${API_BASE}/event_types`);\n u.searchParams.set('organization', this.settings.organizationUri);\n u.searchParams.set('sort', 'updated_at:desc');\n u.searchParams.set('count', String(EVENT_TYPES_PAGE_SIZE));\n if (page !== null) {\n u.searchParams.set('page_token', page);\n }\n const res = await this.fetch<z.infer<typeof eventTypesResponseSchema>>(\n u.toString(),\n 'event_types',\n signal,\n );\n return {\n items: res.body.collection,\n next: res.body.pagination.next_page_token ?? null,\n };\n }\n\n private async fetchInvitees(\n eventUri: string,\n signal: AbortSignal | undefined,\n ): Promise<InviteeRecord[]> {\n const out: InviteeRecord[] = [];\n let pageToken: string | null = null;\n do {\n signal?.throwIfAborted();\n const u = new URL(\n `${API_BASE}/scheduled_events/${eventUuid(eventUri)}/invitees`,\n );\n u.searchParams.set('count', String(INVITEES_PAGE_SIZE));\n if (pageToken !== null) {\n u.searchParams.set('page_token', pageToken);\n }\n const res: HttpResponse<z.infer<typeof inviteesResponseSchema>> =\n await this.fetch<z.infer<typeof inviteesResponseSchema>>(\n u.toString(),\n 'event_invitees',\n signal,\n );\n out.push(...res.body.collection);\n pageToken = res.body.pagination.next_page_token ?? null;\n } while (pageToken !== null);\n return out;\n }\n\n private async fetchScheduledEventsPage(\n page: string | null,\n window: StartWindow,\n signal: AbortSignal | undefined,\n ): Promise<{ items: ScheduledEventWithContext[]; next: string | null }> {\n const wantInvitees = this.isResourceEnabled('scheduled_events');\n const u = new URL(`${API_BASE}/scheduled_events`);\n u.searchParams.set('organization', this.settings.organizationUri);\n u.searchParams.set('sort', 'start_time:asc');\n u.searchParams.set('min_start_time', window.minStartTime);\n u.searchParams.set('max_start_time', window.maxStartTime);\n u.searchParams.set('count', String(SCHEDULED_EVENTS_PAGE_SIZE));\n if (page !== null) {\n u.searchParams.set('page_token', page);\n }\n const res = await this.fetch<z.infer<typeof scheduledEventsResponseSchema>>(\n u.toString(),\n 'scheduled_events',\n signal,\n );\n const items: ScheduledEventWithContext[] = [];\n for (const event of res.body.collection) {\n const invitees = wantInvitees\n ? await this.fetchInvitees(event.uri, signal)\n : [];\n items.push({ event, invitees });\n }\n return {\n items,\n next: res.body.pagination.next_page_token ?? null,\n };\n }\n\n private async writeEventTypes(\n storage: StorageHandle,\n items: EventTypeRecord[],\n ): Promise<void> {\n const now = Date.now();\n for (const record of items) {\n await storage.entity(eventTypeToEntity(record, now));\n }\n }\n\n private async writeScheduledEvents(\n storage: StorageHandle,\n items: ScheduledEventWithContext[],\n ): Promise<void> {\n const writeEvents = this.isResourceEnabled('scheduled_events');\n const writeCancellations = this.isResourceEnabled('cancellations');\n for (const ctx of items) {\n if (writeEvents) {\n await storage.event(scheduledEventToEvent(ctx));\n }\n if (writeCancellations) {\n const cancellation = cancellationToEvent(ctx.event);\n if (cancellation) {\n await storage.event(cancellation);\n }\n }\n }\n }\n\n async sync(\n options: SyncOptions,\n storage: StorageHandle,\n signal?: AbortSignal,\n ): Promise<SyncResult> {\n const cursor = isCalendlySyncCursor(options.cursor)\n ? options.cursor\n : undefined;\n const isFull = options.mode === 'full';\n const lookbackDays = this.settings.lookbackDays ?? DEFAULT_LOOKBACK_DAYS;\n const window = getStartWindow(lookbackDays);\n const phases = this.activePhases();\n\n return paginateChunked<CalendlyPhase, string>({\n phases,\n cursor,\n signal,\n logger: this.logger,\n fetchPage: async (phase, page, sig) => {\n switch (phase) {\n case 'event_types':\n return this.fetchEventTypesPage(page, sig);\n case 'scheduled_events':\n return this.fetchScheduledEventsPage(page, window, sig);\n }\n },\n writeBatch: async (phase, items, page) => {\n if (page === null) {\n switch (phase) {\n case 'event_types':\n if (isFull) {\n await storage.entities([], {\n types: ['calendly_event_type'],\n });\n }\n break;\n case 'scheduled_events':\n if (this.isResourceEnabled('scheduled_events')) {\n await storage.events([], {\n names: ['calendly_scheduled_event'],\n });\n }\n if (this.isResourceEnabled('cancellations')) {\n await storage.events([], {\n names: ['calendly_cancellation'],\n });\n }\n break;\n }\n }\n switch (phase) {\n case 'event_types':\n return this.writeEventTypes(storage, items as EventTypeRecord[]);\n case 'scheduled_events':\n return this.writeScheduledEvents(\n storage,\n items as ScheduledEventWithContext[],\n );\n }\n },\n });\n }\n}\n","import { CalendlyConnector } from './calendly';\n\nexport {\n configFields,\n doc,\n CalendlyConnector,\n calendlyResources as resources,\n id,\n} from './calendly';\nexport type { CalendlySettings, CalendlyResource } from './calendly';\nexport default CalendlyConnector;\n"],"mappings":"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","names":["uri"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rawdash/connector-calendly",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Rawdash connector for Calendly — syncs event types, scheduled events, and cancellations into the six-shape storage model",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/rawdash/rawdash.git",
|
|
11
|
+
"directory": "packages/connectors/calendly"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist",
|
|
15
|
+
"README.md",
|
|
16
|
+
"LICENSE"
|
|
17
|
+
],
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"@rawdash/source": "./src/index.ts",
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"import": "./dist/index.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsup",
|
|
27
|
+
"typecheck": "tsc --noEmit",
|
|
28
|
+
"lint": "eslint src",
|
|
29
|
+
"test": "vitest run"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@rawdash/core": "workspace:*",
|
|
33
|
+
"zod": "^4.4.3"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@rawdash/connector-shared": "workspace:*",
|
|
37
|
+
"@rawdash/connector-test-utils": "workspace:*",
|
|
38
|
+
"fast-check": "^4.8.0",
|
|
39
|
+
"tsup": "^8.0.0",
|
|
40
|
+
"typescript": "^5.7.2",
|
|
41
|
+
"vitest": "^4.1.4"
|
|
42
|
+
}
|
|
43
|
+
}
|