Skip to content

Commit

Permalink
feat(integration-templates): add luma integration template (NangoHQ#2490
Browse files Browse the repository at this point in the history
)

## Describe your changes

- Add Luma `list-events` integration template.

## Issue ticket number and link

[EXT-104](https://linear.app/nango/issue/EXT-104/provide-example-of-luma-pagination)
  • Loading branch information
hassan254-prog authored Jul 11, 2024
1 parent b628b13 commit ee0b06d
Show file tree
Hide file tree
Showing 7 changed files with 245 additions and 0 deletions.
21 changes: 21 additions & 0 deletions docs-v2/integrations/integration-templates/luma.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
title: 'Luma API Integration Template'
sidebarTitle: 'Luma'
---

## Get started with the Luma template

<Card title="How to use integration templates"
href="/understand/concepts/templates"
icon="book-open">
Learn how to use integration templates in Nango
</Card>

<Card title="Get the Luma template"
href="https://github.com/NangoHQ/nango/tree/master/integration-templates/luma"
icon="github">
Get the latest version of the Luma integration template from GitHub
</Card>

## Need help with the template?
Please reach out in the [Slack community](https://nango.dev/slack), we are very active there and happy to help!
1 change: 1 addition & 0 deletions docs-v2/mint.json
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@
"integrations/integration-templates/kustomer",
"integrations/integration-templates/lever",
"integrations/integration-templates/linear",
"integrations/integration-templates/luma",
"integrations/integration-templates/sharepoint-online",
"integrations/integration-templates/microsoft-active-directory",
"integrations/integration-templates/next-cloud",
Expand Down
48 changes: 48 additions & 0 deletions integration-templates/luma/mappers/to-event.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import type { LumaEvent } from '../types';
import type { Event } from '../../models';
/**
* Converts a LumaEvent object to a slim Event object.
* Only includes essential properties mapped from LumaEvent.
* @param event The LumaEvent to be converted.
* @returns The corresponding slim Event object.
*/
export function toEvent(event: LumaEvent): Event {
const formattedEvent: Event = {
id: event.event.api_id,
created_at: new Date(event.event.created_at).toISOString(),
cover_url: event.event.cover_url,
name: event.event.name,
description: event.event.description,
description_md: event.event.description_md,
series_api_id: event.event.series_api_id,
start_at: new Date(event.event.start_at).toISOString(),
duration_interval_iso8601: event.event.duration_interval,
end_at: new Date(event.event.end_at).toISOString(),
geo_latitude: event.event.geo_latitude,
geo_longitude: event.event.geo_longitude,
geo_address_json: event.event.geo_address_json
? {
city: event.event.geo_address_json.city,
type: event.event.geo_address_json.type,
region: event.event.geo_address_json.region,
address: event.event.geo_address_json.address,
country: event.event.geo_address_json.country,
latitude: event.event.geo_address_json.latitude,
place_id: event.event.geo_address_json.place_id,
longitude: event.event.geo_address_json.longitude,
city_state: event.event.geo_address_json.city_state,
description: event.event.geo_address_json.description,
full_address: event.event.geo_address_json.full_address
}
: null,
url: event.event.url,
timezone: event.event.timezone,
event_type: event.event.event_type,
user_api_id: event.event.user_api_id,
visibility: event.event.visibility,
meeting_url: event.event.meeting_url,
zoom_meeting_url: event.event.zoom_meeting_url
};

return formattedEvent;
}
46 changes: 46 additions & 0 deletions integration-templates/luma/nango.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
integrations:
luma:
syncs:
list-events:
description: |
This sync will be used to sync all of the events managed by your Calendar. See https://docs.lu.ma/reference/calendar-list-events for more details.
endpoint: GET /luma/list-events
sync_type: incremental
runs: every day
output: Event
models:
Timestamps:
created_at: string
start_at: string
end_at: string
Event:
id: string
__extends: Timestamps
cover_url: string
name: string
description: string
description_md: string
series_api_id: string | null
duration_interval_iso8601: string
geo_latitude: string | null
geo_longitude: string | null
geo_address_json: GeoAddress | null
url: string
timezone: string
event_type: string
user_api_id: string
visibility: string
meeting_url: string | null
zoom_meeting_url: string | null
GeoAddress:
city: string
type: string
region: string
address: string
country: string
latitude: string
place_id: string
longitude: string
city_state: string
description: string
full_address: string
33 changes: 33 additions & 0 deletions integration-templates/luma/syncs/list-events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import type { NangoSync, Event } from '../../models';
import type { LumaEvent } from '../types';
import { toEvent } from '../mappers/to-event.js';

/**
* Fetches events from a specified endpoint and processes them for synchronization.
* Uses pagination and retries for robust data retrieval and saving.
* Convert LumaEvent to Event using mapping function.
*
* @param nango An instance of NangoSync for handling synchronization tasks.
* @returns Promise that resolves when all events are fetched and saved.
*/
export default async function fetchData(nango: NangoSync): Promise<void> {
const endpoint = '/public/v1/calendar/list-events';
const config = {
// Include 'after' parameter with the lastSyncDate if available
...(nango.lastSyncDate ? { params: { after: nango.lastSyncDate?.toISOString() } } : {}),
paginate: {
type: 'cursor',
cursor_path_in_response: 'next_cursor',
cursor_name_in_request: 'pagination_cursor',
response_path: 'entries',
limit_name_in_request: 'pagination_limit',
limit: 100
},
retries: 10
};

for await (const events of nango.paginate<LumaEvent>({ ...config, endpoint })) {
const formattedEvents = events.map((event: LumaEvent) => toEvent(event));
await nango.batchSave<Event>(formattedEvents, 'Event');
}
}
47 changes: 47 additions & 0 deletions integration-templates/luma/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
interface GeoAddress {
city: string;
type: string;
region: string;
address: string;
country: string;
latitude: string;
place_id: string;
longitude: string;
city_state: string;
description: string;
full_address: string;
}

interface Event {
api_id: string;
created_at: string;
cover_url: string;
name: string;
description: string;
description_md: string;
series_api_id: string | null;
start_at: string;
duration_interval: string;
end_at: string;
geo_address_json: GeoAddress | null;
geo_latitude: string | null;
geo_longitude: string | null;
url: string;
timezone: string;
event_type: string;
user_api_id: string;
visibility: string;
meeting_url: string | null;
zoom_meeting_url: string | null;
}

interface Tag {
api_id: string;
name: string;
}

export interface LumaEvent {
api_id: string;
event: Event;
tags: Tag[];
}
49 changes: 49 additions & 0 deletions packages/shared/flows.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2291,6 +2291,55 @@ integrations:
updatedAt: date
teamId: string
projectIds: string
luma:
syncs:
list-events:
description: >
This sync will be used to sync all of the events managed by your
Calendar. See https://docs.lu.ma/reference/calendar-list-events for
more details.
endpoint: GET /luma/list-events
sync_type: incremental
runs: every day
output: Event
models:
Timestamps:
created_at: string
start_at: string
end_at: string
Event:
created_at: string
start_at: string
end_at: string
id: string
cover_url: string
name: string
description: string
description_md: string
series_api_id: string | null
duration_interval_iso8601: string
geo_latitude: string | null
geo_longitude: string | null
geo_address_json: GeoAddress | null
url: string
timezone: string
event_type: string
user_api_id: string
visibility: string
meeting_url: string | null
zoom_meeting_url: string | null
GeoAddress:
city: string
type: string
region: string
address: string
country: string
latitude: string
place_id: string
longitude: string
city_state: string
description: string
full_address: string
microsoft-teams:
syncs:
org-units:
Expand Down

0 comments on commit ee0b06d

Please sign in to comment.