Quick Start
Learn how to use and get familiar with Quarkinos SDK.
Considering you've already either Generated a new Project using Quarkinos CLI tool or have Added the @quarkino/services package to your project you can start using Quarkinos SDK like this:
Basic React Usage
Client Component Example
Create a file at /components/client-component-example.tsx
:
"use client";
import {
useContentEndpoints,
usePersonsEndpoints,
} from "@quarkino/services/client";
// All of the client side requests are available through "@quarkino/services/client"
// The naming convention is use[endpoint namespace]Endpoints e.g. useContentEndpoints for the Content namespace (https://docs.quarkino.com/docs/features/content)
// And the usePersonsEndpoints for the Person (https://docs.quarkino.com/docs/features/person) endpoint namespace
/**
* @returns A React client component
*/
const ClientComponent = () => {
// GET request example
// This call returns a standard UseQueryResult (https://tanstack.com/query/latest/docs/framework/react/reference/useQuery) object that's been fully typed with the expected results from the Quarkinos API
const blogContent = useContentEndpoints.post.get.contentPostSingle
// The filters that we want applied on the returning data
// The filter function receives an object of known keys that the server expects and can process.
// This object is fully type safe and you can see all of the available keys through your code editors code suggestion
.filter({
type: "blog", // content of type blog - this is a content type that you have defined in your Quarkino panel.
hashid: "Wylzp", // example hashID - change it to a correct ID from your own panel.
locale: "en", // a param to get localised content if it's enabled and defined from the CMS panel e.g. en, fa, ar
})
// The keys we want to be returned from the API
// These keys are also fully type safe and accessible through your code editors code suggestion with what's available from the Quarkinos API.
.include("title", "title2")
// This function executes the query call and can receive an optional object of type reactQueryOptions, so you can expect all of the usual keys that react query offers on a useQuery (https://tanstack.com/query/latest/docs/framework/react/reference/useQuery) call
.useRequest({
queryKey: ["test-list"],
});
// POST request example
// This call returns a standard UseMutationResult fully typed with the expected payload for a mutation and the expected results of that mutation from the Quarkinos API
const editProfile = usePersonsEndpoints.profileEdit.post.save.useRequest();
/**
* Handles the post request execution on button click
*/
const handleClick = () => {
// The mutate object is fully typed and only accepts the appropriate key values for the mutation
editProfile.mutate(
{
birth_at: 1144913752000,
email: "[email protected]",
mobile: "09100000000",
name_first: "First Name",
name_last: "Last Name",
},
{
/**
* success handler
* @param res server response
*/
onSuccess: (res) => {
console.log("fully typed response:", res);
},
}
);
};
return (
<div>
<h1>Client Component</h1>
<button onClick={onClick}>
{editProfile.isPending ? "Loading" : "Click to post data"}
</button>
{blogContent?.data ? (
<p>{JSON.stringify(res.data.results)}</p>
) : (
<p>Loading</p>
)}
</div>
);
};
export default ClientComponent;
Add this component to a page. e.g. if you are using Next.js, import and render this component in your /app/page.tsx
file.
If you have configured your .env correctly you should now be able to see the get request for the blogContent
query at http://localhost:3000/.
Server Component Example
Create a file at /components/server-component-example.tsx
:
import {
getContentEndpoints,
getPersonsEndpoints,
} from "@quarkino/services/server";
// All of the server side requests are available through "@quarkino/services/server"
// The naming convention is get[endpoint namespace]Endpoints e.g. getContentEndpoints for the Content namespace (https://docs.quarkino.com/docs/features/content)
// And the getPersonsEndpoints for the Person (https://docs.quarkino.com/docs/features/person) endpoint namespace
/**
*
* @returns A React server component
*/
const ServerComponent = async () => {
/*
GET request example
This call returns an object structured like this
{
data --> An object representing the result of the query that's fully typed. This will be undefined if the query has encountered an error.
error --> An object representing the encountered error of the query that's fully typed. This will be undefined if the query has been successful.
}
The results and the error object are fully typed with the expected results from the Quarkinos API
*/
const blogContent = await getContentEndpoints.post.get.contentPostSingle
// The filters that we want applied on the returning data
// The filter function receives an object of known keys that the server expects and can process.
// This object is fully type safe and you can see all of the available keys through your code editors code suggestion
.filter({
type: "blog", // content of type blog - this is a content type that you have defined in your Quarkino panel.
hashid: "Wylzp", // example hashID - change it to a correct ID from your own panel.
locale: "en", // a param to get localised content if it's enabled and defined from the CMS panel e.g. en, fa, ar
})
// The keys we want to be returned from the API
// These keys are also fully type safe and accessible through your code editors code suggestion with what's available from the Quarkinos API.
.include("title", "title2")
// This function executes the query call and can receive an optional object of type queryOptions
/*
{
revalidate: 30, --> The revalidate key of Next.js that's available on the fetch request. receives a number in seconds
tags: ["cache-key"], --> the tags key of Next.js that's available on the fetch request --> receives an array of strings
useToken: true --> by setting this true you can include your bearer token in a server side request
}
*/
.request({
queryKey: ["test-list"],
});
/**
* Server action fot mutating data (POST request)
*/
const editProfileReq = async () => {
"use server";
/*
This call returns an object structured like this
POST request example
{
data --> An object representing the result of the query that's fully typed. This will be undefined if the query has encountered an error.
error --> An object representing the encountered error of the query that's fully typed. This will be undefined if the query has been successful.
}
The results and the error object are fully typed with the expected results from the Quarkinos API
*/
const profileEditRes =
await getPersonsEndpoints.profileEdit.post.save.request({
data: {
birth_at: 1144913752000,
email: "[email protected]",
mobile: "09100000000",
name_first: "First Name",
name_last: "Last Name",
},
useToken: true, // includes the bearer token in the request header
});
console.log("profileEdit res: ", JSON.stringify(profileEditRes));
};
return (
<div>
<h1>Server Component</h1>
<form action={editProfileReq}>
<button type="submit">Edit profile</button>
</form>
{blogContent?.data ? (
<p>{JSON.stringify(res.data.results)}</p>
) : (
<p>{JSON.stringify(res.error)}</p>
)}
</div>
);
};
export default ServerComponent;
Add this component to a page. e.g. if you are using Next.js, import and render this component in your /app/page.tsx
file.
If you have configured your .env correctly you should now be able to see the get request for the blogContent
query at http://localhost:3000/ in your terminal.
General SDK function call structure
In both the server and client side functions we have the following structure
const blogContent =
useContentEndpoints // Endpoint namespace group entry point
.post // Name group inside of an endpoint namespace e.g. post (post-list post-single), faq, type, etc
.get // The http verb (get, post, delete, patch, put)
.contentPostSingle // The endpoint name
.filter() // adds a filter to the query for the server to process
.include() // selects the keys that we want in the response
.useRequest(); // last method call that executes the query