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

feat(users): Add users collection to SDK #52

Merged
merged 35 commits into from
Jan 23, 2019
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
3f3c501
Add docs related to adding the users namespace to the API
kwelch Dec 28, 2018
89530c7
updates to users doc based on review
kwelch Dec 31, 2018
174d8b8
more code review updates
kwelch Jan 2, 2019
3f2d2d7
update doc to match emailLookup name
kwelch Jan 2, 2019
6026411
update getById example to use a string for id
kwelch Jan 2, 2019
698b878
Add implementation for users.me
kwelch Jan 2, 2019
ab23e91
add keys to UserObject interface to fix lint issue
kwelch Jan 2, 2019
a3fd6e1
remove unnecessary typing
kwelch Jan 2, 2019
3c16eaa
update users test to use request instead of full sdk
kwelch Jan 2, 2019
5288f3f
add index test for users collection
kwelch Jan 2, 2019
a1f11d4
updated to use instance of instead of any
kwelch Jan 2, 2019
57a0e5c
update doc on each method to remove extra words
kwelch Jan 3, 2019
22b978b
Update type name from collection to methods
kwelch Jan 3, 2019
90b597a
Update type from RequestHelper to JSONRequest
kwelch Jan 3, 2019
c232d53
Add Email type and rename UserObject to User
kwelch Jan 3, 2019
24aae2b
Add transformation of snakeToCamel for objects keys
kwelch Jan 3, 2019
926c305
fixed tests for transformed data
kwelch Jan 3, 2019
ac627ec
fixed test for node@6
kwelch Jan 3, 2019
a71616a
replace Object.entries with keys for node@6 support
kwelch Jan 3, 2019
ab65a28
added rejection case to users.me
kwelch Jan 4, 2019
f1e5574
Added more test and methods to userMethods
kwelch Jan 4, 2019
fcdb247
swap functions for classes
jcreamer898 Jan 7, 2019
28437e5
clean up a bit
jcreamer898 Jan 7, 2019
e05a3b2
a bit more cleanup
jcreamer898 Jan 7, 2019
dfca786
rename interfaces while I make up my mind
jcreamer898 Jan 7, 2019
392ac6d
Merge pull request #1 from jcreamer898/jc-add-users
kwelch Jan 8, 2019
9b6dabb
minor updates to make jsonRequest generic
kwelch Jan 8, 2019
95c2b15
fix(types): update generics in request
jcreamer898 Jan 8, 2019
54dd2b3
add default api response
jcreamer898 Jan 8, 2019
2cb171e
Merge pull request #2 from jcreamer898/jc-add-users
kwelch Jan 9, 2019
817fa36
remove support for emailLookup since it is deprecated
kwelch Jan 10, 2019
7afe721
update test to deconstruct to specific methods
kwelch Jan 10, 2019
2a8c562
avoid async/await for compile purposes
kwelch Jan 10, 2019
1170cc6
fix binding issue with users api functions
kwelch Jan 10, 2019
4c18869
revert arrow functions and fix tests
kwelch Jan 10, 2019
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
6 changes: 3 additions & 3 deletions docs/users.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ View the [User response object](user-object-reference) for details on the proper
<a id="me"></a>

## `sdk.users.me()`
This method is used to get details about the current logged in user.
Gets details about the current logged in user.

**Read [`/users/me` documentation](user-get-me) for more details.**

Expand All @@ -38,7 +38,7 @@ sdk.users.me().then((user) => {
<a id="getById"></a>

## `sdk.users.get(id)`
This method is used to load the details for a specific user by their user id.
Gets the details for a specific user by their user id.

**Read [`/users/:id` documentation](user-get-me) for more details.**

Expand All @@ -63,7 +63,7 @@ sdk.users.get('1234567890').then((user) => {
<a id="lookByEmail"></a>

## `sdk.users.emailLookup(email)`
kwelch marked this conversation as resolved.
Show resolved Hide resolved
This method is used to load the details for a specific user. Currently it supports look ups via the email property.
Gets the details for a specific user using their emaill address.

**_Currently, no public documentation page._**

Expand Down
16 changes: 16 additions & 0 deletions src/__tests__/__fixtures__/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,22 @@ export const MOCK_USERS_ME_RESPONSE_DATA = {
image_id: null as string,
};

export const MOCK_TRANSFORMED_USERS_ME_RESPONSE_DATA = {
emails: [
{
email: '[email protected]',
verified: true,
primary: true,
},
],
id: '142429416488',
name: 'Eventbrite Engineer',
firstName: 'Eventbrite',
lastName: 'Engineer',
isPublic: false,
imageId: null as string,
};

export const MOCK_INTERNAL_ERROR_RESPONSE_DATA = {
status_code: 500,
error: 'INTERNAL_ERROR',
Expand Down
7 changes: 5 additions & 2 deletions src/__tests__/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import {
restoreMockFetch,
getMockResponse,
} from './utils';
import {MOCK_USERS_ME_RESPONSE_DATA} from './__fixtures__';
import {
MOCK_USERS_ME_RESPONSE_DATA,
MOCK_TRANSFORMED_USERS_ME_RESPONSE_DATA,
} from './__fixtures__';

describe('configurations', () => {
it('does not error when creating sdk object w/o configuration', () => {
Expand Down Expand Up @@ -111,7 +114,7 @@ describe('request', () => {
});

await expect(users.me()).resolves.toEqual(
MOCK_USERS_ME_RESPONSE_DATA
MOCK_TRANSFORMED_USERS_ME_RESPONSE_DATA
);

expect(getMockFetch()).toHaveBeenCalledTimes(1);
Expand Down
13 changes: 9 additions & 4 deletions src/__tests__/users.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,23 @@ import {
getMockResponse,
restoreMockFetch,
} from './utils';
import {MOCK_USERS_ME_RESPONSE_DATA} from './__fixtures__';
import {
MOCK_USERS_ME_RESPONSE_DATA,
MOCK_TRANSFORMED_USERS_ME_RESPONSE_DATA,
} from './__fixtures__';

import request from '../request';
import usersCollection from '../users';
import usersMethods from '../users';

const users = usersCollection(request);
const users = usersMethods(request);
kwelch marked this conversation as resolved.
Show resolved Hide resolved

describe('users.me()', () => {
kwelch marked this conversation as resolved.
Show resolved Hide resolved
it('calls fetch and calls fetch with appropriate defaults', async() => {
mockFetch(getMockResponse(MOCK_USERS_ME_RESPONSE_DATA));

await expect(users.me()).resolves.toEqual(MOCK_USERS_ME_RESPONSE_DATA);
await expect(users.me()).resolves.toEqual(
MOCK_TRANSFORMED_USERS_ME_RESPONSE_DATA
);

expect(getMockFetch()).toHaveBeenCalledTimes(1);
expect(getMockFetch()).toHaveBeenCalledWith(
Expand Down
8 changes: 4 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {Sdk, SdkConfig, RequestHelper} from './types';
import {Sdk, SdkConfig, JSONRequest} from './types';
import request from './request';
import userCollection from './users';
import userMethods from './users';

export * from './constants';

Expand All @@ -10,7 +10,7 @@ const eventbrite = ({
baseUrl = DEFAULT_API_URL,
token,
}: SdkConfig = {}): Sdk => {
const requestHelper: RequestHelper = (endpoint, options = {}) => {
const requestHelper: JSONRequest = (endpoint, options = {}) => {
kwelch marked this conversation as resolved.
Show resolved Hide resolved
const url = `${baseUrl}${endpoint}`;
let requestOptions = options;

Expand All @@ -29,7 +29,7 @@ const eventbrite = ({

return {
request: requestHelper,
users: userCollection(requestHelper),
users: userMethods(requestHelper),
};
};

Expand Down
6 changes: 4 additions & 2 deletions src/request.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {JSONResponseData, ParsedResponseError} from './types';
import {JSONRequest, JSONResponseData, ParsedResponseError} from './types';
import 'isomorphic-fetch';

/**
Expand Down Expand Up @@ -145,5 +145,7 @@ const _catchStatusError = (res: Response): Promise<any> =>
* Low-level method that makes fetch requests, returning the response formatted as JSON.
* It parses errors from API v3 and throws exceptions with those errors
*/
export default (url: string, options?: RequestInit): Promise<{}> =>
const jsonRequest: JSONRequest = (url: string, options?: RequestInit) =>
_fetchJSON(url, options).catch(_catchStatusError);

export default jsonRequest;
8 changes: 4 additions & 4 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import {UserCollection} from './users';
import {UserMethods} from './users';

export interface SdkConfig {
token?: string;
baseUrl?: string;
}

export type RequestHelper = (
export type JSONRequest = (
apiPath: string,
options?: RequestInit
) => Promise<{}>;

export interface Sdk {
request: RequestHelper;
users: UserCollection;
request: JSONRequest;
users: UserMethods;
}

export interface ArgumentErrors {
Expand Down
54 changes: 39 additions & 15 deletions src/users.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,48 @@
import {RequestHelper} from './types';
import {JSONRequest} from './types';

export interface UserObject {
export type Email = {
email: string;
primary: boolean;
};

export interface User {
id: string;
first_name: string;
last_name: string;
image_id: string;
email: [
{
email: string;
primary: true;
}
];
firstName: string;
lastName: string;
imageId: string;
email: Email[];
}

export interface UserCollection {
[key: string]: () => Promise<UserObject>;
export interface UserMethods {
me: () => Promise<User>;
}

export default (request: RequestHelper): UserCollection => {
const me = () => request('/users/me/') as Promise<UserObject>;
const SNAKE_CASE_MATCH = /_\w/g;
const snakeToCamel = (str: string) =>
str.replace(SNAKE_CASE_MATCH, (chars: string) => chars[1].toUpperCase());

const transformKeysSnakeToCamel = (obj: {}): {} =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you wanna use a lib like camelize? https://yarnpkg.com/en/package/camelize. Cuz now in theory we need tests for transformKeysSnakeToCamel

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will look into a package, however that one will not work because it also converts dotCase to camel, which breaks our API. That is what led us to making this function internally.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is turning out to be difficult to find something for since it is very generic, but all of them convert expand.destination_event to expandDestinationEvent, which is undesired.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about leaving this and adding tests? It is that or I make a package of it 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved this around and added tests. Also working on adding something to camel-keys to allow us to be able to remove this.

Object.entries(obj).reduce((memo, [key, value]) => {
const camelKey = snakeToCamel(key);
let newValue = value;

if (
newValue &&
typeof newValue === 'object' &&
!Array.isArray(newValue)
) {
newValue = transformKeysSnakeToCamel(newValue);
}

return {
...memo,
[camelKey]: newValue,
};
}, {});

export default (request: JSONRequest): UserMethods => {
const me = () =>
request('/users/me/').then(transformKeysSnakeToCamel) as Promise<User>;

return {
kwelch marked this conversation as resolved.
Show resolved Hide resolved
me,
Expand Down