Merge branch 'gitbeaker-release'

This commit is contained in:
Justin 2020-03-22 15:17:07 +01:00
commit 1fe6b54372
203 changed files with 14799 additions and 19126 deletions

View File

@ -1,21 +0,0 @@
codecov:
max_report_age: off
comment: false
coverage:
precision: 2
round: down
status:
project:
default:
threshold: 0.2
if_not_found: success
patch:
default:
enabled: no
if_not_found: success
changes:
default:
enabled: no
if_not_found: success

12
.commitlintrc.yml Normal file
View File

@ -0,0 +1,12 @@
extends:
- '@commitlint/config-lerna-scopes'
- '@commitlint/config-conventional'
rules:
subject-case:
- 0
- always
- 'sentence-case'
header-case:
- 0
- always
- 'sentence-case'

View File

@ -12,9 +12,12 @@ extends:
parser: '@typescript-eslint/parser'
parserOptions:
project: tsconfig.eslint.json
sourceType: module
ignorePatterns:
- node_modules/
- dist/
- '**/rollup.config.js'
- '**/scripts/*.ts'
- '*d.ts'
plugins:
- '@typescript-eslint'
@ -24,18 +27,18 @@ rules:
import/no-default-export: error
import/prefer-default-export: off
'@typescript-eslint/explicit-function-return-type': off
overrides:
- files:
- 'test/**/*.ts'
rules:
import/no-unresolved: 0
import/no-extraneous-dependencies:
- error
- devDependencies:
- '**/test/**/*.ts'
import/extensions:
- error
- never
- json: always
settings:
import/resolver:
node:
extensions:
- .js
- .jsx
- .ts
- .tsx

11
.github/ASSETS/header.svg vendored Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.4 KiB

10
.github/ASSETS/logo.svg vendored Normal file
View File

@ -0,0 +1,10 @@
<svg width="60" height="100" viewBox="0 0 60 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="36.5172" cy="9.48268" r="2.22414" stroke="#FC6D27" stroke-width="3"/>
<circle cx="41.1724" cy="2.96547" r="1.7931" stroke="#FCA326" stroke-width="2"/>
<path d="M8.06306 76.2369C8.06062 77.2035 7.72081 79.4293 8.64417 79.7048C11.9298 81.1512 14.0865 80.7243 27.9585 80.6987C46.9867 81.4273 43.8306 80.8751 46.9867 78.5964C46.9867 75.4914 47.3839 76.2369 43.8306 71.7642C42.7811 70.4431 39.3162 66.6221 38.9819 66.1952C38.2741 65.2915 37.3497 64.9719 35.5299 65.0019C34.1067 65.0254 32.6426 65.6324 30.1766 67.2215C26.705 69.4587 26.3866 67.2215 24.211 67.2215C22.6235 67.2215 20.3919 69.9202 18.7198 68.561C17.9342 67.9224 17.0538 67.3488 16.7633 67.2861C15.628 67.0414 15.4042 67.2536 11.3249 72.4416C7.74084 75.7675 8.0648 75.5206 8.06306 76.2369Z" fill="#FCA326"/>
<path d="M3.08731 85.4508C3.08393 86.7797 2.61342 89.8403 3.89192 90.2191C8.4413 92.2079 11.4275 91.6209 30.6348 91.5857C56.9816 92.5875 52.6115 91.8283 56.9816 88.695C56.9816 84.4257 57.5315 85.4508 52.6116 79.3007C51.1584 77.4843 46.3609 72.2304 45.898 71.6434C44.918 70.4007 43.638 69.9613 41.1184 70.0026C39.1477 70.0349 37.1205 70.8696 33.706 73.0546C28.8992 76.1307 28.4584 73.0546 25.446 73.0546C23.2479 73.0546 20.158 76.7653 17.8428 74.8963C16.7551 74.0184 15.5361 73.2296 15.1338 73.1435C13.5619 72.807 13.252 73.0987 7.60374 80.2322C2.64116 84.8053 3.08972 84.4658 3.08731 85.4508Z" fill="#FC6D27"/>
<path d="M3.08731 89.9392C3.08393 90.9662 2.61342 93.3312 3.89192 93.6238C8.4413 95.1607 11.4275 94.707 30.6348 94.6799C56.9816 95.454 52.6115 94.8673 56.9816 92.4461C56.9816 89.1471 57.5315 89.9392 52.6116 85.1869C51.1584 83.7833 46.3609 79.7235 45.898 79.2699C44.918 78.3097 43.638 77.9701 41.1184 78.002C39.1477 78.027 37.1205 78.672 33.706 80.3604C28.8992 82.7373 28.4584 80.3604 25.446 80.3604C23.2479 80.3604 20.158 83.2277 17.8428 81.7835C16.7551 81.1051 15.5361 80.4956 15.1338 80.429C13.5619 80.169 13.252 80.3945 7.60374 85.9067C2.64116 89.4404 3.08972 89.1781 3.08731 89.9392Z" fill="#E2432A"/>
<path d="M22.491 60.7898V27.7356L20.0859 24.0653C19.6501 23.4003 20.1272 22.5172 20.9223 22.5172H38.5201C39.3404 22.5172 39.8118 23.4505 39.3249 24.1107L36.6518 27.7356V60.7898L57 84.5242V91.5228L50.5329 97H9.46707L3 91.5228V84.5242L22.491 60.7898Z" stroke="#383838" stroke-width="5"/>
<circle cx="37.3793" cy="79.1034" r="1" fill="#E5E5E5"/>
<circle cx="34.8621" cy="74.8621" r="1.86207" fill="#E5E5E5"/>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
.github/ASSETS/thumbnail.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

2
.gitignore vendored
View File

@ -5,4 +5,4 @@ coverage
.rpt2_cache
.idea
.DS_Store
temp
yarn-error.log

127
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,127 @@
default:
image: node:lts-alpine
# Cache modules in between jobs
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- packages/gitbeaker-core/node_modules/
- packages/gitbeaker-cli/node_modules/
- packages/gitbeaker-browser/node_modules/
- packages/gitbeaker-node/node_modules/
- packages/gitbeaker-requester-utils/node_modules/
- node_modules/
stages:
- install
- build
- lint
- test
- release
#Link and Install all required dependancies
install:
image: node:lts
stage: install
script:
- yarn
# Build core (cjs, es, and browser) and cli packages
# Uses work around to allow for linking of the cli packages
build:
stage: build
script:
- yarn build
artifacts:
paths:
- packages/gitbeaker-core/dist/
- packages/gitbeaker-cli/dist/
- packages/gitbeaker-browser/dist/
- packages/gitbeaker-node/dist/
- packages/gitbeaker-requester-utils/dist/
# Lint all code, tests and supporting documentation (README, CHANGELOG etc)
lint:src:
stage: lint
script: yarn lint
lint:docs:
stage: lint
script: yarn lint:doc
# Test packages and builds
test:core:unit:
stage: test
script: yarn jest core/test/unit && yarn codecov -F core
test:node:unit:
stage: test
script: yarn jest node/test/unit && yarn codecov -F node
test:browser:unit:
stage: test
script: yarn jest browser/test/unit && yarn codecov -F browser
test:utils:unit:
stage: test
script: yarn jest utils/test/unit && yarn codecov -F utils
# test:core:integration: &integration
# image:
# name: docker/compose:latest
# entrypoint: ['/bin/sh', '-c']
# variables:
# DOCKER_HOST: tcp://docker:2375
# GITLAB_URL: http://docker:8080
# services:
# - docker:dind
# stage: test
# before_script:
# # Install docker compose
# - apk add --no-cache nodejs yarn git
# # Spin up container
# - cd scripts
# - docker-compose -f docker-compose.yml up -d
# # Verify Gitlab instance is up and running
# - node probe.js
# # Get the personal token
# - export PERSONAL_ACCESS_TOKEN=$(docker exec -i gitlab sh -c 'gitlab-rails r /mnt/init.rb')
# - cd ..
# - echo $PERSONAL_ACCESS_TOKEN
# - echo $GITLAB_URL
# - echo $CODECOV_TOKEN
# script: yarn jest core/test/integration --runInBand && yarn codecov -F core
# test:cli:integration:
# <<: *integration
# script: yarn jest core/test/integration --runInBand && yarn codecov
# test:cli:integration:dist:
# <<: *integration
# script: yarn jest core/test/integration --runInBand && yarn codecov
# test:core:integration:dist-cjs:
# <<: *integration
# script: yarn jest core/test/integration --runInBand --moduleNameMapper="{dist:dist/index.es.js}"
# test:core:integration:dist-es
# <<: *integration
# script: yarn jest core/test/integration --runInBand --moduleNameMapper="{dist:dist/index.es.js}"
# test:core:integration:browser:
# <<: *integration
# script: npm run test:integration -- --scope=core --moduleNameMapper="{dist:dist/index.umd.js}" && codecov
# Release
release:
only:
refs:
- master
stage: release
before_script:
- apk add --no-cache git
script: yarn release

View File

@ -1,2 +1,3 @@
hooks:
pre-commit: 'lint-staged'
commit-msg: 'commitlint -E HUSKY_GIT_PARAMS'

View File

@ -1,7 +1,4 @@
'*.{ts, !(generate).ts}':
'*.{ts,js,json,md,yml}':
- 'prettier --write'
'*.{ts,js}':
- 'eslint --fix'
- 'git add'
'*.{json, md, yml, js}':
- 'prettier --write'
- 'git add'

View File

@ -1,9 +1,15 @@
tagFormat: '${version}'
verifyConditions:
plugins:
- '@semantic-release/commit-analyzer'
- '@semantic-release/release-notes-generator'
- '@semantic-release/changelog'
- '@semantic-release/npm'
- '@semantic-release/git'
prepare:
- '@semantic-release/changelog'
- '@semantic-release/npm'
- '@semantic-release/git'
- - 'semantic-release-npmx'
- access: 'public'
- '@semantic-release/github'
- - '@semantic-release/git'
- message: "chore: Release 🚀 ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
assets:
- 'CHANGELOG.md'
- '*.lock'
- - '**/package.json'
- '!**/node_modules/**/package.json'

View File

@ -1,78 +0,0 @@
language: node_js
stages:
- lint
- test
- release
notifications:
email: false
env:
- GITLAB_URL=http://localhost:8080
jobs:
include:
- stage: lint
node_js: node
script:
- npm run lint
- prettier --check './*.json' './*.yml'
- &test-unit
stage: test
name: Unit Test LFS
node_js: lts/*
before_script:
- npm run build
- npm link
script:
- npm run test:unit
- <<: *test-unit
name: Unit Test Latest
node_js: node
script:
- npm run test:unit -- --coverage
after_success:
- npm run coverage
- &test-integration
stage: test
name: Integration Test LFS
node_js: lts/*
before_script:
- cd test/docker/
# Spin up container
- docker-compose -f docker-compose.test.yml up -d
# Verify Gitlab instance is up and running
- node test_readiness.js
# Get the personal token
- export PERSONAL_ACCESS_TOKEN=$(docker exec -it gitlab bash -lc 'printf "%q" "$(gitlab-rails r /tmp/init_data.rb)"')
# Display configuration
- echo $PERSONAL_ACCESS_TOKEN
# Build library
- npm run build
- npm link
script:
- npm run test:integration
- <<: *test-integration
name: Integration Test Latest
node_js: node
script:
- npm run test:integration -- --coverage
after_success:
- npm run coverage
- stage: release
node_js: node
before_script:
- npm run build
script:
- npm run release

View File

@ -1,86 +1,73 @@
## [14.2.2](https://github.com/jdalrymple/node-gitlab/compare/14.2.1...14.2.2) (2020-01-30)
### Bug Fixes
* Incorrect request method in MergeRequests.approvalState() method ([#586](https://github.com/jdalrymple/node-gitlab/issues/586)) ([cb5f822](https://github.com/jdalrymple/node-gitlab/commit/cb5f8228ca1f64cc55b79e1ef475c3d49568267a))
- Incorrect request method in MergeRequests.approvalState() method ([#586](https://github.com/jdalrymple/node-gitlab/issues/586)) ([cb5f822](https://github.com/jdalrymple/node-gitlab/commit/cb5f8228ca1f64cc55b79e1ef475c3d49568267a))
## [14.2.1](https://github.com/jdalrymple/node-gitlab/compare/14.2.0...14.2.1) (2020-01-20)
### Bug Fixes
* added file extension for dummy file name in project import ([#561](https://github.com/jdalrymple/node-gitlab/issues/561)) ([f45cb68](https://github.com/jdalrymple/node-gitlab/commit/f45cb68498b54a2ad1ab1371589d0152d76adf11)), closes [/gitlab.com/gitlab-org/gitlab-foss/issues/50944#note_101737263](https://github.com//gitlab.com/gitlab-org/gitlab-foss/issues/50944/issues/note_101737263)
- added file extension for dummy file name in project import ([#561](https://github.com/jdalrymple/node-gitlab/issues/561)) ([f45cb68](https://github.com/jdalrymple/node-gitlab/commit/f45cb68498b54a2ad1ab1371589d0152d76adf11)), closes [/gitlab.com/gitlab-org/gitlab-foss/issues/50944#note_101737263](https://github.com//gitlab.com/gitlab-org/gitlab-foss/issues/50944/issues/note_101737263)
# [14.2.0](https://github.com/jdalrymple/node-gitlab/compare/14.1.1...14.2.0) (2020-01-17)
### Features
* Adding support for merge_requests in the Deployments API ([911078b](https://github.com/jdalrymple/node-gitlab/commit/911078bba30145a98ba051e672963dbbe8816a6a)), closes [#554](https://github.com/jdalrymple/node-gitlab/issues/554)
- Adding support for merge_requests in the Deployments API ([911078b](https://github.com/jdalrymple/node-gitlab/commit/911078bba30145a98ba051e672963dbbe8816a6a)), closes [#554](https://github.com/jdalrymple/node-gitlab/issues/554)
## [14.1.1](https://github.com/jdalrymple/node-gitlab/compare/14.1.0...14.1.1) (2020-01-03)
### Bug Fixes
* resourceDiscussions.editNote add content params, and allowed discussionId to accept a string type ([#524](https://github.com/jdalrymple/node-gitlab/issues/524)) ([22d916a](https://github.com/jdalrymple/node-gitlab/commit/22d916a05fdf2f4361fa2e9d17fdd8784ed6bfb3))
- resourceDiscussions.editNote add content params, and allowed discussionId to accept a string type ([#524](https://github.com/jdalrymple/node-gitlab/issues/524)) ([22d916a](https://github.com/jdalrymple/node-gitlab/commit/22d916a05fdf2f4361fa2e9d17fdd8784ed6bfb3))
# [14.1.0](https://github.com/jdalrymple/node-gitlab/compare/14.0.1...14.1.0) (2019-12-30)
### Bug Fixes
* make ResourceMembers.all/show delivery correct options params ([#521](https://github.com/jdalrymple/node-gitlab/issues/521)) ([505b407](https://github.com/jdalrymple/node-gitlab/commit/505b4072f3441440fd4903089d83d000e701e84c)), closes [#518](https://github.com/jdalrymple/node-gitlab/issues/518)
- make ResourceMembers.all/show delivery correct options params ([#521](https://github.com/jdalrymple/node-gitlab/issues/521)) ([505b407](https://github.com/jdalrymple/node-gitlab/commit/505b4072f3441440fd4903089d83d000e701e84c)), closes [#518](https://github.com/jdalrymple/node-gitlab/issues/518)
### Features
* Added support for the Vulnerability Findings API ([#517](https://github.com/jdalrymple/node-gitlab/issues/517)) ([497bf94](https://github.com/jdalrymple/node-gitlab/commit/497bf948d97d58dbe0bc2f57c47c92d646a29790))
- Added support for the Vulnerability Findings API ([#517](https://github.com/jdalrymple/node-gitlab/issues/517)) ([497bf94](https://github.com/jdalrymple/node-gitlab/commit/497bf948d97d58dbe0bc2f57c47c92d646a29790))
## [14.0.1](https://github.com/jdalrymple/node-gitlab/compare/14.0.0...14.0.1) (2019-12-23)
### Bug Fixes
* Adding back functionality for rejectUnauthorized http option ([#502](https://github.com/jdalrymple/node-gitlab/issues/502)) ([0f17bed](https://github.com/jdalrymple/node-gitlab/commit/0f17bedc0b6ec82793d5f7e6f9c3f53b030a642e))
- Adding back functionality for rejectUnauthorized http option ([#502](https://github.com/jdalrymple/node-gitlab/issues/502)) ([0f17bed](https://github.com/jdalrymple/node-gitlab/commit/0f17bedc0b6ec82793d5f7e6f9c3f53b030a642e))
# [14.0.0](https://github.com/jdalrymple/node-gitlab/compare/13.0.0...14.0.0) (2019-12-21)
### Bug Fixes
* Typing on GPGKey method arguments was missing ([#514](https://github.com/jdalrymple/node-gitlab/issues/514)) ([234c9a7](https://github.com/jdalrymple/node-gitlab/commit/234c9a75db9be752e6d4febee171e3b44be6a30a))
* Typing on Group and Project variable keys was incorrect [#512](https://github.com/jdalrymple/node-gitlab/issues/512) ([#515](https://github.com/jdalrymple/node-gitlab/issues/515)) ([c7afca5](https://github.com/jdalrymple/node-gitlab/commit/c7afca523160ac19707d0207b9892a81b799e645))
- Typing on GPGKey method arguments was missing ([#514](https://github.com/jdalrymple/node-gitlab/issues/514)) ([234c9a7](https://github.com/jdalrymple/node-gitlab/commit/234c9a75db9be752e6d4febee171e3b44be6a30a))
- Typing on Group and Project variable keys was incorrect [#512](https://github.com/jdalrymple/node-gitlab/issues/512) ([#515](https://github.com/jdalrymple/node-gitlab/issues/515)) ([c7afca5](https://github.com/jdalrymple/node-gitlab/commit/c7afca523160ac19707d0207b9892a81b799e645))
### BREAKING CHANGES
* The title property is not required for the add method.
- The title property is not required for the add method.
# [13.0.0](https://github.com/jdalrymple/node-gitlab/compare/12.1.0...13.0.0) (2019-12-09)
### Features
* Adding ability to get a singular member of a project or group, including inheritedMemebrs ([#508](https://github.com/jdalrymple/node-gitlab/issues/508)) ([807171c](https://github.com/jdalrymple/node-gitlab/commit/807171c3ff29977e8f6f5faa9603c550334c2192)), closes [#507](https://github.com/jdalrymple/node-gitlab/issues/507)
- Adding ability to get a singular member of a project or group, including inheritedMemebrs ([#508](https://github.com/jdalrymple/node-gitlab/issues/508)) ([807171c](https://github.com/jdalrymple/node-gitlab/commit/807171c3ff29977e8f6f5faa9603c550334c2192)), closes [#507](https://github.com/jdalrymple/node-gitlab/issues/507)
### BREAKING CHANGES
* Updated the Members.all function to have the inheritedMembers option to be in the optional object.
- Updated the Members.all function to have the inheritedMembers option to be in the optional object.
# [12.1.0](https://github.com/jdalrymple/node-gitlab/compare/12.0.1...12.1.0) (2019-12-05)
### Bug Fixes
* Removing required options object in a few of the API methods ([#505](https://github.com/jdalrymple/node-gitlab/issues/505)) ([b709ef6](https://github.com/jdalrymple/node-gitlab/commit/b709ef6716d15368c8775d77e5eb0cf22d6369a7))
- Removing required options object in a few of the API methods ([#505](https://github.com/jdalrymple/node-gitlab/issues/505)) ([b709ef6](https://github.com/jdalrymple/node-gitlab/commit/b709ef6716d15368c8775d77e5eb0cf22d6369a7))
### Features
* Add Group/File schemas ([#506](https://github.com/jdalrymple/node-gitlab/issues/506)) ([f467816](https://github.com/jdalrymple/node-gitlab/commit/f467816070bffcd3776e5dc3e6074c92bf6d644e))
- Add Group/File schemas ([#506](https://github.com/jdalrymple/node-gitlab/issues/506)) ([f467816](https://github.com/jdalrymple/node-gitlab/commit/f467816070bffcd3776e5dc3e6074c92bf6d644e))
## [12.0.1](https://github.com/jdalrymple/node-gitlab/compare/12.0.0...12.0.1) (2019-11-27)

View File

@ -1,7 +1,7 @@
# The MIT License
Copyright (c)
**2019 Justin Dalrymple**
**2020 Justin Dalrymple**
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

149
README.md
View File

@ -1,18 +1,48 @@
[![npm @latest](https://img.shields.io/npm/v/gitlab.svg)](https://www.npmjs.com/package/gitlab)
[![npm downloads](https://img.shields.io/npm/dt/gitlab.svg)](https://www.npmjs.com/package/gitlab)
[![dependencies Status](https://david-dm.org/jdalrymple/node-gitlab/status.svg)](https://david-dm.org/jdalrymple/node-gitlab)
[![devDependencies Status](https://david-dm.org/jdalrymple/node-gitlab/dev-status.svg)](https://david-dm.org/jdalrymple/node-gitlab?type=dev)
[![Greenkeeper badge](https://badges.greenkeeper.io/jdalrymple/node-gitlab.svg)](https://greenkeeper.io/)
[![Code Climate](https://codeclimate.com/github/jdalrymple/node-gitlab/badges/gpa.svg)](https://codeclimate.com/github/jdalrymple/node-gitlab)
[![Build Status](https://img.shields.io/travis/jdalrymple/node-gitlab/master.svg)](https://travis-ci.org/jdalrymple/node-gitlab)
[![Coverage](https://img.shields.io/codecov/c/github/jdalrymple/node-gitlab/master.svg)](https://codecov.io/gh/jdalrymple/node-gitlab)
[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
[![Code Style: Prettier](https://img.shields.io/badge/code%20style-prettier-ff69b4.svg)](https://img.shields.io/badge/code%20style-prettier-ff69b4.svg)
[![Install Size](https://packagephobia.now.sh/badge?p=gitlab)](https://packagephobia.now.sh/result?p=gitlab)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/jdalrymple/node-gitlab/blob/master/LICENSE.md)
# node-gitlab
<div align="center">
<br>
<img alt="gitbeaker" src=".github/ASSETS/header.svg">
</div>
<br>
<p align="center">
<a href="https://gitlab.com/jdalrymple/gitbeaker/pipelines">
<img src="https://img.shields.io/gitlab/pipeline/jdalrymple/gitbeaker/master" alt="Gitlab Pipeline Status">
</a>
<a href="https://codeclimate.com/github/jdalrymple/gitbeaker">
<img src="https://codeclimate.com/github/jdalrymple/gitbeaker/badges/gpa.svg" alt="Code Climate maintainability">
</a>
<a href="https://codecov.io/gh/jdalrymple/gitbeaker">
<img src="https://img.shields.io/codecov/c/github/jdalrymple/gitbeaker/master.svg" alt="CodeCov test coverage">
</a>
<a href="https://david-dm.org/jdalrymple/gitbeaker">
<img src="https://david-dm.org/jdalrymple/gitbeaker/status.svg" alt="Dependency Status" />
</a>
<a href="https://david-dm.org/jdalrymple/gitbeaker?type=dev">
<img src="https://david-dm.org/jdalrymple/gitbeaker/dev-status.svg.svg" alt="Dev Dependency Status" />
</a>
<img src="https://flat.badgen.net/dependabot/jdalrymple/gitbeaker?icon=dependabot" alt="Dependabot Badge" />
<a href="https://github.com/semantic-release/semantic-release">
<img src="https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg" alt="Semantic Release">
</a>
<a href="http://commitizen.github.io/cz-cli/">
<img src="https://img.shields.io/badge/commitizen-friendly-brightgreen.svg" alt="Commitizen">
</a>
<img src="https://img.shields.io/badge/code%20style-prettier-ff69b4.svg" alt="Prettier">
<a href="https://packagephobia.now.sh/result?p=@gitbeaker/core">
<img src="https://packagephobia.now.sh/badge?p=@gitbeaker/core" alt="Install Size: Core">
</a>
<a href="https://packagephobia.now.sh/result?p=@gitbeaker/node">
<img src="https://packagephobia.now.sh/badge?p=@gitbeaker/node" alt="Install Size: Node">
</a>
<a href="https://packagephobia.now.sh/result?p=@gitbeaker/browser">
<img src="https://packagephobia.now.sh/badge?p=@gitbeaker/browser" alt="Install Size: Browser">
</a>
<a href="https://packagephobia.now.sh/result?p=@gitbeaker/cli">
<img src="https://packagephobia.now.sh/badge?p=@gitbeaker/cli" alt="Install Size: CLI">
</a>
<a href="LICENSE.md">
<img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="Licence: MIT">
</a>
</p>
🤖 [GitLab](https://gitlab.com/gitlab-org/gitlab/) API NodeJS library with full support of all the [Gitlab API](https://gitlab.com/gitlab-org/gitlab/tree/master/doc/api) services.
@ -40,23 +70,42 @@
```bash
# Install from npm
npm install gitlab
npm install @gitbeaker/node # NodeJS default, index.es.js for esm
npm install @gitbeaker/browser # UMD default
npm install @gitbeaker/cli # CLI
```
## Getting Started
Instantiate the library using a basic token created in your [Gitlab Profile](https://docs.gitlab.com/ce/user/profile/personal_access_tokens.html)
**NodeJS**
```javascript
// ES6 (>=node 10.16.0 LTS)
import { Gitlab } from 'gitlab'; // All Resources
import { Projects } from 'gitlab'; // Just the Project Resource
import { Gitlab } from '@gitbeaker/node'; // All Resources
import { Projects } from '@gitbeaker/node'; // Just the Project Resource
//...etc
// ES5, assuming native or polyfilled Promise is available
const { Gitlab } = require('gitlab');
const { Gitlab } = require('@gitbeaker/node');
```
**Browser**
```javascript
// ES6 (>=node 10.16.0 LTS)
import { Gitlab } from '@gitbeaker/browser'; // All Resources
import { Projects } from '@gitbeaker/browser'; // Just the Project Resource
//...etc
// ES5, assuming native or polyfilled Promise is available
const { Gitlab } = require('@gitbeaker/browser');
```
Instantiate the library using a basic token created in your [Gitlab Profile](https://docs.gitlab.com/ce/user/profile/personal_access_tokens.html)
```javascript
const api = new Gitlab({
token: 'personaltoken',
@ -65,46 +114,47 @@ const api = new Gitlab({
Available instantiating options:
| Name | Optional | Default | Description |
| -------------------- | -------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `host` | Yes | `https://gitlab.com` | Gitlab Instance Host URL |
| `token` | No\* | N/A | Personal Token. Required (one of the three tokens are required) |
| `oauthToken` | No\* | N/A | OAuth Token. Required (one of the three tokens are required) |
| `jobToken` | No\* | N/A | CI Job Token. Required (one of the three tokens are required) |
| `rejectUnauthorized` | Yes | `true` | Http Certificate setting, Only applies to HTTPS hosts urls |
| `sudo` | Yes | `false` | [Sudo](https://docs.gitlab.com/ee/api/#sudo) query parameter |
| `version` | Yes | `4` | API Version ID |
| `camelize` | Yes | `false` | Camelizes all response body keys |
| `requester` | Yes | [KyRequester.ts](./src/infrastructure/KyRequester.ts) | Request Library Wrapper. Currently wraps Ky. |
| `requestTimeout` | Yes | `300000` | Request Library Timeout in ms |
| `profileToken` | Yes | N/A | [Requests Profiles Token](https://docs.gitlab.com/ee/administration/monitoring/performance/request_profiling.html) |
| `profileMode` | Yes | `execution` | [Requests Profiles Token](https://docs.gitlab.com/ee/administration/monitoring/performance/request_profiling.html) |
| Name | Optional | Default | Description |
| -------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `host` | Yes | `https://gitlab.com` | Gitlab Instance Host URL |
| `token` | No\* | N/A | Personal Token. Required (one of the three tokens are required) |
| `oauthToken` | No\* | N/A | OAuth Token. Required (one of the three tokens are required) |
| `jobToken` | No\* | N/A | CI Job Token. Required (one of the three tokens are required) |
| `rejectUnauthorized` | Yes | `true` | Http Certificate setting, Only applies to HTTPS hosts urls |
| `sudo` | Yes | `false` | [Sudo](https://docs.gitlab.com/ee/api/#sudo) query parameter |
| `version` | Yes | `4` | API Version ID |
| `camelize` | Yes | `false` | Camelizes all response body keys |
| `requester` | Yes\* | For @gitbeaker/node and @gitbeaker/cli, it uses a Got based requester, for @gitbeaker/browser, it uses a ky based requester. The @gitbeaker/core package **does not** have a default and thus must be set explicitly | Request Library Wrapper |
| `requestTimeout` | Yes | `300000` | Request Library Timeout in ms |
| `profileToken` | Yes | N/A | [Requests Profiles Token](https://docs.gitlab.com/ee/administration/monitoring/performance/request_profiling.html) |
| `profileMode` | Yes | `execution` | [Requests Profiles Token](https://docs.gitlab.com/ee/administration/monitoring/performance/request_profiling.html) |
### CLI Support
The CLI export functions in a similar manner, following the pattern:
```bash
gitlab [service name] [method name] --arg1 --arg2 --arg3
gitbeaker [service name] [method name] --arg1 --arg2 --arg3
```
Where `service name` is any of the supported API names, `method name` is any of the supported commands on that API service (See source for exceptions, but generally all, show, remove, update) and `--arg1...--arg3` are any of the arguments you would normally supply to the function. The names of the args should match the names in the method headers **EXCEPT** all the optional arguments whose names should match what the GitLab API docs request.
There is one small exception with the instantiating arguments, however, which must be supplied using a `gl` prefix. ie.
There is one small exception with the instantiating arguments, however, which must be supplied using a `gb` or `gl` prefix. ie.
```bash
# To get all the projects
gitlab projects all --gl-token="personaltoken"
gitbeaker projects all --gb-token="personaltoken"
# To get a project with id = 2
gitlab projects show --gl-token="personaltoken" --projectId=2
gitbeaker projects show --gl-token="personaltoken" --projectId=2
```
To reduce the annoyance of having to pass those configuration properties each time, it is also possible to pass the token and host information through environment variables in the form of `GITLAB_[option name]` ie:
To reduce the annoyance of having to pass those configuration properties each time, it is also possible to pass the token and host information through environment variables in the form of `GITLAB_[option name]` or `GITBEAKER_[option name]` ie:
```bash
GITLAB_HOST=http://example.com
GITLAB_TOKEN=personaltoken
GITBEAKER_CAMELIZE=true
```
This could be set globally or using a [.env](https://github.com/motdotla/dotenv#readme) file in the project folder.
@ -114,7 +164,7 @@ This could be set globally or using a [.env](https://github.com/motdotla/dotenv#
The library is exported as `gitlab` and can be used by simply adding this script to your html file:
```html
<script src="node_modules/gitlab/dist/index.browser.js" />
<script src="node_modules/@gitbeaker/browser/index.js" />
<script>
const { Gitlab } = gitlab;
@ -352,7 +402,7 @@ const api = new Gitlab({
let users = await api.Users.all();
// Or using Promise-Then notation
api.Projects.all().then(projects => {
api.Projects.all().then((projects) => {
console.log(projects);
});
```
@ -494,10 +544,9 @@ If your Gitlab server is running via HTTPS, the proper way to pass in your certi
For responses such as file data that may be returned from the API, the data is exposed as a buffer. For example, when trying to write a file, this can be done like:
```javascript
let bufferedData = await api.Jobs.downloadLatestArtifactFile(project.id, "test", "job_test");
fs.writeFileSync("test.zip", bufferedData);
let bufferedData = await api.Jobs.downloadLatestArtifactFile(project.id, 'test', 'job_test');
fs.writeFileSync('test.zip', bufferedData);
```
## Development
@ -505,13 +554,13 @@ fs.writeFileSync("test.zip", bufferedData);
To get this running locally rather than from your `node_modules` folder:
```bash
$ git clone https://github.com/jdalrymple/node-gitlab.git
$ cd node-gitlab
$ git clone https://github.com/jdalrymple/gitbeaker.git
$ cd gitbeaker
$ npm install
$ npm run-script build
```
And then inside whatever project you are using `node-gitlab` in you change your references to use that repo. In your package.json of that upstream project change:
And then inside whatever project you are using `gitbeaker` in you change your references to use that repo. In your package.json of that upstream project change:
```json
"dependencies": {
@ -564,7 +613,7 @@ PERSONAL_ACCESS_TOKEN='abcdefg' GITLAB_URL='http://localhost:8080' npm run test
## Contributors
This started as a fork from [node-gitlab](https://github.com/node-gitlab/node-gitlab) but I ended up rewriting much of the code. Here are the original work's [contributors](https://github.com/node-gitlab/node-gitlab#contributors).
This started as a fork from [node-gitlab-legacy](https://github.com/node-gitlab/node-gitlab-legacy) but I ended up rewriting much of the code. Here are the original work's [contributors](https://github.com/node-gitlab/node-gitlab-legacy#contributors).
- [Dylan DesRosier](https://github.com/ddesrosier)
- [Mike Wyatt](https://github.com/mikew)
@ -620,8 +669,8 @@ This started as a fork from [node-gitlab](https://github.com/node-gitlab/node-gi
## License
[MIT](https://github.com/jdalrymple/node-gitlab/blob/master/LICENSE.md)
[MIT](https://github.com/jdalrymple/gitbeaker/blob/master/LICENSE.md)
## Changelog
[Here](https://github.com/jdalrymple/node-gitlab/blob/master/CHANGELOG.md)
[Here](https://github.com/jdalrymple/gitbeaker/blob/master/CHANGELOG.md)

43
codecov.yml Normal file
View File

@ -0,0 +1,43 @@
codecov:
max_report_age: off
comment: false
coverage:
precision: 2
round: down
status:
project:
default: off
cli:
target: 60%
flags: cli
core:
target: 60%
flags: core
browser:
target: 60%
flags: browser
node:
target: 60%
flags: node
utils:
target: 60%
flags: utils
flags:
cli:
paths:
- packages/gitbeaker-cli/src
core:
paths:
- packages/gitbeaker-core/src
browser:
paths:
- packages/gitbeaker-browser/src
node:
paths:
- packages/gitbeaker-node/src
utils:
paths:
- packages/gitbeaker-requester-utils/src

1
global.d.ts vendored Normal file
View File

@ -0,0 +1 @@
import 'jest-extended';

26
jest.config.js Normal file
View File

@ -0,0 +1,26 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
testRegex: 'test\\/.*\\.ts$',
testMatch: null,
testURL: 'http://localhost/',
testTimeout: 15000,
coverageDirectory: 'coverage',
collectCoverage: true,
setupFilesAfterEnv: ['jest-extended'],
moduleNameMapper: {
'^ky$': require.resolve('ky').replace('index.js', 'umd.js'),
},
globals: {
'ts-jest': {
diagnostics: {
ignoreCodes: [2339],
},
},
},
};

View File

@ -1,20 +0,0 @@
{
"preset": "ts-jest",
"testEnvironment": "node",
"testRegex": "test\\/.*\\.ts$",
"testMatch": null,
"testURL": "http://localhost/",
"coverageDirectory": "./coverage/",
"setupFilesAfterEnv": ["jest-extended"],
"globals": {
"ts-jest": {
"diagnostics": {
"ignoreCodes": [2339]
}
}
}
}

17
lerna.json Normal file
View File

@ -0,0 +1,17 @@
{
"packages": ["packages/*"],
"version": "14.2.2",
"npmClient": "yarn",
"useWorkspaces": true,
"tagVersionPrefix": "",
"command": {
"publish": {
"createRelease": "github",
"conventionalCommits": true,
"message": "chore: Release %s"
},
"version": {
"push": false
}
}
}

17544
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,106 +1,58 @@
{
"name": "gitlab",
"description": "Full NodeJS implementation of the GitLab API. Supports Promises, Async/Await.",
"version": "14.2.2",
"author": {
"name": "Justin Dalrymple",
"email": "justin.s.dalrymple@gmail.com"
},
"bin": {
"gitlab": "dist/index.cli.js"
},
"browser": "dist/index.browser.js",
"bugs": {
"url": "https://github.com/jdalrymple/node-gitlab/issues"
"url": "https://github.com/jdalrymple/gitbeaker/issues"
},
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
"path": "cz-conventional-changelog"
}
},
"dependencies": {
"chalk": "^3.0.0",
"form-data": "^3.0.0",
"ky": "^0.16.0",
"ky-universal": "^0.3.0",
"li": "^1.3.0",
"ora": "^4.0.3",
"query-string": "^6.9.0",
"sywac": "^1.2.2",
"xcase": "^2.0.1"
},
"repository": "github:jdalrymple/gitbeaker",
"devDependencies": {
"@semantic-release/changelog": "^3.0.5",
"@semantic-release/git": "^7.0.18",
"@semantic-release/npm": "^5.3.4",
"@types/jest": "^24.0.23",
"@typescript-eslint/eslint-plugin": "^2.8.0",
"@typescript-eslint/parser": "^2.8.0",
"codecov": "^3.6.1",
"cz-conventional-changelog": "^3.0.2",
"eslint": "^6.6.0",
"eslint-config-airbnb-base": "^14.0.0",
"eslint-config-prettier": "^6.7.0",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-jest": "^23.0.4",
"eslint-plugin-prettier": "^3.1.1",
"esm": "^3.2.25",
"fs-extra": "^8.1.0",
"get-param-names": "github:jdalrymple/get-param-names#1-improve-functionality",
"husky": "^4.0.0-beta.1",
"jest": "24.9.0",
"jest-extended": "^0.11.2",
"lint-staged": "^9.4.3",
"prettier": "^1.19.1",
"rollup": "^1.27.2",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-node-builtins": "^2.1.2",
"rollup-plugin-node-globals": "^1.4.0",
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-replace": "^2.2.0",
"rollup-plugin-terser": "^5.1.3",
"rollup-plugin-typescript2": "^0.25.2",
"semantic-release": "^15.13.31",
"strip-ansi": "^6.0.0",
"ts-jest": "24.1.0",
"typescript": "3.7.2"
"@commitlint/cli": "^8.3.5",
"@commitlint/config-conventional": "^8.3.4",
"@commitlint/config-lerna-scopes": "^8.3.4",
"@semantic-release/changelog": "^5.0.0",
"@semantic-release/git": "^9.0.0",
"@types/jest": "^25.1.4",
"@typescript-eslint/eslint-plugin": "^2.24.0",
"@typescript-eslint/parser": "^2.24.0",
"codecov": "^3.6.5",
"commitizen": "^4.0.3",
"cz-conventional-changelog": "^3.1.0",
"eslint": "^6.8.0",
"eslint-config-airbnb-base": "^14.1.0",
"eslint-config-prettier": "^6.10.1",
"eslint-plugin-import": "^2.20.1",
"eslint-plugin-jest": "^23.8.2",
"eslint-plugin-prettier": "^3.1.2",
"got": "^10.6.0",
"husky": "^4.2.3",
"jest": "^25.1.0",
"jest-extended": "^0.11.5",
"lerna": "^3.20.2",
"lint-staged": "^10.0.8",
"prettier": "^2.0.1",
"semantic-release": "^17.0.4",
"semantic-release-npmx": "^1.1.0",
"ts-jest": "^25.2.1",
"typescript": "^3.8.3"
},
"engines": {
"node": ">=10.0.0"
},
"files": [
"dist"
"private": true,
"workspaces": [
"packages/*"
],
"homepage": "https://github.com/jdalrymple/node-gitlab#readme",
"keywords": [
"api",
"browser",
"cli",
"es5",
"es6",
"gitlab",
"ky"
],
"license": "MIT",
"main": "dist/index.js",
"module": "dist/index.es.js",
"repository": {
"type": "git",
"url": "https://github.com/jdalrymple/node-gitlab"
},
"scripts": {
"build": "npm run build:cli && tsc && rollup -c",
"build:cli": "tsc -p tsconfig.cli.json && node -r esm temp/bin/generate",
"commit": "npx git-cz",
"coverage": "codecov",
"lint": "prettier --check '{src,test}/**/*.ts' && eslint '{src,test}/**/*/!(generate).ts'",
"build": "lerna run build",
"lint": "prettier --check 'packages/**/{src,test}/**/*.ts' && eslint 'packages/**/{src,test}/**/*/*.ts'",
"lint:doc": "prettier --check './*.json' './*.yml' './*.js'",
"lint:doc:fix": "prettier --write './*.json' './*.yml' './*.md' './*.js'",
"lint:fix": "prettier --write '{src,test}/**/*.ts' && eslint '{src,test}/**/*/!(generate).ts' --fix",
"prepublishOnly": "npm run build",
"release": "semantic-release",
"test:integration": "jest test/integration -c=jest.config.json",
"test:unit": "jest test/unit -c=jest.config.json"
"lint:fix": "prettier --write 'packages/**/{src,test}/**/*.ts' && eslint 'packages/**/{src,test}/**/*/*.ts' --fix",
"test:integration": "jest test/integration",
"test:unit": "jest test/unit",
"commit": "git-cz --retry",
"prepublishOnly": "lerna run build",
"release": "semantic-release --no-ci"
},
"types": "dist/types/core/index.d.ts"
"version": "15.0.3"
}

View File

@ -0,0 +1,54 @@
{
"name": "@gitbeaker/browser",
"description": "Full Browser implementation of the GitLab API. Supports Promises, Async/Await.",
"version": "15.0.3",
"author": {
"name": "Justin Dalrymple"
},
"bugs": {
"url": "https://github.com/jdalrymple/gitbeaker/issues"
},
"dependencies": {
"@gitbeaker/core": "^15.0.3",
"@gitbeaker/requester-utils": "^15.0.3",
"ky": "^0.16.2"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^11.0.1",
"@rollup/plugin-node-resolve": "^7.0.0",
"@rollup/plugin-replace": "^2.3.0",
"@types/node": "^13.7.0",
"node-fetch": "^2.6.0",
"rollup": "^1.31.0",
"rollup-plugin-node-builtins": "^2.1.2",
"rollup-plugin-node-globals": "^1.4.0",
"rollup-plugin-terser": "^5.2.0",
"rollup-plugin-typescript2": "^0.25.3",
"ts-node": "^8.6.2",
"typescript": "^3.7.5"
},
"engines": {
"node": ">=10.0.0"
},
"files": [
"dist"
],
"homepage": "https://github.com/jdalrymple/gitbeaker#readme",
"keywords": [
"api",
"es5",
"es6",
"gitlab",
"gitbeaker",
"ky"
],
"license": "MIT",
"browser": "dist/index.js",
"repository": {
"type": "git",
"url": "https://github.com/jdalrymple/gitbeaker"
},
"scripts": {
"build": "tsc && rollup -c"
}
}

View File

@ -0,0 +1,19 @@
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import builtins from 'rollup-plugin-node-builtins';
import globals from 'rollup-plugin-node-globals';
import pkg from './package.json';
import { commonConfig, commonPlugins } from '../../rollup.config';
export default [
{
...commonConfig,
output: {
file: pkg.browser,
name: 'gitbeaker',
format: 'umd',
exports: 'named',
},
plugins: [globals(), builtins(), resolve({ browser: true }), commonjs(), ...commonPlugins],
},
];

View File

@ -0,0 +1,66 @@
import Ky from 'ky';
import {
Service,
DefaultRequestOptions,
createInstance,
defaultRequest as baseDefaultRequest,
} from '@gitbeaker/requester-utils';
function responseHeadersAsObject(response): Record<string, string> {
const headers = {};
const keyVals = [...response.headers.entries()];
keyVals.forEach(([key, val]) => {
headers[key] = val;
});
return headers;
}
export function defaultRequest(service: Service, options: DefaultRequestOptions = {}) {
const opts = baseDefaultRequest(service, options);
return { ...opts, headers: new Headers(service.headers as Record<string, string>) };
}
export function processBody(response) {
const contentType = response.headers.get('content-type') || '';
switch (contentType) {
case 'application/json': {
return response.json().then((v) => v || {});
}
case 'application/octet-stream':
case 'binary/octet-stream':
case 'application/gzip': {
return response.blob().then(Buffer.from);
}
default: {
return response.text().then((t) => t || '');
}
}
}
export async function handler(endpoint, options) {
let response;
try {
response = await Ky(endpoint, options);
} catch (e) {
if (e.response) {
const output = await e.response.json();
e.description = output.error || output.message;
}
throw e;
}
const { status } = response;
const headers = responseHeadersAsObject(response);
const body = await processBody(response);
return { body, headers, status };
}
export const Requester = createInstance(defaultRequest, handler);

View File

@ -0,0 +1,15 @@
import * as Gitbeaker from '@gitbeaker/core';
import { Requester } from './KyRequester';
const output = {};
Object.keys(Gitbeaker).forEach((name) => {
output[name] = (args) =>
new Gitbeaker[name]({
requester: Requester,
...args,
});
});
/* eslint-disable */
export default output;

View File

@ -0,0 +1,176 @@
import ky from 'ky';
import fetch from 'node-fetch';
import { processBody, handler, defaultRequest } from '../../src/KyRequester';
// Set globals for testing purposes
if (!global.fetch) {
global.fetch = fetch;
}
if (!global.Headers) {
global.Headers = fetch.Headers;
}
jest.mock('ky');
describe('processBody', () => {
it('should return a json object if type is application/json', async () => {
const output = await processBody({
json() {
return Promise.resolve({ test: 5 });
},
headers: {
get() {
return 'application/json';
},
},
});
expect(output).toMatchObject({ test: 5 });
});
it('should return a buffer if type is octet-stream, binary, or gzip', async () => {
const output = [
processBody({
blob() {
return Promise.resolve('test');
},
headers: {
get() {
return 'application/octet-stream';
},
},
}),
processBody({
blob() {
return Promise.resolve('test');
},
headers: {
get() {
return 'binary/octet-stream';
},
},
}),
processBody({
blob() {
return Promise.resolve('test');
},
headers: {
get() {
return 'application/gzip';
},
},
}),
];
const fulfilled = await Promise.all(output);
fulfilled.forEach((o) => expect(o).toBeInstanceOf(Buffer));
});
it('should return a text body given when presented with an unknown content-type', async () => {
const output = await processBody({
text() {
return Promise.resolve('6');
},
headers: {
get() {
return 'fake';
},
},
});
expect(output).toBe('6');
});
it('should return a empty string when presented with an unknown content-type and undefined body', async () => {
const output = await processBody({
text() {
return Promise.resolve(null);
},
headers: {
get() {
return 'fake';
},
},
});
expect(output).toBe('');
});
});
describe('handler', () => {
it('should return an error with a description when response has an error prop', async () => {
ky.mockImplementationOnce(() => {
const e = {
response: {
json() {
return Promise.resolve({ error: 'msg' });
},
},
};
return Promise.reject(e);
});
await expect(handler('http://test.com', {})).rejects.toContainEntry(['description', 'msg']);
});
it('should return an error with a description when response has an message prop', async () => {
ky.mockImplementationOnce(() => {
const e = {
response: {
json() {
return Promise.resolve({ message: 'msg' });
},
},
};
return Promise.reject(e);
});
await expect(handler('http://test.com', {})).rejects.toContainEntry(['description', 'msg']);
});
it('should return correct properties if request is valid', async () => {
ky.mockImplementationOnce(() => ({
status: 404,
headers: {
get() {
return 'application/json';
},
entries() {
return [['token', '1234']];
},
},
json() {
return Promise.resolve({});
},
}));
const output = await handler('http://test.com', {});
expect(output).toMatchObject({
body: {},
headers: {},
status: 404,
});
});
});
describe('defaultRequest', () => {
const service = {
headers: { test: '5' },
url: 'testurl',
rejectUnauthorized: false,
requestTimeout: 50,
};
it('should stringify body if it isnt of type FormData', async () => {
const testBody = { test: 6 };
const { body, headers } = defaultRequest(service, {
body: testBody,
});
expect(headers).toBeInstanceOf(Headers);
expect(body).toBe(JSON.stringify(testBody));
});
});

View File

@ -0,0 +1,9 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist",
"declaration": true,
"declarationDir": "dist/types"
},
"include": ["src"]
}

View File

@ -0,0 +1,53 @@
{
"name": "@gitbeaker/cli",
"description": "Full NodeJS CLI implementation of the GitLab API.",
"version": "15.0.3",
"author": {
"name": "Justin Dalrymple"
},
"bin": {
"gitbeaker": "dist/index.js"
},
"bugs": {
"url": "https://github.com/jdalrymple/gitbeaker/issues"
},
"dependencies": {
"@gitbeaker/core": "^15.0.3",
"@gitbeaker/node": "^15.0.3",
"chalk": "^3.0.0",
"ora": "^4.0.3",
"sywac": "^1.2.2",
"xcase": "^2.0.1"
},
"devDependencies": {
"@rollup/plugin-json": "^4.0.1",
"rollup": "^1.31.0",
"rollup-plugin-preserve-shebangs": "^0.1.2",
"rollup-plugin-terser": "^5.2.0",
"rollup-plugin-typescript2": "^0.25.3",
"strip-ansi": "^6.0.0",
"typescript": "^3.7.5"
},
"engines": {
"node": ">=10.0.0"
},
"files": [
"dist"
],
"homepage": "https://github.com/jdalrymple/gitbeaker#readme",
"keywords": [
"api",
"cli",
"gitbeaker",
"gitlab",
"got"
],
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/jdalrymple/gitbeaker"
},
"scripts": {
"build": "tsc && rollup -c"
}
}

View File

@ -0,0 +1,14 @@
import json from '@rollup/plugin-json';
import { preserveShebangs } from 'rollup-plugin-preserve-shebangs';
import pkg from './package.json';
import { commonConfig, commonPlugins } from '../../rollup.config.js';
export default {
...commonConfig,
external: [...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.peerDependencies || {})],
output: {
file: pkg.bin.gitbeaker,
format: 'cjs',
},
plugins: [...commonPlugins, json(), preserveShebangs()],
};

View File

@ -5,10 +5,8 @@ import program, { Options } from 'sywac';
import ora from 'ora';
import chalk from 'chalk';
import { camelize, decamelize, depascalize } from 'xcase';
import * as core from '../core';
/* eslint global-require: 0 import/no-unresolved: 0 */
const map: [string, { name: string; args: string[] }[]] = require('./map.json') || {};
import * as Gitbeaker from '@gitbeaker/node';
import * as map from '@gitbeaker/core/dist/map.json';
// Styling settings
const commandStyle = chalk.hex('#e34329').bold;
@ -20,58 +18,75 @@ const hintStyle = chalk.hex('#6a5f88');
// Globally configurable arguments
const globalConfig: { [name: string]: Options } = {
'gl-token': {
'gb-token': {
alias: 'gl-token',
desc: 'Your Gitlab Personal Token',
type: 'string',
defaultValue: process.env.GITLAB_TOKEN,
defaultValue: process.env.GITBEAKER_TOKEN || process.env.GITLAB_TOKEN,
},
'gl-oauth-token': {
'gb-oauth-token': {
alias: 'gl-oauth-token',
desc: 'Your Gitlab OAuth Token',
type: 'string',
defaultValue: process.env.GITLAB_OAUTH_TOKEN,
defaultValue: process.env.GITBEAKER_OAUTH_TOKEN || process.env.GITLAB_OAUTH_TOKEN,
},
'gl-job-token': {
'gb-job-token': {
alias: 'gl-job-token',
desc: 'Your Gitlab Job Token',
type: 'string',
defaultValue: process.env.GITLAB_JOB_TOKEN,
defaultValue: process.env.GITBEAKER_JOB_TOKEN || process.env.GITLAB_JOB_TOKEN,
},
'gl-host': {
'gb-host': {
alias: 'gl-host',
desc: 'Your Gitlab API host (Defaults to https://www.gitlab.com)',
type: 'string',
defaultValue: process.env.GITLAB_HOST,
defaultValue: process.env.GITBEAKER_HOST || process.env.GITLAB_HOST,
},
'gl-version': {
'gb-version': {
alias: 'gl-version',
desc: 'The targetted Gitlab API version (Defaults to 4)',
type: 'number',
defaultValue: process.env.GITLAB_VERSION && parseInt(process.env.GITLAB_VERSION, 10),
defaultValue:
(process.env.GITBEAKER_VERSION && parseInt(process.env.GITBEAKER_VERSION, 10)) ||
(process.env.GITLAB_VERSION && parseInt(process.env.GITLAB_VERSION, 10)),
},
'gl-sudo': {
'gb-sudo': {
alias: 'gl-sudo',
desc: '[Sudo](https://docs.gitlab.com/ee/api/#sudo) query parameter',
type: 'string',
defaultValue: process.env.GITLAB_SUDO,
defaultValue: process.env.GITBEAKER_SUDO || process.env.GITLAB_SUDO,
},
'gl-camelize': {
'gb-camelize': {
alias: 'gl-camelize',
desc: 'Camelizes all response body keys',
type: 'boolean',
defaultValue: process.env.GITLAB_CAMELIZE && process.env.GITLAB_CAMELIZE === 'true',
defaultValue:
(process.env.GITBEAKER_CAMELIZE && process.env.GITBEAKER_CAMELIZE === 'true') ||
(process.env.GITLAB_CAMELIZE && process.env.GITLAB_CAMELIZE === 'true'),
},
'gl-request-timeout': {
'gb-request-timeout': {
alias: 'gl-request-timeout',
desc: 'Timeout for API requests. Measured in ms',
type: 'number',
defaultValue:
process.env.GITLAB_REQUEST_TIMEOUT && parseInt(process.env.GITLAB_REQUEST_TIMEOUT, 10),
(process.env.GITBEAKER_REQUEST_TIMEOUT &&
parseInt(process.env.GITBEAKER_REQUEST_TIMEOUT, 10)) ||
(process.env.GITBEAKER_REQUEST_TIMEOUT &&
parseInt(process.env.GITBEAKER_REQUEST_TIMEOUT, 10)),
},
'gl-profile-token': {
'gb-profile-token': {
alias: 'gl-profile-token',
desc:
'[Requests Profiles Token](https://docs.gitlab.com/ee/administration/monitoring/performance/request_profiling.html)',
type: 'string',
defaultValue: process.env.GITLAB_PROFILE_TOKEN,
defaultValue: process.env.GITBEAKER_PROFILE_TOKEN || process.env.GITLAB_PROFILE_TOKEN,
},
'gl-profile-mode': {
'gb-profile-mode': {
alias: 'gl-profile-mode',
desc:
'[Requests Profiles Token](https://docs.gitlab.com/ee/administration/monitoring/performance/request_profiling.html)',
type: 'string',
defaultValue: process.env.GITLAB_PROFILE_MODE,
defaultValue: process.env.GITBEAKER_PROFILE_MODE || process.env.GITLAB_PROFILE_MODE,
},
};
@ -86,7 +101,7 @@ function param(string) {
}
function setupAPIMethods(setupArgs, methodArgs) {
methodArgs.forEach(name => {
methodArgs.forEach((name) => {
if (name === 'options') return;
setupArgs.positional(`[--${param(name)}] <${param(name)}>`, {
@ -106,7 +121,7 @@ function runAPIMethod(args, apiName, method) {
Object.entries(args).forEach(([argName, value]) => {
if (ignoreOptions.includes(argName)) return;
const camelCased = camelize(argName.replace('gl-', ''), '-');
const camelCased = camelize(argName.replace('gb-', '').replace('gl-', ''), '-');
if (globalConfig[argName]) {
initArgs[camelCased] = value;
@ -115,17 +130,18 @@ function runAPIMethod(args, apiName, method) {
});
// Create service
const s = new core[apiName](initArgs);
const s = new Gitbeaker[apiName](initArgs);
// Execute function
const spinner = ora({ text: 'Calling Gitlab', color: 'yellow' }).start();
return s[method.name](...Object.values(coreArgs), optionalArgs)
.then(r => {
.then((r) => {
spinner.succeed('Success!');
console.log(JSON.stringify(r, null, 3));
})
.catch(e => {
.catch((e) => {
console.debug(e);
spinner.fail(e.description);
});
}
@ -142,8 +158,8 @@ function setupAPIs(setupArgs, apiName, methods) {
const method = methods[i];
setupArgs.command(param(method.name), {
setup: setupMethodArgs => setupAPIMethods(setupMethodArgs, method.args),
run: args => runAPIMethod(args, apiName, method),
setup: (setupMethodArgs) => setupAPIMethods(setupMethodArgs, method.args),
run: (args) => runAPIMethod(args, apiName, method),
});
}
@ -156,13 +172,13 @@ program
.help('-h, --help')
.epilogue('Copyright 2019')
.style({
usagePrefix: s => usageStyle(s),
group: s => groupStyle(s),
flags: s => optionStyle(s),
usageCommandPlaceholder: s => commandStyle(s),
usageOptionsPlaceholder: s => optionStyle(s),
desc: s => descriptionStyle(s),
hints: s => hintStyle(s),
usagePrefix: (s) => usageStyle(s),
group: (s) => groupStyle(s),
flags: (s) => optionStyle(s),
usageCommandPlaceholder: (s) => commandStyle(s),
usageOptionsPlaceholder: (s) => optionStyle(s),
desc: (s) => descriptionStyle(s),
hints: (s) => hintStyle(s),
});
program.option('-g, --global-args', {
@ -174,7 +190,7 @@ program.option('-g, --global-args', {
Object.entries(map).forEach(([apiName, methods]) => {
program.command(param(apiName), {
desc: `The ${apiName} API`,
setup: setupArgs => setupAPIs(setupArgs, apiName, methods),
setup: (setupArgs) => setupAPIs(setupArgs, apiName, methods),
});
});
@ -188,6 +204,7 @@ program.parse().then(({ argv, output }) => {
if (v.defaultValue === undefined) return;
display[k] = {
alias: v.alias,
description: v.desc,
value: v.defaultValue,
};

View File

@ -0,0 +1,234 @@
/* eslint no-console: 0 */
import { exec } from 'child_process';
import { promisify } from 'util';
import strip from 'strip-ansi';
import pkg from '../../package.json';
import bin from '../../src';
const execP = promisify(exec);
let env: Record<string, string | undefined> = {};
function cli(cmd, options = {}) {
const name = cmd.split(' ').shift();
const args = cmd.replace(name, '').trim();
expect(pkg.bin).toHaveProperty(name);
return execP(`node ${bin} ${args}`, options);
}
beforeEach(() => {
env = {};
});
describe('gitbeaker -g -- CLI global Enviroment Variables', () => {
it('should return an object of available gitbeaker cli environment variables', async () => {
const { stdout } = await cli('gitbeaker -g', { env });
expect(strip(stdout)).toBe('No global variables have been set!\n');
});
it('should only have the personal token set', async () => {
env.GITBEAKER_TOKEN = 'faketoken';
const { stdout } = await cli('gitbeaker -g', { env });
expect(JSON.parse(stdout)['gb-token'].value).toBe('faketoken');
});
it('should only have the personal token set by alias', async () => {
env.GITLAB_TOKEN = 'faketoken';
const { stdout } = await cli('gitbeaker -g', { env });
expect(JSON.parse(stdout)['gb-token'].value).toBe('faketoken');
});
it('should only have the oauth token set', async () => {
env.GITBEAKER_OAUTH_TOKEN = 'faketoken';
const { stdout } = await cli('gitbeaker -g', { env });
expect(JSON.parse(stdout)['gb-oauth-token'].value).toBe('faketoken');
});
it('should only have the oauth token set by alias', async () => {
env.GITLAB_OAUTH_TOKEN = 'faketoken';
const { stdout } = await cli('gitbeaker -g', { env });
expect(JSON.parse(stdout)['gb-oauth-token'].value).toBe('faketoken');
});
it('should only have the job token set', async () => {
env.GITBEAKER_JOB_TOKEN = 'faketoken';
const { stdout } = await cli('gitbeaker -g', { env });
expect(JSON.parse(stdout)['gb-job-token'].value).toBe('faketoken');
});
it('should only have the job token set by alias', async () => {
env.GITLAB_JOB_TOKEN = 'faketoken';
const { stdout } = await cli('gitbeaker -g', { env });
expect(JSON.parse(stdout)['gb-job-token'].value).toBe('faketoken');
});
it('should only have the host set', async () => {
env.GITBEAKER_HOST = 'www.fakehost.com';
const { stdout } = await cli('gitbeaker -g', { env });
expect(JSON.parse(stdout)['gb-host'].value).toBe('www.fakehost.com');
});
it('should only have the host set by alias', async () => {
env.GITLAB_HOST = 'www.fakehost.com';
const { stdout } = await cli('gitbeaker -g', { env });
expect(JSON.parse(stdout)['gb-host'].value).toBe('www.fakehost.com');
});
it('should only have the version set', async () => {
env.GITBEAKER_VERSION = '4';
const { stdout } = await cli('gitbeaker -g', { env });
expect(JSON.parse(stdout)['gb-version'].value).toBe(4);
});
it('should only have the version set by alias', async () => {
env.GITLAB_VERSION = '4';
const { stdout } = await cli('gitbeaker -g', { env });
expect(JSON.parse(stdout)['gb-version'].value).toBe(4);
});
it('should only have sudo set', async () => {
env.GITBEAKER_SUDO = 'sudoaccount';
const { stdout } = await cli('gitbeaker -g', { env });
expect(JSON.parse(stdout)['gb-sudo'].value).toBe('sudoaccount');
});
it('should only have sudo set by alias', async () => {
env.GITLAB_SUDO = 'sudoaccount';
const { stdout } = await cli('gitbeaker -g', { env });
expect(JSON.parse(stdout)['gb-sudo'].value).toBe('sudoaccount');
});
it('should only have the camelize set', async () => {
env.GITBEAKER_CAMELIZE = 'true';
const { stdout } = await cli('gitbeaker -g', { env });
expect(JSON.parse(stdout)['gb-camelize'].value).toBe(true);
});
it('should only have the camelize set by alias', async () => {
env.GITLAB_CAMELIZE = 'true';
const { stdout } = await cli('gitbeaker -g', { env });
expect(JSON.parse(stdout)['gb-camelize'].value).toBe(true);
});
it('should only have the profile token set', async () => {
env.GITBEAKER_PROFILE_TOKEN = 'faketoken';
const { stdout } = await cli('gitbeaker -g', { env });
expect(JSON.parse(stdout)['gb-profile-token'].value).toBe('faketoken');
});
it('should only have the profile token set by alias', async () => {
env.GITLAB_PROFILE_TOKEN = 'faketoken';
const { stdout } = await cli('gitbeaker -g', { env });
expect(JSON.parse(stdout)['gb-profile-token'].value).toBe('faketoken');
});
it('should only have the profile mode set', async () => {
env.GITBEAKER_PROFILE_MODE = 'mode1';
const { stdout } = await cli('gitbeaker -g', { env });
expect(JSON.parse(stdout)['gb-profile-mode'].value).toBe('mode1');
});
it('should only have the profile mode set by alias', async () => {
env.GITLAB_PROFILE_MODE = 'mode1';
const { stdout } = await cli('gitbeaker -g', { env });
expect(JSON.parse(stdout)['gb-profile-mode'].value).toBe('mode1');
});
});
describe('gitbeaker -v -- Package Version', () => {
it('should return the current version number of the package', async () => {
const { stdout } = await cli('gitbeaker -v');
expect(stdout.trim()).toBe(pkg.version);
});
});
describe('gitbeaker projects create', () => {
it('should create a valid project using configuration from environment variables', async () => {
env.GITBEAKER_HOST = process.env.GITLAB_URL;
env.GITBEAKER_TOKEN = process.env.PERSONAL_ACCESS_TOKEN;
const { stdout } = await cli('gitbeaker projects create --name="Project Creation CLI test1"', {
env,
});
expect(JSON.parse(stdout).name).toEqual('Project Creation CLI test1');
});
it('should create a valid project using configuration passed in arguments', async () => {
const { stdout } = await cli(
`gitbeaker projects create --gl-token=${process.env.PERSONAL_ACCESS_TOKEN} --gl-host=${process.env.GITLAB_URL} --name="Project Creation CLI test2"`,
{
env: process.env,
},
);
expect(JSON.parse(stdout).name).toEqual('Project Creation CLI test2');
});
it('should create a valid project using configuration passed in arguments and defined in the environment variables', async () => {
process.env.GITLAB_HOST = process.env.GITLAB_URL;
const { stdout } = await cli(
`
gitbeaker projects create --gl-token=${process.env.PERSONAL_ACCESS_TOKEN} --name="Project Creation CLI test3"`,
{
env: process.env,
},
);
expect(JSON.parse(stdout).name).toEqual('Project Creation CLI test3');
});
it('should create a valid project using configuration passed in arguments, overriding those defined in the environment variables', async () => {
process.env.GITLAB_TOKEN = 'faketoken';
const { stdout } = await cli(
`
gitbeaker projects create --gl-host=${process.env.GITLAB_URL} --gl-token=${process.env.PERSONAL_ACCESS_TOKEN} --name="Project Creation CLI test4"`,
{
env: process.env,
},
);
expect(JSON.parse(stdout).name).toEqual('Project Creation CLI test4');
});
});

View File

@ -0,0 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist"
},
"include": ["src"]
}

View File

@ -0,0 +1,54 @@
{
"name": "@gitbeaker/core",
"description": "Core API implementation of the GitLab API. Supports Promises, Async/Await.",
"version": "15.0.3",
"author": {
"name": "Justin Dalrymple"
},
"bugs": {
"url": "https://github.com/jdalrymple/gitbeaker/issues"
},
"dependencies": {
"@gitbeaker/requester-utils": "^15.0.3",
"form-data": "^3.0.0",
"li": "^1.3.0",
"xcase": "^2.0.1"
},
"devDependencies": {
"@types/node": "^13.7.0",
"esm": "^3.2.25",
"fs-extra": "^8.1.0",
"get-param-names": "github:jdalrymple/get-param-names#1-improve-functionality",
"rollup": "^1.31.0",
"rollup-plugin-terser": "^5.2.0",
"rollup-plugin-typescript2": "^0.25.3",
"ts-node": "^8.6.2",
"typescript": "^3.7.5"
},
"engines": {
"node": ">=10.0.0"
},
"files": [
"dist"
],
"homepage": "https://github.com/jdalrymple/gitbeaker#readme",
"keywords": [
"api",
"es5",
"es6",
"gitlab"
],
"license": "MIT",
"main": "dist/index.js",
"module": "dist/index.es.js",
"repository": {
"type": "git",
"url": "https://github.com/jdalrymple/gitbeaker"
},
"scripts": {
"build:self": "tsc && rollup -c",
"build": "yarn run generate-map && yarn run build:self",
"generate-map": "ESM_DISABLE_CACHE=true TS_NODE_PROJECT=scripts/tsconfig.json node -r esm -r ts-node/register scripts/generate.ts"
},
"types": "dist/types/index.d.ts"
}

View File

@ -0,0 +1,18 @@
import pkg from './package.json';
import { commonConfig, commonPlugins } from '../../rollup.config';
export default {
...commonConfig,
external: [...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.peerDependencies || {})],
output: [
{
file: pkg.main, // CommonJS (for Node) (for bundlers) build.
format: 'cjs',
},
{
file: pkg.module, // ES module (for bundlers) build.
format: 'es',
},
],
plugins: commonPlugins,
};

View File

@ -1,7 +1,7 @@
import getParamNames from 'get-param-names';
import { outputJsonSync, removeSync } from 'fs-extra';
import * as core from '../core';
import { BaseService } from '../core/infrastructure';
import { outputJsonSync } from 'fs-extra';
import * as Gitbeaker from '../src';
import { BaseService } from '../src/infrastructure';
function isGetter(x, name) {
return (Object.getOwnPropertyDescriptor(x, name) || {}).get;
@ -16,7 +16,7 @@ function deepFunctions(x) {
x &&
x !== Object.prototype &&
Object.getOwnPropertyNames(x)
.filter(name => isGetter(x, name) || isFunction(x, name))
.filter((name) => isGetter(x, name) || isFunction(x, name))
.concat(deepFunctions(Object.getPrototypeOf(x)) || [])
);
}
@ -26,7 +26,7 @@ function distinctDeepFunctions(x): string[] {
}
function getInstanceMethods(x) {
return distinctDeepFunctions(x).filter(name => name !== 'constructor' && !~name.indexOf('__'));
return distinctDeepFunctions(x).filter((name) => name !== 'constructor' && !~name.indexOf('__'));
}
function removeOptionalArg(list) {
@ -39,10 +39,10 @@ function buildMap() {
const map = {};
const baseArgs = Object.keys(getParamNames(BaseService)[0]);
for (const [name, service] of Object.entries(core)) {
for (const [name, service] of Object.entries(Gitbeaker as object)) {
if (name.includes('Bundle') || name === 'Gitlab') continue;
const s = new service();
const s = new service({ requester: {} });
map[name] = [{ name: 'constructor', args: baseArgs }];
@ -59,5 +59,3 @@ function buildMap() {
// Generate the services map
outputJsonSync('./dist/map.json', buildMap());
removeSync('./temp');

View File

@ -1,8 +1,6 @@
{
"files": ["src/bin/generate.ts"],
"compilerOptions": {
"esModuleInterop": true,
"outDir": "temp",
"allowJs": true,
"target": "es6",
"module": "esnext",

View File

@ -1,9 +1,11 @@
import { bundler } from './infrastructure';
import * as APIServices from './services';
// All separately
/* -------------- Single Services ------------- */
export * from './services';
/* ------------------ Bundles ----------------- */
// Groups
export const GroupsBundle = bundler({
Groups: APIServices.Groups,
@ -87,7 +89,7 @@ export const ProjectsBundle = bundler({
// All initialized
export const Gitlab = bundler(APIServices);
// Types
/* ---------------- Bundles Types-------------- */
export type UsersBundle = InstanceType<typeof UsersBundle>;
export type GroupsBundle = InstanceType<typeof GroupsBundle>;
export type ProjectsBundle = InstanceType<typeof ProjectsBundle>;

View File

@ -1,12 +1,4 @@
import { KyRequester } from './KyRequester';
export interface Requester {
get: Function;
post: Function;
put: Function;
delete: Function;
stream?: Function;
}
import { RequesterType } from '@gitbeaker/requester-utils';
export interface BaseServiceOptions {
oauthToken?: string;
@ -17,7 +9,7 @@ export interface BaseServiceOptions {
version?: 3 | 4;
rejectUnauthorized?: boolean;
camelize?: boolean;
requester?: Requester;
requester?: RequesterType;
requestTimeout?: number;
profileToken?: string;
sudo?: string | number;
@ -27,7 +19,7 @@ export interface BaseServiceOptions {
export class BaseService {
public readonly url: string;
public readonly requester: Requester;
public readonly requester: RequesterType;
public readonly requestTimeout: number;
@ -43,17 +35,21 @@ export class BaseService {
oauthToken,
sudo,
profileToken,
requester,
profileMode = 'execution',
host = 'https://gitlab.com',
url = '',
version = 4,
camelize = false,
rejectUnauthorized = true,
requester = KyRequester as Requester,
requestTimeout = 300000,
}: BaseServiceOptions = {}) {
if (!requester) throw new ReferenceError('Requester must be passed');
this.url = [host, 'api', `v${version}`, url].join('/');
this.headers = {};
this.headers = {
'user-agent': 'gitbeaker',
};
this.rejectUnauthorized = rejectUnauthorized;
this.camelize = camelize;
this.requester = requester;
@ -67,8 +63,7 @@ export class BaseService {
// Profiling
if (profileToken) {
this.headers['X-Profile-Token'] = profileToken;
if (profileMode) this.headers['X-Profile-Mode'] = profileMode;
this.headers['X-Profile-Mode'] = profileMode;
}
// Set sudo

View File

@ -6,6 +6,10 @@ export interface Sudo {
sudo?: string | number;
}
export interface ShowExpanded {
showExpanded?: boolean;
}
export interface PaginationOptions {
total: number;
next: number | null;
@ -20,31 +24,40 @@ export interface BaseRequestOptions extends Sudo {
[key: string]: any;
}
export interface PaginatedRequestOptions extends BaseRequestOptions {
showPagination?: boolean;
export interface PaginatedRequestOptions extends BaseRequestOptions, ShowExpanded {
maxPages?: number;
page?: number;
perPage?: number;
}
export type PaginationResponse = { data: object[]; pagination: PaginationOptions };
export type GetResponse = PaginationResponse | object | object[];
export type PostResponse = object;
export type PutResponse = object;
export type DelResponse = object;
export interface ExpandedResponse {
data: object;
headers: object;
status: number;
}
export interface PaginationResponse {
data: object[];
pagination: PaginationOptions;
}
export type GetResponse = PaginationResponse | ExpandedResponse | object | object[];
export type PostResponse = ExpandedResponse | object;
export type PutResponse = ExpandedResponse | object;
export type DelResponse = ExpandedResponse | object;
async function get(
service: BaseService,
endpoint: string,
options: PaginatedRequestOptions = {},
): Promise<GetResponse> {
const { showPagination, maxPages, sudo, ...query } = options;
const { showExpanded, maxPages, sudo, ...query } = options;
const response = await service.requester.get(service, endpoint, {
query: query || {},
sudo,
});
const { headers } = response;
const { headers, status } = response;
let { body } = response;
let pagination = {
total: parseInt(headers['x-total'], 10),
@ -68,14 +81,27 @@ async function get(
const more = (await get(service, next.replace(regex, ''), {
maxPages,
sudo,
showPagination: true,
showExpanded: true,
})) as PaginationResponse;
pagination = more.pagination;
body = [...body, ...more.data];
}
return (query.page || body.length > 0) && showPagination ? { data: body, pagination } : body;
// If expanded version is not requested, return body
if (!showExpanded) return body;
// Else build the expanded response
const output = { data: body } as Record<string, any>;
if (body.length > 0 || query.page) {
output.pagination = pagination;
} else {
output.headers = headers;
output.status = status;
}
return output;
}
function stream(service: BaseService, endpoint: string, options: BaseRequestOptions = {}) {
@ -93,14 +119,14 @@ async function post(
endpoint: string,
options: BaseRequestOptions = {},
): Promise<PostResponse> {
const { sudo, form, ...body } = options;
const { sudo, form, showExpanded, ...body } = options;
const response = await service.requester.post(service, endpoint, {
const r = await service.requester.post(service, endpoint, {
body: form || body,
sudo,
});
return response.body;
return showExpanded ? { data: r.body, status: r.status, headers: r.headers } : r.body;
}
async function put(
@ -108,13 +134,13 @@ async function put(
endpoint: string,
options: BaseRequestOptions = {},
): Promise<PutResponse> {
const { sudo, ...body } = options;
const response = await service.requester.put(service, endpoint, {
const { sudo, showExpanded, ...body } = options;
const r = await service.requester.put(service, endpoint, {
body,
sudo,
});
return response.body;
return showExpanded ? { data: r.body, status: r.status, headers: r.headers } : r.body;
}
async function del(
@ -122,13 +148,13 @@ async function del(
endpoint: string,
options: BaseRequestOptions = {},
): Promise<DelResponse> {
const { sudo, ...query } = options;
const response = await service.requester.delete(service, endpoint, {
const { sudo, showExpanded, ...query } = options;
const r = await service.requester.delete(service, endpoint, {
query,
sudo,
});
return response.body;
return showExpanded ? { data: r.body, status: r.status, headers: r.headers } : r.body;
}
export const RequestHelper = {

View File

@ -1,5 +1,4 @@
/* eslint @typescript-eslint/no-explicit-any: 0 */
interface Constructor {
new (...args: any): any;
}
@ -19,3 +18,12 @@ export function bundler<T extends { [name: string]: Constructor }, P extends key
});
} as any) as Bundle<T, P>;
}
export function appendFormFromObject(object) {
const form = new FormData();
Object.entries(object).forEach(([k, v]) => {
if (Array.isArray(v)) form.append(k, v[0], v[1]);
else form.append(k, v as any);
});
}

View File

@ -1,4 +1,3 @@
export * from './BaseService';
export { bundler } from './Utils';
export { KyRequester } from './KyRequester';
export * from './RequestHelper';

View File

@ -2,7 +2,7 @@ import { ResourceDiscussions } from '../templates';
import { BaseServiceOptions } from '../infrastructure';
export class CommitDiscussions extends ResourceDiscussions {
constructor(options: BaseServiceOptions) {
constructor(options: BaseServiceOptions = {}) {
super('projects', 'commits', options);
}
}

View File

@ -6,8 +6,10 @@ import {
Sudo,
} from '../infrastructure';
export type CommitSchema = CommitSchemaDefault | CommitSchemaCamelized;
// As of GitLab v12.6.2
export interface CommitSchema {
export interface CommitSchemaDefault {
id: string;
short_id: string;
created_at: Date;
@ -22,6 +24,21 @@ export interface CommitSchema {
committed_date?: Date;
}
export interface CommitSchemaCamelized {
id: string;
shortId: string;
createdAt: Date;
parentIds?: string[];
title: string;
message: string;
authorName: string;
authorEmail: string;
authoredDate?: Date;
committerName?: string;
committerEmail?: string;
committedDate?: Date;
}
interface CommitAction {
/** The action to perform */
action: 'create' | 'delete' | 'move' | 'update';

View File

@ -16,7 +16,9 @@ export interface DeploymentSchema {
user: UserSchema;
}
export interface Deployable {
export type Deployable = DeployableDefault | DeployableCamelized;
export interface DeployableDefault {
id: number;
ref: string;
name: string;
@ -33,6 +35,23 @@ export interface Deployable {
pipeline?: PipelineSchema;
}
export interface DeployableCamelized {
id: number;
ref: string;
name: string;
runner?: RunnerSchema;
stage?: string;
startedAt?: Date;
status?: DeploymentStatus;
tag: boolean;
commit?: CommitSchema;
coverage?: string;
createdAt?: Date;
finishedAt?: Date;
user?: UserSchema;
pipeline?: PipelineSchema;
}
export class Deployments extends BaseService {
all(projectId: string | number, options?: PaginatedRequestOptions) {
const pId = encodeURIComponent(projectId);

View File

@ -6,23 +6,43 @@ import {
Sudo,
} from '../infrastructure';
import { DeploymentSchema } from './Deployments';
import { ProjectSchema } from './Projects';
import { ProjectSchemaDefault, ProjectSchemaCamelized } from './Projects';
// ref: https://docs.gitlab.com/12.6/ee/api/environments.html#list-environments
export interface EnvironmentSchema {
export type EnvironmentSchema = EnvironmentSchemaDefault | EnvironmentSchemaCamelized;
export interface EnvironmentSchemaDefault {
id: number;
name: string;
slug?: string;
external_url?: string;
project?: ProjectSchema;
project?: ProjectSchemaDefault;
state?: string;
}
export interface EnvironmentDetailSchema extends EnvironmentSchema {
export interface EnvironmentSchemaCamelized {
id: number;
name: string;
slug?: string;
externalUrl?: string;
project?: ProjectSchemaCamelized;
state?: string;
}
export type EnvironmentDetailSchema =
| EnvironmentDetailSchemaDefault
| EnvironmentDetailSchemaCamelized;
export interface EnvironmentDetailSchemaDefault extends EnvironmentSchemaDefault {
last_deployment?: DeploymentSchema;
deployable?: DeploymentSchema;
}
export interface EnvironmentDetailSchemaCamelized extends EnvironmentSchemaCamelized {
lastDeployment?: DeploymentSchema;
deployable?: DeploymentSchema;
}
export class Environments extends BaseService {
all(projectId: string | number, options?: PaginatedRequestOptions): Promise<EnvironmentSchema[]> {
const pId = encodeURIComponent(projectId);

View File

@ -2,7 +2,7 @@ import { ResourceDiscussions } from '../templates';
import { BaseServiceOptions } from '../infrastructure';
export class EpicDiscussions extends ResourceDiscussions {
constructor(options: BaseServiceOptions) {
constructor(options: BaseServiceOptions = {}) {
super('groups', 'epics', options);
}
}

View File

@ -2,7 +2,7 @@ import { ResourceNotes } from '../templates';
import { BaseServiceOptions } from '../infrastructure';
export class EpicNotes extends ResourceNotes {
constructor(options: BaseServiceOptions) {
constructor(options: BaseServiceOptions = {}) {
super('groups', 'epics', options);
}
}

View File

@ -2,7 +2,7 @@ import { ResourceTemplates } from '../templates';
import { BaseServiceOptions } from '../infrastructure';
export class GitLabCIYMLTemplates extends ResourceTemplates {
constructor(options: BaseServiceOptions) {
constructor(options: BaseServiceOptions = {}) {
super('gitlab_ci_ymls', options);
}
}

View File

@ -2,7 +2,7 @@ import { ResourceTemplates } from '../templates';
import { BaseServiceOptions } from '../infrastructure';
export class GitignoreTemplates extends ResourceTemplates {
constructor(options: BaseServiceOptions) {
constructor(options: BaseServiceOptions = {}) {
super('gitignores', options);
}
}

View File

@ -2,7 +2,7 @@ import { ResourceAccessRequests } from '../templates';
import { BaseServiceOptions } from '../infrastructure';
export class GroupAccessRequests extends ResourceAccessRequests {
constructor(options: BaseServiceOptions) {
constructor(options: BaseServiceOptions = {}) {
super('groups', options);
}
}

View File

@ -2,7 +2,7 @@ import { ResourceBadges } from '../templates';
import { BaseServiceOptions } from '../infrastructure';
export class GroupBadges extends ResourceBadges {
constructor(options: BaseServiceOptions) {
constructor(options: BaseServiceOptions = {}) {
super('groups', options);
}
}

View File

@ -2,7 +2,7 @@ import { ResourceCustomAttributes } from '../templates';
import { BaseServiceOptions } from '../infrastructure';
export class GroupCustomAttributes extends ResourceCustomAttributes {
constructor(options: BaseServiceOptions) {
constructor(options: BaseServiceOptions = {}) {
super('groups', options);
}
}

View File

@ -2,7 +2,7 @@ import { ResourceIssueBoards } from '../templates';
import { BaseServiceOptions } from '../infrastructure';
export class GroupIssueBoards extends ResourceIssueBoards {
constructor(options: BaseServiceOptions) {
constructor(options: BaseServiceOptions = {}) {
super('groups', options);
}
}

View File

@ -2,7 +2,7 @@ import { BaseServiceOptions } from '../infrastructure';
import { ResourceLabels } from '../templates';
export class GroupLabels extends ResourceLabels {
constructor(options: BaseServiceOptions) {
constructor(options: BaseServiceOptions = {}) {
super('groups', options);
}
}

View File

@ -2,7 +2,7 @@ import { ResourceMembers } from '../templates';
import { BaseServiceOptions } from '../infrastructure';
export class GroupMembers extends ResourceMembers {
constructor(options: BaseServiceOptions) {
constructor(options: BaseServiceOptions = {}) {
super('groups', options);
}
}

View File

@ -2,7 +2,7 @@ import { ResourceMilestones } from '../templates';
import { BaseServiceOptions } from '../infrastructure';
export class GroupMilestones extends ResourceMilestones {
constructor(options: BaseServiceOptions) {
constructor(options: BaseServiceOptions = {}) {
super('groups', options);
}
}

View File

@ -2,7 +2,7 @@ import { ResourceVariables } from '../templates';
import { BaseServiceOptions } from '../infrastructure';
export class GroupVariables extends ResourceVariables {
constructor(options: BaseServiceOptions) {
constructor(options: BaseServiceOptions = {}) {
super('groups', options);
}
}

View File

@ -4,49 +4,56 @@ import {
PaginatedRequestOptions,
RequestHelper,
Sudo,
ShowExpanded,
} from '../infrastructure';
import { ProjectSchema } from './Projects';
// As of GitLab v12.6.2
export interface GroupSchema {
export type GroupSchema = GroupSchemaDefault | GroupSchemaCamelized;
export interface GroupSchemaDefault {
id: number;
web_url: string;
name: string;
path: string;
description: string;
visibility: string;
share_with_group_lock: boolean;
require_two_factor_authentication: boolean;
two_factor_grace_period: number;
project_creation_level: string;
auto_devops_enabled?: boolean;
subgroup_creation_level: string;
emails_disabled?: boolean;
lfs_enabled: boolean;
avatar_url: string;
request_access_enabled: boolean;
full_name: string;
full_path: string;
parent_id?: number;
parent_id: number;
visibility: string;
avatar_url: string;
web_url: string;
}
// As of GitLab v12.6.2
export interface GroupDetailSchema extends GroupSchema {
projects: ProjectSchema[];
shared_projects: ProjectSchema[];
runners_token: string;
export interface GroupSchemaCamelized {
id: number;
name: string;
path: string;
fullName: string;
fullPath: string;
parentId: number;
visibility: string;
avatarUrl: string;
webUrl: string;
}
export type GroupDetailSchema = GroupSchema & {
projects: ProjectSchema[];
};
export class Groups extends BaseService {
all(options?: PaginatedRequestOptions): Promise<GroupSchema[]> {
return RequestHelper.get(this, 'groups', options) as Promise<GroupSchema[]>;
}
create(options?: BaseRequestOptions) {
return RequestHelper.post(this, 'groups', options);
create(name, path, options?: BaseRequestOptions & ShowExpanded) {
return RequestHelper.post(this, 'groups', { name, path, ...options });
}
createLDAPLink(groupId: string | number, cn, groupAccess, provider: string, options?: Sudo) {
createLDAPLink(
groupId: string | number,
cn,
groupAccess,
provider: string,
options?: Sudo & ShowExpanded,
) {
const gId = encodeURIComponent(groupId);
return RequestHelper.post(this, `groups/${gId}/ldap_group_links`, {
@ -57,7 +64,7 @@ export class Groups extends BaseService {
});
}
edit(groupId: string | number, options?: BaseRequestOptions) {
edit(groupId: string | number, options?: BaseRequestOptions & ShowExpanded) {
const gId = encodeURIComponent(groupId);
return RequestHelper.put(this, `groups/${gId}`, options);
@ -69,7 +76,7 @@ export class Groups extends BaseService {
return RequestHelper.get(this, `groups/${gId}/projects`, options) as Promise<ProjectSchema[]>;
}
remove(groupId: string | number, options?: Sudo) {
remove(groupId: string | number, options?: Sudo & ShowExpanded) {
const gId = encodeURIComponent(groupId);
return RequestHelper.del(this, `groups/${gId}`, options);
@ -78,7 +85,7 @@ export class Groups extends BaseService {
removeLDAPLink(
groupId: string | number,
cn,
{ provider, ...options }: Sudo & { provider?: string } = {},
{ provider, ...options }: Sudo & ShowExpanded & { provider?: string } = {},
) {
const gId = encodeURIComponent(groupId);
const url = provider ? `${provider}/${cn}` : `${cn}`;
@ -99,18 +106,13 @@ export class Groups extends BaseService {
return RequestHelper.get(this, `groups/${gId}`, options) as Promise<GroupDetailSchema>;
}
subgroups(
groupId: string | number,
options?: PaginatedRequestOptions,
): Promise<GroupDetailSchema[]> {
subgroups(groupId: string | number, options?: PaginatedRequestOptions) {
const gId = encodeURIComponent(groupId);
return RequestHelper.get(this, `groups/${gId}/subgroups`, options) as Promise<
GroupDetailSchema[]
>;
return RequestHelper.get(this, `groups/${gId}/subgroups`, options);
}
syncLDAP(groupId: string | number, options?: Sudo) {
syncLDAP(groupId: string | number, options?: Sudo & ShowExpanded) {
const gId = encodeURIComponent(groupId);
return RequestHelper.post(this, `groups/${gId}/ldap_sync`, options);

View File

@ -2,7 +2,7 @@ import { ResourceAwardEmojis } from '../templates';
import { BaseServiceOptions } from '../infrastructure';
export class IssueAwardEmojis extends ResourceAwardEmojis {
constructor(options: BaseServiceOptions) {
constructor(options: BaseServiceOptions = {}) {
super('issues', options);
}
}

View File

@ -2,7 +2,7 @@ import { ResourceDiscussions } from '../templates';
import { BaseServiceOptions } from '../infrastructure';
export class IssueDiscussions extends ResourceDiscussions {
constructor(options: BaseServiceOptions) {
constructor(options: BaseServiceOptions = {}) {
super('projects', 'issues', options);
}
}

View File

@ -2,7 +2,7 @@ import { ResourceNotes } from '../templates';
import { BaseServiceOptions } from '../infrastructure';
export class IssueNotes extends ResourceNotes {
constructor(options: BaseServiceOptions) {
constructor(options: BaseServiceOptions = {}) {
super('projects', 'issues', options);
}
}

View File

@ -6,6 +6,8 @@ import {
Sudo,
} from '../infrastructure';
type ProjectOrGroup = { projectId: string | number } | { groupId: string | number } | {};
export class Issues extends BaseService {
addSpentTime(projectId: string | number, issueId: number, duration: string, options?: Sudo) {
const [pId, iId] = [projectId, issueId].map(encodeURIComponent);
@ -25,12 +27,7 @@ export class Issues extends BaseService {
});
}
all({
projectId,
groupId,
...options
}: ({ projectId?: string | number } | { groupId?: string | number } | {}) &
PaginatedRequestOptions = {}) {
all({ projectId, groupId, ...options }: ProjectOrGroup & PaginatedRequestOptions = {}) {
let url;
if (projectId) {

View File

@ -1,12 +1,9 @@
import { BaseService, RequestHelper, BaseRequestOptions } from '../infrastructure';
type ProjectOrGroup = { projectId: string | number } | { groupId: string | number } | {};
export class IssuesStatistics extends BaseService {
all({
projectId,
groupId,
...options
}: ({ projectId?: string | number } | { groupId?: string | number } | {}) &
BaseRequestOptions = {}) {
all({ projectId, groupId, ...options }: ProjectOrGroup & BaseRequestOptions = {}) {
let url;
if (projectId) {

View File

@ -5,10 +5,10 @@ import {
RequestHelper,
Sudo,
} from '../infrastructure';
import { CommitSchema } from './Commits';
import { PipelineSchema } from './Pipelines';
import { RunnerSchema } from './Runners';
import { UserSchema } from './Users';
import { CommitSchemaDefault, CommitSchemaCamelized } from './Commits';
import { PipelineSchemaDefault, PipelineSchemaCamelized } from './Pipelines';
import { RunnerSchemaDefault, RunnerSchemaCamelized } from './Runners';
import { UserSchemaDefault, UserSchemaCamelized } from './Users';
export type JobScope =
| 'created'
@ -21,15 +21,26 @@ export type JobScope =
| 'manual';
// As of GitLab v12.6.2
export interface ArtifactSchema {
export type ArtifactSchema = ArtifactSchemaDefault | ArtifactSchemaCamelized;
export interface ArtifactSchemaDefault {
file_type: string;
size: number;
filename: string;
file_format?: string;
}
export interface ArtifactSchemaCamelized {
fileType: string;
size: number;
filename: string;
fileFormat?: string;
}
// As of GitLab v12.6.2
export interface JobSchema {
export type JobSchema = JobSchemaDefault | JobSchemaCamelized;
export interface JobSchemaDefault {
id: number;
status: string;
stage: string;
@ -42,15 +53,37 @@ export interface JobSchema {
started_at?: Date;
finished_at?: Date;
duration?: number;
user: UserSchema;
commit: CommitSchema;
pipeline: PipelineSchema;
user: UserSchemaDefault;
commit: CommitSchemaDefault;
pipeline: PipelineSchemaDefault;
web_url: string;
artifacts: ArtifactSchema[];
runner: RunnerSchema;
artifacts: ArtifactSchemaDefault[];
runner: RunnerSchemaDefault;
artifacts_expire_at?: Date;
}
export interface JobSchemaCamelized {
id: number;
status: string;
stage: string;
name: string;
ref: string;
tag: boolean;
coverage?: string;
allowFailure: boolean;
createdAt: Date;
startedAt?: Date;
finishedAt?: Date;
duration?: number;
user: UserSchemaCamelized;
commit: CommitSchemaCamelized;
pipeline: PipelineSchemaCamelized;
webUrl: string;
artifacts: ArtifactSchemaCamelized[];
runner: RunnerSchemaCamelized;
artifactsExpireAt?: Date;
}
export class Jobs extends BaseService {
all(projectId: string | number, options?: PaginatedRequestOptions) {
const pId = encodeURIComponent(projectId);

View File

@ -2,7 +2,7 @@ import { BaseServiceOptions } from '../infrastructure';
import { ResourceLabels } from '../templates';
export class Labels extends ResourceLabels {
constructor(options: BaseServiceOptions) {
constructor(options: BaseServiceOptions = {}) {
super('projects', options);
}
}

View File

@ -2,7 +2,7 @@ import { ResourceTemplates } from '../templates';
import { BaseServiceOptions } from '../infrastructure';
export class LicenceTemplates extends ResourceTemplates {
constructor(options: BaseServiceOptions) {
constructor(options: BaseServiceOptions = {}) {
super('licences', options);
}
}

View File

@ -0,0 +1,21 @@
import { BaseService, RequestHelper, Sudo } from '../infrastructure';
export class Licence extends BaseService {
add(licence: string, options?: Sudo) {
return RequestHelper.post(this, 'licence', { licence, ...options });
}
all(options?: Sudo) {
return RequestHelper.get(this, 'licences', options);
}
show(options?: Sudo) {
return RequestHelper.get(this, 'licence', options);
}
remove(licenceId: number, options?: Sudo) {
const lId = encodeURIComponent(licenceId);
return RequestHelper.del(this, `licence/${lId}`, options);
}
}

View File

@ -2,7 +2,7 @@ import { ResourceAwardEmojis } from '../templates';
import { BaseServiceOptions } from '../infrastructure';
export class MergeRequestAwardEmojis extends ResourceAwardEmojis {
constructor(options: BaseServiceOptions) {
constructor(options: BaseServiceOptions = {}) {
super('merge_requests', options);
}
}

View File

@ -2,7 +2,7 @@ import { ResourceDiscussions } from '../templates';
import { BaseServiceOptions } from '../infrastructure';
export class MergeRequestDiscussions extends ResourceDiscussions {
constructor(options: BaseServiceOptions) {
constructor(options: BaseServiceOptions = {}) {
super('projects', 'merge_requests', options);
}
}

View File

@ -2,7 +2,7 @@ import { ResourceNotes } from '../templates';
import { BaseServiceOptions } from '../infrastructure';
export class MergeRequestNotes extends ResourceNotes {
constructor(options: BaseServiceOptions) {
constructor(options: BaseServiceOptions = {}) {
super('projects', 'merge_requests', options);
}
}

View File

@ -1,3 +1,4 @@
import { formatQuery } from '@gitbeaker/requester-utils';
import {
BaseRequestOptions,
BaseService,
@ -13,12 +14,11 @@ type NotificationSettingLevel =
| 'mention'
| 'custom';
type ProjectOrGroup = { projectId: string | number } | { groupId: string | number } | {};
export class NotificationSettings extends BaseService {
all({
projectId,
groupId,
...options
}: ({ projectId: string | number } | { groupId: string | number }) & PaginatedRequestOptions) {
all({ projectId, groupId, sudo, ...query }: ProjectOrGroup & PaginatedRequestOptions = {}) {
const q = formatQuery(query);
let url = '';
if (projectId) {
@ -27,18 +27,16 @@ export class NotificationSettings extends BaseService {
url += `groups/${encodeURIComponent(groupId)}/`;
}
return RequestHelper.get(this, `${url}notification_settings`, options);
return RequestHelper.get(this, `${url}notification_settings?${q}`, { sudo });
}
edit({
projectId,
groupId,
...options
}: { level?: NotificationSettingLevel } & (
| { projectId: string | number }
| { groupId: string | number }
) &
BaseRequestOptions) {
sudo,
...query
}: { level?: NotificationSettingLevel } & ProjectOrGroup & BaseRequestOptions = {}) {
const q = formatQuery(query);
let url = '';
if (projectId) {
@ -47,6 +45,6 @@ export class NotificationSettings extends BaseService {
url += `groups/${encodeURIComponent(groupId)}/`;
}
return RequestHelper.put(this, `${url}notification_settings`, options);
return RequestHelper.put(this, `${url}notification_settings?${q}`, { sudo });
}
}

View File

@ -8,7 +8,9 @@ import {
import { JobScope } from './Jobs';
// As of GitLab v12.6.2
export interface PipelineSchema {
export type PipelineSchema = PipelineSchemaDefault | PipelineSchemaCamelized;
export interface PipelineSchemaDefault {
id: number;
sha: string;
ref: string;
@ -18,6 +20,16 @@ export interface PipelineSchema {
web_url: string;
}
export interface PipelineSchemaCamelized {
id: number;
sha: string;
ref: string;
status: string;
createdAt: Date;
updatedAt: Date;
webUrl: string;
}
export class Pipelines extends BaseService {
all(projectId: string | number, options?: PaginatedRequestOptions) {
const pId = encodeURIComponent(projectId);

View File

@ -2,7 +2,7 @@ import { ResourceAccessRequests } from '../templates';
import { BaseServiceOptions } from '../infrastructure';
export class ProjectAccessRequests extends ResourceAccessRequests {
constructor(options: BaseServiceOptions) {
constructor(options: BaseServiceOptions = {}) {
super('projects', options);
}
}

View File

@ -2,7 +2,7 @@ import { ResourceBadges } from '../templates';
import { BaseServiceOptions } from '../infrastructure';
export class ProjectBadges extends ResourceBadges {
constructor(options: BaseServiceOptions) {
constructor(options: BaseServiceOptions = {}) {
super('projects', options);
}
}

View File

@ -2,7 +2,7 @@ import { ResourceCustomAttributes } from '../templates';
import { BaseServiceOptions } from '../infrastructure';
export class ProjectCustomAttributes extends ResourceCustomAttributes {
constructor(options: BaseServiceOptions) {
constructor(options: BaseServiceOptions = {}) {
super('projects', options);
}
}

View File

@ -2,7 +2,7 @@ import { ResourceIssueBoards } from '../templates';
import { BaseServiceOptions } from '../infrastructure';
export class ProjectIssueBoards extends ResourceIssueBoards {
constructor(options: BaseServiceOptions) {
constructor(options: BaseServiceOptions = {}) {
super('projects', options);
}
}

View File

@ -2,7 +2,7 @@ import { ResourceMembers } from '../templates';
import { BaseServiceOptions } from '../infrastructure';
export class ProjectMembers extends ResourceMembers {
constructor(options: BaseServiceOptions) {
constructor(options: BaseServiceOptions = {}) {
super('projects', options);
}
}

Some files were not shown because too many files have changed in this diff Show More