Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compass variables type #110

Merged
merged 34 commits into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
4b79cbe
Compass variables type
jm42 Apr 9, 2024
da7f2db
Version 0.1.9
jm42 Apr 9, 2024
b964b06
Generic type for variables
jm42 Apr 9, 2024
7767b5d
Type search drops variables
jm42 Apr 9, 2024
b3bbfae
Add type="module" in providers package
jm42 Apr 9, 2024
c2e85e1
Lint
jm42 Apr 9, 2024
8dfc173
Fix exports of utils
jm42 Apr 9, 2024
5bc2525
Version 0.2.0
jm42 Apr 12, 2024
ca619d7
Utils exports
jm42 Apr 12, 2024
37080eb
Type order
jm42 Apr 12, 2024
f985976
Type bool filter
jm42 Apr 12, 2024
1fcd02d
Type equal filter
jm42 Apr 12, 2024
8aca628
Type not equal filter
jm42 Apr 12, 2024
c02c4b6
Type like filter
jm42 Apr 12, 2024
ca90b84
Type address filter
jm42 Apr 12, 2024
9be6c58
Type in filter
jm42 Apr 12, 2024
3be0d90
Type between filter
jm42 Apr 12, 2024
4327afa
Add filter types
jm42 Apr 12, 2024
7e95ff6
Move filter queries utils to own file
jm42 Apr 12, 2024
7eed41d
Move queries order utils to own file
jm42 Apr 12, 2024
8c12f1d
Fix optional _in in Filter type
jm42 Apr 12, 2024
3bb0541
Type fetch drops variables
jm42 Apr 12, 2024
b2d9f17
Type fetch moments variables
jm42 Apr 12, 2024
b82ed84
Type fetch poaps variables
jm42 Apr 12, 2024
7b9b4cc
Remove unused object filter
jm42 Apr 12, 2024
0546241
Add utils documentation
jm42 Apr 12, 2024
410e198
Add bad request and unauthorized errors
jm42 Apr 12, 2024
2ed54a8
Data type not include data key
jm42 Apr 12, 2024
75fcb72
Compass documentation
jm42 Apr 12, 2024
9b9a579
Fix moments examples
jm42 Apr 12, 2024
b330d68
Type fetch in Drop API
jm42 Apr 12, 2024
77a9f82
Removes HTTP provider
jm42 Apr 12, 2024
a941738
Adds changelog
jm42 Apr 12, 2024
dc12f50
More items to changelog
jm42 Apr 12, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/pages/_meta.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"index": "Introduction",
"packages": "Packages"
"packages": "Packages",
"changelog": "Changelog"
}
11 changes: 11 additions & 0 deletions docs/pages/changelog.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Changelog

## 0.2.0

- Change types where before there was `any` to be strict.
- Removes `HttpProvider`.
- Rename query utils to create filters and order by.
- Compass response type must not include `data` anymore.
- Compass variables can be typed.
- Compass throws errors on malformed requests/queries.
- Fetch moments order must be value from enum `Order` instead of string.
88 changes: 88 additions & 0 deletions docs/pages/packages/providers/Compass.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Compass Provider

To query Compass, a simple request wrapper is provided. To initialize it you'll need an API key.

```typescript
import { PoapCompass } from '@poap-xyz/providers';

const compass = new PoapCompass({
apiKey: 'my-secret-api-key',
});
```

## Requests

Query requests can be made by giving the query in string and optionally the variables to pass. All
success requests are returned as an object with a `data` property which the structure differs
depending on the query done. When the request fail, errors are thrown instead.

### Quering

To do a query request, a response data type is needed and, in the case the query accepts variables,
a type for its structure is also needed.

For example, if we want to retrieve the last POAP token ids we could have the query:

```typescript
const query = `
query LastTokenIds($limit: Int!) {
poaps(limit: $limit, order_by: { id: desc }) {
id
}
}
`;
```

Which will return the type:

```typescript
type LastTokenIdsResponse = {
poaps: Array<{
id: number;
}>;
};
```

And have the variables type:

```typescript
type LastTokenIdsVariables = {
limit: number;
};
```

Then the query can be executed:

```typescript
const lastTokenIds: number[] = [];
try {
const { data } = await compass.request<
LastTokenIdsResponse,
LastTokenIdsVariables
>(query, { limit: 3 });

lastTokenIds.push(
...data.poaps.map((poap) => poap.id)
);
} catch (error: unknown) {
console.error(error)
}
```

### Errors

There are two types of errors, HTTP errors and requests errors. The former are thrown when there is
an issue with the HTTP requests itself and the later when the query has some malformed or
unavailable structure.

#### HTTP errors

When the HTTP request is malformed a `CompassBadRequestError` is thrown, which should not happen
unless there is a migration to be made. When the API key given is incorrect or expired, then a
`CompassUnauthorizedError` error will be thrown.

#### Query errors

All errors derived from a malformed structure on the query will throw a `CompassRequestError` which
has a public property called `errors` of the type `CompassError` with more information about what
went wrong.
3 changes: 3 additions & 0 deletions docs/pages/packages/providers/_meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"Compass": "Compass"
}
77 changes: 77 additions & 0 deletions docs/pages/packages/utils/Queries.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Queries Utils

When building Compass queries, it might be useful to have some little utilities to not repeat the
same code many times. There two types of utils for queries, building orders and building filters.

## Order By

When you have a query that accepts an `$orderBy` variable that let you input the field name and the
sort order, for example:

```graphql
query MyDrops(
$orderBy: [drops_order_by!]
$where: {
drop_id: { _in: [14] }
}
) {
drops(order_by: $orderBy) {
id
name
}
}
```

And an enum that let you choose what fields you want to order by:

```typescript
enum MyDropSortFields {
Id = 'id',
Name = 'name',
}
```

You can then build the variable `$orderBy` with `createOrderBy`:

```typescript
import { Order, OrderByVariables, createOrderBy } from '@poap-xyz/utils';

const variables: OrderByVariables = {
orderBy: createOrderBy<MyDropSortFields>(MyDropSortFields.Name, Order.ASC),
};
```

## Filters

There are many filters with different types and for different results, normally you will have a
query that accepts a `$where` variable and then you can construct the variables with the use of the
filters utils.

For example:

```typescript
import {
FilterVariables,
createBoolFilter,
createLikeFilter,
createBetweenFilter,
} from '@poap-xyz/utils';

const variables: FilterVariables = {
where: {
...createBoolFilter('private', true),
...createLikeFilter('name', 'My Awesome POAP'),
...createBetweenFilter('created_date', '2023-12-23', '2024-02-28'),
},
};
```

The possible filters to create are:

- `createLikeFilter`: searchs for the value to be included case-unsensitive in the field.
- `createEqFilter`: match exact field value.
- `createNeqFilter`: match not equal field value.
- `createBoolFilter`: when the value is true or false.
- `createAddressFilter`: given the address match it case-unsensitive and/or excludes the zero address.
- `createInFilter`: if the field is contained in any of the given values.
- `createBetweenFilter`: from and to values, mostly used for dates.
3 changes: 3 additions & 0 deletions docs/pages/packages/utils/_meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"Queries": "Queries"
}
4 changes: 3 additions & 1 deletion examples/moments/backend/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ async function main(): Promise<void> {
});

// We use Compass for read operations
const compass = new PoapCompass('your_api_key');
const compass = new PoapCompass({
apiKey: 'your_api_key',
});

// Use your library here
const client = new MomentsClient(momentsApi, compass);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { FetchMomentsInput, Moment, MomentsClient } from '@poap-xyz/moments';
import { PaginatedResult } from '@poap-xyz/utils';
import { Order, PaginatedResult } from '@poap-xyz/utils';

export const fetch_moments_by_drop_ids = async (
client: MomentsClient,
Expand All @@ -9,7 +9,7 @@ export const fetch_moments_by_drop_ids = async (
offset: 0,
limit: 10,
drop_ids: [1],
idOrder: 'desc',
idOrder: Order.DESC,
};
console.log(input);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { FetchMomentsInput, Moment, MomentsClient } from '@poap-xyz/moments';
import { PaginatedResult } from '@poap-xyz/utils';
import { Order, PaginatedResult } from '@poap-xyz/utils';

export const fetch_multiple_moments = async (
client: MomentsClient,
): Promise<void> => {
const input: FetchMomentsInput = {
offset: 0,
limit: 10,
idOrder: 'desc',
idOrder: Order.DESC,
};

try {
Expand Down
4 changes: 2 additions & 2 deletions examples/moments/backend/src/methods/fetch_single_moment.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { FetchMomentsInput, Moment, MomentsClient } from '@poap-xyz/moments';
import { PaginatedResult } from '@poap-xyz/utils';
import { Order, PaginatedResult } from '@poap-xyz/utils';

export const fetch_single_moment = async (
client: MomentsClient,
Expand All @@ -8,7 +8,7 @@ export const fetch_single_moment = async (
offset: 0,
limit: 10,
id: '7284219b-1bc7-43b8-ab27-44749bdd91e1',
idOrder: 'desc',
idOrder: Order.DESC,
};
try {
const data: PaginatedResult<Moment> = await client.fetch(input);
Expand Down
6 changes: 3 additions & 3 deletions packages/drops/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@poap-xyz/drops",
"version": "0.1.8",
"version": "0.2.0",
"description": "Drops module for the poap.js library",
"main": "dist/cjs/index.cjs",
"module": "dist/esm/index.mjs",
Expand Down Expand Up @@ -29,7 +29,7 @@
"node": ">=18"
},
"dependencies": {
"@poap-xyz/providers": "0.1.8",
"@poap-xyz/utils": "0.1.8"
"@poap-xyz/providers": "0.2.0",
"@poap-xyz/utils": "0.2.0"
}
}
45 changes: 27 additions & 18 deletions packages/drops/src/DropsClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,38 @@ import {
DropResponse as ProviderDropResponse,
} from '@poap-xyz/providers';
import { Drop } from './domain/Drop';
import { PaginatedDropsResponse, PAGINATED_DROPS_QUERY } from './queries';
import {
PAGINATED_DROPS_QUERY,
PaginatedDropsResponse,
PaginatedDropsVariables,
} from './queries/PaginatedDrop';
import {
CreateDropsInput,
DropImageResponse,
DropResponse,
DropsSortFields,
FetchDropsInput,
SearchDropsInput,
UpdateDropsInput,
} from './types';
import {
PaginatedResult,
nextCursor,
creatPrivateFilter,
createUndefinedOrder,
createBetweenFilter,
createFilter,
createInFilter,
Order,
isNumeric,
removeSpecialCharacters,
createOrderBy,
createBoolFilter,
createLikeFilter,
} from '@poap-xyz/utils';
import { DropImage } from './types/dropImage';
import { SEARCH_DROPS_QUERY, SearchDropsResponse } from './queries/SearchDrops';
import {
SEARCH_DROPS_QUERY,
SearchDropsResponse,
SearchDropsVariables,
} from './queries/SearchDrops';

/**
* Represents a client for working with POAP drops.
Expand Down Expand Up @@ -67,22 +76,22 @@ export class DropsClient {
isPrivate,
} = input;

const variables = {
const variables: PaginatedDropsVariables = {
limit,
offset,
orderBy: createUndefinedOrder(sortField, sortDir),
orderBy: createOrderBy<DropsSortFields>(sortField, sortDir),
where: {
...creatPrivateFilter('private', isPrivate),
...createFilter('name', name),
...createBoolFilter('private', isPrivate),
...createLikeFilter('name', name),
...createBetweenFilter('created_date', from, to),
...createInFilter('id', ids),
},
};

const { data } = await this.compassProvider.request<PaginatedDropsResponse>(
PAGINATED_DROPS_QUERY,
variables,
);
const { data } = await this.compassProvider.request<
PaginatedDropsResponse,
PaginatedDropsVariables
>(PAGINATED_DROPS_QUERY, variables);

const drops = data.drops.map(
(drop: DropResponse): Drop => this.mapDrop(drop),
Expand All @@ -109,7 +118,7 @@ export class DropsClient {
return new PaginatedResult<Drop>([], null);
}

const variables = {
const variables: SearchDropsVariables = {
limit,
offset,
...(isNumeric(search) && { orderBy: { id: Order.ASC } }),
Expand All @@ -118,10 +127,10 @@ export class DropsClient {
},
};

const { data } = await this.compassProvider.request<SearchDropsResponse>(
SEARCH_DROPS_QUERY,
variables,
);
const { data } = await this.compassProvider.request<
SearchDropsResponse,
SearchDropsVariables
>(SEARCH_DROPS_QUERY, variables);

const drops = data.search_drops.map(
(drop: DropResponse): Drop => this.mapDrop(drop),
Expand Down
13 changes: 10 additions & 3 deletions packages/drops/src/queries/PaginatedDrop.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import {
FilterVariables,
OrderByVariables,
PaginatedVariables,
} from '@poap-xyz/utils';
import { DropResponse } from '../types/DropResponse';

export const PAGINATED_DROPS_QUERY = `
Expand Down Expand Up @@ -49,7 +54,9 @@ export const PAGINATED_DROPS_QUERY = `
`;

export interface PaginatedDropsResponse {
data: {
drops: DropResponse[];
};
drops: DropResponse[];
}

export type PaginatedDropsVariables = FilterVariables &
OrderByVariables &
PaginatedVariables;
Loading