Develop
Root Item
The first thing we'll want to do is to expose the root of our graph. Every connector has a root
item,
which defines the entry point of its graph. This root
item, having not been described by a schema, usually
only defines relations. In our case, our root
item will only link to one relation — our pokémons!
Open up the root
handler (src/handlers/root.ts), and modify it as follow;
import { GetItemHandler, Api } from '@unito/integration-sdk';
export const getItem: GetItemHandler = async () => {
return {
fields: {},
relations: [
{
name: 'pokemons',
label: 'Pokémons',
path: '/pokemons',
schema: {
label: 'Pokémon',
fields: [
{
name: 'id',
label: 'Unique ID',
type: Api.FieldValueType.INTEGER,
},
{
name: 'name',
label: 'Name',
type: Api.FieldValueType.STRING,
},
{
name: 'base_experience',
label: 'Base experience',
type: Api.FieldValueType.NUMBER,
},
],
}
}
],
};
};
With that done, start the CLI (integration-cli dev
), navigate to the debugger
tab, and step into your first item!
Pokémons List
Alright, our root
item specifies that we can find Pokémons at the /pokemons
path, but we haven't coded that yet!
First, create a new pokemons
handler (src/handlers/pokemons.ts), and modify it as follow;
import { GetCollectionHandler } from '@unito/integration-sdk';
export const getCollection: GetCollectionHandler = async () => {
return {
info: {},
data: [],
};
};
And then, open up the index
file (src/index.ts) and modify it as follow;
import { Integration } from '@unito/integration-sdk';
import * as meHandler from './handlers/me.js';
import * as rootHandler from './handlers/root.js';
import * as pokemonsHandler from './handlers/pokemons.js';
const integration = new Integration();
integration.addHandler('/', rootHandler);
integration.addHandler('/me', meHandler);
integration.addHandler('/pokemons', pokemonsHandler);
integration.start();
Alright, now we can step into our root
, and step again into our collection! It works, but it sadly sits empty for now.
Let's add some Pokémons!
Provider
Create a new provider.ts
(src/provider.ts) file and modify it as follow;
import { Provider } from '@unito/integration-sdk';
const provider = new Provider({
prepareRequest: _context => {
return {
url: 'https://pokeapi.co/api/v2',
headers: {}, // Here we would normaly provide the user's credentials in the provider's defined header of choice. Since the pokeapi is unauthenticated, we will leave empty
};
},
});
export default provider;
Now let's go back to our pokemons
handler, and modify it as follow;
import { GetCollectionContext, GetCollectionHandler, HttpErrors } from '@unito/integration-sdk';
import provider from '../provider.js';
export const getCollection: GetCollectionHandler = async (context: GetCollectionContext<{}, { offset?: string }>) => {
const offset = Number(context.query.offset) || 0;
const limit = 100;
const response = await provider.get<{ next: string; results: { name: string }[] }>('/pokemon', {
...context,
queryParams: { limit: limit.toString(), offset: offset.toString() },
});
return {
info: {
nextPage: response.body.next ? `/pokemons?offset=${offset + limit}` : undefined,
},
data: response.data?.results.map(pokemon => ({
path: `/pokemons/${pokemon.name}`,
})),
};
};
Try again the CLI, and you should see a list of Pokémons!
Single Pokémon
The only thing missing now is a way to retrieve a single Pokémon. For this, we'll need two things.
First, open up index.ts
(src/index.ts), we need to add a way for our handler's path to distingish between a
collection and an individual item. This is done by adding a path identifier to our path.
import { Integration } from '@unito/integration-sdk';
import * as meHandler from './handlers/me.js';
import * as rootHandler from './handlers/root.js';
import * as pokemonsHandler from './handlers/pokemons.js';
const integration = new Integration();
integration.addHandler('/', rootHandler);
integration.addHandler('/me', meHandler);
integration.addHandler('/pokemons/:name', pokemonsHandler);
integration.start();
And finally, from within the same pokemons
handler, add a new getItem
property as follow;
import { GetCollectionContext, GetCollectionHandler, GetItemHandler, GetItemContext, HttpErrors } from '@unito/integration-sdk';
import provider from '../provider.js';
export const getCollection: GetCollectionHandler = async (context: GetCollectionContext<{}, { offset?: string }>) => {
const offset = Number(context.query.offset) || 0;
const limit = 100;
const response = await provider.get<{ next: string; results: { name: string }[] }>('/pokemon', {
...context,
queryParams: { limit: limit.toString(), offset: offset.toString() },
});
return {
info: {
nextPage: response.data.next ? `/pokemons?offset=${offset + limit}` : undefined,
},
data: response.data?.results.map(pokemon => ({
path: `/pokemons/${pokemon.name}`,
})),
};
};
export const getItem: GetItemHandler = async (context: GetItemContext<{ name: string }>) => {
const response = await provider.get<{
id: number;
name: string;
base_experience: number;
}>(`pokemon/${context.params.name}`, context);
return {
fields: {
id: response.data.id,
name: response.data.name,
base_experience: response.data.base_experience,
},
relations: [],
};
};
And with that, magically, we should be able to crawl all of our Pokémons!