knack-object-api
Version:
Object based api calls in Knack
178 lines (155 loc) • 5 kB
text/typescript
import { State } from "../types";
import { sortMultiple } from "../helpers";
const defaultState: State = {
objectKey: "",
recordId: "",
wait: 0,
attempts: 3,
page: 1,
rowsPerPage: 1000,
additions: [],
failed: false,
records: [],
combined: {},
};
const requestFactory = () => {
let state: { [key: string]: State } = {};
const initialize = (requestId: string) => {
state[requestId] = { ...defaultState };
return state[requestId];
};
// objectKey
const setObjectKey = (requestId: string, objectKey: string) =>
(state[requestId].objectKey = objectKey);
// recordId
const setRecordId = (requestId: string, recordId: string) =>
(state[requestId].recordId = `/${recordId}`);
// wait
const setWaitTime = (requestId: string, wait: number) =>
(state[requestId].wait = wait);
const getWaitTime = (requestId: string) => state[requestId].wait;
const incrementWaitTime = (requestId: string) => {
state[requestId].wait = state[requestId].wait + 2000;
return state[requestId].wait;
};
// attempts
const getAttempts = (requestId: string) => state[requestId].attempts;
const decrementAttempts = (requestId: string) =>
(state[requestId].attempts = state[requestId].attempts - 1);
const setAttempts = (requestId: string, attempts: number) =>
(state[requestId].attempts = attempts);
// page
const incrementPage = (requestId: string) => {
state[requestId].page = state[requestId].page + 1;
return state[requestId].page;
};
// rowsPerPage
const setRowsPerPage = (requestId: string, rows: number) => {
state[requestId].rowsPerPage = rows;
return state[requestId].rowsPerPage;
};
// additions
const resetAdditions = (requestId: string) =>
(state[requestId].additions = []);
const addAddition = (requestId: string, addition: string) => {
if (state[requestId].additions.indexOf(addition) === -1)
state[requestId].additions = [...state[requestId].additions, addition];
};
// failed
const setFailed = (requestId: string, failed: boolean) =>
(state[requestId].failed = failed);
// utils
const getUrl = (requestId: string, host?: string) => {
const { objectKey, recordId, additions } = state[requestId];
const knackHost: string = host || "knack";
const rootUrl = `https://api.${knackHost}.com/v1/objects/${objectKey}/records${recordId}`;
if (additions.length) {
const requestUrl = `${rootUrl}?${additions.join("&")}`;
return requestUrl;
}
return rootUrl;
};
const combineRecords = (requestId: string, settings: any, response: any) => {
let records = [...state[requestId].records];
let combined = { ...state[requestId].combined };
if (!response.records) {
if (response.id) {
records = [...records, response];
combined = {
...combined,
records,
};
const recordResponse = combined;
remove(requestId);
return recordResponse;
}
combined = { ...response };
const recordResponse = combined;
remove(requestId);
return recordResponse;
}
// initially set combined obj to response so it will have current_page, total_pages, etc.
if (!Object.keys(combined).length) combined = response;
// combine request records with existing records from previous calls
records = [...records, ...response.records];
// set combined response obj records to all records
combined = {
...combined,
records,
};
// check if we have a limit on the settings and if the records is over that limit
const hasLimit = !!settings.recordLimit;
const overLimit = !hasLimit
? false
: combined.records.length >= settings.recordLimit
? true
: false;
// call again if we havent reached total pages
if (response.current_page < response.total_pages && !overLimit) {
settings.page = incrementPage(requestId);
resetAdditions(requestId);
state[requestId].combined = combined;
state[requestId].records = records;
return {
retry: true,
settings,
};
}
if (settings.sort && Array.isArray(settings.sort)) {
combined = {
...combined,
records: sortMultiple(settings.sort, combined.records),
};
}
const recordResponse = combined;
remove(requestId);
return recordResponse;
};
const getState = (requestId: string) => state[requestId];
const remove = (requestId: string) => {
const { [requestId]: removeState, ...remainingState } = state;
state = remainingState;
};
return {
initialize,
setObjectKey,
setRecordId,
setWaitTime,
decrementAttempts,
setAttempts,
incrementPage,
setRowsPerPage,
addAddition,
resetAdditions,
setFailed,
incrementWaitTime,
combineRecords,
getWaitTime,
getAttempts,
getUrl,
getState,
remove,
};
};
const factory = requestFactory();
export default factory;