Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
@decathlon/moon
Advanced tools
Moon is a featured, production ready caching REST client for every React UI. It allows you to manage queries life cycle with an api and easily build React UI components that fetch data via Axios. The only thing you have to do is transmit the configuration. Moon does the rest ! 🚀
Moon client can be used in any React app where you want to use data. It's:
npm install @decathlon/moon --save
You get started by create REST links. A link is an object which need an id and a baseUrl of your REST server (for more information about the REST link config please see the Moon config section).
To connect Moon to your React app, you will need to use the MoonProvider component exported from @decathlon/moon
. The MoonProvider is a React's Context.Provider. It wraps your React app and places the client on the context, which allows you to access it from anywhere in your component tree.
import { MoonProvider } from "@decathlon/moon";
const links = [
{
id: "FOO",
baseUrl: "http://foo.com"
}
];
const App = () => {
return (
<MoonProvider links={links}>
<MyComponent />
</MoonProvider>
);
};
Once your MoonProvider is hooked up, you're ready to start requesting data with the Query component or with the useQuery hook!
import { Query } from '@decathlon/moon';
const MyComponent = () => {
return (
<Query<QueryData, QueryVariables> source="FOO" endPoint="/users" variables={{ foo: "bar" }}>
{({ loading, data, error }) => {
if (loading) return <span> Loading ...</span>;
return <span>{error ? error.message : "success"}</span>;
}}
</Query>
);
};
Congrats 🎉, you just made your first query with the Query component!
The same query with the useQuery hook
import { useQuery } from '@decathlon/moon';
const MyComponent = () => {
const variables = React.useMemo(() => ({ foo: "bar" }), [...]);
const [{ loading, error }, { refetch }] = useQuery<QueryData, QueryVariables>({ source: "FOO", endPoint: "/users", variables });
if (loading) return <span> Loading ...</span>;
return <span>{error ? error.message : "success"}</span>;
};
Now that we've learned how to fetch data with the Query/useQuery component/hook, the next step is to learn how to mutate that data with mutations. For that we need to use the Mutation/useMutation component/hook.
import { Mutation } from '@decathlon/moon';
const MyComponent = () => {
return (
<Mutation<MutationResponse, MutationVariables> source="FOO" endPoint="/users" variables={{ foo: "bar" }}>
{({ response, error, actions: { mutate } }) => {
const result = response ? <span>{response.status && "Success"}</span> : <div onClick={mutate}>Go</div>;
return error ? <span>{error.message}</span> : result;
}}
</Mutation>
);
};
The same mutation with useMutation:
import { useQuery } from '@decathlon/moon';
const MyComponent = () => {
const variables = React.useMemo(() => ({ foo: "bar" }), [...]);
const [{ loading, error, response }, { mutate }] = useMutation<MutationResponse, MutationVariables>({
source: "FOO",
endPoint: "/users",
variables
});
const result = response ? <span>{response.status && "Success"}</span> : <div onClick={mutate}>Go</div>;
return error ? <span>{error.message}</span> : result;
};
Sometimes we need to retrieve the state/result of a query in another component. useQueryResult/useQueriesResult/useQueryState/useQueriesStates allows you to do this. For that, it is enough to give him the id/ids of the query/queries:
Updated when the query state is changed. The optional stateToProps function is used for selecting the part of the data from the query state that the connected component needs.
import { useQueryState } from '@decathlon/moon';
const MyComponent = () => {
const stateToProps = (queryState) => queryState
const { loading } = useQueryState("queryId", stateToProps);
return <span>{loading ? "Loading..." : "success"}</span>;
};
Updated when one of the query states is changed.The optional statesToProps function is used for selecting the part of the data from the query state that the connected component needs.
import { useQueriesStates } from '@decathlon/moon';
const MyComponent = () => {
const statesToProps = (queriesStates) => queriesStates
const { queryId: { loading } } = useQueriesStates(["queryId"], statesToProps);
return <span>{loading ? "Loading..." : "success"}</span>;
};
Updated only when the query result is changed. .The optional resultToProps function is used for selecting the part of the data from the query result that the connected component needs.
import { useQueryResult } from '@decathlon/moon';
const MyComponent = () => {
const resultToProps = (queryResult) => queryResult
const result = useQueryResult("queryId", resultToProps);
return <span>{...result...}</span>;
};
Updated only when one of the query results is changed. The optional statesToProps function is used for selecting the part of the data from the queries results that the connected component needs.
import { useQueriesResults } from '@decathlon/moon';
const MyComponent = () => {
const resultsToProps = (queriesResults) => queriesResults
const { queryId: queryIdResult } = useQueriesResults(["queryId"], statesToProps);
return <span>{...queryIdResult...}</span>;
};
You can use the moon client directly like this:
import { useMoon } from '@decathlon/moon';
const MyComponent = () => {
const { client, store } = useMoon();
client.query(...);
client.mutate(...);
store.readQuery(...);
store.writeQuery(...);
};
Same as useMoon hook.
import { withMoon } from '@decathlon/moon';
const MyComponent = ({ client, store }) => {
...
};
export withMoon(MyComponent);
Same as useQueryResult hook.
import { withQueryResult } from '@decathlon/moon';
const MyComponent = ({ queryId }) => {
...
};
export withQueryResult(queryId, resultToProps)(MyComponent);
Same as useQueriesResults hook.
import { withQueriesResults } from '@decathlon/moon';
const MyComponent = ({ queryId, queryId2 }) => {
...
};
export withQueriesResults([queryId, queryId2], resultsToProps)(MyComponent);
This the Typescript interface of the Query/useQuery component/hook.
interface IQueryProps<QueryData = any, QueryVariables = any, DeserializedData = QueryData> {
id?: string;
source: string;
endPoint: string;
variables?: QueryVariables;
fetchOnMount?: boolean;
autoRefetchOnUpdate?: boolean;
fetchPolicy?: FetchPolicy;
options?: AxiosRequestConfig;
deserialize?: (response: QueryData) => DeserializedData;
onResponse?: (response: DeserializedData) => void;
onError?: (error: any) => void;
children?: (props: IChildren<DeserializedData>) => Nullable<JSX.Element | JSX.Element[]>;
}
The fetch policy is an option which allows you to specify how you want your component to interact with the Moon data cache. By default your component will try to read from the cache first, and if the full data for your query is in the cache then Moon simply returns the data from the cache. If the full data for your query is not in the cache then Moon will execute your request using your network interface. By changing this option you can change this behavior.
Valid fetchPolicy values are:
This the Typescript interface of the Mutation/useMutation component/hook.
export interface IMutationProps<MutationResponse = any, MutationVariables = any> {
source: string;
endPoint: string;
variables?: MutationVariables;
type?: MutateType;
children?: (props: IChildren<MutationResponse>) => React.ReactNode;
onResponse?: (response: MutationResponse) => void;
onError?: (error: any) => void;
}
For each Moon link we can add interceptors (middleware: language, api token, success Handler....) for the request and/or the response like this:
import { AxiosRequestConfig } from "axios";
function successHandler(response: AxiosResponse){...};
function setLanguage(config: AxiosRequestConfig): AxiosRequestConfig | Promise<AxiosRequestConfig> {
return {
...config,
headers: {
...config.headers,
"Accept-Language": "en"
}
};
}
const requestInterceptors = [{ onFulfilled: setLanguage }];
const responseInterceptors = [{ onFulfilled: successHandler }];
const links = [
{
id: "FOO",
baseUrl: "http://foo.com",
interceptors: { request: requestInterceptors, response: responseInterceptors }
},
{
id: "BAR",
baseUrl: "http://bar.com"
}
];
git clone ...
cd moon
npm ci
npm run test
PRs are welcome! You noticed a bug, a possible improvement or whatever? Any help is always appreciated, so don't hesitate opening one!
Be sure to check out the contributing guidelines to fasten up the merging process.
See also the list of contributors who participated in this project.
This project is licensed under the Apache-2.0 License - see the LICENSE.md file for details
FAQs
A featured, production ready caching REST client for every React UI
The npm package @decathlon/moon receives a total of 7 weekly downloads. As such, @decathlon/moon popularity was classified as not popular.
We found that @decathlon/moon demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 4 open source maintainers 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.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.