Skip to content

Commit

Permalink
Merge pull request #511 from MoralisWeb3/feat/apiutils
Browse files Browse the repository at this point in the history
feat(apiUtils): apiUtil package without test
  • Loading branch information
sogunshola authored Jul 19, 2022
2 parents bd8e07c + 386263e commit 8b8cc4c
Show file tree
Hide file tree
Showing 68 changed files with 377 additions and 1,336 deletions.
6 changes: 6 additions & 0 deletions .changeset/forty-yaks-tie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@moralisweb3/core': major
'@moralisweb3/evm-api': major
---

Refactor evmApi package to use apiUtils
5 changes: 5 additions & 0 deletions .changeset/old-cherries-jam.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@moralisweb3/api': major
---

Generic logic for api modules
5 changes: 5 additions & 0 deletions .changeset/short-baboons-study.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@moralisweb3/api': major
---

rename package from apiUtils to api
Empty file added packages/api/.eslintrc.js
Empty file.
8 changes: 8 additions & 0 deletions packages/api/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CHANGELOG.md

# Output folders
lib/**/*
dist
coverage/
lib.esm
node_modules
3 changes: 3 additions & 0 deletions packages/api/.prettierrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
...require('../../.prettierrc'),
};
1 change: 1 addition & 0 deletions packages/api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# @moralisweb3/api
3 changes: 3 additions & 0 deletions packages/api/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
...require('../../jest.config'),
};
30 changes: 30 additions & 0 deletions packages/api/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "@moralisweb3/api",
"author": "Moralis",
"version": "2.0.0-alpha.2",
"license": "MIT",
"private": false,
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
"sideEffects": false,
"files": [
"lib/index.*",
"lib/**/*.d.ts",
"dist"
],
"scripts": {
"format": "prettier . \"**/*.+(js|ts|json)\" --write",
"lint": "eslint . --ext .js,.ts,.tsx,jsx",
"format:check": "prettier . \"**/*.+(js|ts|json)\" --check",
"clean": "rm -rf lib && rm -rf lib.esm && rm -rf tsconfig.tsbuildinfo",
"build": "tsc",
"dev": "tsc --watch"
},
"devDependencies": {
"prettier": "^2.5.1",
"typescript": "^4.5.5"
},
"dependencies": {
"@moralisweb3/core": "^2.0.0-alpha.2"
}
}
4 changes: 4 additions & 0 deletions packages/api/rollup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import packageJson from './package.json';
import { commonJs, esm } from '../../rollup.config';

export default [commonJs(packageJson), esm(packageJson)];
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import { ApiErrorCode, MoralisApiError } from '@moralisweb3/core';
import { EvmApiResultAdapter } from './EvmApiResultAdapter';
import { PaginatedResponse } from './resolvers/PaginatedResolver';
import { ApiResultAdapter } from './ApiResultAdapter';
import { ApiPaginatedResponse } from './PaginatedResolver';

export class EvmApiPaginatedResultAdapter<
Data extends PaginatedResponse<unknown>,
export class ApiPaginatedResultAdapter<
Data extends ApiPaginatedResponse<unknown>,
AdaptedData,
JSONData,
Params,
> extends EvmApiResultAdapter<Data, AdaptedData, JSONData, Params> {
private _nextCall?: () => Promise<EvmApiPaginatedResultAdapter<Data, AdaptedData, JSONData, Params>>;
> extends ApiResultAdapter<Data, AdaptedData, JSONData, Params> {
private _nextCall?: () => Promise<ApiPaginatedResultAdapter<Data, AdaptedData, JSONData, Params>>;

constructor(
data: Data,
adapter: (data: Data, params: Params) => AdaptedData,
jsonAdapter: (data: AdaptedData) => JSONData,
params: Params,
nextCall?: () => Promise<EvmApiPaginatedResultAdapter<Data, AdaptedData, JSONData, Params>>,
nextCall?: () => Promise<ApiPaginatedResultAdapter<Data, AdaptedData, JSONData, Params>>,
) {
super(data, adapter, jsonAdapter, params);
this._nextCall = nextCall;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ApiErrorCode, EvmAddress, EvmChain, MoralisApiError } from '@moralisweb
import { MoralisDataObject } from '@moralisweb3/core';

// TODO: make part of core config? The challenge in that case is to make sure it is Typed correctly
enum EvmApiFormatType {
enum ApiFormatType {
// Return the data directly, as is provided by the API
RAW = 'raw',
// Return the formatted result of all moralis DataTypes
Expand Down Expand Up @@ -37,7 +37,7 @@ export type JSONApiResult<Value extends object = object> =
}
| JSONApiResult[];

export class EvmApiResultAdapter<Data, AdaptedData, JSONData, Params> {
export class ApiResultAdapter<Data, AdaptedData, JSONData, Params> {
protected _data: Data;
protected _adapter: (data: Data, params: Params) => AdaptedData;
protected _jsonAdapter: (data: AdaptedData) => JSONData;
Expand Down Expand Up @@ -68,20 +68,20 @@ export class EvmApiResultAdapter<Data, AdaptedData, JSONData, Params> {
return this._jsonAdapter(this.result);
}

format(formatType: EvmApiFormatType.RAW): Data;
format(formatType: ApiFormatType.RAW): Data;
// WIP: add type
format(formatType: EvmApiFormatType.JSON): unknown;
format(formatType: EvmApiFormatType.NORMAL): AdaptedData;
format(formatType: EvmApiFormatType) {
if (formatType === EvmApiFormatType.RAW) {
format(formatType: ApiFormatType.JSON): unknown;
format(formatType: ApiFormatType.NORMAL): AdaptedData;
format(formatType: ApiFormatType) {
if (formatType === ApiFormatType.RAW) {
return this.raw;
}

if (formatType === EvmApiFormatType.JSON) {
if (formatType === ApiFormatType.JSON) {
return this.toJSON();
}

if (formatType === EvmApiFormatType.NORMAL) {
if (formatType === ApiFormatType.NORMAL) {
return this.result;
}

Expand Down
16 changes: 16 additions & 0 deletions packages/api/src/MoralisApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { ApiModule, MoralisCore } from '@moralisweb3/core';
import { ApiConfigSetup } from './config/ApiConfigSetup';

export class MoralisApi extends ApiModule {
public constructor(moduleName: string, core: MoralisCore, baseUrl: string) {
super(moduleName, core, baseUrl);
}

public setup() {
ApiConfigSetup.register(this.core.config);
}

public start(): void | Promise<void> {
// Nothing...
}
}
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
import { checkObjEqual } from './../utils/checkObjEqual';
import { EvmResolver, EvmResolverOptions } from './Resolver';
import { getNextParams } from '../utils/getNextParams';
import { EvmApiPaginatedResultAdapter } from '../EvmApiPaginatedResultAdapter';
import { EvmApiConfig } from '../config/EvmApiConfig';
import { ApiErrorCode, MoralisApiError } from '@moralisweb3/core/lib';

export interface PaginatedResponse<Data> {
import { checkObjEqual } from './utils/checkObjEqual';
import { ApiResolver, ApiResolverOptions } from './Resolver';
import { getNextParams } from './utils/getNextParams';
import { ApiPaginatedResultAdapter } from './ApiPaginatedResultAdapter';
import { ApiConfig } from './config/ApiConfig';
import { ApiErrorCode, MoralisApiError } from '@moralisweb3/core';

export interface ApiPaginatedResponse<Data> {
total: number;
page: number;
page_size: number;
cursor: string;
result: Data;
}

export interface PaginatedOptions extends Record<string, unknown> {
export interface ApiPaginatedOptions extends Record<string, unknown> {
offset?: number;
limit?: number;
cursor?: string;
}

export class EvmPaginatedResolver<
export class ApiPaginatedResolver<
ApiParams,
Params extends PaginatedOptions,
Params extends ApiPaginatedOptions,
ApiResult,
AdaptedResult,
JSONResult,
> extends EvmResolver<ApiParams, Params, PaginatedResponse<ApiResult>, AdaptedResult, JSONResult> {
> extends ApiResolver<ApiParams, Params, ApiPaginatedResponse<ApiResult>, AdaptedResult, JSONResult> {
constructor({
getPath,
getUrl,
apiToResult,
resultToJson,
parseParams,
method,
bodyParams,
bodyType,
name,
}: EvmResolverOptions<ApiParams, Params, PaginatedResponse<ApiResult>, AdaptedResult, JSONResult>) {
super({ getPath, apiToResult, resultToJson, parseParams, method, bodyParams, bodyType, name });
}: ApiResolverOptions<ApiParams, Params, ApiPaginatedResponse<ApiResult>, AdaptedResult, JSONResult>) {
super({ getUrl, apiToResult, resultToJson, parseParams, method, bodyParams, bodyType, name });
}

// TODO: error handler to ApiError
Expand All @@ -50,11 +50,11 @@ export class EvmPaginatedResolver<
// @ts-ignore TODO: fix the ApiParams type, as it should extend Searchparams
const result = await this.requestController.get<PaginatedResponse<ApiResult>, ApiParams>(url, searchParams, {
headers: {
'x-api-key': this.config.get(EvmApiConfig.apiKey),
'x-api-key': this.config.get(ApiConfig.apiKey),
},
});

return new EvmApiPaginatedResultAdapter(
return new ApiPaginatedResultAdapter(
result,
this.apiToResult,
this.resultToJson,
Expand All @@ -70,21 +70,21 @@ export class EvmPaginatedResolver<
const searchParams = this.getSearchParams(apiParams);
const bodyParams = this.getBodyParams(apiParams);

const apiKey = this.config.get(EvmApiConfig.apiKey);
const apiKey = this.config.get(ApiConfig.apiKey);
const headers: { [key: string]: string } = {};
if (apiKey) {
headers['x-api-key'] = apiKey;
}

const result = await this.requestController.post<
PaginatedResponse<ApiResult>,
ApiPaginatedResponse<ApiResult>,
Record<string, string>,
Record<string, string>
>(url, searchParams, bodyParams, {
headers,
});

return new EvmApiPaginatedResultAdapter(
return new ApiPaginatedResultAdapter(
result,
this.apiToResult,
this.resultToJson,
Expand All @@ -93,17 +93,17 @@ export class EvmPaginatedResolver<
);
};

private resolveNextCall = (params: Params, result: Awaited<PaginatedResponse<ApiResult>>) => {
private resolveNextCall = (params: Params, result: Awaited<ApiPaginatedResponse<ApiResult>>) => {
const nextParams = getNextParams(params, result);
return checkObjEqual(params, nextParams) ? undefined : () => this.fetch(nextParams);
};

fetch = (
params: Params,
): Promise<
EvmApiPaginatedResultAdapter<Awaited<PaginatedResponse<ApiResult>>, AdaptedResult, JSONResult, Params>
ApiPaginatedResultAdapter<Awaited<ApiPaginatedResponse<ApiResult>>, AdaptedResult, JSONResult, Params>
> => {
const apiKey = this.config.get(EvmApiConfig.apiKey);
const apiKey = this.config.get(ApiConfig.apiKey);

if (!apiKey) {
throw new MoralisApiError({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { ApiErrorCode, Config, MoralisCoreProvider, MoralisApiError, RequestController } from '@moralisweb3/core';
import { EvmApiConfig } from '../config/EvmApiConfig';
import { BASE_URL } from '../EvmApi';
import { EvmApiResultAdapter } from '../EvmApiResultAdapter';
import { ApiConfig } from './config/ApiConfig';
import { ApiResultAdapter } from './ApiResultAdapter';

type Method = 'get' | 'post' | 'put';
export enum BodyType {
PROPERTY = 'property',
BODY = 'body',
}
export interface EvmResolverOptions<ApiParams, Params, ApiResult, AdaptedResult, JSONResult> {
getPath: (params: Params) => string;

export interface ApiResolverOptions<ApiParams, Params, ApiResult, AdaptedResult, JSONResult> {
getUrl: (params: Params) => string;
apiToResult: (result: ApiResult, params: Params) => AdaptedResult;
resultToJson: (result: AdaptedResult) => JSONResult;
parseParams: (params: Params) => ApiParams;
Expand All @@ -19,8 +19,8 @@ export interface EvmResolverOptions<ApiParams, Params, ApiResult, AdaptedResult,
name: string;
}

export class EvmResolver<ApiParams, Params, ApiResult, AdaptedResult, JSONResult> {
protected getPath: (params: Params) => string;
export class ApiResolver<ApiParams, Params, ApiResult, AdaptedResult, JSONResult> {
protected getUrl: (params: Params) => string;
protected apiToResult: (result: ApiResult, params: Params) => AdaptedResult;
protected resultToJson: (result: AdaptedResult) => JSONResult;
protected parseParams: (params: Params) => ApiParams;
Expand All @@ -32,16 +32,16 @@ export class EvmResolver<ApiParams, Params, ApiResult, AdaptedResult, JSONResult
protected readonly requestController: RequestController;

constructor({
getPath,
getUrl,
apiToResult,
resultToJson,
parseParams,
method,
bodyParams,
bodyType,
name,
}: EvmResolverOptions<ApiParams, Params, ApiResult, AdaptedResult, JSONResult>) {
this.getPath = getPath;
}: ApiResolverOptions<ApiParams, Params, ApiResult, AdaptedResult, JSONResult>) {
this.getUrl = getUrl;
this.apiToResult = apiToResult;
this.resultToJson = resultToJson;
this.parseParams = parseParams;
Expand All @@ -54,10 +54,6 @@ export class EvmResolver<ApiParams, Params, ApiResult, AdaptedResult, JSONResult
this.requestController = RequestController.create(core);
}

protected getUrl = (params: Params) => {
return `${BASE_URL}/${this.getPath(params)}`;
};

protected isBodyParam = (param: string) => {
if (this.method === 'get') {
return false;
Expand Down Expand Up @@ -109,7 +105,7 @@ export class EvmResolver<ApiParams, Params, ApiResult, AdaptedResult, JSONResult
headers: this.createHeaders(),
});

return new EvmApiResultAdapter(result, this.apiToResult, this.resultToJson, params);
return new ApiResultAdapter(result, this.apiToResult, this.resultToJson, params);
};

protected _apiPost = async (params: Params) => {
Expand All @@ -128,7 +124,7 @@ export class EvmResolver<ApiParams, Params, ApiResult, AdaptedResult, JSONResult
},
);

return new EvmApiResultAdapter(result, this.apiToResult, this.resultToJson, params);
return new ApiResultAdapter(result, this.apiToResult, this.resultToJson, params);
};

protected _apiPut = async (params: Params) => {
Expand All @@ -147,11 +143,11 @@ export class EvmResolver<ApiParams, Params, ApiResult, AdaptedResult, JSONResult
},
);

return new EvmApiResultAdapter(result, this.apiToResult, this.resultToJson, params);
return new ApiResultAdapter(result, this.apiToResult, this.resultToJson, params);
};

private createHeaders(): { [key: string]: string } {
const apiKey = this.config.get(EvmApiConfig.apiKey);
const apiKey = this.config.get(ApiConfig.apiKey);
const headers: { [key: string]: string } = {};
if (apiKey) {
headers['x-api-key'] = apiKey;
Expand All @@ -160,7 +156,7 @@ export class EvmResolver<ApiParams, Params, ApiResult, AdaptedResult, JSONResult
}

fetch = (params: Params) => {
const apiKey = this.config.get(EvmApiConfig.apiKey);
const apiKey = this.config.get(ApiConfig.apiKey);

if (!apiKey) {
throw new MoralisApiError({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ConfigKey } from '@moralisweb3/core';

export const EvmApiConfig = {
export const ApiConfig = {
apiKey: {
name: 'apiKey',
defaultValue: null,
Expand Down
Loading

0 comments on commit 8b8cc4c

Please sign in to comment.