UNPKG

knack-api

Version:
436 lines (402 loc) 13.5 kB
const { verifyUserToken } = require("./helpers/verifyUserToken"); const { showCustomModal } = require("./helpers/showCustomModal"); interface rules { field: string; operator: | "is" | "is not" | "is blank" | "is not blank" | "contains" | "does not contain" | "starts with" | "ends with" | "is any" | "is during the current" | "is during the previous" | "is during the next" | "is before the previous" | "is after the next" | "is before" | "is after" | "is today" | "is today or before" | "is today or after" | "is before today" | "is after today" | "is before current time" | "is after current time" | "higher than" | "lower than" | "near"; value?: string; range?: number; type?: string; } interface filters { match: "and" | "or"; rules: rules[]; } interface sort { field: string; order: "asc" | "desc"; } type contextProp = `${string}_id`; interface getSettings { sceneKey: string; viewKey: string; recordId?: string; filters?: filters; sort?: sort[] | sort; retry?: boolean; page?: number; recordLimit?: number; rowsPerPage?: number; cb?: (data: any) => any; isPublic?: boolean; context?: Record<contextProp, string>; // page-slug-of-where-the-view-and-scene-is_id=idofrecord } interface putSettings { sceneKey: string; viewKey: string; recordId: string; payload: any; retry: boolean; isPublic?: boolean; } interface postSettings { sceneKey: string; viewKey: string; payload: any; retry: boolean; isPublic?: boolean; } interface deleteSettings { sceneKey: string; viewKey: string; recordId: string; retry: boolean; } declare let knack_api: any; declare const Knack: any; module.exports.knack_api = { get: function ( settings: getSettings, ajaxAttemptsRemaining?: number, combinedRecords?: any ) { const { sceneKey, viewKey, recordId, filters, sort, retry, cb, isPublic, context } = settings; // if Knack user session has expired we want to show a warning and return without making a network req if (!isPublic && !verifyUserToken()) { showCustomModal( "Session Expired", "Your session has expired. To prevent network errors and ensure proper functionality, please log out and then log back in." ); return Promise.reject("User token is invalid."); } this.data = { records: new Promise((resolve, reject) => { let rowsPerPage = settings.rowsPerPage; let recordLimit = settings.recordLimit; //handle retry upon failure if (!retry) ajaxAttemptsRemaining = 3; if (!combinedRecords) combinedRecords = {}; if (!settings.page) settings.page = 1; if (!rowsPerPage || rowsPerPage > 1000) rowsPerPage = 1000; let reqUrl = `https://api.knack.com/v1/pages/${sceneKey}/views/${viewKey}/records/`; if (recordId) { reqUrl += `${recordId}`; } if (filters) { reqUrl += `?filters=${encodeURIComponent(JSON.stringify(filters))}`; } if (sort) { if (Array.isArray(sort)) { sort.forEach((value: sort) => { const field = value.field; const order = value.order; reqUrl.indexOf("?") == -1 ? (reqUrl += `?sort_field=${field}&sort_order=${order}`) : (reqUrl += `&sort_field=${field}&sort_order=${order}`); }); } else { reqUrl.indexOf("?") == -1 ? (reqUrl += `?sort_field=${sort.field}&sort_order=${sort.order}`) : (reqUrl += `&sort_field=${sort.field}&sort_order=${sort.order}`); } } if (context) { const [key, value] = Object.entries(context)[0]; if (key && value) { reqUrl.indexOf("?") == -1 ? (reqUrl += `?${key}=${value}`) : (reqUrl += `&${key}=${value}`); } } reqUrl.indexOf("?") == -1 ? (reqUrl += `?page=${settings.page}&rows_per_page=${rowsPerPage}`) : (reqUrl += `&page=${settings.page}&rows_per_page=${rowsPerPage}`); console.log("Request URL: ", reqUrl); Knack.$.ajax({ url: reqUrl, type: "GET", dataType: "json", headers: { "X-Knack-Application-Id": Knack.application_id, "X-Knack-REST-API-KEY": "knack", Authorization: Knack.getUserToken(), "content-type": "application/json", }, success: function (data: any) { cb && cb(data); if ( data && data.records && data.records.length > 0 && data.total_pages > 0 ) { if ((settings.page || 1) < data.total_pages) { combinedRecords.records ? combinedRecords.records.push(...data.records) : (combinedRecords = data); settings.page && settings.page++; if (recordLimit) { if (combinedRecords.records.length >= recordLimit) { if (combinedRecords.records.length > recordLimit) combinedRecords.records = combinedRecords.records.slice( 0, recordLimit ); resolve(combinedRecords); } else { resolve( module.exports.knack_api.get( settings, ajaxAttemptsRemaining, combinedRecords ) ); } } else { resolve( module.exports.knack_api.get( settings, ajaxAttemptsRemaining, combinedRecords ) ); } } else { combinedRecords.records ? combinedRecords.records.push(...data.records) : (combinedRecords = data); if (recordLimit && combinedRecords.records.length > recordLimit) combinedRecords.records = combinedRecords.records.slice( 0, recordLimit ); resolve(combinedRecords); } } else { resolve(data); } }, error: function (err: any) { if (ajaxAttemptsRemaining) { ajaxAttemptsRemaining--; settings.retry = true; console.log(`Ajax get error: ${err}`); console.log(`Attempts remaining: ${ajaxAttemptsRemaining}`); resolve( module.exports.knack_api.get( settings, ajaxAttemptsRemaining, combinedRecords ) ); } else { reject(err); } }, }); }) .then((result) => { this.data.result = result; return this.data.result; }) .catch((reason) => { console.log(`Failure reason: ${reason}`); }), }; this.data.records.include = async (filterParam) => { await this.data.records; this.data.result.records.forEach((record) => { for (let prop in record) { if (filterParam.indexOf(prop) == -1) { delete record[prop]; } } }); return this.data.result; }; this.data.records.exclude = async (filterParam) => { await this.data.records; this.data.result.records.forEach((record) => { for (let prop in record) { if (filterParam.indexOf(prop) != -1) { delete record[prop]; } } }); return this.data.result; }; return this.data.records; }, put: (settings: putSettings, ajaxAttemptsRemaining?: number) => { const { sceneKey, viewKey, recordId, payload, retry, isPublic } = settings; // if Knack user session has expired we want to show a warning and return without making a network req if (!isPublic && !verifyUserToken()) { showCustomModal( "Session Expired", "Your session has expired. To prevent network errors and ensure proper functionality, please log out and then log back in." ); return Promise.reject("User token is invalid."); } return new Promise((resolve, reject) => { //handle retry upon failure if (!retry) ajaxAttemptsRemaining = 3; let reqUrl = `https://api.knack.com/v1/pages/${sceneKey}/views/${viewKey}/records/`; if (recordId) { reqUrl += `${recordId}`; } console.log("Request URL: ", reqUrl); Knack.$.ajax({ url: reqUrl, type: "PUT", dataType: "json", headers: { "X-Knack-Application-Id": Knack.application_id, "X-Knack-REST-API-KEY": "knack", Authorization: Knack.getUserToken(), "content-type": "application/json", }, data: JSON.stringify(payload), success: function (data: any) { resolve(data); }, error: function (err: any) { if (ajaxAttemptsRemaining) { ajaxAttemptsRemaining--; settings.retry = true; console.log(`Ajax put error: ${err}`); console.log(`Attempts remaining: ${ajaxAttemptsRemaining}`); resolve( module.exports.knack_api.put(settings, ajaxAttemptsRemaining) ); } else { reject(err); } }, }); }).catch((reason) => { console.log(`Failure reason: ${reason}`); }); }, post: (settings: postSettings, ajaxAttemptsRemaining?: number) => { const { sceneKey, viewKey, payload, retry, isPublic } = settings; // if Knack user session has expired we want to show a warning and return without making a network req if (!isPublic && !verifyUserToken()) { showCustomModal( "Session Expired", "Your session has expired. To prevent network errors and ensure proper functionality, please log out and then log back in." ); return Promise.reject("User token is invalid."); } return new Promise((resolve, reject) => { //handle retry upon failure if (!retry) ajaxAttemptsRemaining = 3; let reqUrl = `https://api.knack.com/v1/pages/${sceneKey}/views/${viewKey}/records/`; console.log("Request URL: ", reqUrl); Knack.$.ajax({ url: reqUrl, type: "POST", dataType: "json", headers: { "X-Knack-Application-Id": Knack.application_id, "X-Knack-REST-API-KEY": "knack", Authorization: Knack.getUserToken(), "content-type": "application/json", }, data: JSON.stringify(payload), success: function (data: any) { resolve(data); }, error: function (err: any) { if (ajaxAttemptsRemaining) { ajaxAttemptsRemaining--; settings.retry = true; console.log(`Ajax post error: ${err}`); console.log(`Attempts remaining: ${ajaxAttemptsRemaining}`); resolve( module.exports.knack_api.post(settings, ajaxAttemptsRemaining) ); } else { reject(err); } }, }); }).catch((reason) => { console.log(`Failure reason: ${reason}`); }); }, deletion: (settings: deleteSettings, ajaxAttemptsRemaining?: number) => { // if Knack user session has expired we want to show a warning and return without making a network req if (!verifyUserToken()) { showCustomModal( "Session Expired", "Your session has expired. To prevent network errors and ensure proper functionality, please log out and then log back in." ); return Promise.reject("User token is invalid."); } return new Promise((resolve, reject) => { const { sceneKey, viewKey, recordId, retry } = settings; //handle retry upon failure if (!retry) ajaxAttemptsRemaining = 3; let reqUrl = `https://api.knack.com/v1/pages/${sceneKey}/views/${viewKey}/records/`; if (recordId) { reqUrl += `${recordId}`; } console.log("Request URL: ", reqUrl); Knack.$.ajax({ url: reqUrl, type: "DELETE", dataType: "json", headers: { "X-Knack-Application-Id": Knack.application_id, "X-Knack-REST-API-KEY": "knack", Authorization: Knack.getUserToken(), "content-type": "application/json", }, success: function (data: any) { resolve(data); }, error: function (err: any) { if (ajaxAttemptsRemaining) { ajaxAttemptsRemaining--; settings.retry = true; console.log(`Ajax delete error: ${err}`); console.log(`Attempts remaining: ${ajaxAttemptsRemaining}`); resolve( module.exports.knack_api.deletion(settings, ajaxAttemptsRemaining) ); } else { reject(err); } }, }); }).catch((reason) => { console.log(`Failure reason: ${reason}`); }); }, };