farrow-api-client
An client for farrow-api-server.
Installation
- npm
- Yarn
npm install farrow-api-client
yarn add farrow-api-client
Usage
Using farrow to codegen the code for client, and config apiPipeline if needed.
Simply, we can import
the file via codegen directly without modification.
If we need to touch request/response, there are two ways.
The first way only affects one url.
import { apiPipeline } from "../api/todo";
/**
* farrow-api-client is based on farrow-pipeline
* use pipeline.use(middleware) to do something you want
*/
apiPipeline.use(async (request, next) => {
// add extra fileds for post requeset body
let body = {
...request.body,
token: "abc",
};
// add extra headers for post request
let options: RequestInit = {
headers: {
"x-access-token": "abc",
},
};
// pass new request to next and await for the response
let response = await next({
...request,
body,
options,
});
// handle the response if needed
return response;
});
The second way only affects all URLs.
import { apiPipeline } from "farrow-api-client";
// all request performed via farrow-api-client will come here
// it should be handled carefully
apiPipeline.use(async (request, next) => {
let response = await next(request);
return response;
});
/**
* match(string | regexp, middleware)
* match the request url and handle it via farrow-pipeline
* if pass a string, it will be matched by url.endsWith(pattern)
* if pass a regexp, it will be matched by pattern.test(url)
*/
apiPipeline.match("/todo", async (request, next) => {
// add extra fileds for post requeset body
let body = {
...request.body,
token: "abc",
};
// add extra headers for post request
let options: RequestInit = {
headers: {
"x-access-token": "abc",
},
};
// pass new request to next and await for the response
let response = await next({
...request,
body,
options,
});
// handle the response if needed
return response;
});
API
createApiPipeline
Type Signature:
const createApiPipeline: ({ fetcher }?: ApiPipelineOptions) => ApiPipeline;
type ApiPipeline = AsyncPipeline<ApiRequest, ApiResponse> & {
match(
pattern: string | RegExp,
middleware: MiddlewareInput<ApiRequest, MaybeAsync<ApiResponse>>
): void;
invoke(
url: string,
calling: SingleCalling,
options?: ApiInvokeOptions
): Promise<JsonType | Error>;
invoke(
url: string,
calling: BatchCalling,
options?: ApiInvokeOptions
): Promise<(JsonType | Error)[]>;
invoke(
url: string,
calling: Calling,
options?: ApiInvokeOptions
): Promise<JsonType | Error | (JsonType | Error)[]>;
setFetcher(newFetcher: Fetcher): void;
};
export type ApiPipelineOptions = {
// custom fetcher
fetcher?: Fetcher;
};
Example Usage:
import { createApiPipeline } from 'farrow-api-client'
cconst apiPipeline = createApiPipeline()
apiPipeline.invoke
Type Signature:
invoke(url: string, calling: SingleCalling, options?: ApiInvokeOptions): Promise<JsonType | Error>
invoke(url: string, calling: BatchCalling, options?: ApiInvokeOptions): Promise<(JsonType | Error)[]>
invoke(url: string, calling: Calling, options?: ApiInvokeOptions): Promise<JsonType | Error | (JsonType | Error)[]>
type ApiInvokeOptions = {
fetcher?: Fetcher
}
Example Usage:
const result = await apiPipeline.invoke("http://localhost:3000/api", {
type: "Single",
path: ["getTodo"],
input: {},
});
const result = await apiPipeline.invoke("http://localhost:3000/api", {
type: "Batch",
callings: [
{
type: "Single",
path: ["getTodo"],
input: {},
},
{
type: "Single",
path: ["getUser"],
input: {},
},
],
});
const result = await apiPipeline.invoke("http://localhost:3000/api", {
type: "Introspection",
});
const result = await apiPipeline.invoke(
"http://localhost:3000/api",
{
type: "Single",
path: ["getTodo"],
input: {},
},
{ fetcher: customFetcher }
);
Options:
fetcher?: Fetcher
Custom fetcher.
apiPipeline.setFetcher
Custom fetcher.
Type Signature:
setFetcher(newFetcher: Fetcher): void
Example Usage:
apiPipeline.setFetcher(customFetcher);
apiPipeline.match
Mocking data fro client.
Type Signature:
match(pattern: string | RegExp, middleware: MiddlewareInput<ApiRequest, MaybeAsync<ApiResponse>>): void
Example Usage:
api.match("/api.foo", () => {
// do somethings
});
createApiPipelineWithUrl
Type Signature:
const createApiPipelineWithUrl: (
url: string,
options?: ApiPipelineOptions
) => ApiPipelineWithUrl;
type ApiPipelineWithUrl = AsyncPipeline<ApiRequest, ApiResponse> & {
invoke(
calling: SingleCalling,
options?: ApiWithUrlInvokeOptions
): Promise<JsonType>;
};
Example Usage:
import { createApiPipelineWithUrl } from 'farrow-api-client'
cconst apiPipeline = createApiPipelineWithUrl("http://localhost:3000/api")
apiPipeline.invoke
Type Signature:
invoke(calling: SingleCalling, options?: ApiWithUrlInvokeOptions | undefined): Promise<JsonType>
type ApiWithUrlInvokeOptions = ApiInvokeOptions & {
batch?: boolean;
};
Example Usage:
const result = await apiPipeline.invoke({
type: "Single",
path: ["getTodo"],
input: {},
});
const [result0, result1] = await Promise.all([
apiPipeline.invoke(
{
type: "Single",
path: ["getTodo"],
input: {},
},
{ batch: true }
),
apiPipeline.invoke(
{
type: "Single",
path: ["getTodo"],
input: {},
},
{ batch: true }
),
]);
Options:
batch?: boolean
If open the batch feature for merging request and date caching. It implement by dataloader. Default:
false
.
Used for CORS.
Learn more
Relative Module
- farrow-schema: Powerful and extensible schema builder library. Create Schema like type of TypeSccript.
- farrow-api: Schema-based Api builder.
- farrow-api-server: farrow-api adapter for farrow-http.
- farrow-federation: A aggregation tool for farrow-api.
Sample
- farrow-sample/06-deno-api: Sample of deno api.
- farrow-sample/13-api-federation: Sample for api federation.
- farrow-sample/14-api-todo-app: Todo App with farrow-api.
- farrow-sample/23-api-todo: A template for farrow with rpc api.