diff --git a/packages/nodes-base/nodes/Github/Github.node.ts b/packages/nodes-base/nodes/Github/Github.node.ts index afe0e8e59c..032f88e73c 100644 --- a/packages/nodes-base/nodes/Github/Github.node.ts +++ b/packages/nodes-base/nodes/Github/Github.node.ts @@ -37,95 +37,210 @@ export class Github implements INodeType { ], properties: [ { - displayName: 'Operation', - name: 'operation', + displayName: 'Resource', + name: 'resource', type: 'options', options: [ { - name: 'Create File', - value: 'createFile', - description: 'Creates a new file in a repository', + name: 'File', + value: 'file', }, { - name: 'Create Issue', - value: 'createIssue', - description: 'Creates a new issue', + name: 'Issue', + value: 'issue', }, { - name: 'Create Issue Comment', - value: 'createIssueComment', - description: 'Creates a new comment on an issue', + name: 'Repository', + value: 'repository', }, { - name: 'Create Release', - value: 'createRelease', - description: 'Creates a new release', + name: 'Release', + value: 'release', }, { - name: 'Delete File', - value: 'deleteFile', - description: 'Deletes a file', + name: 'User', + value: 'user', + }, + ], + default: 'issue', + description: 'The resource to operate on.', + }, + + + + // ---------------------------------- + // operations + // ---------------------------------- + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'issue', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + description: 'Create a new issue', }, { - name: 'Edit Issue', - value: 'editIssue', - description: 'Edits an existing issue', + name: 'Create Comment', + value: 'createComment', + description: 'Create a new comment on an issue', }, { - name: 'Get Community Profile', - value: 'getCommunityProfile', - description: 'Get the community profile of a repository with metrics, health score, description, license, ...', + name: 'Edit', + value: 'edit', + description: 'Edit an issue', }, { - name: 'Get File', - value: 'getFile', - description: 'Get the data of a file', - }, - { - name: 'Get Issue', - value: 'getIssue', + name: 'Get', + value: 'get', description: 'Get the data of a single issues', }, { - name: 'Get Repository Issues', - value: 'getRepositoryIssues', + name: 'Lock', + value: 'lock', + description: 'Lock an issue', + }, + ], + default: 'create', + description: 'The operation to perform.', + }, + + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'file', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + description: 'Create a new file in repository', + }, + { + name: 'Delete', + value: 'delete', + description: 'Delete a file in repository', + }, + { + name: 'Edit', + value: 'edit', + description: 'Edit a file in repository', + }, + { + name: 'Get', + value: 'get', + description: 'Get the data of a single issues', + }, + ], + default: 'create', + description: 'The operation to perform.', + }, + + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'repository', + ], + }, + }, + options: [ + { + name: 'Get License', + value: 'getLicense', + description: 'Returns the contents of the repository\'s license file, if one is detected', + }, + { + name: 'Get Issues', + value: 'getIssues', description: 'Returns issues of a repository', }, { - name: 'Get Repository License', - value: 'getRepositoryLicense', - description: 'Returns the contents of the repository\'s license file, if one is detected', + name: 'Get Profile', + value: 'getProfile', + description: 'Get the community profile of a repository with metrics, health score, description, license, ...', }, { name: 'List Popular Paths', value: 'listPopularPaths', - description: 'Get the top 10 popular content paths over the last 14 days.', + description: 'Get the data of a file in repositoryGet the top 10 popular content paths over the last 14 days.', }, { name: 'List Referrers', value: 'listReferrers', description: 'Get the top 10 referrering domains over the last 14 days', }, - { - name: 'List User Repositories', - value: 'listUserRepositories', - description: 'Returns the repositories of a user', - }, - { - name: 'Lock Issue', - value: 'lockIssue', - description: 'Lock an issue', - }, - { - name: 'Update File', - value: 'updateFile', - description: 'Updates an existing file', - }, ], - default: 'createIssue', + default: 'getIssues', description: 'The operation to perform.', }, + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'user', + ], + }, + }, + options: [ + { + name: 'Get Repositories', + value: 'getRepositories', + description: 'Returns the repositories of a user', + }, + ], + default: 'getRepositories', + description: 'The operation to perform.', + }, + + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'release', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + description: 'Creates a new release', + }, + ], + default: 'create', + description: 'The operation to perform.', + }, + + + + // ---------------------------------- + // shared + // ---------------------------------- { displayName: 'Repository Owner', name: 'owner', @@ -143,8 +258,11 @@ export class Github implements INodeType { required: true, displayOptions: { hide: { + resource: [ + 'user', + ], operation: [ - 'listUserRepositories', + 'getRepositories', ], }, }, @@ -155,9 +273,12 @@ export class Github implements INodeType { // ---------------------------------- - // createFile / deleteFile / getFile / updateFile + // file // ---------------------------------- + // ---------------------------------- + // file:create/delete/edit/get + // ---------------------------------- { displayName: 'File Path', name: 'filePath', @@ -166,11 +287,8 @@ export class Github implements INodeType { required: true, displayOptions: { show: { - operation: [ - 'createFile', - 'deleteFile', - 'getFile', - 'updateFile', + resource: [ + 'file', ], }, }, @@ -178,12 +296,9 @@ export class Github implements INodeType { description: 'The file path of the file. Has to contain the full path.', }, - - // ---------------------------------- - // createFile / updateFile + // file:create/edit // ---------------------------------- - { displayName: 'Binary Data', name: 'binaryData', @@ -193,8 +308,11 @@ export class Github implements INodeType { displayOptions: { show: { operation: [ - 'createFile', - 'updateFile', + 'create', + 'edit', + ], + resource: [ + 'file', ], }, }, @@ -208,13 +326,16 @@ export class Github implements INodeType { required: true, displayOptions: { show: { - operation: [ - 'createFile', - 'updateFile', - ], binaryData: [ false, ], + operation: [ + 'create', + 'edit', + ], + resource: [ + 'file', + ], }, }, @@ -229,13 +350,16 @@ export class Github implements INodeType { required: true, displayOptions: { show: { - operation: [ - 'createFile', - 'updateFile', - ], binaryData: [ true, ], + operation: [ + 'create', + 'edit', + ], + resource: [ + 'file', + ], }, }, @@ -251,15 +375,17 @@ export class Github implements INodeType { displayOptions: { show: { operation: [ - 'createFile', - 'deleteFile', - 'updateFile', + 'create', + 'delete', + 'edit', + ], + resource: [ + 'file', ], }, }, description: 'The commit message.', }, - { displayName: 'Additional Parameters', name: 'additionalParameters', @@ -270,9 +396,12 @@ export class Github implements INodeType { displayOptions: { show: { operation: [ - 'createFile', - 'deleteFile', - 'updateFile', + 'create', + 'delete', + 'edit', + ], + resource: [ + 'file', ], }, }, @@ -333,12 +462,59 @@ export class Github implements INodeType { ], }, + // ---------------------------------- + // file:get + // ---------------------------------- + { + displayName: 'As Binary Property', + name: 'asBinaryProperty', + type: 'boolean', + default: true, + displayOptions: { + show: { + operation: [ + 'get', + ], + resource: [ + 'file', + ], + }, + }, + description: 'If set it will set the data of the file as binary property
instead of returning the raw API response.', + }, + { + displayName: 'Binary Property', + name: 'binaryPropertyName', + type: 'string', + default: 'data', + required: true, + displayOptions: { + show: { + asBinaryProperty: [ + true, + ], + operation: [ + 'get', + ], + resource: [ + 'file', + ], + }, + + }, + placeholder: '', + description: 'Name of the binary property in which to save
the binary data of the received file.', + }, + // ---------------------------------- - // createIssue + // issue // ---------------------------------- + // ---------------------------------- + // issue:create + // ---------------------------------- { displayName: 'Title', name: 'title', @@ -348,7 +524,10 @@ export class Github implements INodeType { displayOptions: { show: { operation: [ - 'createIssue', + 'create', + ], + resource: [ + 'issue', ], }, }, @@ -365,7 +544,10 @@ export class Github implements INodeType { displayOptions: { show: { operation: [ - 'createIssue', + 'create', + ], + resource: [ + 'issue', ], }, }, @@ -382,7 +564,10 @@ export class Github implements INodeType { displayOptions: { show: { operation: [ - 'createIssue', + 'create', + ], + resource: [ + 'issue', ], }, }, @@ -408,7 +593,10 @@ export class Github implements INodeType { displayOptions: { show: { operation: [ - 'createIssue', + 'create', + ], + resource: [ + 'issue', ], }, }, @@ -424,11 +612,9 @@ export class Github implements INodeType { ], }, - // ---------------------------------- - // createIssueComment + // issue:createComment // ---------------------------------- - { displayName: 'Issue Number', name: 'issueNumber', @@ -438,7 +624,10 @@ export class Github implements INodeType { displayOptions: { show: { operation: [ - 'createIssueComment', + 'createComment', + ], + resource: [ + 'issue', ], }, }, @@ -454,7 +643,10 @@ export class Github implements INodeType { displayOptions: { show: { operation: [ - 'createIssueComment', + 'createComment', + ], + resource: [ + 'issue', ], }, }, @@ -462,88 +654,9 @@ export class Github implements INodeType { description: 'The body of the comment.', }, - // ---------------------------------- - // createRelease + // issue:edit // ---------------------------------- - - { - displayName: 'Tag', - name: 'releaseTag', - type: 'string', - default: '', - required: true, - displayOptions: { - show: { - operation: [ - 'createRelease', - ], - }, - }, - description: 'The tag of the release.', - }, - { - displayName: 'Edit Fields', - name: 'createReleaseFields', - type: 'collection', - typeOptions: { - multipleValueButtonText: 'Add Field', - }, - displayOptions: { - show: { - operation: [ - 'createRelease' - ], - }, - }, - default: {}, - options: [ - { - displayName: 'Name', - name: 'name', - type: 'string', - default: '', - description: 'The name of the issue.', - }, - { - displayName: 'Body', - name: 'body', - type: 'string', - typeOptions: { - rows: 5, - }, - default: '', - description: 'The body of the release.', - }, - { - displayName: 'Draft', - name: 'draft', - type: 'boolean', - default: false, - description: 'Set "true" to create a draft (unpublished) release, "false" to create a published one.', - }, - { - displayName: 'Prerelease', - name: 'prerelease', - type: 'boolean', - default: false, - description: 'If set to "true" it will point out that the release is non-production ready.', - }, - { - displayName: 'Target Commitish', - name: 'target_commitish', - type: 'string', - default: '', - description: 'Specifies the commitish value that determines where the Git tag is created from. Can be any branch or commit SHA. Unused if the Git tag already exists. Default: the repository\'s default branch(usually master).', - }, - ], - }, - - - // ---------------------------------- - // editIssue - // ---------------------------------- - { displayName: 'Issue Number', name: 'issueNumber', @@ -553,7 +666,10 @@ export class Github implements INodeType { displayOptions: { show: { operation: [ - 'editIssue', + 'edit', + ], + resource: [ + 'issue', ], }, }, @@ -569,7 +685,10 @@ export class Github implements INodeType { displayOptions: { show: { operation: [ - 'editIssue' + 'edit', + ], + resource: [ + 'issue', ], }, }, @@ -652,53 +771,9 @@ export class Github implements INodeType { ], }, - - // ---------------------------------- - // getFile + // issue:get // ---------------------------------- - - { - displayName: 'As Binary Property', - name: 'asBinaryProperty', - type: 'boolean', - default: true, - displayOptions: { - show: { - operation: [ - 'getFile', - ], - }, - }, - description: 'If set it will set the data of the file as binary property
instead of returning the raw API response.', - }, - { - displayName: 'Binary Property', - name: 'binaryPropertyName', - type: 'string', - default: 'data', - required: true, - displayOptions: { - show: { - operation: [ - 'getFile', - ], - asBinaryProperty: [ - true, - ], - }, - - }, - placeholder: '', - description: 'Name of the binary property in which to save
the binary data of the received file.', - }, - - - - // ---------------------------------- - // getIssue - // ---------------------------------- - { displayName: 'Issue Number', name: 'issueNumber', @@ -708,19 +783,173 @@ export class Github implements INodeType { displayOptions: { show: { operation: [ - 'getIssue', + 'get', + ], + resource: [ + 'issue', ], }, }, description: 'The number of the issue get data of.', }, + // ---------------------------------- + // issue:lock + // ---------------------------------- + { + displayName: 'Issue Number', + name: 'issueNumber', + type: 'number', + default: 0, + required: true, + displayOptions: { + show: { + operation: [ + 'lock', + ], + resource: [ + 'issue', + ], + }, + }, + description: 'The number of the issue to lock.', + }, + { + displayName: 'Lock Reason', + name: 'lockReason', + type: 'options', + displayOptions: { + show: { + operation: [ + 'lock', + ], + resource: [ + 'issue', + ], + }, + }, + options: [ + { + name: 'Off-Topic', + value: 'off-topic', + description: 'The issue is Off-Topic', + }, + { + name: 'Too Heated', + value: 'too heated', + description: 'The discussion is too heated', + }, + { + name: 'Resolved', + value: 'resolved', + description: 'The issue got resolved', + }, + { + name: 'Spam', + value: 'spam', + description: 'The issue is spam', + }, + ], + default: 'resolved', + description: 'The reason to lock the issue.', + }, + + // ---------------------------------- - // getRepositoryIssues + // release // ---------------------------------- + // ---------------------------------- + // release:create + // ---------------------------------- + { + displayName: 'Tag', + name: 'releaseTag', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + operation: [ + 'create', + ], + resource: [ + 'release', + ], + }, + }, + description: 'The tag of the release.', + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + typeOptions: { + multipleValueButtonText: 'Add Field', + }, + displayOptions: { + show: { + operation: [ + 'create', + ], + resource: [ + 'release', + ], + }, + }, + default: {}, + options: [ + { + displayName: 'Name', + name: 'name', + type: 'string', + default: '', + description: 'The name of the issue.', + }, + { + displayName: 'Body', + name: 'body', + type: 'string', + typeOptions: { + rows: 5, + }, + default: '', + description: 'The body of the release.', + }, + { + displayName: 'Draft', + name: 'draft', + type: 'boolean', + default: false, + description: 'Set "true" to create a draft (unpublished) release, "false" to create a published one.', + }, + { + displayName: 'Prerelease', + name: 'prerelease', + type: 'boolean', + default: false, + description: 'If set to "true" it will point out that the release is non-production ready.', + }, + { + displayName: 'Target Commitish', + name: 'target_commitish', + type: 'string', + default: '', + description: 'Specifies the commitish value that determines where the Git tag is created from. Can be any branch or commit SHA. Unused if the Git tag already exists. Default: the repository\'s default branch(usually master).', + }, + ], + }, + + + // ---------------------------------- + // repository + // ---------------------------------- + + // ---------------------------------- + // repository:getIssues + // ---------------------------------- { displayName: 'Filters', name: 'getRepositoryIssuesFilters', @@ -731,7 +960,10 @@ export class Github implements INodeType { displayOptions: { show: { operation: [ - 'getRepositoryIssues' + 'getIssues' + ], + resource: [ + 'repository', ], }, }, @@ -843,62 +1075,6 @@ export class Github implements INodeType { ], }, - - // ---------------------------------- - // lockIssue - // ---------------------------------- - - { - displayName: 'Issue Number', - name: 'issueNumber', - type: 'number', - default: 0, - required: true, - displayOptions: { - show: { - operation: [ - 'lockIssue', - ], - }, - }, - description: 'The number of the issue to lock.', - }, - { - displayName: 'Lock Reason', - name: 'lockReason', - type: 'options', - displayOptions: { - show: { - operation: [ - 'lockIssue' - ], - }, - }, - options: [ - { - name: 'Off-Topic', - value: 'off-topic', - description: 'The issue is Off-Topic', - }, - { - name: 'Too Heated', - value: 'too heated', - description: 'The discussion is too heated', - }, - { - name: 'Resolved', - value: 'resolved', - description: 'The issue got resolved', - }, - { - name: 'Spam', - value: 'spam', - description: 'The issue is spam', - }, - ], - default: 'resolved', - description: 'The reason to lock the issue.', - }, ], }; @@ -915,25 +1091,25 @@ export class Github implements INodeType { // Operations which overwrite the returned data const overwriteDataOperations = [ - 'createFile', - 'createIssue', - 'createIssueComment', - 'createRelease', - 'deleteFile', - 'editIssue', - 'getCommunityProfile', - 'getFile', - 'getIssue', - 'getRepositoryLicense', - 'updateFile', + 'file:create', + 'file:delete', + 'file:edit', + 'file:get', + 'issue:create', + 'issue:createComment', + 'issue:edit', + 'issue:get', + 'release:create', + 'repository:getLicense', + 'repository:getProfile', ]; // Operations which overwrite the returned data and return arrays // and has so to be merged with the data of other items const overwriteDataOperationsArray = [ - 'getRepositoryIssues', - 'listPopularPaths', - 'listReferrers', - 'listUserRepositories', + 'repository:getIssues', + 'repository:listPopularPaths', + 'repository:listReferrers', + 'user:getRepositories', ]; @@ -946,6 +1122,8 @@ export class Github implements INodeType { let endpoint: string; const operation = this.getNodeParameter('operation', 0) as string; + const resource = this.getNodeParameter('resource', 0) as string; + const fullOperation = `${resource}:${operation}`; for (let i = 0; i < items.length; i++) { // Reset all values @@ -957,169 +1135,232 @@ export class Github implements INodeType { // Request the parameters which almost all operations need const owner = this.getNodeParameter('owner', i) as string; let repository = ''; - if (operation !== 'listUserRepositories') { + if (fullOperation !== 'user:getRepositories') { repository = this.getNodeParameter('repository', i) as string; } - if (['createFile', 'updateFile'].includes(operation)) { - requestMethod = 'PUT'; + if (resource === 'file') { + if (['create', 'edit'].includes(operation)) { + // ---------------------------------- + // create/edit + // ---------------------------------- - const filePath = this.getNodeParameter('filePath', i) as string; + requestMethod = 'PUT'; - const additionalParameters = this.getNodeParameter('additionalParameters', i, {}) as IDataObject; - if (additionalParameters.author) { - body.author = additionalParameters.author; - } - if (additionalParameters.committer) { - body.committer = additionalParameters.committer; - } - if (additionalParameters.branch && (additionalParameters.branch as IDataObject).branch) { - body.branch = (additionalParameters.branch as IDataObject).branch; - } + const filePath = this.getNodeParameter('filePath', i) as string; + + const additionalParameters = this.getNodeParameter('additionalParameters', i, {}) as IDataObject; + if (additionalParameters.author) { + body.author = additionalParameters.author; + } + if (additionalParameters.committer) { + body.committer = additionalParameters.committer; + } + if (additionalParameters.branch && (additionalParameters.branch as IDataObject).branch) { + body.branch = (additionalParameters.branch as IDataObject).branch; + } + + if (operation === 'edit') { + // If the file should be updated the request has to contain the SHA + // of the file which gets replaced. + body.sha = await getFileSha.call(this, owner, repository, filePath, body.branch as string | undefined); + } + + body.message = this.getNodeParameter('commitMessage', i) as string; + + if (this.getNodeParameter('binaryData', i) === true) { + // Is binary file to upload + const item = items[i]; + + if (item.binary === undefined) { + throw new Error('No binary data exists on item!'); + } + + const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i) as string; + + if (item.binary[binaryPropertyName] === undefined) { + throw new Error(`No binary data property "${binaryPropertyName}" does not exists on item!`); + } + + // Currently internally n8n uses base64 and also Github expects it base64 encoded. + // If that ever changes the data has to get converted here. + body.content = item.binary[binaryPropertyName].data; + } else { + // Is text file + // body.content = Buffer.from(this.getNodeParameter('fileContent', i) as string, 'base64'); + body.content = Buffer.from(this.getNodeParameter('fileContent', i) as string).toString('base64'); + } + + endpoint = `/repos/${owner}/${repository}/contents/${encodeURI(filePath)}`; + } else if (operation === 'delete') { + // ---------------------------------- + // delete + // ---------------------------------- + + requestMethod = 'DELETE'; + + const additionalParameters = this.getNodeParameter('additionalParameters', i, {}) as IDataObject; + if (additionalParameters.author) { + body.author = additionalParameters.author; + } + if (additionalParameters.committer) { + body.committer = additionalParameters.committer; + } + if (additionalParameters.branch && (additionalParameters.branch as IDataObject).branch) { + body.branch = (additionalParameters.branch as IDataObject).branch; + } + + const filePath = this.getNodeParameter('filePath', i) as string; + body.message = this.getNodeParameter('commitMessage', i) as string; - if (operation === 'updateFile') { - // If the file should be updated the request has to contain the SHA - // of the file which gets replaced. body.sha = await getFileSha.call(this, owner, repository, filePath, body.branch as string | undefined); + + endpoint = `/repos/${owner}/${repository}/contents/${encodeURI(filePath)}`; + } else if (operation === 'get') { + requestMethod = 'GET'; + + const filePath = this.getNodeParameter('filePath', i) as string; + + endpoint = `/repos/${owner}/${repository}/contents/${encodeURI(filePath)}`; } + } else if (resource === 'issue') { + if (operation === 'create') { + // ---------------------------------- + // create + // ---------------------------------- - body.message = this.getNodeParameter('commitMessage', i) as string; + requestMethod = 'POST'; - if (this.getNodeParameter('binaryData', i) === true) { - // Is binary file to upload - const item = items[i]; + body.title = this.getNodeParameter('title', i) as string; + body.body = this.getNodeParameter('body', i) as string; + const labels = this.getNodeParameter('labels', i) as IDataObject[]; - if (item.binary === undefined) { - throw new Error('No binary data exists on item!'); + const assignees = this.getNodeParameter('assignees', i) as IDataObject[]; + + body.labels = labels.map((data) => data['label']); + body.assignees = assignees.map((data) => data['assignee']); + + endpoint = `/repos/${owner}/${repository}/issues`; + } else if (operation === 'createComment') { + // ---------------------------------- + // createComment + // ---------------------------------- + requestMethod = 'POST'; + + const issueNumber = this.getNodeParameter('issueNumber', i) as string; + + body.body = this.getNodeParameter('body', i) as string; + + endpoint = `/repos/${owner}/${repository}/issues/${issueNumber}/comments`; + } else if (operation === 'edit') { + // ---------------------------------- + // edit + // ---------------------------------- + + requestMethod = 'PATCH'; + + const issueNumber = this.getNodeParameter('issueNumber', i) as string; + + body = this.getNodeParameter('editFields', i, {}) as IDataObject; + + if (body.labels !== undefined) { + body.labels = (body.labels as IDataObject[]).map((data) => data['label']); + } + if (body.assignees !== undefined) { + body.assignees = (body.assignees as IDataObject[]).map((data) => data['assignee']); } - const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i) as string; + endpoint = `/repos/${owner}/${repository}/issues/${issueNumber}`; + } else if (operation === 'get') { + // ---------------------------------- + // get + // ---------------------------------- - if (item.binary[binaryPropertyName] === undefined) { - throw new Error(`No binary data property "${binaryPropertyName}" does not exists on item!`); - } + requestMethod = 'GET'; - // Currently internally n8n uses base64 and also Github expects it base64 encoded. - // If that ever changes the data has to get converted here. - body.content = item.binary[binaryPropertyName].data; - } else { - // Is text file - // body.content = Buffer.from(this.getNodeParameter('fileContent', i) as string, 'base64'); - body.content = Buffer.from(this.getNodeParameter('fileContent', i) as string).toString('base64'); + const issueNumber = this.getNodeParameter('issueNumber', i) as string; + + endpoint = `/repos/${owner}/${repository}/issues/${issueNumber}`; + } else if (operation === 'lock') { + // ---------------------------------- + // lock + // ---------------------------------- + + requestMethod = 'PUT'; + + const issueNumber = this.getNodeParameter('issueNumber', i) as string; + + qs.lock_reason = this.getNodeParameter('lockReason', i) as string; + + endpoint = `/repos/${owner}/${repository}/issues/${issueNumber}/lock`; } + } else if (resource === 'release') { + if (operation === 'create') { + // ---------------------------------- + // create + // ---------------------------------- - endpoint = `/repos/${owner}/${repository}/contents/${encodeURI(filePath)}`; - } else if (operation === 'createIssue') { - requestMethod = 'POST'; + requestMethod = 'POST'; - body.title = this.getNodeParameter('title', i) as string; - body.body = this.getNodeParameter('body', i) as string; - const labels = this.getNodeParameter('labels', i) as IDataObject[]; + body = this.getNodeParameter('additionalFields', i, {}) as IDataObject; - const assignees = this.getNodeParameter('assignees', i) as IDataObject[]; + body.tag_name = this.getNodeParameter('releaseTag', i) as string; - body.labels = labels.map((data) => data['label']); - body.assignees = assignees.map((data) => data['assignee']); - - endpoint = `/repos/${owner}/${repository}/issues`; - } else if (operation === 'createIssueComment') { - requestMethod = 'POST'; - - const issueNumber = this.getNodeParameter('issueNumber', i) as string; - - body.body = this.getNodeParameter('body', i) as string; - - endpoint = `/repos/${owner}/${repository}/issues/${issueNumber}/comments`; - } else if (operation === 'createRelease') { - requestMethod = 'POST'; - - body = this.getNodeParameter('createReleaseFields', i, {}) as IDataObject; - - body.tag_name = this.getNodeParameter('releaseTag', i) as string; - - endpoint = `/repos/${owner}/${repository}/releases`; - } else if (operation === 'deleteFile') { - requestMethod = 'DELETE'; - - const additionalParameters = this.getNodeParameter('additionalParameters', i, {}) as IDataObject; - if (additionalParameters.author) { - body.author = additionalParameters.author; + endpoint = `/repos/${owner}/${repository}/releases`; } - if (additionalParameters.committer) { - body.committer = additionalParameters.committer; + } else if (resource === 'repository') { + if (operation === 'listPopularPaths') { + // ---------------------------------- + // listPopularPaths + // ---------------------------------- + + requestMethod = 'GET'; + + endpoint = `/repos/${owner}/${repository}/traffic/popular/paths`; + } else if (operation === 'listReferrers') { + // ---------------------------------- + // listReferrers + // ---------------------------------- + + requestMethod = 'GET'; + + endpoint = `/repos/${owner}/${repository}/traffic/popular/referrers`; + } else if (operation === 'getLicense') { + // ---------------------------------- + // getLicense + // ---------------------------------- + + requestMethod = 'GET'; + + endpoint = `/repos/${owner}/${repository}/license`; + } else if (operation === 'getIssues') { + // ---------------------------------- + // getIssues + // ---------------------------------- + + requestMethod = 'GET'; + + qs = this.getNodeParameter('getRepositoryIssuesFilters', i) as IDataObject; + + endpoint = `/repos/${owner}/${repository}/issues`; } - if (additionalParameters.branch && (additionalParameters.branch as IDataObject).branch) { - body.branch = (additionalParameters.branch as IDataObject).branch; + } else if (resource === 'user') { + if (operation === 'getRepositories') { + // ---------------------------------- + // getRepositories + // ---------------------------------- + + requestMethod = 'GET'; + + endpoint = `/users/${owner}/repos`; } - - const filePath = this.getNodeParameter('filePath', i) as string; - body.message = this.getNodeParameter('commitMessage', i) as string; - - body.sha = await getFileSha.call(this, owner, repository, filePath, body.branch as string | undefined); - - endpoint = `/repos/${owner}/${repository}/contents/${encodeURI(filePath)}`; - } else if (operation === 'editIssue') { - requestMethod = 'PATCH'; - - const issueNumber = this.getNodeParameter('issueNumber', i) as string; - - body = this.getNodeParameter('editFields', i, {}) as IDataObject; - - if (body.labels !== undefined) { - body.labels = (body.labels as IDataObject[]).map((data) => data['label']); - } - if (body.assignees !== undefined) { - body.assignees = (body.assignees as IDataObject[]).map((data) => data['assignee']); - } - - endpoint = `/repos/${owner}/${repository}/issues/${issueNumber}`; - } else if (operation === 'getFile') { - requestMethod = 'GET'; - - const filePath = this.getNodeParameter('filePath', i) as string; - - endpoint = `/repos/${owner}/${repository}/contents/${encodeURI(filePath)}`; - } else if (operation === 'getIssue') { - requestMethod = 'GET'; - - const issueNumber = this.getNodeParameter('issueNumber', i) as string; - - endpoint = `/repos/${owner}/${repository}/issues/${issueNumber}`; - } else if (operation === 'listPopularPaths') { - requestMethod = 'GET'; - - endpoint = `/repos/${owner}/${repository}/traffic/popular/paths`; - } else if (operation === 'listReferrers') { - requestMethod = 'GET'; - - endpoint = `/repos/${owner}/${repository}/traffic/popular/referrers`; - } else if (operation === 'getRepositoryLicense') { - requestMethod = 'GET'; - - endpoint = `/repos/${owner}/${repository}/license`; - } else if (operation === 'getRepositoryIssues') { - requestMethod = 'GET'; - - qs = this.getNodeParameter('getRepositoryIssuesFilters', i) as IDataObject; - - endpoint = `/repos/${owner}/${repository}/issues`; - } else if (operation === 'listUserRepositories') { - requestMethod = 'GET'; - - endpoint = `/users/${owner}/repos`; - } else if (operation === 'lockIssue') { - requestMethod = 'PUT'; - - const issueNumber = this.getNodeParameter('issueNumber', i) as string; - - qs.lock_reason = this.getNodeParameter('lockReason', i) as string; - - endpoint = `/repos/${owner}/${repository}/issues/${issueNumber}/lock`; + } else { + throw new Error(`The resource "${resource}" is not known!`); } const responseData = await githubApiRequest.call(this, requestMethod, endpoint, body, qs); - if (operation === 'getFile') { + if (fullOperation === 'file:get') { const asBinaryProperty = this.getNodeParameter('asBinaryProperty', i); if (asBinaryProperty === true) { @@ -1133,14 +1374,14 @@ export class Github implements INodeType { } } - if (overwriteDataOperations.includes(operation)) { + if (overwriteDataOperations.includes(fullOperation)) { returnData.push(responseData); - } else if (overwriteDataOperationsArray.includes(operation)) { + } else if (overwriteDataOperationsArray.includes(fullOperation)) { returnData.push.apply(returnData, responseData); } } - if (overwriteDataOperations.includes(operation) || overwriteDataOperationsArray.includes(operation)) { + if (overwriteDataOperations.includes(fullOperation) || overwriteDataOperationsArray.includes(fullOperation)) { // Return data gets replaced return [this.helpers.returnJsonArray(returnData)]; } else {