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

feature: added support for graphql api querying #49

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

ShayElkana
Copy link
Contributor

Copy link
Contributor

@gregra81 gregra81 left a comment

Choose a reason for hiding this comment

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

My main comment here, is that I think we should create a new package called
@mondaycom/api and reuse it here and in monday-sdk-js. The reason is that during this year we are going to enhance api sdk to support popular methods, such as createItem, etc and I want both SDKs to enjoy it

import { Logger } from 'utils/logger';
const logger = new Logger('MondayApiClient', { mondayInternal: true });
const API_URL = 'https://api.monday.com/v2/';
export class MondayApiClient implements IMondayApiClient {
Copy link
Contributor

Choose a reason for hiding this comment

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

we can call it simply ApiClient, no need for the Monday prefix

@@ -0,0 +1,60 @@

export type APIOptions = {
Copy link
Contributor

Choose a reason for hiding this comment

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

IMO we don't need it, as it allows the developer to use different tokens and apiVersions for different api calls using the same client. This is not standard in the industry. Regarding the variables param - simple move it to the api function and maybe change its type to Record<string, any>

Copy link
Collaborator

Choose a reason for hiding this comment

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

This may make the life of developers a little bit harder. If they have one mutation that they don't know how to deprecate yet (move to the new version) and they know how to move the rest of their stuff - Without this option, They will "have" to stay on the old version instead of moving and staying in the old version only for this mutation

Copy link
Contributor

Choose a reason for hiding this comment

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

@DorShakedMonday in that case they can simply create another ApiClient with the right version and use it for their deprecated methods


export type APIVersion = string;

export type APIResponse = {
Copy link
Contributor

Choose a reason for hiding this comment

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

that's not always the case, what about errors?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Look at lines 35 ~ 37.
@ShayElkana Why are these types separated in this manner? Developers can get errors, no?

* Placeholders may be used, which will be substituted by the variables object passed within the options.
* @param options
*/
api: (query: string, options: APIOptions) => Promise<APIResponse>,
Copy link
Contributor

@gregra81 gregra81 Jan 7, 2024

Choose a reason for hiding this comment

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

use generics to allow the developer to get the type, i.e.:

export type APIResponse<T> = {
    data: T,
    account_id: number
}

export type APIFetchResponse<T> = {
    errors?: Array<{ message: string }>,
} & APIResponse<T>;


export type IMondayApiClient = {
    api: <T = object>(query: string) => Promise<APIFetchResponse<T>>
}


const mondayClient = new MondayApiClient();
mondayClient.setToken(token);
mondayClient.setApiVersion('2023-10');
Copy link
Collaborator

Choose a reason for hiding this comment

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

Question out of gap in knowledge. Is this the best practice we dictate to our developers? to hardcode the api version? there is no env variable or something we suggest using/creating to manage this?

logger.debug(`getApiToGetColumnValue->query:
${query}
`);
const response = await mondayClient.api(query);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why don't you use variables here like in the mutation? this would look like we don't recommend using variables in queries (like in lines 265~281)

Comment on lines +1 to +3
import {BadRequestError, InternalServerError} from 'errors/apps-sdk-error';
import {Token} from 'types/general';
import {isDefined} from 'types/guards';
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you please run your linter?


async api(query: string, options: APIOptions = {}) {
if (!this.token) {
logger.warn('[mondayApiClientFetch] Error Token is missing');
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should not be a warn level log if it states there was an error

async api(query: string, options: APIOptions = {}) {
if (!this.token) {
logger.warn('[mondayApiClientFetch] Error Token is missing');
throw new BadRequestError('Token is missing');
Copy link
Collaborator

Choose a reason for hiding this comment

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

I am not sure BadRequest is the way to go here (api wise) this should be Unauthorized, no?


if (isDefined(result.errors)) {
const errorMessage = result.errors.map(e=>e?.message).join(', ');
logger.error(`[mondayApiClientFetch] Errors occurred while communicating with secure storage.\nErrors: ${errorMessage}`);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think this is related to secure storage here 😅

throw new InternalServerError('some thing went wrong when communicating with mondayApiClientFetch data filed returned empty');
}

const { data, account_id } = result;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we commit on returning account_id as snake case?
And a general question - Why do we return accountId here?

Comment on lines 2 to +3
import {RequestOptions} from 'types/fetch';
import {Token} from 'types/general';
Copy link
Collaborator

Choose a reason for hiding this comment

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

Lint

@@ -0,0 +1,60 @@

export type APIOptions = {
Copy link
Collaborator

Choose a reason for hiding this comment

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

This may make the life of developers a little bit harder. If they have one mutation that they don't know how to deprecate yet (move to the new version) and they know how to move the rest of their stuff - Without this option, They will "have" to stay on the old version instead of moving and staying in the old version only for this mutation


export type APIVersion = string;

export type APIResponse = {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Look at lines 35 ~ 37.
@ShayElkana Why are these types separated in this manner? Developers can get errors, no?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants