diff --git a/packages/nodes-base/credentials/KitemakerApi.credentials.ts b/packages/nodes-base/credentials/KitemakerApi.credentials.ts new file mode 100644 index 0000000000..2f372e0d31 --- /dev/null +++ b/packages/nodes-base/credentials/KitemakerApi.credentials.ts @@ -0,0 +1,18 @@ +import { + ICredentialType, + NodePropertyTypes, +} from 'n8n-workflow'; + +export class KitemakerApi implements ICredentialType { + name = 'kitemakerApi'; + displayName = 'Kitemaker API'; + documentationUrl = 'kitemaker'; + properties = [ + { + displayName: 'Personal Access Token', + name: 'personalAccessToken', + type: 'string' as NodePropertyTypes, + default: '', + }, + ]; +} diff --git a/packages/nodes-base/nodes/Kitemaker/GenericFunctions.ts b/packages/nodes-base/nodes/Kitemaker/GenericFunctions.ts new file mode 100644 index 0000000000..6b623a6a5f --- /dev/null +++ b/packages/nodes-base/nodes/Kitemaker/GenericFunctions.ts @@ -0,0 +1,85 @@ +import { + IExecuteFunctions, + ILoadOptionsFunctions, +} from 'n8n-core'; + +import { + IDataObject, + IHookFunctions, + NodeApiError, +} from 'n8n-workflow'; + +export async function kitemakerRequest( + this: IExecuteFunctions | ILoadOptionsFunctions | IHookFunctions, + body: IDataObject = {}, +) { + const { personalAccessToken } = this.getCredentials('kitemakerApi') as { personalAccessToken: string }; + + const options = { + headers: { + Authorization: `Bearer ${personalAccessToken}`, + }, + method: 'POST', + body, + uri: 'https://toil.kitemaker.co/developers/graphql', + json: true, + }; + + const responseData = await this.helpers.request!.call(this, options); + + if (responseData.errors) { + throw new NodeApiError(this.getNode(), responseData); + } + + return responseData; +} + +export async function kitemakerRequestAllItems( + this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions, + body: { query: string; variables: { [key: string]: string } }, +) { + const resource = this.getNodeParameter('resource', 0) as 'space' | 'user' | 'workItem'; + const [group, items] = getGroupAndItems(resource); + + const returnAll = this.getNodeParameter('returnAll', 0, false) as boolean; + const limit = this.getNodeParameter('limit', 0, 0) as number; + + const returnData: IDataObject[] = []; + let responseData; + + do { + responseData = await kitemakerRequest.call(this, body); + body.variables.cursor = responseData.data[group].cursor; + returnData.push(...responseData.data[group][items]); + + if (!returnAll && returnData.length > limit) { + return returnData.slice(0, limit); + } + + } while (responseData.data[group].hasMore); + + return returnData; +} + +function getGroupAndItems(resource: 'space' | 'user' | 'workItem') { + const map: { [key: string]: { [key: string]: string } } = { + space: { group: 'organization', items: 'spaces' }, + user: { group: 'organization', items: 'users' }, + workItem: { group: 'workItems', items: 'workItems' }, + }; + + return [ + map[resource]['group'], + map[resource]['items'], + ]; +} + +export function createLoadOptions( + resources: Array<{ name?: string; username?: string; title?: string; id: string }>, +): Array<{ name: string; value: string }> { + return resources.map(option => { + if (option.username) return ({ name: option.username, value: option.id }); + if (option.title) return ({ name: option.title, value: option.id }); + return ({ name: option.name ?? 'Unnamed', value: option.id }); + }); +} diff --git a/packages/nodes-base/nodes/Kitemaker/Kitemaker.node.ts b/packages/nodes-base/nodes/Kitemaker/Kitemaker.node.ts new file mode 100644 index 0000000000..650049be61 --- /dev/null +++ b/packages/nodes-base/nodes/Kitemaker/Kitemaker.node.ts @@ -0,0 +1,321 @@ +import { + IExecuteFunctions +} from 'n8n-core'; + +import { + IDataObject, + ILoadOptionsFunctions, + INodeExecutionData, + INodeType, + INodeTypeDescription +} from 'n8n-workflow'; + +import { + organizationOperations, + spaceFields, + spaceOperations, + userFields, + userOperations, + workItemFields, + workItemOperations, +} from './descriptions'; + +import { + createLoadOptions, + kitemakerRequest, + kitemakerRequestAllItems, +} from './GenericFunctions'; + +import { + getAllSpaces, + getAllUsers, + getAllWorkItems, + getLabels, + getOrganization, + getSpaces, + getStatuses, + getUsers, + getWorkItem, + getWorkItems, +} from './queries'; + +import { + createWorkItem, + editWorkItem, +} from './mutations'; + +export class Kitemaker implements INodeType { + description: INodeTypeDescription = { + displayName: 'Kitemaker', + name: 'kitemaker', + icon: 'file:kitemaker.svg', + group: ['input'], + version: 1, + subtitle: '={{$parameter["resource"] + ": " + $parameter["operation"]}}', + description: 'Consume the Kitemaker GraphQL API', + defaults: { + name: 'Kitemaker', + color: '#662482', + }, + inputs: ['main'], + outputs: ['main'], + credentials: [ + { + name: 'kitemakerApi', + required: true, + }, + ], + properties: [ + { + displayName: 'Resource', + name: 'resource', + type: 'options', + options: [ + { + name: 'Organization', + value: 'organization', + }, + { + name: 'Space', + value: 'space', + }, + { + name: 'User', + value: 'user', + }, + { + name: 'Work Item', + value: 'workItem', + }, + ], + default: 'workItem', + required: true, + description: 'Resource to operate on.', + }, + ...organizationOperations, + ...spaceOperations, + ...spaceFields, + ...userOperations, + ...userFields, + ...workItemOperations, + ...workItemFields, + ], + }; + + methods = { + loadOptions: { + async getLabels(this: ILoadOptionsFunctions) { + const responseData = await kitemakerRequest.call(this, { query: getLabels }); + const { data: { organization: { spaces } } } = responseData; + + return createLoadOptions(spaces[0].labels); + }, + + async getSpaces(this: ILoadOptionsFunctions) { + const responseData = await kitemakerRequest.call(this, { query: getSpaces }); + const { data: { organization: { spaces } } } = responseData; + + return createLoadOptions(spaces); + }, + + async getStatuses(this: ILoadOptionsFunctions) { + const responseData = await kitemakerRequest.call(this, { query: getStatuses }); + const { data: { organization: { spaces } } } = responseData; + + return createLoadOptions(spaces[0].statuses); + }, + + async getUsers(this: ILoadOptionsFunctions) { + const responseData = await kitemakerRequest.call(this, { query: getUsers }); + const { data: { organization: { users } } } = responseData; + + return createLoadOptions(users); + }, + + async getWorkItems(this: ILoadOptionsFunctions) { + const spaceId = this.getNodeParameter('spaceId', 0) as string; + + const responseData = await kitemakerRequest.call(this, { + query: getWorkItems, + variables: { spaceId }, + }); + + const { data: { workItems: { workItems } } } = responseData; + + return createLoadOptions(workItems); + }, + + }, + }; + + async execute(this: IExecuteFunctions): Promise { + const items = this.getInputData(); + + const resource = this.getNodeParameter('resource', 0); + const operation = this.getNodeParameter('operation', 0); + + let responseData; + const returnData: IDataObject[] = []; + + // https://github.com/kitemakerhq/docs/blob/main/kitemaker.graphql + + for (let i = 0; i < items.length; i++) { + + if (resource === 'organization') { + + // ********************************************************************* + // organization + // ********************************************************************* + + if (operation === 'get') { + + // ---------------------------------- + // organization: get + // ---------------------------------- + + responseData = await kitemakerRequest.call(this, { + query: getOrganization, + }); + + returnData.push(responseData.data.organization); + + } + + } else if (resource === 'space') { + + // ********************************************************************* + // space + // ********************************************************************* + + if (operation === 'getAll') { + + // ---------------------------------- + // space: getAll + // ---------------------------------- + + const allItems = await kitemakerRequestAllItems.call(this, { + query: getAllSpaces, + variables: {}, + }); + + returnData.push(...allItems); + + } + + } else if (resource === 'user') { + + // ********************************************************************* + // user + // ********************************************************************* + + if (operation === 'getAll') { + + // ---------------------------------- + // user: getAll + // ---------------------------------- + + const allItems = await kitemakerRequestAllItems.call(this, { + query: getAllUsers, + variables: {}, + }); + + returnData.push(...allItems); + + } + + } else if (resource === 'workItem') { + + // ********************************************************************* + // workItem + // ********************************************************************* + + if (operation === 'create') { + + // ---------------------------------- + // workItem: create + // ---------------------------------- + + const input = { + title: this.getNodeParameter('title', i) as string, + statusId: this.getNodeParameter('statusId', i) as string[], + }; + + if (!input.statusId.length) { + throw new Error('Please enter a status to set for the work item to create.'); + } + + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + + if (Object.keys(additionalFields).length) { + Object.assign(input, additionalFields); + } + + responseData = await kitemakerRequest.call(this, { + query: createWorkItem, + variables: { input }, + }); + + returnData.push(responseData.data.createWorkItem.workItem); + + } else if (operation === 'get') { + + // ---------------------------------- + // workItem: get + // ---------------------------------- + + const workItemId = this.getNodeParameter('workItemId', i) as string; + + responseData = await kitemakerRequest.call(this, { + query: getWorkItem, + variables: { workItemId }, + }); + + returnData.push(responseData.data.workItem); + + } else if (operation === 'getAll') { + + // ---------------------------------- + // workItem: getAll + // ---------------------------------- + + const allItems = await kitemakerRequestAllItems.call(this, { + query: getAllWorkItems, + variables: { + spaceId: this.getNodeParameter('spaceId', i) as string, + }, + }); + + returnData.push(...allItems); + + } else if (operation === 'update') { + + // ---------------------------------- + // workItem: update + // ---------------------------------- + + const input = { + id: this.getNodeParameter('workItemId', i), + }; + + const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; + + if (!Object.keys(updateFields).length) { + throw new Error('Please enter at least one field to update for the work item.'); + } + + Object.assign(input, updateFields); + + responseData = await kitemakerRequest.call(this, { + query: editWorkItem, + variables: { input }, + }); + + returnData.push(responseData.data.editWorkItem.workItem); + + } + } + } + + return [this.helpers.returnJsonArray(returnData)]; + } +} diff --git a/packages/nodes-base/nodes/Kitemaker/descriptions/OrganizationDescription.ts b/packages/nodes-base/nodes/Kitemaker/descriptions/OrganizationDescription.ts new file mode 100644 index 0000000000..ee478b044f --- /dev/null +++ b/packages/nodes-base/nodes/Kitemaker/descriptions/OrganizationDescription.ts @@ -0,0 +1,27 @@ +import { + INodeProperties, +} from 'n8n-workflow'; + +export const organizationOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + default: 'get', + description: 'Operation to perform.', + options: [ + { + name: 'Get', + value: 'get', + description: 'Retrieve data on the logged-in user\'s organization.', + }, + ], + displayOptions: { + show: { + resource: [ + 'organization', + ], + }, + }, + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Kitemaker/descriptions/SpaceDescription.ts b/packages/nodes-base/nodes/Kitemaker/descriptions/SpaceDescription.ts new file mode 100644 index 0000000000..0c48ab3c67 --- /dev/null +++ b/packages/nodes-base/nodes/Kitemaker/descriptions/SpaceDescription.ts @@ -0,0 +1,71 @@ +import { + INodeProperties, +} from 'n8n-workflow'; + +export const spaceOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + default: 'getAll', + description: 'Operation to perform.', + options: [ + { + name: 'Get All', + value: 'getAll', + description: 'Retrieve data on all the spaces in the
logged-in user\'s organization.', + }, + ], + displayOptions: { + show: { + resource: [ + 'space', + ], + }, + }, + }, +] as INodeProperties[]; + +export const spaceFields = [ + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + default: false, + description: 'Return all results.', + displayOptions: { + show: { + resource: [ + 'space', + ], + operation: [ + 'getAll', + ], + }, + }, + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + default: 5, + description: 'The number of results to return.', + typeOptions: { + minValue: 1, + maxValue: 1000, + }, + displayOptions: { + show: { + resource: [ + 'space', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Kitemaker/descriptions/UserDescription.ts b/packages/nodes-base/nodes/Kitemaker/descriptions/UserDescription.ts new file mode 100644 index 0000000000..aca2711242 --- /dev/null +++ b/packages/nodes-base/nodes/Kitemaker/descriptions/UserDescription.ts @@ -0,0 +1,71 @@ +import { + INodeProperties, +} from 'n8n-workflow'; + +export const userOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + default: 'getAll', + description: 'Operation to perform.', + options: [ + { + name: 'Get All', + value: 'getAll', + description: 'Retrieve data on all the users in the
logged-in user\'s organization.', + }, + ], + displayOptions: { + show: { + resource: [ + 'user', + ], + }, + }, + }, +] as INodeProperties[]; + +export const userFields = [ + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + default: false, + description: 'Return all results.', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'getAll', + ], + }, + }, + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + default: 5, + description: 'The number of results to return.', + typeOptions: { + minValue: 1, + maxValue: 1000, + }, + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Kitemaker/descriptions/WorkItemDescription.ts b/packages/nodes-base/nodes/Kitemaker/descriptions/WorkItemDescription.ts new file mode 100644 index 0000000000..637b279fde --- /dev/null +++ b/packages/nodes-base/nodes/Kitemaker/descriptions/WorkItemDescription.ts @@ -0,0 +1,372 @@ +import { + INodeProperties, +} from 'n8n-workflow'; + +export const workItemOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + default: 'get', + description: 'Operation to perform.', + options: [ + { + name: 'Create', + value: 'create', + }, + { + name: 'Get', + value: 'get', + }, + { + name: 'Get All', + value: 'getAll', + }, + { + name: 'Update', + value: 'update', + }, + ], + displayOptions: { + show: { + resource: [ + 'workItem', + ], + }, + }, + }, +] as INodeProperties[]; + +export const workItemFields = [ + // ---------------------------------- + // workItem: create + // ---------------------------------- + { + displayName: 'Title', + name: 'title', + type: 'string', + default: '', + required: true, + description: 'Title of the work item to create.', + displayOptions: { + show: { + resource: [ + 'workItem', + ], + operation: [ + 'create', + ], + }, + }, + }, + { + displayName: 'Status ID', + name: 'statusId', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getStatuses', + }, + default: [], + required: true, + description: 'ID of the status to set on the item to create.', + displayOptions: { + show: { + resource: [ + 'workItem', + ], + operation: [ + 'create', + ], + }, + }, + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'workItem', + ], + operation: [ + 'create', + ], + }, + }, + options: [ + { + displayName: 'Description', + name: 'description', + type: 'string', + default: '', + typeOptions: { + alwaysOpenEditWindow: true, + }, + description: 'Description of the item to create. Markdown supported.', + }, + { + displayName: 'Effort', + name: 'effort', + type: 'options', + default: 'SMALL', + description: 'Effort to set for the item to create.', + options: [ + { + name: 'Small', + value: 'SMALL', + }, + { + name: 'Medium', + value: 'MEDIUM', + }, + { + name: 'Large', + value: 'LARGE', + }, + ], + }, + { + displayName: 'Impact', + name: 'impact', + type: 'options', + default: 'SMALL', + description: 'Impact to set for the item to create.', + options: [ + { + name: 'Small', + value: 'SMALL', + }, + { + name: 'Medium', + value: 'MEDIUM', + }, + { + name: 'Large', + value: 'LARGE', + }, + ], + }, + { + displayName: 'Label IDs', + name: 'labelIds', + type: 'multiOptions', + typeOptions: { + loadOptionsMethod: 'getLabels', + }, + default: [], + description: 'ID of the label to set on the item to create.', + }, + { + displayName: 'Member IDs', + name: 'memberIds', + type: 'multiOptions', + typeOptions: { + loadOptionsMethod: 'getUsers', + }, + default: [], + description: 'ID of the user to assign to the item to create.', + }, + ], + }, + + // ---------------------------------- + // workItem: get + // ---------------------------------- + { + displayName: 'Work Item ID', + name: 'workItemId', + type: 'string', + default: '', + required: true, + description: 'ID of the work item to retrieve.', + displayOptions: { + show: { + resource: [ + 'workItem', + ], + operation: [ + 'get', + ], + }, + }, + }, + + // ---------------------------------- + // workItem: getAll + // ---------------------------------- + { + displayName: 'Space ID', + name: 'spaceId', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getSpaces', + }, + default: [], + required: true, + description: 'ID of the space to retrieve the work items from.', + displayOptions: { + show: { + resource: [ + 'workItem', + ], + operation: [ + 'getAll', + ], + }, + }, + }, + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + default: false, + description: 'Return all results.', + displayOptions: { + show: { + resource: [ + 'workItem', + ], + operation: [ + 'getAll', + ], + }, + }, + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + default: 5, + description: 'The number of results to return.', + typeOptions: { + minValue: 1, + maxValue: 1000, + }, + displayOptions: { + show: { + resource: [ + 'workItem', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + }, + + // ---------------------------------- + // workItem: update + // ---------------------------------- + { + displayName: 'Work Item ID', + name: 'workItemId', + type: 'string', + default: '', + required: true, + description: 'ID of the work item to update.', + displayOptions: { + show: { + resource: [ + 'workItem', + ], + operation: [ + 'update', + ], + }, + }, + }, + { + displayName: 'Update Fields', + name: 'updateFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'workItem', + ], + operation: [ + 'update', + ], + }, + }, + options: [ + { + displayName: 'Description', + name: 'description', + type: 'string', + default: '', + typeOptions: { + alwaysOpenEditWindow: true, + }, + description: 'Description of the item to update. Markdown supported.', + }, + { + displayName: 'Effort', + name: 'effort', + type: 'options', + default: 'SMALL', + description: 'Effort to set for the item to update.', + options: [ + { + name: 'Small', + value: 'SMALL', + }, + { + name: 'Medium', + value: 'MEDIUM', + }, + { + name: 'Large', + value: 'LARGE', + }, + ], + }, + { + displayName: 'Impact', + name: 'impact', + type: 'options', + default: 'SMALL', + description: 'Impact to set for the item to update.', + options: [ + { + name: 'Small', + value: 'SMALL', + }, + { + name: 'Medium', + value: 'MEDIUM', + }, + { + name: 'Large', + value: 'LARGE', + }, + ], + }, + { + displayName: 'Status ID', + name: 'statusId', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getStatuses', + }, + default: [], + description: 'ID of the status to set on the item to update.', + }, + { + displayName: 'Title', + name: 'title', + type: 'string', + default: '', + description: 'Title to set for the work item to update.', + }, + ], + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Kitemaker/descriptions/index.ts b/packages/nodes-base/nodes/Kitemaker/descriptions/index.ts new file mode 100644 index 0000000000..1e2d9a6b8e --- /dev/null +++ b/packages/nodes-base/nodes/Kitemaker/descriptions/index.ts @@ -0,0 +1,4 @@ +export * from './OrganizationDescription'; +export * from './SpaceDescription'; +export * from './UserDescription'; +export * from './WorkItemDescription'; diff --git a/packages/nodes-base/nodes/Kitemaker/kitemaker.svg b/packages/nodes-base/nodes/Kitemaker/kitemaker.svg new file mode 100644 index 0000000000..b6053c44a2 --- /dev/null +++ b/packages/nodes-base/nodes/Kitemaker/kitemaker.svg @@ -0,0 +1,18 @@ + + + + + + + + + diff --git a/packages/nodes-base/nodes/Kitemaker/mutations.ts b/packages/nodes-base/nodes/Kitemaker/mutations.ts new file mode 100644 index 0000000000..be23cb45ab --- /dev/null +++ b/packages/nodes-base/nodes/Kitemaker/mutations.ts @@ -0,0 +1,69 @@ +// ---------------------------------- +// mutations +// ---------------------------------- + +export const createWorkItem = ` + mutation($input: CreateWorkItemInput!) { + createWorkItem(input: $input) { + workItem { + id + number + title + description + status { + id + name + } + members { + id + username + } + watchers { + id + username + } + labels { + id + name + } + effort + impact + updatedAt + createdAt + } + } + } +`; + +export const editWorkItem = ` + mutation ($input: EditWorkItemInput!) { + editWorkItem(input: $input) { + workItem { + id + number + title + description + status { + id + name + } + members { + id + username + } + watchers { + id + username + } + labels { + id + name + } + effort + impact + updatedAt + createdAt + } + } + } +`; diff --git a/packages/nodes-base/nodes/Kitemaker/queries.ts b/packages/nodes-base/nodes/Kitemaker/queries.ts new file mode 100644 index 0000000000..74f584a7c7 --- /dev/null +++ b/packages/nodes-base/nodes/Kitemaker/queries.ts @@ -0,0 +1,199 @@ +// ---------------------------------- +// queries +// ---------------------------------- + +export const getAllSpaces = ` + query { + organization { + spaces { + id + name + labels { + id + name + color + } + statuses { + id + name + type + default + } + } + } + } +`; + +export const getAllUsers = ` + query { + organization { + users { + id + username + } + } + } +`; + +export const getLabels = ` + query { + organization { + spaces { + labels { + id + name + color + } + } + } + } +`; + +export const getOrganization = ` + query { + organization { + id + name + } + } +`; + +export const getSpaces = ` + query { + organization { + spaces { + id + name + labels { + id + name + color + } + statuses { + id + name + type + default + } + } + } + } +`; + +export const getStatuses = ` + query { + organization { + spaces { + statuses { + id + name + type + default + } + } + } + } +`; + +export const getUsers = ` + query { + organization { + users { + id + username + } + } + } +`; + +export const getWorkItems = ` + query($spaceId: ID!) { + workItems(spaceId: $spaceId) { + workItems { + id + title + } + } + } +`; + +export const getWorkItem = ` + query($workItemId: ID!) { + workItem(id: $workItemId) { + id + number + title + description + status { + id + name + } + sort + members { + id + username + } + watchers { + id + username + } + labels { + id + name + } + comments { + id + actor { + __typename + } + body + threadId + updatedAt + createdAt + } + effort + impact + updatedAt + createdAt + } + } +`; + +export const getAllWorkItems = ` + query($spaceId: ID!, $cursor: String) { + workItems(spaceId: $spaceId, cursor: $cursor) { + hasMore, + cursor, + workItems { + id + title + description + labels { + id + } + comments { + id + body + actor { + ... on User { + id + username + } + ... on IntegrationUser { + id + externalName + } + ... on Integration { + id + type + } + ... on Application { + id + name + } + } + } + } + } + } +`; diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index 6056f40f71..963d6c5912 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -133,6 +133,7 @@ "dist/credentials/JotFormApi.credentials.js", "dist/credentials/Kafka.credentials.js", "dist/credentials/KeapOAuth2Api.credentials.js", + "dist/credentials/KitemakerApi.credentials.js", "dist/credentials/LemlistApi.credentials.js", "dist/credentials/LineNotifyOAuth2Api.credentials.js", "dist/credentials/LingvaNexApi.credentials.js", @@ -406,6 +407,7 @@ "dist/nodes/Kafka/KafkaTrigger.node.js", "dist/nodes/Keap/Keap.node.js", "dist/nodes/Keap/KeapTrigger.node.js", + "dist/nodes/Kitemaker/Kitemaker.node.js", "dist/nodes/Lemlist/Lemlist.node.js", "dist/nodes/Lemlist/LemlistTrigger.node.js", "dist/nodes/Line/Line.node.js",