diff --git a/api/endpoints/attributes.js b/api/endpoints/attributes.js index c7b4815..b2c60b4 100644 --- a/api/endpoints/attributes.js +++ b/api/endpoints/attributes.js @@ -2,3 +2,93 @@ import config from "../utils/config.js"; //Optimizely Rest API V2 //https://library.optimizely.com/docs/api/app/v2/index.html + +const section = "attributes"; + +const attributes_api = { + attributes: { + list: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to list attributes."); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}?project_id=${options?.projectId ? options.projectId : 0}&page=${options?.linkPageIndex ? options.linkPageIndex : 1}&per_page=${options?.perPage ? options.perPage : 100}`, + params: {}, + body: null, + }; + }, + create: (options = {}) => { + if (!options.body) { + throw new Error("A JSON payload representing the new attribute that should be created is required."); + } + + if (!options.body.project_id) { + throw new Error("project_id is required in the JSON payload."); + } + + if (!options.body.key) { + throw new Error("key is required in the JSON payload."); + } + + return { + method: "POST", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}`, + params: {}, + body: { + ...options.body, + }, + }; + }, + delete: (options = {}) => { + if (!options.attributeId) { + throw new Error("An attribute ID is required to delete an attribute."); + } + + return { + method: "DEL", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.attributeId ? options.attributeId : 0}`, + params: {}, + body: null, + }; + }, + read: (options = {}) => { + if (!options.attributeId) { + throw new Error("An attribute ID is required to read an attribute."); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.attributeId ? options.attributeId : 0}`, + params: {}, + body: null, + }; + }, + update: (options = {}) => { + if (!options.attributeId) { + throw new Error("An attribute ID is required to read an attribute."); + } + + if (!options.body) { + throw new Error("A JSON payload representing the properties to update an attribute is required."); + } + + return { + method: "PATCH", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.attributeId ? options.attributeId : 0}`, + params: {}, + body: { + ...options.body, + }, + }; + }, + }, +}; + +export default attributes_api; diff --git a/api/endpoints/audiences.js b/api/endpoints/audiences.js index 8e90a17..5c52953 100644 --- a/api/endpoints/audiences.js +++ b/api/endpoints/audiences.js @@ -3,6 +3,7 @@ import config from "../utils/config.js"; //Optimizely Rest API V2 //https://library.optimizely.com/docs/api/app/v2/index.html +const section = "audiences"; const audiences_api = { audiences: { @@ -10,25 +11,28 @@ const audiences_api = { if (!options.projectId) { throw new Error("A project ID is required to list all audiences."); } + return { method: "GET", // prettier-ignore - resource: `${config.apiURL_V2}/audiences?project_id=${options?.projectId ? options.projectId : 0}&page=${options?.linkPageIndex ? options.linkPageIndex : 1}&per_page=100`, + resource: `${config.apiURL_V2}/${section}?project_id=${options?.projectId ? options.projectId : 0}&page=${options?.linkPageIndex ? options.linkPageIndex : 1}&per_page=${options?.perPage ? options.perPage : 100}`, params: {}, body: null, }; }, create: (options = {}) => { if (!options.body) { - throw new Error( - "A JSON payload representing the new audience that should be created is required." - ); + throw new Error("A JSON payload representing the new audience that should be created is required."); + } + + if (!options.body.project_id) { + throw new Error("A project_id in the JSON payload is required."); } return { method: "POST", // prettier-ignore - resource: `${config.apiURL_V2}/audiences"}`, + resource: `${config.apiURL_V2}/${section}`, params: {}, body: { ...options.body, @@ -43,7 +47,7 @@ const audiences_api = { return { method: "GET", // prettier-ignore - resource: `${config.apiURL_V2}/audiences/${options?.audienceId ? options.audienceId : 0}`, + resource: `${config.apiURL_V2}/${section}/${options?.audienceId ? options.audienceId : 0}`, params: {}, body: null, }; @@ -54,15 +58,13 @@ const audiences_api = { } if (!options.body) { - throw new Error( - "A JSON payload representing the properties to update the audience is required." - ); + throw new Error("A JSON payload representing the properties to update the audience is required."); } return { method: "PATCH", // prettier-ignore - resource: `${config.apiURL_V2}/audiences/${options?.audienceId ? options.audienceId : 0}`, + resource: `${config.apiURL_V2}/${section}/${options?.audienceId ? options.audienceId : 0}`, params: {}, body: { ...options.body, diff --git a/api/endpoints/campaigns.js b/api/endpoints/campaigns.js index c7b4815..99de918 100644 --- a/api/endpoints/campaigns.js +++ b/api/endpoints/campaigns.js @@ -2,3 +2,89 @@ import config from "../utils/config.js"; //Optimizely Rest API V2 //https://library.optimizely.com/docs/api/app/v2/index.html + +const section = "campaigns"; + +const campaigns_api = { + campaigns: { + list: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to list campaigns."); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}?project_id=${options?.projectId ? options.projectId : 0}&page=${options?.linkPageIndex ? options.linkPageIndex : 1}&per_page=${options?.perPage ? options.perPage : 100}`, + params: {}, + body: null, + }; + }, + create: (options = {}) => { + if (!options.body) { + throw new Error("A JSON payload representing the new campaign that should be created is required."); + } + + if (!options.body.project_id) { + throw new Error("project_id is required in the JSON payload."); + } + + return { + method: "POST", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}?action=${options?.action ? options.action : "pause"}`, + params: {}, + body: { + ...options.body, + }, + }; + }, + delete: (options = {}) => { + if (!options.campaignId) { + throw new Error("A campaign ID is required to delete a campaign."); + } + + return { + method: "DEL", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.campaignId ? options.campaignId : 0}`, + params: {}, + body: null, + }; + }, + read: (options = {}) => { + if (!options.campaignId) { + throw new Error("An campaign ID is required to read a campaign."); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.campaignId ? options.campaignId : 0}`, + params: {}, + body: null, + }; + }, + update: (options = {}) => { + if (!options.campaignId) { + throw new Error("An campaign ID is required to update a campaign."); + } + + if (!options.body) { + throw new Error("A JSON payload representing the properties to update a campaign is required."); + } + + return { + method: "PATCH", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.attributeId ? options.attributeId : 0}&action=${options?.action ? options.action : "pause"}`, + params: {}, + body: { + ...options.body, + }, + }; + }, + }, +}; + +export default campaigns_api; \ No newline at end of file diff --git a/api/endpoints/change-history.js b/api/endpoints/change-history.js index c7b4815..08a63ec 100644 --- a/api/endpoints/change-history.js +++ b/api/endpoints/change-history.js @@ -2,3 +2,25 @@ import config from "../utils/config.js"; //Optimizely Rest API V2 //https://library.optimizely.com/docs/api/app/v2/index.html + +const section = "changes"; + +const changes_api = { + changes: { + list: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to list all changes."); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}?project_id=${options?.projectId ? options.projectId : 0}${options?.id ? '&id=' + options.id : ''}${options?.startTime ? '&start_time=' + options.startTime : ''}${options?.endTime ? '&end_time=' + options.endTime : ''}${options?.user ? '&user=' + options.user : ''}${options?.entityType ? '&entity_type=' + options.entityType : ''}${options?.entity ? '&entity=' + options.entity : ''}&page=${options?.linkPageIndex ? options.linkPageIndex : 1}&per_page=${options?.perPage ? options.perPage : 100}`, + params: {}, + body: null, + }; + }, + }, +}; + +export default changes_api; \ No newline at end of file diff --git a/api/endpoints/environments.js b/api/endpoints/environments.js index c7b4815..84950b6 100644 --- a/api/endpoints/environments.js +++ b/api/endpoints/environments.js @@ -2,3 +2,126 @@ import config from "../utils/config.js"; //Optimizely Rest API V2 //https://library.optimizely.com/docs/api/app/v2/index.html + +const section = "environments"; + +const environments_api = { + environments: { + list: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to list environments."); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}?project_id=${options?.projectId ? options.projectId : 0}&page=${options?.linkPageIndex ? options.linkPageIndex : 1}&per_page=${options?.perPage ? options.perPage : 100}`, + params: {}, + body: null, + }; + }, + create: (options = {}) => { + if (!options.body) { + throw new Error("A JSON payload representing the new environment that should be created is required."); + } + + if (!options.body.projectId) { + throw new Error("A project ID is required in the JSON payload."); + } + + if (!options.body.key) { + throw new Error("An key is required in the JSON payload."); + } + + if (!options.body.name) { + throw new Error("An name is required in the JSON payload."); + } + + return { + method: "POST", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}`, + params: {}, + body: { + ...options.body, + }, + }; + }, + delete: (options = {}) => { + if (!options.environmentId) { + throw new Error("An environment ID is required to delete an environment."); + } + + return { + method: "DEL", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.environmentId ? options.environmentId : 0}`, + params: {}, + body: null, + }; + }, + read: (options = {}) => { + if (!options.environmentId) { + throw new Error("An environment ID is required to read an environment."); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.environmentId ? options.environmentId : 0}`, + params: {}, + body: null, + }; + }, + update: (options = {}) => { + if (!options.body) { + throw new Error("A JSON payload representing the environment that should be updated is required."); + } + + if (!options.environmentId) { + throw new Error("An environment ID is required to update an environment."); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.environmentId ? options.environmentId : 0}`, + params: {}, + body: null, + }; + }, + listFlags: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to pull a list of flag environments"); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_FlagsV1}/projects/${options.projectId}/${section}`, + params: {}, + body: null, + }; + }, + patchFlags: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to create/update a flag environment"); + } + + if (!options.body) { + throw new Error("A JSON payload representing the environment that should be created/updated is required."); + } + + return { + method: "PATCH", + // prettier-ignore + resource: `${config.apiURL_FlagsV1}/projects/${options.projectId}/${section}`, + params: {}, + body: null, + }; + } + }, + +}; + +export default environments_api; diff --git a/api/endpoints/events.js b/api/endpoints/events.js index c7b4815..5862da0 100644 --- a/api/endpoints/events.js +++ b/api/endpoints/events.js @@ -2,3 +2,163 @@ import config from "../utils/config.js"; //Optimizely Rest API V2 //https://library.optimizely.com/docs/api/app/v2/index.html + +const section = "events"; + +const events_api = { + events: { + list: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to list all events."); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}?project_id=${options?.projectId ? options.projectId : 0}${options?.includeClassic ? 'include_classic=' + options.includeClassic : ''}&page=${options?.linkPageIndex ? options.linkPageIndex : 1}&per_page=${options?.perPage ? options.perPage : 100}`, + params: {}, + body: null, + }; + }, + read: (options = {}) => { + if (!options.eventId) { + throw new Error("An event ID is required to read an event."); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}?event_id=${options?.projectId ? options.projectId : 0}${options?.includeClassic ? 'include_classic=' + options.includeClassic : ''}`, + params: {}, + body: null, + }; + }, + createCustom: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to create a custom event."); + } + + if (!options.body) { + throw new Error("A JSON payload representing the custom event to create is required."); + } + + if (!options.body.key) { + throw new Error("key is required in the JSON payload."); + } + + return { + method: "POST", + // prettier-ignore + resource: `${config.apiURL_V2}/projects/?project_id=${options?.projectId ? options.projectId : 0}/custom_events`, + params: {}, + body: { + ...options.body, + }, + }; + }, + deleteCustom: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to delete a custom event."); + } + if (!options.eventId) { + throw new Error("An event ID is required to delete a custom event."); + } + + return { + method: "DEL", + // prettier-ignore + resource: `${config.apiURL_V2}/projects/${options.projectId}/custom_events/${options.eventId}`, + params: {}, + body: null, + }; + }, + updateCustom: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to update a custom event."); + } + + if (!options.eventId) { + throw new Error("An event ID is required to update a custom event.") + } + + return { + method: "PATCH", + // prettier-ignore + resource: `${config.apiURL_V2}/projects/${options.projectId}/custom_events/${options.eventId}`, + params: {}, + body: { + ...options.body, + }, + }; + }, + createInPage: (options = {}) => { + if (!options.pageId) { + throw new Error("A page ID is required to create an in page event."); + } + + if (!options.body) { + throw new Error("A JSON payload representing the in page event to create is required."); + } + + if (!options.body.event_type) { + throw new Error("event_type is required in the JSON payload."); + } + + if (!options.body.name) { + throw new Error("name is required in the JSON payload."); + } + + return { + method: "POST", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}?page_id=${options?.pageId ? options.pageId : 0}/events`, + params: {}, + body: { + ...options.body, + }, + }; + }, + deleteInPage: (options = {}) => { + if (!options.pageId) { + throw new Error("A page ID is required to delete an In-page event."); + } + + if (!options.eventId) { + throw new Error("An event ID is required to delete an In-page event."); + } + + return { + method: "DEL", + // prettier-ignore + resource: `${config.apiURL_V2}/pages/${options.pageId}/${section}/${options.eventId}`, + params: {}, + body: null, + }; + }, + updateInPage: (options = {}) => { + if (!options.pageId) { + throw new Error("A page ID is required to update an In-page event."); + } + + if (!options.eventId) { + throw new Error("An event ID is required to update an In-page event."); + } + + if (!options.body) { + throw new Error("A body in JSON format the requested update is required to update an In-page event."); + } + + return { + method: "PATCH", + // prettier-ignore + resource: `${config.apiURL_V2}/pages/${options.pageId}/${section}/${options.eventId}`, + params: {}, + body: { + ...options.body, + }, + }; + } + } +}; + +export default events_api; diff --git a/api/endpoints/experiments.js b/api/endpoints/experiments.js index 3162d2f..86c688b 100644 --- a/api/endpoints/experiments.js +++ b/api/endpoints/experiments.js @@ -3,6 +3,8 @@ import config from "../utils/config.js"; //Optimizely Rest API V2 //https://library.optimizely.com/docs/api/app/v2/index.html +const section = "experiments"; + const experiments_api = { experiments: { list: (options = {}) => { @@ -12,22 +14,24 @@ const experiments_api = { return { method: "GET", // prettier-ignore - resource: `${config.apiURL_V2}/experiments?project_id=${options?.projectId ? options.projectId : 0}&page=${options?.linkPageIndex ? options.linkPageIndex : 1}&per_page=100`, + resource: `${config.apiURL_V2}/${section}?project_id=${options?.projectId ? options.projectId : 0}&page=${options?.linkPageIndex ? options.linkPageIndex : 1}&per_page=${options?.perPage ? options.perPage : 100}`, params: {}, body: null, }; }, create: (options = {}) => { if (!options.body) { - throw new Error( - "A JSON payload representing the new experiment that should be created is required." - ); + throw new Error("A JSON payload representing the new experiment that should be created is required."); + } + + if (!options.body.projectId) { + throw new Error("A project ID is required to create a enw experiment."); } return { method: "POST", // prettier-ignore - resource: `${config.apiURL_V2}/experiments?action=${options?.action ? options.action : "pause"}`, + resource: `${config.apiURL_V2}/${section}?action=${options?.action ? options.action : "pause"}`, params: {}, body: { ...options.body, @@ -36,15 +40,13 @@ const experiments_api = { }, delete: (options = {}) => { if (!options.experimentId) { - throw new Error( - "An experiment ID is required to delete an experiment." - ); + throw new Error("An experiment ID is required to delete an experiment."); } return { method: "DEL", // prettier-ignore - resource: `${config.apiURL_V2}/experiments/${options?.experimentId ? options.experimentId : 0}`, + resource: `${config.apiURL_V2}/${section}/${options?.experimentId ? options.experimentId : 0}`, params: {}, body: null, }; @@ -57,7 +59,7 @@ const experiments_api = { return { method: "GET", // prettier-ignore - resource: `${config.apiURL_V2}/experiments/${options?.experimentId ? options.experimentId : 0}`, + resource: `${config.apiURL_V2}/${section}/${options?.experimentId ? options.experimentId : 0}`, params: {}, body: null, }; @@ -68,15 +70,13 @@ const experiments_api = { } if (!options.body) { - throw new Error( - "A JSON payload representing the properties to update an experiment is required." - ); + throw new Error("A JSON payload representing the properties to update an experiment is required."); } return { method: "PATCH", // prettier-ignore - resource: `${config.apiURL_V2}/experiments/${options?.experimentId ? options.experimentId : 0}`, + resource: `${config.apiURL_V2}/${section}/${options?.experimentId ? options.experimentId : 0}`, params: {}, body: { ...options.body, @@ -85,45 +85,39 @@ const experiments_api = { }, results: (options = {}) => { if (!options.experimentId) { - throw new Error( - "An experiment ID is required to get the results for an experiment." - ); + throw new Error("An experiment ID is required to get the results for an experiment."); } return { method: "GET", // prettier-ignore - resource: `${config.apiURL_V2}/experiments/${options?.experimentId ? options.experimentId : 0}/results`, + resource: `${config.apiURL_V2}/${section}/${options?.experimentId ? options.experimentId : 0}/results`, params: {}, body: null, }; }, resultsTimeSeries: (options = {}) => { if (!options.experimentId) { - throw new Error( - "An experiment ID is required to get the results time series for an experiment." - ); + throw new Error("An experiment ID is required to get the results time series for an experiment."); } return { method: "GET", // prettier-ignore - resource: `${config.apiURL_V2}/experiments/${options?.experimentId ? options.experimentId : 0}/timeseries`, + resource: `${config.apiURL_V2}/${section}/${options?.experimentId ? options.experimentId : 0}/timeseries`, params: {}, body: null, }; }, resultsCSV: (options = {}) => { if (!options.experimentId) { - throw new Error( - "An experiment ID is required to get the results as a CSV file for an experiment." - ); + throw new Error("An experiment ID is required to get the results as a CSV file for an experiment."); } return { method: "GET", // prettier-ignore - resource: `${config.apiURL_V2}/experiments/${options?.experimentId ? options.experimentId : 0}/results/csv`, + resource: `${config.apiURL_V2}/${section}/${options?.experimentId ? options.experimentId : 0}/results/csv`, params: {}, body: null, }; diff --git a/api/endpoints/export-credentials.js b/api/endpoints/export-credentials.js index c7b4815..97d4d68 100644 --- a/api/endpoints/export-credentials.js +++ b/api/endpoints/export-credentials.js @@ -2,3 +2,23 @@ import config from "../utils/config.js"; //Optimizely Rest API V2 //https://library.optimizely.com/docs/api/app/v2/index.html + +const section = "credentials"; + +const credentials_api = { + credentials: { + + exportCredentials: (options = {}) => { + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/export/credentials?duration="1h"`, + params: {}, + body: null, + }; + } + } +}; + +export default credentials_api; diff --git a/api/endpoints/extensions.js b/api/endpoints/extensions.js index c7b4815..67fb476 100644 --- a/api/endpoints/extensions.js +++ b/api/endpoints/extensions.js @@ -2,3 +2,101 @@ import config from "../utils/config.js"; //Optimizely Rest API V2 //https://library.optimizely.com/docs/api/app/v2/index.html + +const section = "extensions"; + +const extensions_api = { + extensions: { + list: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to list extensions."); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}?project_id=${options?.projectId ? options.projectId : 0}&page=${options?.linkPageIndex ? options.linkPageIndex : 1}&per_page=${options?.perPage ? options.perPage : 100}`, + params: {}, + body: null, + }; + }, + create: (options = {}) => { + if (!options.body) { + throw new Error("A JSON payload representing the new extension that should be created is required."); + } + + if (!options.body.project_id) { + throw new Error("project_id is required in the JSON payload."); + } + + if (!options.body.name) { + throw new Error("name is required in the JSON payload."); + } + + if (!options.body.implementation) { + throw new Error("implementation is required in the JSON payload."); + } + + if (!options.body.edit_url) { + throw new Error("edit_url is required in the JSON payload."); + } + + return { + method: "POST", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}`, + params: {}, + body: { + ...options.body, + }, + }; + }, + delete: (options = {}) => { + if (!options.extensionId) { + throw new Error("An extension ID is required to delete an extension."); + } + + return { + method: "DEL", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.extensionId ? options.extensionId : 0}`, + params: {}, + body: null, + }; + }, + read: (options = {}) => { + if (!options.extensionId) { + throw new Error("An extension ID is required to read an extension."); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.extensionId ? options.extensionId : 0}`, + params: {}, + body: null, + }; + }, + update: (options = {}) => { + if (!options.extensionId) { + throw new Error("An extension ID is required to update an extension."); + } + + if (!options.body) { + throw new Error("A JSON payload representing the properties to update an extension is required."); + } + + return { + method: "PATCH", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.extensionId ? options.extensionId : 0}`, + params: {}, + body: { + ...options.body, + }, + }; + }, + }, +}; + +export default extensions_api; diff --git a/api/endpoints/features.js b/api/endpoints/features.js index c7b4815..1b8f562 100644 --- a/api/endpoints/features.js +++ b/api/endpoints/features.js @@ -2,3 +2,93 @@ import config from "../utils/config.js"; //Optimizely Rest API V2 //https://library.optimizely.com/docs/api/app/v2/index.html + +const section = "features"; + +const features_api = { + features: { + list: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to list features."); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}?project_id=${options?.projectId ? options.projectId : 0}&page=${options?.linkPageIndex ? options.linkPageIndex : 1}&per_page=${options?.perPage ? options.perPage : 100}`, + params: {}, + body: null, + }; + }, + create: (options = {}) => { + if (!options.body) { + throw new Error("A JSON payload representing the new feature that should be created is required."); + } + + if (!options.body.project_id) { + throw new Error("project_id is required in the JSON payload."); + } + + if (!options.body.key) { + throw new Error("name is required in the JSON payload."); + } + + return { + method: "POST", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}`, + params: {}, + body: { + ...options.body, + }, + }; + }, + delete: (options = {}) => { + if (!options.featureId) { + throw new Error("A feature ID is required to delete a feature."); + } + + return { + method: "DEL", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.featureId ? options.featureId : 0}`, + params: {}, + body: null, + }; + }, + read: (options = {}) => { + if (!options.featureId) { + throw new Error("A feature ID is required to read a feature."); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.featureId ? options.featureId : 0}`, + params: {}, + body: null, + }; + }, + update: (options = {}) => { + if (!options.featureId) { + throw new Error("A feature ID is required to update a feature."); + } + + if (!options.body) { + throw new Error("A JSON payload representing the properties to update a feature is required."); + } + + return { + method: "PATCH", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.featureId ? options.featureId : 0}`, + params: {}, + body: { + ...options.body, + }, + }; + }, + }, +}; + +export default features_api; diff --git a/api/endpoints/flags.js b/api/endpoints/flags.js new file mode 100644 index 0000000..4a612aa --- /dev/null +++ b/api/endpoints/flags.js @@ -0,0 +1,146 @@ +import config from "../utils/config.js"; + + +const section = "flags"; + +const flags_api = { + flags: { + list: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to list flags."); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_FlagsV1}/projects/${options.projectId}/${section}?project_id=${options?.projectId ? options.projectId : 0}&sort=${options?.sort ? options.sort : ""}&archived=${options?.archived ? options.archived : false}&page=${options?.linkPageIndex ? options.linkPageIndex : 1}&per_page=${options?.perPage ? options.perPage : 100}`, + params: {}, + body: null, + }; + }, + create: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to create a flag."); + } + + if (!options.body) { + throw new Error("A JSON payload representing the new flag that should be created is required."); + } + + if (!options.body.key) { + throw new Error("A key is required to create a flag."); + } + + return { + method: "POST", + // prettier-ignore + resource: `${config.apiURL_FlagsV1}/project/${options.projectId}/${section}`, + params: {}, + body: { + ...options.body, + }, + }; + }, + update: (options = {}) => { + if (!options.projectId) { + throw new Error( + "A project ID is required to update a flag."); + } + + if (!options.path) { + throw new Error( + "A path is required to update a flag."); + } + + if (!options.body) { + throw new Error( + "A JSON payload representing the flag that should be updated is required."); + } + + return { + method: "PATCH", + // prettier-ignore + resource: `${config.apiURL_FlagsV1}/project/${options.projectId}/${section}`, + params: {}, + body: { + ...options.body, + }, + }; + + }, + delete: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to delete a flag."); + } + + if (!options.flagKey) { + throw new Error("A flag_key is required to delete a flag."); + } + + return { + method: "DEL", + // prettier-ignore + resource: `${config.apiURL_FlagsV1}/projects/${options.projectId}/${section}/${options.flagKey}`, + params: {}, + body: null, + }; + }, + fetch: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to fetch a flag."); + } + + if (!options.flagKey) { + throw new Error("A flag_key is required to fetch a flag."); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_FlagsV1}/projects/${options.projectId}/${section}/${options.flagKey}`, + params: {}, + body: null, + }; + }, + archive: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to archive a flag."); + } + + if (!options.body) { + throw new Error("A JSON payload representing the properties to archive a flag is required."); + } + + return { + method: "POST", + // prettier-ignore + resource: `${config.apiURL_FlagsV1}/projects/${options.projectId}/${section}/archived`, + params: {}, + body: { + ...options.body, + }, + }; + }, + unarchive: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to unarchive a flag."); + } + + if (!options.body) { + throw new Error("A JSON payload representing the properties to unarchive a flag is required."); + } + + return { + method: "POST", + // prettier-ignore + resource: `${config.apiURL_FlagsV1}/projects/${options.projectId}/${section}/unarchived`, + params: {}, + body: { + ...options.body, + }, + }; + } + } +}; + +export default flags_api; \ No newline at end of file diff --git a/api/endpoints/groups.js b/api/endpoints/groups.js index c7b4815..473fbe9 100644 --- a/api/endpoints/groups.js +++ b/api/endpoints/groups.js @@ -2,3 +2,103 @@ import config from "../utils/config.js"; //Optimizely Rest API V2 //https://library.optimizely.com/docs/api/app/v2/index.html + + +const section = "groups"; + +const groups_api = { + groups: { + list: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to list all groups."); + } + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}?project_id=${options?.projectId ? options.projectId : 0}&page=${options?.linkPageIndex ? options.linkPageIndex : 1}&per_page=${options?.perPage ? options.perPage : 100}`, + params: {}, + body: null, + }; + }, + create: (options = {}) => { + if (!options.body.projectId) { + throw new Error( + "A project ID is required to create a group." + ) + } + + if (!options.body.name) { + throw new Error( + "A group name is required to create a group." + ) + } + + if (!options.body) { + throw new Error( + "A JSON payload representing the new group that should be created is required." + ); + } + + return { + method: "POST", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}`, + params: {}, + body: { + ...options.body, + }, + }; + }, + delete: (options = {}) => { + if (!options.groupId) { + throw new Error( + "A group ID is required to delete a group." + ); + } + + return { + method: "DEL", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.groupId ? options.groupId : 0}`, + params: {}, + body: null, + }; + }, + read: (options = {}) => { + if (!options.groupId) { + throw new Error("A group ID is required to read a group."); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.groupId ? options.groupId : 0}`, + params: {}, + body: null, + }; + }, + update: (options = {}) => { + if (!options.groupId) { + throw new Error("A group ID is required to update a group."); + } + + if (!options.body) { + throw new Error( + "A JSON payload representing the properties to update the group is required." + ); + } + + return { + method: "PATCH", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.groupId ? options.groupId : 0}`, + params: {}, + body: { + ...options.body, + }, + }; + }, + }, +}; + +export default groups_api; \ No newline at end of file diff --git a/api/endpoints/impressions-usage.js b/api/endpoints/impressions-usage.js index c7b4815..4e17c3d 100644 --- a/api/endpoints/impressions-usage.js +++ b/api/endpoints/impressions-usage.js @@ -2,3 +2,70 @@ import config from "../utils/config.js"; //Optimizely Rest API V2 //https://library.optimizely.com/docs/api/app/v2/index.html + + +const section = "billing"; +const subSection = "usage"; +const dateFormat = /^\d{4}\-\d{2}\-\d{2}$/; +const todayDate = new Date().dateFormat('yyyy-mm-dd'); + + +function checkingForValidDate(date) { + + dateFormat.test(date); +} + +const impressionsUsage_api = { + impressionsUsage: { + list: (options = {}) => { + if (!options.accountId) { + throw new Error( + "An account ID is required to list all Impressions."); + } + + if (!options.usageDateFrom) { + throw new Error( + "Usage From Date is required to list all Impressions."); + } + + if (!options.usageDateTo) { + throw new Error( + "Usage To Date is required to list all Impressions."); + } + + if (!checkingForValidDate(options.usageDateFrom)) { + throw new Error( + "A valid formatted Usage Date From is needed to list all Impressions." + ); + } + + if (!checkingForValidDate(options.usageDateTo)) { + throw new Error( + "A valid formatted Usage Date To is needed to list all Impressions." + ); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${subSection}/${options?.accountId ? options.accountId : 0}?usage_date_from="${options?.usageDateFrom ? options.usageDateFrom : todayDate}"&usage_date_to="${options?.usageDateTo ? options.usageDateTo : todayDate}"&page=${options?.linkPageIndex ? options.linkPageIndex : 1}&per_page=${options?.page ? options.page : 100}&platforms=${options?.platforms ? options.platforms : ["edge", "fullstack", "web"]}&sort=${options?.sort ? options.sort : "impression_count"}&order=${options?.order ? options.order : "desc"}`, + params: {}, + body: null, + }; + }, + read: (options = {}) => { + if (!options.accountId) { + throw new Error("An account ID is required to read an impression."); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${subSection}/${options?.accountId ? options.accountId : 0}/summary`, + params: {}, + body: null, + }; + } + } +}; +export default impressionsUsage_api; \ No newline at end of file diff --git a/api/endpoints/list-attributes.js b/api/endpoints/list-attributes.js index c7b4815..be7ae87 100644 --- a/api/endpoints/list-attributes.js +++ b/api/endpoints/list-attributes.js @@ -2,3 +2,108 @@ import config from "../utils/config.js"; //Optimizely Rest API V2 //https://library.optimizely.com/docs/api/app/v2/index.html + +const section = "list_attributes"; + +const list_attributes_api = { + list_attributes: { + list: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to list all attributes for a project."); + } + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}?project_id=${options?.projectId ? options.projectId : 0}`, + params: {}, + body: null, + }; + }, + create: (options = {}) => { + if (!options.body.projectId) { + throw new Error( + "A project ID is required to create a new list attribute." + ) + } + + if (!options.body.keyField) { + throw new Error( + "A key field is required to create a new list attribute." + ) + } + + if (!options.body.name) { + throw new Error( + "A name is required to create a new list attribute." + ) + } + + if (!options.body) { + throw new Error( + "A JSON payload representing the new list attribute that should be created is required." + ); + } + + return { + method: "POST", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}`, + params: {}, + body: { + ...options.body, + }, + }; + }, + delete: (options = {}) => { + if (!options.listAttributeId) { + throw new Error( + "A list attribute ID is required to delete a list attribute." + ); + } + + return { + method: "DEL", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.listAttributeId ? options.listAttributeId : 0}`, + params: {}, + body: null, + }; + }, + read: (options = {}) => { + if (!options.listAttributeId) { + throw new Error("A list attribute ID is required to read a list attribute."); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.listAttributeId ? options.listAttributeId : 0}`, + params: {}, + body: null, + }; + }, + update: (options = {}) => { + if (!options.listAttributeId) { + throw new Error("A list attribute ID is required to update a list attribute."); + } + + if (!options.body) { + throw new Error( + "A JSON payload representing the properties to update the list attribute is required." + ); + } + + return { + method: "PATCH", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.listAttributeId ? options.listAttributeId : 0}`, + params: {}, + body: { + ...options.body, + }, + }; + }, + }, +}; + +export default list_attributes_api; \ No newline at end of file diff --git a/api/endpoints/pages.js b/api/endpoints/pages.js index c7b4815..6bdc52a 100644 --- a/api/endpoints/pages.js +++ b/api/endpoints/pages.js @@ -2,3 +2,97 @@ import config from "../utils/config.js"; //Optimizely Rest API V2 //https://library.optimizely.com/docs/api/app/v2/index.html + + +const section = "pages"; + +const pages_api = { + pages: { + list: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to get all pages."); + } + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}?project_id=${options?.projectId ? options.projectId : 0}&page=${options?.linkPageIndex ? options.linkPageIndex : 1}&per_page=${options?.perPage ? options.perPage : 100}`, + params: {}, + body: null, + }; + }, + create: (options = {}) => { + if (!options.body) { + throw new Error("A JSON payload representing the new page that should be created is required."); + } + + if (!options.body.projectId) { + throw new Error("A project ID is required to create a page."); + } + + if (!options.body.pageName) { + throw new Error("A page name is required to create a page."); + } + + if (!options.body.editUrl) { + throw new Error("A edit URL is required to create a page."); + } + + return { + method: "POST", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}`, + params: {}, + body: { + ...options.body, + }, + }; + }, + delete: (options = {}) => { + if (!options.pageId) { + throw new Error("A page ID is required to delete a page."); + } + + return { + method: "DEL", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.pageId ? options.pageId : 0}`, + params: {}, + body: null, + }; + }, + read: (options = {}) => { + if (!options.pageId) { + throw new Error("A page ID is required to read a page."); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.pageId ? options.pageId : 0}`, + params: {}, + body: null, + }; + }, + update: (options = {}) => { + if (!options.pageId) { + throw new Error("A page ID is required to update a page."); + } + + if (!options.body) { + throw new Error("A JSON payload representing the properties to update the page is required."); + } + + return { + method: "PATCH", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.pageId ? options.pageId : 0}`, + params: {}, + body: { + ...options.body, + }, + }; + }, + }, +}; + +export default pages_api; \ No newline at end of file diff --git a/api/endpoints/plan.js b/api/endpoints/plan.js index c7b4815..3801d7b 100644 --- a/api/endpoints/plan.js +++ b/api/endpoints/plan.js @@ -2,3 +2,21 @@ import config from "../utils/config.js"; //Optimizely Rest API V2 //https://library.optimizely.com/docs/api/app/v2/index.html + +const section = "plan"; + +const plan_api = { + plan: { + read: (options = {}) => { + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}`, + params: {}, + body: null, + }; + } + } +}; + +export default plan_api; diff --git a/api/endpoints/projects.js b/api/endpoints/projects.js index c7b4815..b098b77 100644 --- a/api/endpoints/projects.js +++ b/api/endpoints/projects.js @@ -2,3 +2,73 @@ import config from "../utils/config.js"; //Optimizely Rest API V2 //https://library.optimizely.com/docs/api/app/v2/index.html + + +const section = "projects"; + +const projects_api = { + projects: { + list: (options = {}) => { + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}?page=${options?.linkPageIndex ? options.linkPageIndex : 1}&per_page=${options?.perPage ? options.perPage : 100}`, + params: {}, + body: null, + }; + }, + create: (options = {}) => { + if (!options.body) { + throw new Error("A JSON payload representing the new project that should be created is required."); + } + + if (!options.body.name) { + throw new Error("A name is required to create a project."); + } + + return { + method: "POST", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}`, + params: {}, + body: { + ...options.body, + }, + }; + }, + read: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to read a project."); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.projectId ? options.projectId : 0}`, + params: {}, + body: null, + }; + }, + update: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to update a project."); + } + + if (!options.body) { + throw new Error("A JSON payload representing the properties to update the project is required."); + } + + return { + method: "PATCH", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.projectId ? options.projectId : 0}`, + params: {}, + body: { + ...options.body, + }, + }; + }, + }, +}; + +export default projects_api; \ No newline at end of file diff --git a/api/endpoints/recommendations.js b/api/endpoints/recommendations.js index c7b4815..63e7ab0 100644 --- a/api/endpoints/recommendations.js +++ b/api/endpoints/recommendations.js @@ -2,3 +2,88 @@ import config from "../utils/config.js"; //Optimizely Rest API V2 //https://library.optimizely.com/docs/api/app/v2/index.html + + +const section = "recommendations"; +const subSection = "catalogs"; + +const dateFormat = /^\d{4}\-\d{2}\-\d{2}$/; +const todayDate = new Date().dateFormat('yyyy-mm-dd'); + +function checkingForValidDate(date) { + + dateFormat.test(date); +} + +const recommendations_api = { + recommendations: { + currentCatalogData: (options = {}) => { + if (!options.date) { + throw new Error("A date is required to download a csv of current catalog data."); + } + + if (!checkingForValidDate(options.date)) { + throw new Error("A valid formatted Date is needed to download a csv of current catalog data."); + } + + if (!options.catalogId) { + throw new Error("A catalog ID is required to download a csv of current catalog data."); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${subSection}/"${options?.catalogId ? options.catalogId : ""}"/"${options?.date ? options.date : todayDate}"`, + params: {}, + body: null, + }; + }, + computedRecommendationData: (options = {}) => { + if (!options.date) { + throw new Error("A date is required to download a csv of computed recommendations output data."); + } + + if (!checkingForValidDate(options.date)) { + throw new Error("A valid formatted Date is needed to download a csv of computed recommendations output data."); + } + + if (!options.catalogId) { + throw new Error("A catalog ID is required to download a csv of computed recommendations output data."); + } + + if (!options.recommenderId) { + throw new Error("A recommender ID is required to download a csv of computed recommendations output data."); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${subSection}/"${options?.catalogId ? options.catalogId : ""}"/recommenders/"${options?.recommenderId ? options.recommenderId : ""}"/"${options?.date ? options.date : todayDate}"`, + params: {}, + body: null, + }; + }, + summaryStatsData: (options = {}) => { + if (!options.date) { + throw new Error("A date is required to download a csv with summary stats data."); + } + + if (!checkingForValidDate(options.date)) { + throw new Error("A valid formatted Date is needed to download a csv with summary stats data."); + } + + if (!options.catalogId) { + throw new Error("A catalog ID is required to download a csv with summary stats data."); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${subSection}/"${options?.catalogId ? options.catalogId : ""}"/stats/"${options?.date ? options.date : todayDate}"`, + params: {}, + body: null, + }; + } + } +}; +export default recommendations_api; \ No newline at end of file diff --git a/api/endpoints/reports.js b/api/endpoints/reports.js index 7a42e1c..848e8c3 100644 --- a/api/endpoints/reports.js +++ b/api/endpoints/reports.js @@ -46,40 +46,86 @@ const reports_api = { }; }, delete: (options = {}) => { - if (!options.audienceId) { - throw new Error("An audience ID is required to read an audience."); + if (!options.projectId) { + throw new Error("A project ID is required to delete a report."); } + if (!options.environmentKey) { + throw new Error("An environment key is required to delete a report."); + } + + if (!options.reportKey) { + throw new Error("A report key is required to delete a report."); + + } return { - method: "DEL", + method: "DELETE", // prettier-ignore - resource: `${config.apiURL_V2}/audiences/${options?.audienceId ? options.audienceId : 0}`, + resource: `${config.apiURL_FlagsV1}/projects/${options?.projectId ? options.projectId : 0}/environments/${options?.environmentKey ? options.environmentKey : 0}/reports/${options?.reportKey ? options.reportKey : 0}`, params: {}, body: null, }; }, - update: (options = {}) => { - if (!options.audienceId) { - throw new Error("An audience ID is required to read an audience."); + reset: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to reset report results."); } - if (!options.body) { - throw new Error( - "A JSON payload representing the properties to update the audience is required." - ); + if (!options.environmentKey) { + throw new Error("An environment key is required reset report results."); + } + + if (!options.reportKey) { + throw new Error("A report key is required reset report results."); + + } + return { + method: "POST", + // prettier-ignore + resource: `${config.apiURL_FlagsV1}/projects/${options?.projectId ? options.projectId : 0}/environments/${options?.environmentKey ? options.environmentKey : 0}/reports/${options?.reportKey ? options.reportKey : 0}/reset-results`, + params: {}, + body: null, + }; + }, + archive: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to archive a report."); + } + + if (!options.environmentKey) { + throw new Error("An environment key is required to archive a report."); } return { - method: "PATCH", + method: "POST", // prettier-ignore - resource: `${config.apiURL_V2}/audiences/${options?.audienceId ? options.audienceId : 0}`, + resource: `${config.apiURL_FlagsV1}/projects/${options?.projectId ? options.projectId : 0}/environments/${options?.environmentKey ? options.environmentKey : 0}/reports/archive`, params: {}, body: { ...options.body, }, }; }, - }, + unarchive: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to unarchive a report."); + } + + if (!options.environmentKey) { + throw new Error("An environment key is required to unarchive a report."); + } + + return { + method: "POST", + // prettier-ignore + resource: `${config.apiURL_FlagsV1}/projects/${options?.projectId ? options.projectId : 0}/environments/${options?.environmentKey ? options.environmentKey : 0}/reports/unarchive`, + params: {}, + body: { + ...options.body, + }, + }; + } + } }; export default reports_api; diff --git a/api/endpoints/rulesets.js b/api/endpoints/rulesets.js new file mode 100644 index 0000000..753388a --- /dev/null +++ b/api/endpoints/rulesets.js @@ -0,0 +1,116 @@ +import config from "../utils/config.js"; + + +const section = "ruleset"; + +const ruleset_api = { + ruleset: { + fetch: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to fetch a ruleset."); + } + + if (!options.flagKey) { + throw new Error("A flag_key is required to fetch a ruleset."); + } + + if (!options.environmentKey) { + throw new Error("An environment_key is required to fetch a ruleset."); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_FlagsV1}/projects/${options.projectId}/flags/${options.flagKey}/environments/${options.environmentKey}/${section}`, + params: {}, + body: null, + }; + }, + update: (options = {}) => { + if (!options.projectId) { + throw new Error( + "A project ID is required to update a ruleset."); + } + + if (!options.flagKey) { + throw new Error( + "A flag_key is required to update a ruleset."); + } + + if (!options.environmentKey) { + throw new Error( + "An environment_key is required to update a ruleset."); + } + + if (!options.body) { + throw new Error( + "A JSON payload representing the ruleset that should be updated is required."); + } + + return { + method: "PATCH", + // prettier-ignore + resource: `${config.apiURL_FlagsV1}/projects/${options.projectId}/flags/${options.flagKey}/environments/${options.environmentKey}/${section}`, + params: {}, + body: { + ...options.body, + }, + }; + + }, + enable: (options = {}) => { + if (!options.projectId) { + throw new Error( + "A project ID is required to enable a ruleset."); + } + + if (!options.flagKey) { + throw new Error( + "A flag_key is required to enable a ruleset."); + } + + if (!options.environmentKey) { + throw new Error( + "An environment_key is required to enable a ruleset."); + } + + return { + method: "POST", + // prettier-ignore + resource: `${config.apiURL_FlagsV1}/projects/${options.projectId}/flags/${options.flagKey}/environments/${options.environmentKey}/${section}/enabled`, + params: {}, + body: { + ...options.body, + }, + }; + }, + disable: (options = {}) => { + if (!options.projectId) { + throw new Error( + "A project ID is required to disable a ruleset."); + } + + if (!options.flagKey) { + throw new Error( + "A flag_key is required to disable a ruleset."); + } + + if (!options.environmentKey) { + throw new Error( + "An environment_key is required to disable a ruleset."); + } + + return { + method: "POST", + // prettier-ignore + resource: `${config.apiURL_FlagsV1}/projects/${options.projectId}/flags/${options.flagKey}/environments/${options.environmentKey}/${section}/disabled`, + params: {}, + body: { + ...options.body, + }, + }; + } + } +}; + +export default ruleset_api; \ No newline at end of file diff --git a/api/endpoints/search.js b/api/endpoints/search.js index c7b4815..1d079c2 100644 --- a/api/endpoints/search.js +++ b/api/endpoints/search.js @@ -2,3 +2,5 @@ import config from "../utils/config.js"; //Optimizely Rest API V2 //https://library.optimizely.com/docs/api/app/v2/index.html + + diff --git a/api/endpoints/sections.js b/api/endpoints/sections.js index c7b4815..430b64f 100644 --- a/api/endpoints/sections.js +++ b/api/endpoints/sections.js @@ -2,3 +2,106 @@ import config from "../utils/config.js"; //Optimizely Rest API V2 //https://library.optimizely.com/docs/api/app/v2/index.html + + +const section = "experiments"; +const subSection = "sections"; + +const sections_api = { + sections: { + list: (options = {}) => { + if (!options.experimentId) { + throw new Error("A experiment ID is required to get all sections in a multivariate test."); + } + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.experimentId ? options.experimentId : 0}/${subSection}?page=${options?.linkPageIndex ? options.linkPageIndex : 1}&per_page=${options?.perPage ? options.perPage : 100}`, + params: {}, + body: null, + }; + }, + create: (options = {}) => { + if (!options.experimentId) { + throw new Error("An experiment ID is required to create a section to a multivariate test."); + } + + if (!options.body) { + throw new Error("A JSON payload representing the new section to a multivariate test that should be created is required."); + } + + if (!options.body.variations) { + throw new Error("Variation(s) are required to create a section to a multivariate test."); + } + + return { + method: "POST", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.experimentId ? options.experimentId : 0}/${subSection}`, + params: {}, + body: { + ...options.body, + }, + }; + }, + delete: (options = {}) => { + if (!options.sectionId) { + throw new Error("A section ID is required to delete a section of a multivariate test."); + } + + if (!options.experimentId) { + throw new Error("An experiment ID is required to delete a section of a multivariate test."); + } + + return { + method: "DEL", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.experimentId ? options.experimentId : 0}/${subSection}/${options?.sectionId ? options.sectionId : 0}`, + params: {}, + body: null, + }; + }, + read: (options = {}) => { + if (!options.sectionId) { + throw new Error("A section ID is required to read a section of a multivariate test."); + } + + if (!options.experimentId) { + throw new Error("An experiment ID is required to read a section of a multivariate test."); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.experimentId ? options.experimentId : 0}/${subSection}/${options?.sectionId ? options.sectionId : 0}`, + params: {}, + body: null, + }; + }, + update: (options = {}) => { + if (!options.sectionId) { + throw new Error("A section ID is required to update a section of a multivariate test."); + } + + if (!options.experimentId) { + throw new Error("An experiment ID is required to update a section of a multivariate test."); + } + + if (!options.body) { + throw new Error("A JSON payload representing the properties to update the section of a multivariate test is required."); + } + + return { + method: "PATCH", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.experimentId ? options.experimentId : 0}/${subSection}/${options?.sectionId ? options.sectionId : 0}`, + params: {}, + body: { + ...options.body, + }, + }; + }, + }, +}; + +export default sections_api; \ No newline at end of file diff --git a/api/endpoints/subject-access-requests.js b/api/endpoints/subject-access-requests.js index c7b4815..58c74da 100644 --- a/api/endpoints/subject-access-requests.js +++ b/api/endpoints/subject-access-requests.js @@ -2,3 +2,77 @@ import config from "../utils/config.js"; //Optimizely Rest API V2 //https://library.optimizely.com/docs/api/app/v2/index.html + + + +const section = "subject-access-requests"; + +const subjectAccessRequest_api = { + subjectAccessRequest: { + list: (options = {}) => { + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}?page=${options?.linkPageIndex ? options.linkPageIndex : 1}&per_page=${options?.perPage ? options.perPage : 100}`, + params: {}, + body: null, + }; + }, + create: (options = {}) => { + if (!options.body) { + throw new Error( + "A JSON payload representing the new Subject Access Request that should be created is required." + ); + } + + if (!options.body.dataType) { + throw new Error( + "A data type is required to create a Subject Access Request." + ); + } + + if (!options.body.identifier) { + throw new Error( + "An identifier is required to create a Subject Access Request." + ); + } + + if (!options.body.identifierType) { + throw new Error( + "An identifier type is required to create a Subject Access Request." + ); + } + + if (!options.body.requestType) { + throw new Error( + "A request type is required to create a Subject Access Request." + ); + } + + return { + method: "POST", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}`, + params: {}, + body: { + ...options.body, + }, + }; + }, + read: (options = {}) => { + if (!options.requestId) { + throw new Error("A request ID is required to read a Subject Access Request."); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_V2}/${section}/${options?.requestId ? options.requestId : 0}`, + params: {}, + body: null, + }; + }, + }, +}; + +export default subjectAccessRequest_api; \ No newline at end of file diff --git a/api/endpoints/variations.js b/api/endpoints/variations.js new file mode 100644 index 0000000..6a3f256 --- /dev/null +++ b/api/endpoints/variations.js @@ -0,0 +1,172 @@ +import config from "../utils/config.js"; + +const section = "variations"; + +const variations_api = { + variations: { + list: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to get a list of variations."); + } + + if (!options.flagKey) { + throw new Error("A flag_key is required to get a list of variations."); + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_FlagsV1}/projects/${options.projectId}/flags/${options.flagKey}/${section}?per_page=${options?.perPage ? options.perPage : 100}&query=${options?.query ? options.query : ""}`, + params: {}, + body: null, + }; + }, + create: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to create a variation."); + } + + if (!options.flagKey) { + throw new Error("A flag_key is required to create a variation."); + } + + if (!options.body) { + throw new Error("A JSON payload representing the new variation that should be created is required."); + } + + if (!options.body.key) { + throw new Error("A key is required in the JSON payload to create a variation."); + } + + if (!options.body.name) { + throw new Error("A name is required in the JSON payload to create a variation."); + } + + return { + method: "POST", + // prettier-ignore + resource: `${config.apiURL_FlagsV1}/projects/${options.projectId}/flags/${options.flagKey}/${section}`, + params: {}, + body: { + ...options.body, + }, + }; + }, + update: (options = {}) => { + if (!options.projectId) { + throw new Error( + "A project ID is required to update a variation." + ) + } + + if (!options.flagKey) { + throw new Error( + "A flag_key is required to update a variation." + ) + } + + if (!options.body) { + throw new Error( + "A JSON payload representing the ruleset that should be updated is required." + ); + } + + if (!options.body.op) { + throw new Error("An operation is required in the JSON payload to update a variation."); + } + + if (!options.body.path) { + throw new Error("A path is required in the JSON payload to update a variation."); + } + + return { + method: "PATCH", + // prettier-ignore + resource: `${config.apiURL_FlagsV1}/projects/${options.projectId}/flags/${options.flagKey}/${section}`, + params: {}, + body: { + ...options.body, + }, + }; + + }, + fetch: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to get a variation."); + } + + if (!options.flagKey) { + throw new Error("A flag_key is required to get a variation."); + } + + if (!options.variationKey) { + throw new Error("A variation key is required to get a variation.") + } + + return { + method: "GET", + // prettier-ignore + resource: `${config.apiURL_FlagsV1}/projects/${options.projectId}/flags/${options.flagKey}/${section}/${options.variationKey}`, + params: {}, + body: null, + }; + }, + delete: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to delete a variation."); + } + + if (!options.flagKey) { + throw new Error("A flag_key is required to delete a variation."); + } + + if (!options.variationKey) { + throw new Error("A variation key is required to delete a variation.") + } + + return { + method: "DELETE", + // prettier-ignore + resource: `${config.apiURL_FlagsV1}/projects/${options.projectId}/flags/${options.flagKey}/${section}/${options.variationKey}`, + params: {}, + body: null, + }; + }, + archive: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to archive a variation."); + } + + if (!options.flagKey) { + throw new Error("A flag_key is required to archive a variation."); + } + + return { + method: "POST", + // prettier-ignore + resource: `${config.apiURL_FlagsV1}/projects/${options.projectId}/flags/${options.flagKey}/${section}/archived`, + params: {}, + body: null, + }; + }, + unarchive: (options = {}) => { + if (!options.projectId) { + throw new Error("A project ID is required to unarchive a variation."); + } + + if (!options.flagKey) { + throw new Error("A flag_key is required to unarchive a variation."); + } + + return { + method: "POST", + // prettier-ignore + resource: `${config.apiURL_FlagsV1}/projects/${options.projectId}/flags/${options.flagKey}/${section}/unarchived`, + params: {}, + body: null, + }; + } + } +}; + +export default variations_api; \ No newline at end of file diff --git a/api/optly-rest-toolkit.js b/api/optly-rest-toolkit.js index 92f0254..6446589 100644 --- a/api/optly-rest-toolkit.js +++ b/api/optly-rest-toolkit.js @@ -1,13 +1,59 @@ import axios from "axios"; import { parseLinkHeader, deepCloneJson } from "./utils/http-tools.js"; import experiments from "./endpoints/experiments.js"; +import features from "./endpoints/features.js"; +import attributes from "./endpoints/attributes.js"; +import audiences from "./endpoints/audiences.js"; +import campaigns from "./endpoints/campaigns.js"; +import changes from "./endpoints/change-history.js"; +import environments from "./endpoints/environments.js"; +import events from "./endpoints/events.js"; +import credentials from "./endpoints/export-credentials.js"; +import extensions from "./endpoints/extensions.js"; +import groups from "./endpoints/groups.js"; +import impressionusage from "./endpoints/impression-usage.js"; +import list_attributes from "./endpoints/list-attributes.js"; +import pages from "./endpoints/pages.js"; +import plan from "./endpoints/plan.js"; +import project from "./endpoints/project.js"; +import recommendations from "./endpoints/recommendations.js"; +import reports from "./endpoints/reports.js"; +import sections from "./endpoints/sections.js"; +import subjectAccessRequest from "./endpoints/subject-access-requests.js"; +import flags from "./endpoints/flags.js"; +import rulesets from "/endpoints/rulesets.js" +import variations from "./endpoints/variations.js"; +import reports from "./endpoints/reports.js"; + -//Personal Token: 2:K0omYPe8MUA1jnB05LbNhwYrPu7RfOmYWVUuAidd4eqhElqJn_Ls export class OptlyRestToolkit { constructor(configOptions) { this.endpoints = { ...experiments, + ...features, + ...attributes, + ...audiences, + ...campaigns, + ...changes, + ...environments, + ...events, + ...credentials, + ...extensions, + ...groups, + ...impressionusage, + ...list_attributes, + ...pages, + ...plan, + ...project, + ...recommendations, + ...reports, + ...sections, + ...subjectAccessRequest, + ...flags, + ...rulesets, + ...variations, + ...reports }; if (!configOptions.token) { @@ -30,7 +76,7 @@ export class OptlyRestToolkit { Authorization: `Bearer ${this.token}`, "Content-Type": "application/json", }; - + let URL; let headerLink; let result = []; @@ -61,7 +107,7 @@ export class OptlyRestToolkit { // result = deepCloneJson(result.filter((item) => item.archived === false)); - return result; + return result; } async experiments(method = "", options = {}) { @@ -75,6 +121,282 @@ export class OptlyRestToolkit { return result; } } + + async features(method = "", options = {}) { + options.projectId = this.projectId; + const existingEndpoint = this.endpoints.features[method]; + + if (existingEndpoint) { + const endpoint = existingEndpoint(options); + let result = await this.request(endpoint); + //console.log(result); + return result; + } + } + + async attributes(method = "", options = {}) { + options.projectId = this.projectId; + const existingEndpoint = this.endpoints.attributes[method]; + + if (existingEndpoint) { + const endpoint = existingEndpoint(options); + let result = await this.request(endpoint); + //console.log(result); + return result; + } + } + + async audiences(method = "", options = {}) { + options.projectId = this.projectId; + const existingEndpoint = this.endpoints.audiences[method]; + + if (existingEndpoint) { + const endpoint = existingEndpoint(options); + let result = await this.request(endpoint); + //console.log(result); + return result; + } + } + + async campaigns(method = "", options = {}) { + options.projectId = this.projectId; + const existingEndpoint = this.endpoints.campaigns[method]; + + if (existingEndpoint) { + const endpoint = existingEndpoint(options); + let result = await this.request(endpoint); + //console.log(result); + return result; + } + } + + async changes(method = "", options = {}) { + options.projectId = this.projectId; + const existingEndpoint = this.endpoints.changes[method]; + + if (existingEndpoint) { + const endpoint = existingEndpoint(options); + let result = await this.request(endpoint); + //console.log(result); + return result; + } + } + + async environments(method = "", options = {}) { + options.projectId = this.projectId; + const existingEndpoint = this.endpoints.environments[method]; + + if (existingEndpoint) { + const endpoint = existingEndpoint(options); + let result = await this.request(endpoint); + //console.log(result); + return result; + } + } + + async events(method = "", options = {}) { + options.projectId = this.projectId; + const existingEndpoint = this.endpoints.events[method]; + + if (existingEndpoint) { + const endpoint = existingEndpoint(options); + let result = await this.request(endpoint); + //console.log(result); + return result; + } + } + + async credentials(method = "", options = {}) { + options.projectId = this.projectId; + const existingEndpoint = this.endpoints.credentials[method]; + + if (existingEndpoint) { + const endpoint = existingEndpoint(options); + let result = await this.request(endpoint); + //console.log(result); + return result; + } + } + + async extensions(method = "", options = {}) { + options.projectId = this.projectId; + const existingEndpoint = this.endpoints.extensions[method]; + + if (existingEndpoint) { + const endpoint = existingEndpoint(options); + let result = await this.request(endpoint); + //console.log(result); + return result; + } + } + + async groups(method = "", options = {}) { + options.projectId = this.projectId; + const existingEndpoint = this.endpoints.groups[method]; + + if (existingEndpoint) { + const endpoint = existingEndpoint(options); + let result = await this.request(endpoint); + //console.log(result); + return result; + } + } + + async impressionusage(method = "", options = {}) { + options.projectId = this.projectId; + const existingEndpoint = this.endpoints.impressionusage[method]; + + if (existingEndpoint) { + const endpoint = existingEndpoint(options); + let result = await this.request(endpoint); + //console.log(result); + return result; + } + } + + async list_attributes(method = "", options = {}) { + options.projectId = this.projectId; + const existingEndpoint = this.endpoints.list_attributes[method]; + + if (existingEndpoint) { + const endpoint = existingEndpoint(options); + let result = await this.request(endpoint); + //console.log(result); + return result; + } + } + + async pages(method = "", options = {}) { + options.projectId = this.projectId; + const existingEndpoint = this.endpoints.pages[method]; + + if (existingEndpoint) { + const endpoint = existingEndpoint(options); + let result = await this.request(endpoint); + //console.log(result); + return result; + } + } + + async plan(method = "", options = {}) { + options.projectId = this.projectId; + const existingEndpoint = this.endpoints.plan[method]; + + if (existingEndpoint) { + const endpoint = existingEndpoint(options); + let result = await this.request(endpoint); + //console.log(result); + return result; + } + } + + async project(method = "", options = {}) { + options.projectId = this.projectId; + const existingEndpoint = this.endpoints.project[method]; + + if (existingEndpoint) { + const endpoint = existingEndpoint(options); + let result = await this.request(endpoint); + //console.log(result); + return result; + } + } + + async recommendations(method = "", options = {}) { + options.projectId = this.projectId; + const existingEndpoint = this.endpoints.recommendations[method]; + + if (existingEndpoint) { + const endpoint = existingEndpoint(options); + let result = await this.request(endpoint); + //console.log(result); + return result; + } + } + + async reports(method = "", options = {}) { + options.projectId = this.projectId; + const existingEndpoint = this.endpoints.reports[method]; + + if (existingEndpoint) { + const endpoint = existingEndpoint(options); + let result = await this.request(endpoint); + //console.log(result); + return result; + } + } + + async sections(method = "", options = {}) { + options.projectId = this.projectId; + const existingEndpoint = this.endpoints.sections[method]; + + if (existingEndpoint) { + const endpoint = existingEndpoint(options); + let result = await this.request(endpoint); + //console.log(result); + return result; + } + } + + async subjectAccessRequest(method = "", options = {}) { + options.projectId = this.projectId; + const existingEndpoint = this.endpoints.subjectAccessRequest[method]; + + if (existingEndpoint) { + const endpoint = existingEndpoint(options); + let result = await this.request(endpoint); + //console.log(result); + return result; + } + } + + async flags(method = "", options = {}) { + options.projectId = this.projectId; + const existingEndpoint = this.endpoints.flags[method]; + + if (existingEndpoint) { + const endpoint = existingEndpoint(options); + let result = await this.request(endpoint); + //console.log(result); + return result; + } + } + + async rulesets(method = "", options = {}) { + options.projectId = this.projectId; + const existingEndpoint = this.endpoints.rulesets[method]; + + if (existingEndpoint) { + const endpoint = existingEndpoint(options); + let result = await this.request(endpoint); + //console.log(result); + return result; + } + } + + async variations(method = "", options = {}) { + options.projectId = this.projectId; + const existingEndpoint = this.endpoints.variations[method]; + + if (existingEndpoint) { + const endpoint = existingEndpoint(options); + let result = await this.request(endpoint); + //console.log(result); + return result; + } + } + + async reports(method = "", options = {}) { + options.projectId = this.projectId; + const existingEndpoint = this.endpoints.reports[method]; + + if (existingEndpoint) { + const endpoint = existingEndpoint(options); + let result = await this.request(endpoint); + //console.log(result); + return result; + } + } } //module.exports = {OptlyRestToolkit}; diff --git a/index.js b/index.js index 876dc5f..a7a68e5 100644 --- a/index.js +++ b/index.js @@ -22,6 +22,8 @@ var testResult = await testAPI(); console.log(testResult); testResult = null; + + // Do Not Delete Below // webix.ui({ @@ -72,7 +74,7 @@ testResult = null; // { id: "project_read", type: "folder", value: "Read a project" }, // { id: "project_update", type: "folder", value: "Update a project" }, // ], -// }, +// }, // { // id: "2", // type: "folder", diff --git a/package-lock.json b/package-lock.json index 2770159..8917983 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,14 +9,14 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "axios": "^0.26.0", + "axios": "^0.26.1", "node-fetch": "^3.2.0" } }, "node_modules/axios": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.0.tgz", - "integrity": "sha512-lKoGLMYtHvFrPVt3r+RBMp9nh34N0M8zEfCWqdWZx6phynIEhQqAdydpyBAAG211zlhX9Rgu08cOamy6XjE5Og==", + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", "dependencies": { "follow-redirects": "^1.14.8" } @@ -127,9 +127,9 @@ }, "dependencies": { "axios": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.0.tgz", - "integrity": "sha512-lKoGLMYtHvFrPVt3r+RBMp9nh34N0M8zEfCWqdWZx6phynIEhQqAdydpyBAAG211zlhX9Rgu08cOamy6XjE5Og==", + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", "requires": { "follow-redirects": "^1.14.8" } diff --git a/package.json b/package.json index e0c1dcc..6a08b90 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "author": "", "license": "ISC", "dependencies": { - "axios": "^0.26.0", + "axios": "^0.26.1", "node-fetch": "^3.2.0" } } diff --git a/todo.txt b/todo.txt new file mode 100644 index 0000000..abe973d --- /dev/null +++ b/todo.txt @@ -0,0 +1,51 @@ +Add this code but change to be able to select the type to search through. + +/* + +Ex. + +https://api.optimizely.com/v2/search?query=TheTextThatYouAreLookingFor&project_id=17574920715&per_page=100&page=1&expand=project_name + + + +https://api.optimizely.com/v2/search?query=COVID Homepage: Industry-based Personalization&project_id=3867211201&type=campaign&per_page=100&page=1&expand=project_name&archived=false&status=running + +*/ + +function getSearchURL( + + _query_, + + _project_id_, + + _type_, + + _per_page_ = 1, + + _page_ = 1, + + _extra_params_ + +) { + + // Available types + + // ['experiment', 'campaign', 'feature', 'audience', 'page', 'event']", + + let result = + + `https://api.optimizely.com/v2/search?query=` + + + `'${_query_}'&project_id=${_project_id_}&type=${_type_}` + + + `&archived=false&per_page=${_per_page_}&page=${_page_}&expand=project_name`; + + if (_extra_params_) { + + result = result + _extra_params_; + + } + + return result; + +} \ No newline at end of file