Files
n8n-enterprise-unlocked/packages/editor-ui/src/utils/apiUtils.ts
T
cd7c312fbd feat(editor): Add cloud ExecutionsUsage and API blocking using licenses (#6159)
* Add ExecutionsUsage component

* set $sidebar-expanded-width back to 200px

* add days using interpolation

* Rename PlanData type to CloudPlanData

* Rename Metadata type to PlanMetadata

* Make prop block in the update button

* Use variable in line-height

* Remove progressBarSection class

* fix trial expiration calculation

* mock expirationDate and fix issue with days left

* Remove unnecesary property from class .container

* inject component data via props

* Check for plan data during app mounting and keep data in the store

* Remove mounted hook

* redirect when upgrade plan is clicked

* Remove computed properties

* Remove instance property as it's not needed anymore

* Flatten plan object

* remove console.log

* Add all cloud types within its own namespace

* keep redirection inside component

* get computed properties back

* Improve polling logic

* Move cloudData to its own store

* Remove commented interfaces

* remove cloudPlan from user store

* fix imports

* update logic for userIsTrialing method

* centralize userIsTrialing method

* redirect to production change plan page always

* Call staging or production cloud api depending on base URL

* remove setting store form ExecutionUsage.vue

* fix linting issue

* Add trial group to PlanMetadata group

* Move helpers into the store

* make staging url check more specific

* make cloud state nullable

* fix linting issue

* swap mockup date for endpoint

* Make getCurrentPlan async

* asas

* Improvements

* small improvements

* chore: resolve conflicts

* make sure there is data before calculating trial expiration

* Fix issue with component not loading on first page load

* type safety improvements

* apply component ui feedback

* fix linting issue

* chore: clean up unnecessary change from merge conflict

* feat: Block api feature using licenses, show notice page for trial cloud users (#6187)

* rename planSpec to plan

* Remove instance property as it's not needed anymore

* Flatten plan object

* remove console.log

* feat: disable api using license

* feat: add api page

* chore: resolve conflicts

* chore: resolve conflicts

* feat: update and refactor a bit

* fix: update endpoints

* fix: update endpoints

* fix: use host

* feat: update copy

* fix linting issues

---------

Co-authored-by: ricardo <ricardoespinoza105@gmail.com>

* add pluralization to days left text

---------

Co-authored-by: Mutasem <mutdmour@gmail.com>
Co-authored-by: Mutasem Aldmour <4711238+mutdmour@users.noreply.github.com>
2023-05-15 17:16:13 -04:00

165 lines
3.9 KiB
TypeScript

import type { AxiosRequestConfig, Method } from 'axios';
import axios from 'axios';
import type { IDataObject } from 'n8n-workflow';
import type {
IExecutionFlattedResponse,
IExecutionResponse,
IRestApiContext,
IWorkflowDb,
} from '@/Interface';
import { parse } from 'flatted';
export const NO_NETWORK_ERROR_CODE = 999;
class ResponseError extends Error {
// The HTTP status code of response
httpStatusCode?: number;
// The error code in the response
errorCode?: number;
// The stack trace of the server
serverStackTrace?: string;
/**
* Creates an instance of ResponseError.
* @param {string} message The error message
* @param {number} [errorCode] The error code which can be used by frontend to identify the actual error
* @param {number} [httpStatusCode] The HTTP status code the response should have
* @param {string} [stack] The stack trace
*/
constructor(
message: string,
options: { errorCode?: number; httpStatusCode?: number; stack?: string } = {},
) {
super(message);
this.name = 'ResponseError';
const { errorCode, httpStatusCode, stack } = options;
if (errorCode) {
this.errorCode = errorCode;
}
if (httpStatusCode) {
this.httpStatusCode = httpStatusCode;
}
if (stack) {
this.serverStackTrace = stack;
}
}
}
async function request(config: {
method: Method;
baseURL: string;
endpoint: string;
headers?: IDataObject;
data?: IDataObject;
}) {
const { method, baseURL, endpoint, headers, data } = config;
const options: AxiosRequestConfig = {
method,
url: endpoint,
baseURL,
headers,
};
if (
import.meta.env.NODE_ENV !== 'production' &&
!baseURL.includes('api.n8n.io') &&
!baseURL.includes('n8n.cloud')
) {
options.withCredentials = true;
}
if (['POST', 'PATCH', 'PUT'].includes(method)) {
options.data = data;
} else {
options.params = data;
}
try {
const response = await axios.request(options);
return response.data;
} catch (error) {
if (error.message === 'Network Error') {
throw new ResponseError('API-Server can not be reached. It is probably down.', {
errorCode: NO_NETWORK_ERROR_CODE,
});
}
const errorResponseData = error.response.data;
if (errorResponseData !== undefined && errorResponseData.message !== undefined) {
if (errorResponseData.name === 'NodeApiError') {
errorResponseData.httpStatusCode = error.response.status;
throw errorResponseData;
}
throw new ResponseError(errorResponseData.message, {
errorCode: errorResponseData.code,
httpStatusCode: error.response.status,
stack: errorResponseData.stack,
});
}
throw error;
}
}
export async function makeRestApiRequest(
context: IRestApiContext,
method: Method,
endpoint: string,
data?: IDataObject,
) {
const response = await request({
method,
baseURL: context.baseUrl,
endpoint,
headers: { sessionid: context.sessionId },
data,
});
// @ts-ignore all cli rest api endpoints return data wrapped in `data` key
return response.data;
}
export async function get(
baseURL: string,
endpoint: string,
params?: IDataObject,
headers?: IDataObject,
) {
return request({ method: 'GET', baseURL, endpoint, headers, data: params });
}
export async function post(
baseURL: string,
endpoint: string,
params?: IDataObject,
headers?: IDataObject,
) {
return request({ method: 'POST', baseURL, endpoint, headers, data: params });
}
/**
* Unflattens the Execution data.
*
* @param {IExecutionFlattedResponse} fullExecutionData The data to unflatten
*/
export function unflattenExecutionData(
fullExecutionData: IExecutionFlattedResponse,
): IExecutionResponse {
// Unflatten the data
const returnData: IExecutionResponse = {
...fullExecutionData,
workflowData: fullExecutionData.workflowData as IWorkflowDb,
data: parse(fullExecutionData.data),
};
returnData.finished = returnData.finished ? returnData.finished : false;
if (fullExecutionData.id) {
returnData.id = fullExecutionData.id;
}
return returnData;
}