
Product
Introducing GitHub Actions Scanning Support
Detect malware, unsafe data flows, and license issues in GitHub Actions with Socket’s new workflow scanning support.
@apparts/api
Advanced tools
#+TITLE: @apparts/api #+DATE: [2019-02-07 Thu] #+AUTHOR: Philipp Uhl
To tell the =@apparts/api= package, how to work with your API, you have to overload the =Request= class. If you are using tokens for users to be authenticated (e.g. when using =@apparts/login-server=) you also need to overload the =Token= class and tell the =Request= class to use the =Token= class in a custom authentication method (compare =authUser= below).
Finally, give your new =Request= class to =useApi= and export the functions that you recieve.
#+BEGIN_SRC js import { useApi, Token, Request, ApiFnParams } from "@apparts/api";
const APIVERSION = 1; const URL = DEV // eslint-disable-line no-undef ? "https://devendpoint/v/" : "https://prodendpoint/v/";
const logout = () => { // Log out user on 401 HTTP-Error window.location.href = "/login?force=true"; };
class MyToken extends Token { constructor(user) { super(user);
// Tell Token where to find the users api token, should you
// already have one
this._apiToken = user.apiToken;
}
async renewAPIToken(user) {
// Tell Token how to renew the API Token
const apiToken = await get("user/apiToken").authPW(
user.email,
user.loginToken
);
return apiToken;
}
static getUserKey(user) {
// Tell Token how to identify users
return user.email;
}
}
class MyRequest extends Request { getURL(apiVersion) { // Tell Request what the URL prefix is return URL + apiVersion; } getAPIVersion() { // Tell Request what the default APIVersion is return APIVERSION; }
online() {
// Will be called, when a network-call succeded
}
authUser(user) {
// Define a method for authenticating with a user token.
// This will be called by you, when you want to authenticate with a user
this._auth = MyToken.getAPIToken(user);
return this;
}
async middleware() {
// Tell Request what to do on recieving not-yet caught errors, that should be
// handled globally.
this.on(410, () => alert("Your website is out of date, please reload it."));
this.on({ status: 401, error: "Token invalid" }, () => {
throw "Invalid token";
});
this.on(401, logout);
this.on(0, () => alert("We could not reach the server. Are you online?"));
}
}
const api = useApi(MyRequest);
const get = (...ps: ApiFnParams) => api.get(...ps) as unknown as MyRequest, put = (...ps: ApiFnParams) => api.put(...ps) as unknown as MyRequest, patch = (...ps: ApiFnParams) => api.patch(...ps) as unknown as MyRequest, post = (...ps: ApiFnParams) => api.post(...ps) as unknown as MyRequest, del = (...ps: ApiFnParams) => api.del(...ps) as unknown as MyRequest;
export { get, put, patch, post, del }; #+END_SRC
The functions =get=, =put=, =patch=, =post=, =del= have this signature (exemplary for =get=):
The functions =get=, =put=, =patch=, =post=, =del= return a =Request=. Requests have the following methods:
Example:
#+BEGIN_SRC js try { const resp = await put("users/$1/name") .data({ name: "John" }) .userAuth(user) .on({ status: 400, error: "Too short" }, () => { alert("Please choose a longer username."); }) .on({ status: 400, error: "Is taken" }, () => { alert("This username is taken, already. Please choose a different username."); }); } catch (e) { // If e is not false, then, no error-catcher caught the error and // you might want to take care of it e && alert(e);
// Do, what you have to do on an error. Catch will be called, even
// when the error was caught by an error catcher. If you have some
// error-unspecific cleanup to do, this would be a good place:
/* setLoading(false); */
} #+END_SRC
=@apparts/api= supports generating a fully typed TypeScript SDK to access an API that is defined through an API description as generated by =@apparts/prep=.
You might want to install =prettier= (=npm i -D prettier=) to improve the output.
To generate the SDK, run the following:
#+BEGIN_SRC js import * as prettier from "prettier"; const prettify = (src) => prettier.format(src, { parser: "typescript" });
// The API definition as output by the getApi function from @apparts/prep import { testApi } from "./api-description.json"; import { genFile, EndpointDefinition } from "@apparts/api";
// Pipe to file or write to fs from here console.log(prettify(genFile(testApi.routes as EndpointDefinition[], {
// includePaths?: string[][];
// Can be used to only include a subset of the routes in the output
// excludePaths?: string[][];
// Can be used to exclude a subset of the routes from the output
// emitNoSchema?: boolean;
// If true, schemas will not be generated, but typescript types still will be. (default: false)
}))); #+END_SRC
The resulting API SDK code exports the function =createApi= which expects one parameter: the api as exported from =useApi(MyRequest)= as setup above.
In your application:
#+BEGIN_SRC js import { createApi } from "./"
// setup MyRequest, etc. const apiRaw = useApi(MyRequest); export const api = createApi(apiRaw); #+END_SRC
The resulting api object contains all API endpoints in the following manner:
An endpoint =GET /v/1/user/:userId/info= with the returns
Can be accessed like this:
#+BEGIN_SRC js try { const res = await api.user.info.get({ params: { userId }, /* data, query /}) // Optional error catchers. Matching checked in order of function // usage. So in this example, first the catcher for { status: 404, // error: "user not found" } is checked, then { status: 404, error: // "user info not found" }, at last all status 404 responses. .on404UserNotFound(/ catcher fn /) .on404UserInfoNotFound(/ catcher fn /) .on404(/ catcher fn */) // catch all for code 404
// a Request object is returned, just with the normal
// get/put/post/etc functions from this package. Hence, you can call
// all helper functinos as wanted. E.g.:
.auth(user);
} catch (e) { // If e is not false, then, no error-catcher caught the error and // you might want to take care of it e && alert(e); } #+END_SRC
FAQs
A unified API package for @apparts
The npm package @apparts/api receives a total of 81 weekly downloads. As such, @apparts/api popularity was classified as not popular.
We found that @apparts/api demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Detect malware, unsafe data flows, and license issues in GitHub Actions with Socket’s new workflow scanning support.
Product
Add real-time Socket webhook events to your workflows to automatically receive pull request scan results and security alerts in real time.
Research
The Socket Threat Research Team uncovered malicious NuGet packages typosquatting the popular Nethereum project to steal wallet keys.