fix: build

This commit is contained in:
2023-05-31 14:01:59 +02:00
parent 3792a14e90
commit fd740b3091
185 changed files with 21932 additions and 71486 deletions
+5
View File
@@ -0,0 +1,5 @@
.idea
.vscode
.turbo
node_modules
.env.local
+28
View File
@@ -0,0 +1,28 @@
image: node:18-buster
before_script:
- echo TURBO_API=$TURBO_API >> .env.local
- echo TURBO_TOKEN=$TURBO_TOKEN >> .env.local
- echo TURBO_TEAM=$TURBO_TEAM >> .env.local
stages:
- build
build:
stage: build
before_script:
- corepack enable
- corepack prepare pnpm@latest-7 --activate
- pnpm config set store-dir .pnpm-store
script:
- pnpm install
- pnpm run syncpack
- pnpm lint
- pnpm format
- pnpm build
cache:
key:
files:
- pnpm-lock.yaml
paths:
- .pnpm-store
+5
View File
@@ -0,0 +1,5 @@
#!/bin/bash
echo TURBO_API=$TURBO_API >> .env.local
echo TURBO_TOKEN=$TURBO_TOKEN >> .env.local
echo TURBO_TEAM=$TURBO_TEAM >> .env.local
+32
View File
@@ -0,0 +1,32 @@
## Summary
(Summarize the bug encountered concisely)
## Steps to reproduce
(How one can reproduce the issue - this is very important)
## Example Project
(If possible, please create an example project here on GitLab.com that exhibits the problematic behaviour, and link to it here in the bug report)
(If you are using an older version of GitLab, this will also determine whether the bug has been fixed in a more recent version)
## What is the current bug behavior?
(What actually happens)
## What is the expected correct behavior?
(What you should see instead)
## Relevant logs and/or screenshots
(Paste any relevant logs - please use code blocks (```) to format console output,
logs, and code as it's very hard to read otherwise.)
## Possible fixes
(If you can, link to the line of code that might be responsible for the problem)
/label ~bug ~meeting
+17
View File
@@ -0,0 +1,17 @@
## Description
(Describe the feature that you're requesting concisely)
## Explanation
(Explain why the feature is necessary)
## Mockups/Screenshots
(If possible, provide mockups or screenshots, which demonstrate the feature)
## Dependencies, issues to be resolved beforehand
(List issues or dependencies that need to be resolved before this feature can be implemented)
/label ~feature ~meeting
+17
View File
@@ -0,0 +1,17 @@
## What needs to be changed?
??? - Describe use case!
## How is the current state not sufficient?
???
## Which changes are necessary?
???
## Do the proposed changes impact current use cases?
???
/label ~improvement ~meeting
+1
View File
@@ -0,0 +1 @@
auto-install-peers=true
+90
View File
@@ -0,0 +1,90 @@
{
"semverRange": "",
"source": [
"package.json",
"**/package.json"
],
"indent": " ",
"sortFirst": [
"name",
"description",
"version",
"type",
"license",
"repository",
"author",
"contributors",
"prettier",
"main",
"types",
"bin",
"scripts",
"dependencies",
"devDependencies",
"peerDependencies"
],
"versionGroups": [
{
"label": "ES Mapping Generator Special Dependencies",
"dependencies": ["typescript", "typedoc", "ts-node"],
"packages": ["@openstapps/es-mapping-generator"],
"isIgnored": true
},
{
"label": "Should have the same version",
"dependencies": ["**"],
"dependencyTypes": ["workspace"],
"packages": ["**"],
"pinVersion": "2.1.0"
},
{
"label": "Packages should use workspace version",
"dependencies": ["@openstapps/**"],
"dependencyTypes": ["prod", "dev"],
"packages": ["**"],
"pinVersion": "workspace:*"
},
{
"label": "Packages should be synced to configuration",
"dependencies": [
"typescript",
"ts-node",
"eslint",
"prettier"
],
"packages": [
"**"
],
"snapTo": [
"@openstapps/configuration",
"@openstapps/prettier-config",
"@openstapps/eslint-config",
"@openstapps/app"
]
},
{
"label": "No Banned Dependencies",
"dependencies": [
"tslint",
"lodash",
"@types/lodash"
],
"packages": [
"**"
],
"isBanned": true
},
{
"label": "No @types package in prod dependencies of applications",
"dependencies": ["@types/**"],
"dependencyTypes": ["prod"],
"packages": [
"@openstapps/app",
"@openstapps/backend",
"@openstapps/proxy",
"@openstapps/minimal**"
],
"isBanned": true
}
]
}
+38
View File
@@ -0,0 +1,38 @@
# Open StApps Monorepo
## Remote caching
Turbo supports remote caching, which massively speeds up build processes.
### Connecting to the remote cache locally
`.env.local`
```dotenv
TURBO_API=http://example:3000
TURBO_TEAM=openstapps
TURBO_TOKEN=abc123
```
### Connecting to the remote cache in GitLab Pipelines
You will need to define
* `TURBO_API`
* `TURBO_TEAM`
* `TURBO_TOKEN`
Like you did locally as described in [this](https://turbo.build/repo/docs/ci/gitlabci#remote-caching)
guide.
### Hosting a cache
Self-hosting via Docker is extremely simple, just follow
[this](http://v2202207178592194230.supersrv.de:6341) guide
or in short:
`.env`
```dotenv
PORT=...
TURBO_TOKEN=...
```
```shell
docker run --env-file=.env -p 3000:3000 fox1t/turborepo-remote-cache
```
+18 -17
View File
@@ -1,7 +1,7 @@
{
"name": "@openstapps/backend",
"version": "1.0.0",
"description": "A reference implementation for a StApps backend",
"version": "2.1.0",
"license": "AGPL-3.0-only",
"author": "André Bierlein <andre.mt.bierlein@gmail.com>",
"contributors": [
@@ -18,9 +18,10 @@
"build": "npm run lint && npm run compile",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md",
"check-configuration": "openstapps-configuration",
"compile": "rimraf lib && tsc && prepend lib/cli.js '#!/usr/bin/env node\n'",
"compile": "rimraf lib && tsc",
"documentation": "typedoc --includeVersion --out docs --readme README.md --listInvalidSymbolLinks --entryPointStrategy expand src && openstapps-core-tools openapi ./node_modules/@openstapps/core/lib ./docs/openapi && openapi build-docs docs/openapi/openapi.json -o docs/openapi/index.html",
"version": "npm run changelog",
"lint": "eslint -c .eslintrc.json --ignore-path .eslintignore --ext .ts src/ test/",
"lint:fix": "eslint --fix -c .eslintrc.json --ignore-path .eslintignore --ext .ts src/ test/",
"prepublishOnly": "npm ci && npm run build",
"preversion": "npm run prepublishOnly",
"push": "git push && git push origin \"v$npm_package_version\"",
@@ -29,14 +30,14 @@
"test": "npm run test-unit && npm run test-integration",
"test-unit": "cross-env NODE_CONFIG_ENV=elasticsearch ALLOW_NO_TRANSPORT=true STAPPS_LOG_LEVEL=0 nyc mocha --require ts-node/register --exit 'test/**/*.spec.ts'",
"test-integration": "docker-compose -f integration-test.yml pull && docker-compose -f integration-test.yml up --build --abort-on-container-exit --exit-code-from apicli",
"lint": "eslint -c .eslintrc.json --ignore-path .eslintignore --ext .ts src/ test/",
"lint:fix": "eslint --fix -c .eslintrc.json --ignore-path .eslintignore --ext .ts src/ test/"
"test-unit": "env NODE_CONFIG_ENV=elasticsearch ALLOW_NO_TRANSPORT=true STAPPS_LOG_LEVEL=0 nyc mocha --require ts-node/register --exit 'test/**/*.spec.ts'",
"version": "npm run changelog"
},
"dependencies": {
"@elastic/elasticsearch": "8.4.0",
"@openstapps/core": "1.0.1",
"@openstapps/core-tools": "0.34.0",
"@openstapps/logger": "1.1.1",
"@openstapps/core": "workspace:*",
"@openstapps/core-tools": "workspace:*",
"@openstapps/logger": "workspace:*",
"@redocly/cli": "1.0.0-beta.125",
"@types/node": "14.18.43",
"config": "3.3.9",
@@ -44,7 +45,7 @@
"express": "4.18.2",
"express-prom-bundle": "6.6.0",
"express-promise-router": "4.1.1",
"got": "11.8.6",
"got": "12.6.0",
"moment": "2.29.4",
"morgan": "1.10.0",
"nock": "13.3.1",
@@ -57,9 +58,9 @@
"uuid": "8.3.2"
},
"devDependencies": {
"@openstapps/configuration": "0.34.0",
"@openstapps/es-mapping-generator": "0.6.0",
"@openstapps/eslint-config": "1.1.0",
"@openstapps/configuration": "workspace:*",
"@openstapps/es-mapping-generator": "workspace:*",
"@openstapps/eslint-config": "workspace:*",
"@testdeck/mocha": "0.3.3",
"@types/chai": "4.3.4",
"@types/chai-as-promised": "7.1.5",
@@ -69,14 +70,15 @@
"@types/geojson": "1.0.6",
"@types/mocha": "10.0.1",
"@types/morgan": "1.9.4",
"@types/node": "18.15.3",
"@types/node-cron": "3.0.7",
"@types/nodemailer": "6.4.7",
"@types/promise-queue": "2.2.0",
"@types/sinon-express-mock": "1.3.9",
"@types/supertest": "2.0.12",
"@types/uuid": "8.3.4",
"@typescript-eslint/eslint-plugin": "5.42.0",
"@typescript-eslint/parser": "5.42.0",
"@typescript-eslint/eslint-plugin": "5.49.0",
"@typescript-eslint/parser": "5.49.0",
"chai": "4.3.7",
"chai-as-promised": "7.1.1",
"conventional-changelog-cli": "2.2.2",
@@ -85,14 +87,13 @@
"eslint-config-prettier": "8.8.0",
"eslint-plugin-jsdoc": "39.9.1",
"eslint-plugin-prettier": "4.2.1",
"eslint-plugin-unicorn": "43.0.2",
"eslint-plugin-unicorn": "45.0.2",
"get-port": "5.1.1",
"mocha": "10.2.0",
"mocked-env": "1.3.5",
"nyc": "15.1.0",
"prepend-file-cli": "1.0.6",
"prettier": "2.8.8",
"rimraf": "3.0.2",
"rimraf": "4.4.0",
"sinon": "14.0.2",
"sinon-express-mock": "2.2.1",
"supertest": "6.3.3",
+11 -6
View File
@@ -1,3 +1,5 @@
#!/usr/bin/env node
/*
* Copyright (C) 2019 StApps
* This program is free software: you can redistribute it and/or modify
@@ -68,16 +70,19 @@ async function onError(error: {code: string; syscall: string}) {
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
case 'EACCES': {
await Logger.error(`${bind} requires elevated privileges`);
process.exit(1);
break;
case 'EADDRINUSE':
}
case 'EADDRINUSE': {
await Logger.error(`${bind} is already in use`);
process.exit(1);
break;
default:
}
default: {
throw error;
}
}
}
@@ -87,11 +92,11 @@ async function onError(error: {code: string; syscall: string}) {
function onListening() {
const addr = server.address();
if (addr !== null) {
if (addr === null) {
void Logger.error(`Failed to start binding`);
} else {
const bind = typeof addr === 'string' ? `pipe ${addr}` : `port ${addr.port}`;
Logger.ok(`Listening on ${bind}`);
} else {
void Logger.error(`Failed to start binding`);
}
}
+10 -10
View File
@@ -83,18 +83,18 @@ export class MailQueue {
throw new Error('Failed to initialize the SMTP transport for the mail queue');
}
if (!this.transport.isVerified()) {
this.verificationCounter++;
setTimeout(() => {
Logger.warn('Transport not verified yet. Trying to send mails here...');
this.checkForVerification();
}, MailQueue.VERIFICATION_TIMEOUT);
} else {
if (this.transport.isVerified()) {
Logger.ok('Transport for mail queue was verified. We can send mails now');
// if the transport finally was verified send all our mails from the dry queue
for (const mail of this.dryQueue) {
void this.addToQueue(mail);
}
} else {
this.verificationCounter++;
setTimeout(() => {
Logger.warn('Transport not verified yet. Trying to send mails here...');
this.checkForVerification();
}, MailQueue.VERIFICATION_TIMEOUT);
}
}
@@ -104,12 +104,12 @@ export class MailQueue {
* @param mail Information required for sending a mail
*/
public async push(mail: MailOptions) {
if (!this.transport.isVerified()) {
if (this.transport.isVerified()) {
await this.addToQueue(mail);
} else {
// the transport has verification, but is not verified yet
// push to a dry queue which gets pushed to the real queue when the transport is verified
this.dryQueue.push(mail);
} else {
await this.addToQueue(mail);
}
}
}
@@ -47,10 +47,12 @@ export async function pluginRegisterHandler(
_app: Express.Application,
): Promise<SCPluginRegisterResponse> {
switch (request.action) {
case 'add':
case 'add': {
return addPlugin(request.plugin);
case 'remove':
}
case 'remove': {
return removePlugin(request.route);
}
}
}
@@ -114,17 +114,21 @@ export async function setUp(
// make a schedule for each trigger
for (const trigger of watcher.triggers) {
switch (trigger.executionTime) {
case 'hourly':
case 'hourly': {
trigger.executionTime = '5 * * * *';
break;
case 'daily':
}
case 'daily': {
trigger.executionTime = '5 0 * * *';
break;
case 'weekly':
}
case 'weekly': {
trigger.executionTime = '5 0 * * 0';
break;
case 'monthly':
}
case 'monthly': {
trigger.executionTime = '5 0 1 * *';
}
}
cron.schedule(trigger.executionTime, async () => {
-4601
View File
File diff suppressed because it is too large Load Diff
+45 -44
View File
@@ -1,10 +1,34 @@
{
"name": "@openstapps/proxy",
"version": "1.5.1",
"description": "NGINX proxy that is dynamically configured by a Node.js script",
"version": "2.1.0",
"license": "AGPL-3.0-only",
"repository": "git@gitlab.com:openstapps/proxy.git",
"author": "Anselm Rochus Stordeur <anselmstordeur@gmail.com>",
"contributors": [
"André Bierlein <andre.mt.bierlein@gmail.com>",
"Benjamin Joeckel",
"Jovan Krunic <jovan.krunic@gmail.com>",
"Karl-Philipp Wulfert <krlwlfrt@gmail.com>",
"Michel Jonathan Schmitz <michel.schmitz_1992@hotmail.com>",
"Rainer Killinger <mail-openstapps@killinger.co>"
],
"main": "./lib/cli.js",
"scripts": {
"build": "npm run lint && npm run compile",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md && git commit -m 'docs: update changelog'",
"check-configuration": "openstapps-configuration",
"compile": "rimraf lib && tsc",
"documentation": "typedoc --includeVersion --out docs --readme README.md --entryPointStrategy expand src",
"lint": "eslint --ext .ts src/",
"postversion": "npm run changelog",
"prepublishOnly": "npm ci && npm run build",
"preversion": "npm run prepublishOnly",
"push": "git push && git push origin \"v$npm_package_version\"",
"test": "nyc mocha --require ts-node/register 'test/**/*.spec.ts'"
},
"dependencies": {
"@openstapps/logger": "1.1.1",
"@openstapps/logger": "workspace:*",
"@types/config": "3.3.0",
"@types/dockerode": "3.3.17",
"@types/node": "14.18.36",
@@ -17,66 +41,37 @@
"semver": "7.3.8"
},
"devDependencies": {
"@openstapps/configuration": "0.34.0",
"@openstapps/eslint-config": "1.1.0",
"@openstapps/configuration": "workspace:*",
"@openstapps/eslint-config": "workspace:*",
"@testdeck/mocha": "0.3.3",
"@types/chai": "4.3.5",
"@types/chai-spies": "1.0.3",
"@types/config": "3.3.0",
"@types/dockerode": "3.3.14",
"@types/mustache": "4.2.2",
"@types/node": "18.15.3",
"@types/proxyquire": "1.3.28",
"@typescript-eslint/eslint-plugin": "5.42.1",
"@typescript-eslint/parser": "5.42.1",
"@types/semver": "7.3.13",
"@types/sha1": "1.1.3",
"@typescript-eslint/eslint-plugin": "5.49.0",
"@typescript-eslint/parser": "5.49.0",
"chai": "4.3.7",
"chai-spies": "1.0.0",
"conventional-changelog-cli": "2.2.2",
"eslint": "8.31.0",
"eslint": "8.33.0",
"eslint-config-prettier": "8.6.0",
"eslint-plugin-jsdoc": "39.6.4",
"eslint-plugin-jsdoc": "39.7.4",
"eslint-plugin-prettier": "4.2.1",
"eslint-plugin-unicorn": "44.0.2",
"eslint-plugin-unicorn": "45.0.2",
"mocha": "10.2.0",
"nyc": "15.1.0",
"prepend-file-cli": "1.0.6",
"prettier": "2.8.2",
"prettier": "2.8.3",
"proxyquire": "2.1.3",
"rimraf": "3.0.2",
"ts-node": "10.9.1",
"typedoc": "0.22.18",
"typescript": "4.4.4"
},
"scripts": {
"build": "npm run lint && npm run compile",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md && git commit -m 'docs: update changelog'",
"check-configuration": "openstapps-configuration",
"compile": "rimraf lib && tsc && prepend lib/cli.js '#!/usr/bin/env node\n'",
"documentation": "typedoc --includeVersion --out docs --readme README.md --entryPointStrategy expand src",
"lint": "eslint --ext .ts src/",
"postversion": "npm run changelog",
"prepublishOnly": "npm ci && npm run build",
"preversion": "npm run prepublishOnly",
"push": "git push && git push origin \"v$npm_package_version\"",
"test": "nyc mocha --require ts-node/register 'test/**/*.spec.ts'"
},
"repository": {
"type": "git",
"url": "git@gitlab.com:openstapps/proxy.git"
},
"author": "Anselm Rochus Stordeur <anselmstordeur@gmail.com>",
"contributors": [
"André Bierlein <andre.mt.bierlein@gmail.com>",
"Benjamin Joeckel",
"Jovan Krunic <jovan.krunic@gmail.com>",
"Karl-Philipp Wulfert <krlwlfrt@gmail.com>",
"Michel Jonathan Schmitz <michel.schmitz_1992@hotmail.com>",
"Rainer Killinger <mail-openstapps@killinger.co>"
],
"license": "AGPL-3.0-only",
"openstappsConfiguration": {
"forPackaging": false,
"ignoreCiEntries": [
"package"
]
},
"nyc": {
"all": true,
"branches": 95,
@@ -99,5 +94,11 @@
"text-summary"
],
"statements": 95
},
"openstappsConfiguration": {
"forPackaging": false,
"ignoreCiEntries": [
"package"
]
}
}
+2
View File
@@ -1,3 +1,5 @@
#!/usr/bin/env node
/*
* Copyright (C) 2022 StApps
* This program is free software: you can redistribute it and/or modify
-1
View File
@@ -192,7 +192,6 @@ export async function generateUpstreamMap(
})
.join('\n');
// eslint-disable-next-line prettier/prettier
result += '\n\}';
if (!foundMatchingContainer) {
+2
View File
@@ -0,0 +1,2 @@
#!/usr/bin/env node
require('./lib/cli.js')
File diff suppressed because it is too large Load Diff
+31 -33
View File
@@ -1,22 +1,9 @@
{
"name": "@openstapps/configuration",
"version": "0.34.0",
"description": "A collection of configuration base files for StApps projects.",
"scripts": {
"build": "npm run lint && npm run compile",
"compile": "rimraf lib && tsc --outDir lib && prepend lib/cli.js '#!/usr/bin/env node\n'",
"version": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md",
"documentation": "typedoc --out docs --readme README.md --includeVersion --listInvalidSymbolLinks --entryPointStrategy expand src",
"prepublishOnly": "npm ci && npm run build",
"preversion": "npm run prepublishOnly",
"push": "git push && git push origin \"v$npm_package_version\"",
"test": "echo \"Error: no test specified\" && exit 1",
"lint": "eslint -c .eslintrc.json --ignore-path .eslintignore --ext .ts src/"
},
"repository": {
"type": "git",
"url": "git@gitlab.com:openstapps/configuration.git"
},
"version": "2.1.0",
"license": "GPL-3.0-only",
"repository": "git@gitlab.com:openstapps/configuration.git",
"author": "Karl-Philipp Wulfert <krlwlfrt@gmail.com>",
"contributors": [
"Anselm Rochus Stordeur",
@@ -24,36 +11,47 @@
"Rainer Killinger <mail-openstapps@killinger.co>",
"Thea Schöbl"
],
"license": "GPL-3.0-only",
"prettier": "@openstapps/prettier-config",
"bin": {
"openstapps-configuration": "app.js"
},
"scripts": {
"build": "npm run lint && npm run compile",
"compile": "rimraf lib && tsc --outDir lib",
"documentation": "typedoc --out docs --readme README.md --includeVersion --listInvalidSymbolLinks --entryPointStrategy expand src",
"format:fix": "prettier --write .",
"lint": "eslint -c .eslintrc.json --ignore-path .eslintignore --ext .ts src/",
"prepublishOnly": "npm ci && npm run build",
"preversion": "npm run prepublishOnly",
"push": "git push && git push origin \"v$npm_package_version\"",
"test": "echo \"Error: no test specified\" && exit 1",
"version": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md"
},
"dependencies": {
"@types/node": "14.18.36",
"@types/semver": "7.3.13",
"@types/yaml": "1.9.7",
"chalk": "4.1.2",
"commander": "9.5.0",
"commander": "10.0.0",
"semver": "7.3.8",
"yaml": "1.10.2"
},
"devDependencies": {
"@openstapps/eslint-config": "1.1.0",
"@typescript-eslint/eslint-plugin": "5.33.1",
"@typescript-eslint/parser": "5.33.1",
"@openstapps/eslint-config": "workspace:*",
"@openstapps/prettier-config": "workspace:*",
"@types/node": "18.15.3",
"@types/semver": "7.3.13",
"@typescript-eslint/eslint-plugin": "5.49.0",
"@typescript-eslint/parser": "5.49.0",
"conventional-changelog-cli": "2.2.2",
"eslint": "8.31.0",
"eslint": "8.33.0",
"eslint-config-prettier": "8.6.0",
"eslint-plugin-jsdoc": "39.6.4",
"eslint-plugin-jsdoc": "39.7.4",
"eslint-plugin-prettier": "4.2.1",
"eslint-plugin-unicorn": "43.0.2",
"prepend-file-cli": "1.0.6",
"prettier": "2.8.2",
"rimraf": "3.0.2",
"eslint-plugin-unicorn": "45.0.2",
"prettier": "2.8.3",
"rimraf": "4.4.0",
"typedoc": "0.22.18",
"typescript": "4.4.4"
},
"peerDependencies": {
"typescript": "4.4.4"
},
"bin": {
"openstapps-configuration": "lib/cli.js"
}
}
@@ -819,11 +819,6 @@ export function getRules(configuration: Configuration): Rules {
scripts.build = 'npm run lint && npm run compile';
scripts.compile = 'rimraf lib && tsc';
devDependencies.push('rimraf');
if (configuration.hasCli) {
devDependencies.push('prepend-file-cli');
scripts.compile += " && prepend lib/cli.js '#!/usr/bin/env node\n'";
}
}
if (configuration.standardDocumentation) {
@@ -6,6 +6,7 @@
"esModuleInterop": true,
"experimentalDecorators": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true,
"inlineSourceMap": true,
"module": "CommonJS",
"moduleResolution": "node",
@@ -16,6 +17,7 @@
"noUnusedLocals": true,
"noUnusedParameters": true,
"outDir": "../../../lib/",
"lib": ["ES2021", "DOM"],
"strict": true,
"target": "es6"
},
+5 -19
View File
@@ -13,12 +13,11 @@ module.exports = {
},
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
'plugin:prettier/recommended',
'plugin:jsdoc/recommended',
'plugin:unicorn/recommended',
'prettier'
],
plugins: ['eslint-plugin-unicorn', 'eslint-plugin-jsdoc', 'prettier'],
plugins: ['eslint-plugin-unicorn', 'eslint-plugin-jsdoc'],
settings: {
jsdoc: {
mode: 'typescript',
@@ -43,6 +42,9 @@ module.exports = {
],
'unicorn/no-nested-ternary': 'off',
'unicorn/better-regex': 'off',
'unicorn/no-typeof-undefined': 'off',
'unicorn/no-non-null-assertion': 'off',
'unicorn/prefer-array-some': 'off',
'jsdoc/no-types': 'error',
'jsdoc/require-param': 'off',
@@ -82,22 +84,6 @@ module.exports = {
'@typescript-eslint/lines-between-class-members': ['error', 'always'],
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/no-non-null-assertion': 'off',
'prettier/prettier': [
'error',
{
tabWidth: 2,
printWidth: 110,
useTabs: false,
semi: true,
singleQuote: true,
quoteProps: 'consistent',
trailingComma: 'all',
bracketSpacing: false,
arrowParens: 'avoid',
endOfLine: 'lf',
},
],
},
},
],
File diff suppressed because it is too large Load Diff
+28 -33
View File
@@ -1,47 +1,42 @@
{
"name": "@openstapps/eslint-config",
"version": "1.1.0",
"main": "index.js",
"description": "A collection of configuration base files for StApps projects.",
"scripts": {
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md && git commit -m 'docs: update changelog'",
"test": "eslint -c index.js test/test-file.ts",
"prepublishOnly": "npm ci && npm test",
"postversion": "npm run changelog",
"preversion": "npm run prepublishOnly",
"push": "git push && git push origin \"v$npm_package_version\""
},
"repository": {
"type": "git",
"url": "git@gitlab.com:openstapps/eslint-config.git"
},
"version": "2.1.0",
"license": "GPL-3.0-only",
"repository": "git@gitlab.com:openstapps/eslint-config.git",
"author": "Thea Schöbl",
"contributors": [
"Rainer Killinger <mail-openstapps@killinger.co>"
],
"license": "GPL-3.0-only",
"dependencies": {},
"main": "index.js",
"scripts": {
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md && git commit -m 'docs: update changelog'",
"postversion": "npm run changelog",
"prepublishOnly": "npm ci && npm test",
"preversion": "npm run prepublishOnly",
"push": "git push && git push origin \"v$npm_package_version\"",
"test": "eslint -c index.js test/test-file.ts"
},
"devDependencies": {
"@openstapps/configuration": "0.31.0",
"@typescript-eslint/eslint-plugin": ">=5.29.0",
"@typescript-eslint/parser": ">=5.29.0",
"@typescript-eslint/eslint-plugin": "5.49.0",
"@typescript-eslint/parser": "5.49.0",
"conventional-changelog-cli": "2.2.2",
"eslint": ">=8.18.0",
"eslint-config-prettier": ">=8.5.0",
"eslint-plugin-jsdoc": ">=39.3.3",
"eslint-plugin-prettier": ">=4.0.0",
"eslint-plugin-unicorn": ">=42.0.0",
"prettier": ">=2.7.1",
"eslint": "8.33.0",
"eslint-config-prettier": "8.6.0",
"eslint-plugin-jsdoc": "39.7.4",
"eslint-plugin-prettier": "4.2.1",
"eslint-plugin-unicorn": "45.0.2",
"prettier": "2.8.3",
"typescript": "4.4.4"
},
"peerDependencies": {
"@typescript-eslint/eslint-plugin": ">=5.29.0",
"@typescript-eslint/parser": ">=5.29.0",
"eslint": ">=8.18.0",
"eslint-config-prettier": ">=8.5.0",
"eslint-plugin-jsdoc": ">=39.3.3",
"eslint-plugin-prettier": ">=4.0.0",
"eslint-plugin-unicorn": ">=41.0.1",
"prettier": ">=2.7.1"
"@typescript-eslint/eslint-plugin": "5.49.0",
"@typescript-eslint/parser": "5.49.0",
"eslint": "8.33.0",
"eslint-config-prettier": "8.6.0",
"eslint-plugin-jsdoc": "39.7.4",
"eslint-plugin-prettier": "4.2.1",
"eslint-plugin-unicorn": "45.0.2",
"prettier": "2.8.3"
}
}
@@ -1,12 +0,0 @@
/**
* Simple TS source file to get linted
* Can be used to verify new/changed rule behavior
*/
function addNumbers(a: number, b: number) {
return a + b;
}
const sum: number = addNumbers(10, 15);
// eslint-disable-next-line no-console
console.log('Sum of the two numbers is: ' + sum);
+7 -10
View File
@@ -1,23 +1,20 @@
{
"name": "@openstapps/prettier-config",
"version": "1.0.0",
"description": "StApps Prettier Config",
"main": "index.json",
"author": "Thea Schöbl <dev@theaninova.de>",
"version": "2.1.0",
"license": "GPL-3.0-only",
"repository": "git@gitlab.com:openstapps/prettier-config.git",
"author": "Thea Schöbl <dev@theaninova.de>",
"contributors": [
"Rainer Killinger <mail-openstapps@killinger.co>"
],
"repository": {
"type": "git",
"url": "git@gitlab.com:openstapps/prettier-config.git"
},
"main": "index.json",
"scripts": {
"changelog": "npx conventional-changelog-cli -p angular -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md && git commit -m 'docs: update changelog'",
"test": "npx prettier --config index.json --check \"test/*.js\"",
"prepublishOnly": "npm test",
"postversion": "npm run changelog",
"prepublishOnly": "npm test",
"preversion": "npm run prepublishOnly",
"push": "git push && git push origin \"v$npm_package_version\""
"push": "git push && git push origin \"v$npm_package_version\"",
"test": "npx prettier --config index.json --check \"test/*.js\""
}
}
@@ -116,7 +116,7 @@ remind:
stage: maintenance
only:
variables:
- $MAINTENANCE_MODE == "remind"
- $MAINTENANCE_MODE == "remind"
tags:
- secrecy
@@ -173,7 +173,7 @@ renovate:
DOCKER_TLS_VERIFY: 1
DOCKER_TLS_CERTDIR: /certs
DOCKER_CERT_PATH: /certs/client
RENOVATE_EXTENDS: "gitlab>openstapps/projectmanagement"
RENOVATE_EXTENDS: 'gitlab>openstapps/projectmanagement'
RENOVATE_BASE_DIR: $CI_PROJECT_DIR/renovate
RENOVATE_ENDPOINT: $CI_API_V4_URL
RENOVATE_PLATFORM: gitlab
@@ -195,7 +195,7 @@ renovate:
when: always
expire_in: 1d
paths:
- "$RENOVATE_LOG_FILE"
- '$RENOVATE_LOG_FILE'
before_script: []
script:
- renovate $RENOVATE_EXTRA_FLAGS
@@ -2,35 +2,29 @@
(Summarize the bug encountered concisely)
## Steps to reproduce
(How one can reproduce the issue - this is very important)
## Example Project
(If possible, please create an example project here on GitLab.com that exhibits the problematic behaviour, and link to it here in the bug report)
(If you are using an older version of GitLab, this will also determine whether the bug has been fixed in a more recent version)
## What is the current bug behavior?
(What actually happens)
## What is the expected correct behavior?
(What you should see instead)
## Relevant logs and/or screenshots
(Paste any relevant logs - please use code blocks (```) to format console output,
logs, and code as it's very hard to read otherwise.)
## Possible fixes
(If you can, link to the line of code that might be responsible for the problem)
@@ -2,15 +2,12 @@
(Describe the feature that you're requesting concisely)
## Explanation
(Explain why the feature is necessary)
## Dependencies, issues to be resolved beforehand
(List issues or dependencies that need to be resolved before this feature can be implemented)
/label ~meeting
+38 -146
View File
@@ -1,314 +1,206 @@
# [0.25.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.24.0...v0.25.0) (2023-01-17)
### Bug Fixes
* broken cypress build ([a37d3a9](https://gitlab.com/openstapps/projectmanagement/commit/a37d3a9ec4c8303bef7f7f29fdb8f7401ef7b02a))
* renovate job timeout ([116c880](https://gitlab.com/openstapps/projectmanagement/commit/116c8809e4f7d524361275e910fdc582a9baf78a))
- broken cypress build ([a37d3a9](https://gitlab.com/openstapps/projectmanagement/commit/a37d3a9ec4c8303bef7f7f29fdb8f7401ef7b02a))
- renovate job timeout ([116c880](https://gitlab.com/openstapps/projectmanagement/commit/116c8809e4f7d524361275e910fdc582a9baf78a))
# [0.24.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.23.1...v0.24.0) (2022-10-10)
## [0.23.1](https://gitlab.com/openstapps/projectmanagement/compare/v0.23.0...v0.23.1) (2022-07-05)
### Bug Fixes
* documentation not generating ([ac226d1](https://gitlab.com/openstapps/projectmanagement/commit/ac226d178a41e24a57f5e24409255aee2cfabf8d))
- documentation not generating ([ac226d1](https://gitlab.com/openstapps/projectmanagement/commit/ac226d178a41e24a57f5e24409255aee2cfabf8d))
# [0.23.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.22.0...v0.23.0) (2022-07-05)
# [0.22.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.21.0...v0.22.0) (2021-12-14)
# [0.21.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.20.1...v0.21.0) (2021-12-14)
### Bug Fixes
* exclude npm audit from maintenance runs ([42e6812](https://gitlab.com/openstapps/projectmanagement/commit/42e68120b7215b6fe0f929955d99907103b7bfed))
* link to old gitlab server ([aa9991a](https://gitlab.com/openstapps/projectmanagement/commit/aa9991ad708dd80b873b738a304c94f6f21dd4ba)), closes [#27](https://gitlab.com/openstapps/projectmanagement/issues/27)
- exclude npm audit from maintenance runs ([42e6812](https://gitlab.com/openstapps/projectmanagement/commit/42e68120b7215b6fe0f929955d99907103b7bfed))
- link to old gitlab server ([aa9991a](https://gitlab.com/openstapps/projectmanagement/commit/aa9991ad708dd80b873b738a304c94f6f21dd4ba)), closes [#27](https://gitlab.com/openstapps/projectmanagement/issues/27)
### Features
* make slack notification optional ([84921ad](https://gitlab.com/openstapps/projectmanagement/commit/84921ad5ce90c24ce53197235e8f8a8aff0f4aba))
- make slack notification optional ([84921ad](https://gitlab.com/openstapps/projectmanagement/commit/84921ad5ce90c24ce53197235e8f8a8aff0f4aba))
## [0.20.1](https://gitlab.com/openstapps/projectmanagement/compare/v0.20.0...v0.20.1) (2020-07-27)
### Bug Fixes
* ignore archived projects in milestone tidy ([cd768a9](https://gitlab.com/openstapps/projectmanagement/commit/cd768a9dcdb8edc62f8277a45b054e261311e404))
* remove invalid project name element ([e4c065d](https://gitlab.com/openstapps/projectmanagement/commit/e4c065d5058512ecab1b7fb173e34d950abb123f))
- ignore archived projects in milestone tidy ([cd768a9](https://gitlab.com/openstapps/projectmanagement/commit/cd768a9dcdb8edc62f8277a45b054e261311e404))
- remove invalid project name element ([e4c065d](https://gitlab.com/openstapps/projectmanagement/commit/e4c065d5058512ecab1b7fb173e34d950abb123f))
### Features
* add merge request assignment ([65d05bf](https://gitlab.com/openstapps/projectmanagement/commit/65d05bfe692c7589ae4138439724ba7c0c73bec5))
- add merge request assignment ([65d05bf](https://gitlab.com/openstapps/projectmanagement/commit/65d05bfe692c7589ae4138439724ba7c0c73bec5))
# [0.20.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.19.0...v0.20.0) (2020-05-06)
### Features
* change builder base image to docker/compose ([5ea40b2](https://gitlab.com/openstapps/projectmanagement/commit/5ea40b2ece8cb2ae764096121492dd9703963f1d))
- change builder base image to docker/compose ([5ea40b2](https://gitlab.com/openstapps/projectmanagement/commit/5ea40b2ece8cb2ae764096121492dd9703963f1d))
# [0.19.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.18.0...v0.19.0) (2020-01-08)
# [0.18.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.17.1...v0.18.0) (2019-11-25)
## [0.17.1](https://gitlab.com/openstapps/projectmanagement/compare/v0.17.0...v0.17.1) (2019-11-19)
### Features
* add documentation for automatic publishing ([ab45e35](https://gitlab.com/openstapps/projectmanagement/commit/ab45e35117ef0cca3f42c557e100d4e57a2571df)), closes [#23](https://gitlab.com/openstapps/projectmanagement/issues/23)
- add documentation for automatic publishing ([ab45e35](https://gitlab.com/openstapps/projectmanagement/commit/ab45e35117ef0cca3f42c557e100d4e57a2571df)), closes [#23](https://gitlab.com/openstapps/projectmanagement/issues/23)
# [0.17.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.16.1...v0.17.0) (2019-11-13)
### Features
* update to new meeting date ([98c73b5](https://gitlab.com/openstapps/projectmanagement/commit/98c73b575846fb342c4ffb6a2cf09152a3205f95))
- update to new meeting date ([98c73b5](https://gitlab.com/openstapps/projectmanagement/commit/98c73b575846fb342c4ffb6a2cf09152a3205f95))
## [0.16.1](https://gitlab.com/openstapps/projectmanagement/compare/v0.16.0...v0.16.1) (2019-08-20)
### Bug Fixes
* add colors to cli log output ([7d271a7](https://gitlab.com/openstapps/projectmanagement/commit/7d271a73648d2367e57a3b6c6bb5725d106dced6))
- add colors to cli log output ([7d271a7](https://gitlab.com/openstapps/projectmanagement/commit/7d271a73648d2367e57a3b6c6bb5725d106dced6))
# [0.16.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.15.0...v0.16.0) (2019-08-20)
### Features
* only unlabel closed issues before last meeting ([d7b68ae](https://gitlab.com/openstapps/projectmanagement/commit/d7b68ae45c8321f0a1d9cba998b604507445f9fb))
- only unlabel closed issues before last meeting ([d7b68ae](https://gitlab.com/openstapps/projectmanagement/commit/d7b68ae45c8321f0a1d9cba998b604507445f9fb))
# [0.15.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.14.1...v0.15.0) (2019-07-23)
### Features
* add function and task to get version of used dependency ([067a201](https://gitlab.com/openstapps/projectmanagement/commit/067a2011c03b1e3e9d164844d594e4f332982f12)), closes [#20](https://gitlab.com/openstapps/projectmanagement/issues/20)
- add function and task to get version of used dependency ([067a201](https://gitlab.com/openstapps/projectmanagement/commit/067a2011c03b1e3e9d164844d594e4f332982f12)), closes [#20](https://gitlab.com/openstapps/projectmanagement/issues/20)
## [0.14.1](https://gitlab.com/openstapps/projectmanagement/compare/v0.14.0...v0.14.1) (2019-06-05)
# [0.14.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.13.0...v0.14.0) (2019-06-04)
### Bug Fixes
* fix regression with protected tags ([65a7233](https://gitlab.com/openstapps/projectmanagement/commit/65a723390572f48601e52dac975c9e2b4a0f06c4))
- fix regression with protected tags ([65a7233](https://gitlab.com/openstapps/projectmanagement/commit/65a723390572f48601e52dac975c9e2b4a0f06c4))
### Features
* add max depth for reminders ([3641ec4](https://gitlab.com/openstapps/projectmanagement/commit/3641ec4d00890f81b24301b61d689cd113e33997))
- add max depth for reminders ([3641ec4](https://gitlab.com/openstapps/projectmanagement/commit/3641ec4d00890f81b24301b61d689cd113e33997))
# [0.13.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.12.1...v0.13.0) (2019-06-03)
### Features
* add curl to Node.js image ([2ec80fb](https://gitlab.com/openstapps/projectmanagement/commit/2ec80fbb2f1256530e61a389a8444163c7aef8bd)), closes [#18](https://gitlab.com/openstapps/projectmanagement/issues/18)
- add curl to Node.js image ([2ec80fb](https://gitlab.com/openstapps/projectmanagement/commit/2ec80fbb2f1256530e61a389a8444163c7aef8bd)), closes [#18](https://gitlab.com/openstapps/projectmanagement/issues/18)
## [0.12.1](https://gitlab.com/openstapps/projectmanagement/compare/v0.12.0...v0.12.1) (2019-05-27)
# [0.12.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.11.0...v0.12.0) (2019-05-27)
### Bug Fixes
* use user 'node' in Node.js image ([0c8aa72](https://gitlab.com/openstapps/projectmanagement/commit/0c8aa7257add9fd5997105f18b69211152fd8971)), closes [#17](https://gitlab.com/openstapps/projectmanagement/issues/17)
- use user 'node' in Node.js image ([0c8aa72](https://gitlab.com/openstapps/projectmanagement/commit/0c8aa7257add9fd5997105f18b69211152fd8971)), closes [#17](https://gitlab.com/openstapps/projectmanagement/issues/17)
### Features
* add git to node image ([c0058f9](https://gitlab.com/openstapps/projectmanagement/commit/c0058f9c2918bae3e5fce58f11802174ea08084c)), closes [#16](https://gitlab.com/openstapps/projectmanagement/issues/16)
* notify merge request assignee instead of author ([d60625c](https://gitlab.com/openstapps/projectmanagement/commit/d60625c461c6fe54b7c60091050a31f7f77a958e))
- add git to node image ([c0058f9](https://gitlab.com/openstapps/projectmanagement/commit/c0058f9c2918bae3e5fce58f11802174ea08084c)), closes [#16](https://gitlab.com/openstapps/projectmanagement/issues/16)
- notify merge request assignee instead of author ([d60625c](https://gitlab.com/openstapps/projectmanagement/commit/d60625c461c6fe54b7c60091050a31f7f77a958e))
# [0.11.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.10.0...v0.11.0) (2019-04-30)
### Features
* tidy sub groups ([de05b52](https://gitlab.com/openstapps/projectmanagement/commit/de05b52f24985a882dbacdf82cc1a7c3c4efbe88))
- tidy sub groups ([de05b52](https://gitlab.com/openstapps/projectmanagement/commit/de05b52f24985a882dbacdf82cc1a7c3c4efbe88))
# [0.10.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.9.0...v0.10.0) (2019-04-17)
### Features
* add timestamp to reports ([ad99e45](https://gitlab.com/openstapps/projectmanagement/commit/ad99e45ee3de59de4b5fcca312cb077d90d73335))
- add timestamp to reports ([ad99e45](https://gitlab.com/openstapps/projectmanagement/commit/ad99e45ee3de59de4b5fcca312cb077d90d73335))
# [0.9.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.8.1...v0.9.0) (2019-04-09)
### Features
* add check for protected tags to tidy task ([feb0c3b](https://gitlab.com/openstapps/projectmanagement/commit/feb0c3ba019b1fdfdc5912db86b20d9cc2dd650f)), closes [#14](https://gitlab.com/openstapps/projectmanagement/issues/14)
- add check for protected tags to tidy task ([feb0c3b](https://gitlab.com/openstapps/projectmanagement/commit/feb0c3ba019b1fdfdc5912db86b20d9cc2dd650f)), closes [#14](https://gitlab.com/openstapps/projectmanagement/issues/14)
## [0.8.1](https://gitlab.com/openstapps/projectmanagement/compare/v0.8.0...v0.8.1) (2019-03-20)
# [0.8.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.7.0...v0.8.0) (2019-03-20)
### Features
* use mustache instead of tangular ([95f7521](https://gitlab.com/openstapps/projectmanagement/commit/95f7521dbddc13a6acb5835ae05dd5535cce067f))
- use mustache instead of tangular ([95f7521](https://gitlab.com/openstapps/projectmanagement/commit/95f7521dbddc13a6acb5835ae05dd5535cce067f))
# [0.7.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.6.0...v0.7.0) (2019-03-20)
# [0.6.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.5.0...v0.6.0) (2019-02-25)
### Features
* adjust reminder for unfixed merge requests ([e02939c](https://gitlab.com/openstapps/projectmanagement/commit/e02939c470ff9a63fb33c9754e06ea4dfbbd9b15))
- adjust reminder for unfixed merge requests ([e02939c](https://gitlab.com/openstapps/projectmanagement/commit/e02939c470ff9a63fb33c9754e06ea4dfbbd9b15))
# [0.5.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.4.1...v0.5.0) (2019-02-05)
### Features
* add new task to remind about open merge requests ([201ec09](https://gitlab.com/openstapps/projectmanagement/commit/201ec093b7ab676d5d7a84972c5d9e64664af7e0))
- add new task to remind about open merge requests ([201ec09](https://gitlab.com/openstapps/projectmanagement/commit/201ec093b7ab676d5d7a84972c5d9e64664af7e0))
## [0.4.1](https://gitlab.com/openstapps/projectmanagement/compare/v0.4.0...v0.4.1) (2019-01-30)
# [0.4.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.3.0...v0.4.0) (2019-01-30)
### Features
* add slack reminder for open merge requests ([47e9775](https://gitlab.com/openstapps/projectmanagement/commit/47e977583bc036d48194d1e6bc9e6214dbbe6062))
- add slack reminder for open merge requests ([47e9775](https://gitlab.com/openstapps/projectmanagement/commit/47e977583bc036d48194d1e6bc9e6214dbbe6062))
# [0.3.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.2.2...v0.3.0) (2019-01-28)
### Features
* include sub groups in report generation ([040c666](https://gitlab.com/openstapps/projectmanagement/commit/040c666e747df35b773be1a0e30b7ba99f3b6598))
- include sub groups in report generation ([040c666](https://gitlab.com/openstapps/projectmanagement/commit/040c666e747df35b773be1a0e30b7ba99f3b6598))
## [0.2.2](https://gitlab.com/openstapps/projectmanagement/compare/v0.2.1...v0.2.2) (2019-01-23)
### Bug Fixes
* correctly determine project for issue ([8f06fc3](https://gitlab.com/openstapps/projectmanagement/commit/8f06fc35347f06e8409e4190079323af91fc0a37))
- correctly determine project for issue ([8f06fc3](https://gitlab.com/openstapps/projectmanagement/commit/8f06fc35347f06e8409e4190079323af91fc0a37))
## [0.2.1](https://gitlab.com/openstapps/projectmanagement/compare/v0.2.0...v0.2.1) (2019-01-17)
### Bug Fixes
* correctly add shebang line to cli ([f2933ef](https://gitlab.com/openstapps/projectmanagement/commit/f2933ef9e23e6fa92086800d791c9e4c6685fd4b))
- correctly add shebang line to cli ([f2933ef](https://gitlab.com/openstapps/projectmanagement/commit/f2933ef9e23e6fa92086800d791c9e4c6685fd4b))
# [0.2.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.1.1...v0.2.0) (2019-01-17)
### Bug Fixes
* correct link for projects ([a95ec14](https://gitlab.com/openstapps/projectmanagement/commit/a95ec14be8e169ee1e9f84e3ef98a9712babd302))
* do not add issues to report from backlog ([e902d70](https://gitlab.com/openstapps/projectmanagement/commit/e902d705bf66e07f70a9c34f9f13160c5db5982f))
* unlabel issues with label meeting only ([41a349e](https://gitlab.com/openstapps/projectmanagement/commit/41a349ead50db256916f5506829e587d1ecb4a43))
- correct link for projects ([a95ec14](https://gitlab.com/openstapps/projectmanagement/commit/a95ec14be8e169ee1e9f84e3ef98a9712babd302))
- do not add issues to report from backlog ([e902d70](https://gitlab.com/openstapps/projectmanagement/commit/e902d705bf66e07f70a9c34f9f13160c5db5982f))
- unlabel issues with label meeting only ([41a349e](https://gitlab.com/openstapps/projectmanagement/commit/41a349ead50db256916f5506829e587d1ecb4a43))
## [0.1.1](https://gitlab.com/openstapps/projectmanagement/compare/v0.1.0...v0.1.1) (2019-01-07)
### Bug Fixes
* remove failing deletion of labels ([ac8f2e1](https://gitlab.com/openstapps/projectmanagement/commit/ac8f2e10f965ef0e4950d8f294b6c34a26f4bad0))
- remove failing deletion of labels ([ac8f2e1](https://gitlab.com/openstapps/projectmanagement/commit/ac8f2e10f965ef0e4950d8f294b6c34a26f4bad0))
# [0.1.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.0.2...v0.1.0) (2018-12-13)
## [0.0.2](https://gitlab.com/openstapps/projectmanagement/compare/v0.0.1...v0.0.2) (2018-12-03)
### Features
* add issue template for features ([8ae1a51](https://gitlab.com/openstapps/projectmanagement/commit/8ae1a5166962c5d0b41b869c6021ddc456407022))
* add nyc configuration ([883ab9b](https://gitlab.com/openstapps/projectmanagement/commit/883ab9bfa55def9a0a8dd4ee5427c1eb9ad2960b))
- add issue template for features ([8ae1a51](https://gitlab.com/openstapps/projectmanagement/commit/8ae1a5166962c5d0b41b869c6021ddc456407022))
- add nyc configuration ([883ab9b](https://gitlab.com/openstapps/projectmanagement/commit/883ab9bfa55def9a0a8dd4ee5427c1eb9ad2960b))
## [0.0.1](https://gitlab.com/openstapps/projectmanagement/compare/19fd0f6e4cb8b44152333242aa17db84b2bd038a...v0.0.1) (2018-11-29)
### Features
* add projectmanagement and pack ([19fd0f6](https://gitlab.com/openstapps/projectmanagement/commit/19fd0f6e4cb8b44152333242aa17db84b2bd038a))
- add projectmanagement and pack ([19fd0f6](https://gitlab.com/openstapps/projectmanagement/commit/19fd0f6e4cb8b44152333242aa17db84b2bd038a))
+10 -10
View File
@@ -2,16 +2,16 @@
To contribute effectively to this or other Open StApps projects you should read the documentation in this repository first.
* What's the scope of one [project](../project-docs/workflow/PROJECT.md)?
* How to create [issues](../project-docs/workflow/ISSUES.md) in projects.
* How to [set up](../project-docs/SETUP.md) your machine?
* How to contribute code?
* What's the [branching model](../project-docsworkflow/BRANCHING.md)?
* How to write [code](../project-docs/workflow/CODING.md)?
* How to create [merge requests](../project-docs/workflow/MERGING.md)?
* How to write [documentation](../project-docs/workflow/DOCUMENTATION.md)?
* How to [version](../project-docs/workflow/VERSIONING.md) the code?
- What's the scope of one [project](../project-docs/workflow/PROJECT.md)?
- How to create [issues](../project-docs/workflow/ISSUES.md) in projects.
- How to [set up](../project-docs/SETUP.md) your machine?
- How to contribute code?
- What's the [branching model](../project-docsworkflow/BRANCHING.md)?
- How to write [code](../project-docs/workflow/CODING.md)?
- How to create [merge requests](../project-docs/workflow/MERGING.md)?
- How to write [documentation](../project-docs/workflow/DOCUMENTATION.md)?
- How to [version](../project-docs/workflow/VERSIONING.md) the code?
## Further resources
* [Docker cheat sheet](../project-docs/DOCKER_CHEAT_SHEET.md)
- [Docker cheat sheet](../project-docs/DOCKER_CHEAT_SHEET.md)
+2 -2
View File
@@ -1,6 +1,6 @@
# @openstapps/projectmanagement
[![pipeline status](https://img.shields.io/gitlab/pipeline/openstapps/projectmanagement.svg?style=flat-square)](https://gitlab.com/openstapps/projectmanagement/commits/master)
[![pipeline status](https://img.shields.io/gitlab/pipeline/openstapps/projectmanagement.svg?style=flat-square)](https://gitlab.com/openstapps/projectmanagement/commits/master)
[![npm](https://img.shields.io/npm/v/@openstapps/projectmanagement.svg?style=flat-square)](https://npmjs.com/package/@openstapps/projectmanagement)
[![license)](https://img.shields.io/npm/l/@openstapps/projectmanagement.svg?style=flat-square)](https://www.gnu.org/licenses/gpl-3.0.en.html)
[![documentation](https://img.shields.io/badge/documentation-online-blue.svg?style=flat-square)](https://openstapps.gitlab.io/projectmanagement)
@@ -21,7 +21,7 @@ Every school gets their own subgroup on GitLab inside the group `@openstapps`.
The technical name is the license plate of the school. This can be found in the [list of license plates](project-docs/SCHOOL_IDENTIFIERS.md).
The official name of the school is used as the group's name and a matching logo is picked to act as the group's logo - this should be a square one because of the way that GitLab handles/shows logos.
The official name of the school is used as the group's name and a matching logo is picked to act as the group's logo - this should be a square one because of the way that GitLab handles/shows logos.
#### Permissions on the group
+2
View File
@@ -0,0 +1,2 @@
#!/usr/bin/env node
require('./lib/cli.js')
File diff suppressed because it is too large Load Diff
+41 -44
View File
@@ -1,23 +1,9 @@
{
"name": "@openstapps/projectmanagement",
"version": "0.25.0",
"description": "Main documentation and scripts for maintenance.",
"repository": {
"type": "git",
"url": "git@gitlab.com:openstapps/projectmanagement.git"
},
"scripts": {
"build": "npm run lint && npm run compile",
"check-configuration": "openstapps-configuration",
"compile": "rimraf lib && tsc && prepend lib/cli.js '#!/usr/bin/env node\n'",
"documentation": "typedoc --out docs --readme README.md --listInvalidSymbolLinks --entryPointStrategy expand src",
"prepublishOnly": "npm ci && npm run build && npm run test",
"preversion": "npm run prepublishOnly",
"version": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md",
"push": "git push && git push origin \"v$npm_package_version\"",
"test": "nyc mocha --require ts-node/register 'test/**/*.spec.ts'",
"lint": "eslint --ext .ts src/"
},
"version": "2.1.0",
"license": "GPL-3.0-only",
"repository": "git@gitlab.com:openstapps/projectmanagement.git",
"author": "Karl-Philipp Wulfert <krlwlfrt@gmail.com>",
"contributors": [
"Anselm Stordeur <anselmstordeur@gmail.com>",
@@ -26,54 +12,64 @@
"Rainer Killinger <mail-openstapps@killinger.co>",
"Thea Schöbl <dev@theaninova.de>"
],
"license": "GPL-3.0-only",
"prettier": "@openstapps/prettier-config",
"main": "lib/common.js",
"bin": {
"openstapps-projectmanagement": "app.js"
},
"scripts": {
"build": "npm run lint && npm run compile",
"check-configuration": "openstapps-configuration",
"compile": "rimraf lib && tsc",
"documentation": "typedoc --out docs --readme README.md --listInvalidSymbolLinks --entryPointStrategy expand src",
"format:fix": "prettier --write .",
"lint": "eslint --ext .ts src/",
"prepublishOnly": "npm ci && npm run build && npm run test",
"preversion": "npm run prepublishOnly",
"push": "git push && git push origin \"v$npm_package_version\"",
"test": "nyc mocha --require ts-node/register 'test/**/*.spec.ts'",
"version": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md"
},
"dependencies": {
"@krlwlfrt/async-pool": "0.4.1",
"@openstapps/gitlab-api": "0.10.0",
"@openstapps/logger": "1.1.1",
"@slack/client": "5.0.2",
"@types/glob": "7.2.0",
"@types/mustache": "4.2.2",
"@types/node": "14.18.36",
"@types/tmp": "0.2.3",
"commander": "9.5.0",
"@openstapps/gitlab-api": "workspace:*",
"@openstapps/logger": "workspace:*",
"@slack/web-api": "6.8.1",
"commander": "10.0.0",
"date-fns": "2.29.3",
"glob": "8.1.0",
"moment": "2.29.4",
"mustache": "4.2.0",
"tmp": "0.2.1"
},
"devDependencies": {
"@openstapps/configuration": "0.33.0",
"@openstapps/eslint-config": "1.1.0",
"@openstapps/configuration": "workspace:*",
"@openstapps/eslint-config": "workspace:*",
"@openstapps/prettier-config": "workspace:*",
"@testdeck/mocha": "0.3.3",
"@types/chai": "4.3.4",
"@types/chai-as-promised": "7.1.5",
"@types/glob": "8.0.1",
"@types/mocha": "10.0.1",
"@typescript-eslint/eslint-plugin": "5.39.0",
"@typescript-eslint/parser": "5.39.0",
"@types/mustache": "4.2.2",
"@types/node": "18.15.3",
"@types/tmp": "0.2.3",
"@typescript-eslint/eslint-plugin": "5.49.0",
"@typescript-eslint/parser": "5.49.0",
"chai": "4.3.7",
"chai-as-promised": "7.1.1",
"conventional-changelog-cli": "2.2.2",
"eslint": "8.32.0",
"eslint": "8.33.0",
"eslint-config-prettier": "8.6.0",
"eslint-plugin-jsdoc": "39.6.4",
"eslint-plugin-jsdoc": "39.7.4",
"eslint-plugin-prettier": "4.2.1",
"eslint-plugin-unicorn": "44.0.2",
"eslint-plugin-unicorn": "45.0.2",
"mocha": "10.2.0",
"nyc": "15.1.0",
"prepend-file-cli": "1.0.6",
"prettier": "2.8.3",
"rimraf": "3.0.2",
"rimraf": "4.4.0",
"ts-node": "10.9.1",
"tslint": "6.1.3",
"typedoc": "0.22.18",
"typescript": "4.4.4"
},
"main": "lib/common.js",
"typings": "lib/common.d.ts",
"bin": {
"openstapps-projectmanagement": "lib/cli.js"
},
"nyc": {
"all": true,
"branches": 95,
@@ -98,5 +94,6 @@
"ts-node/register"
],
"statements": 95
}
},
"typings": "lib/common.d.ts"
}
@@ -42,6 +42,6 @@ Please consult the [Docker documentation](https://docs.docker.com/engine/referen
## Further resources
* [An Exhaustive Guide to Writing Dockerfiles for Node.js Web Apps](https://blog.hasura.io/an-exhaustive-guide-to-writing-dockerfiles-for-node-js-web-apps-bbee6bd2f3c4)
* [Docker and Node.js Best Practices
](https://github.com/nodejs/docker-node/blob/master/docs/BestPractices.md)
- [An Exhaustive Guide to Writing Dockerfiles for Node.js Web Apps](https://blog.hasura.io/an-exhaustive-guide-to-writing-dockerfiles-for-node-js-web-apps-bbee6bd2f3c4)
- [Docker and Node.js Best Practices
](https://github.com/nodejs/docker-node/blob/master/docs/BestPractices.md)
File diff suppressed because it is too large Load Diff
@@ -2,11 +2,11 @@
## Required tools/packages
* [SSH](https://docs.gitlab.com/ee/ssh/README.html)
* [Git](https://docs.gitlab.com/ee/gitlab-basics/start-using-git.html)
* [Docker](https://docs.gitlab.com/ee/user/project/container_registry.html) & Docker-Compose
* Node.js & NPM - be sure to install the "Fermium" (14.x) LTS version, might need a [PPA](https://github.com/nodesource/distributions/blob/master/README.md#installation-instructions) or use NVM
* [NVM](https://github.com/creationix/nvm#installation) - if you want to use multiple different versions of node
- [SSH](https://docs.gitlab.com/ee/ssh/README.html)
- [Git](https://docs.gitlab.com/ee/gitlab-basics/start-using-git.html)
- [Docker](https://docs.gitlab.com/ee/user/project/container_registry.html) & Docker-Compose
- Node.js & NPM - be sure to install the "Fermium" (14.x) LTS version, might need a [PPA](https://github.com/nodesource/distributions/blob/master/README.md#installation-instructions) or use NVM
- [NVM](https://github.com/creationix/nvm#installation) - if you want to use multiple different versions of node
Example for Debian based distributions:
@@ -16,13 +16,13 @@ apt install ssh git docker docker-compose nodejs
## IDE - recommended choices
* [VSCode](https://code.visualstudio.com/)
* [Webstorm](https://www.jetbrains.com/webstorm/download/) - Educational or OpenSource License **cannot** be used
- [VSCode](https://code.visualstudio.com/)
- [Webstorm](https://www.jetbrains.com/webstorm/download/) - Educational or OpenSource License **cannot** be used
## Optional helpful tools
* Curl - for executing HTTP requests on the command line
* Postman or Insomnia - for executing HTTP requests with a GUI
- Curl - for executing HTTP requests on the command line
- Postman or Insomnia - for executing HTTP requests with a GUI
## Before you start (Windows only)
@@ -31,8 +31,8 @@ Depending on your preferred settings you could consider applying `git config cor
## Clone starter repositories
* [Minimal deployment](https://gitlab.com/openstapps/minimal-deployment) - contains backend, database, minimal connector, copy (from api) and app
* [Minimal connector](https://gitlab.com/openstapps/minimal-connector) - an example connector to learn the principles of connector development
- [Minimal deployment](https://gitlab.com/openstapps/minimal-deployment) - contains backend, database, minimal connector, copy (from api) and app
- [Minimal connector](https://gitlab.com/openstapps/minimal-connector) - an example connector to learn the principles of connector development
```shell
git clone git@gitlab.com:openstapps/minimal-deployment.git
@@ -2,9 +2,9 @@
## Possible branch names
* `master`
* `develop`
* `$ID-$TITLE`
- `master`
- `develop`
- `$ID-$TITLE`
### `master`
@@ -22,4 +22,4 @@ Development of features, bugfixes or refactoring is done in branches referencing
## Further resources
* [Git - A successful Git branching model](http://nvie.com/posts/a-successful-git-branching-model/)
- [Git - A successful Git branching model](http://nvie.com/posts/a-successful-git-branching-model/)
@@ -16,6 +16,6 @@ Inline comments should not explain what code from external projects is doing. Ad
## Further resources
* [Commit guidelines](COMMITS.md)
* [TypeScript coding guidelines](https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines)
* [Licensing guidelines](LICENSING.md)
- [Commit guidelines](COMMITS.md)
- [TypeScript coding guidelines](https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines)
- [Licensing guidelines](LICENSING.md)
@@ -5,24 +5,24 @@
Commit subjects should match the following template:
> `TYPE`: `SUBJECT`
>
>
> `DESCRIPTION`
### `TYPE`
`TYPE` can have one of the following values:
| value | meaning |
| --- | --- |
| build | Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm) |
| ci | Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs) |
| docs | Documentation only changes |
| feat | A new feature |
| fix | A bug fix |
| perf | A code change that improves performance |
| refactor | A code change that neither fixes a bug nor adds a feature |
| style | Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc) |
| test | Adding missing tests or correcting existing tests |
| value | meaning |
| -------- | ----------------------------------------------------------------------------------------------------------- |
| build | Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm) |
| ci | Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs) |
| docs | Documentation only changes |
| feat | A new feature |
| fix | A bug fix |
| perf | A code change that improves performance |
| refactor | A code change that neither fixes a bug nor adds a feature |
| style | Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc) |
| test | Adding missing tests or correcting existing tests |
These are the [types](https://github.com/angular/angular/blob/master/CONTRIBUTING.md#type), that angular uses. They are easily adaptable for all TypeScript based web related projects.
@@ -56,5 +56,5 @@ conventional-changelog -p angular -i CHANGELOG.md -s -r 0
## Further resources
* [Recommendations on commit messages](https://chris.beams.io/posts/git-commit/)
* [Versioning](VERSIONING.md)
- [Recommendations on commit messages](https://chris.beams.io/posts/git-commit/)
- [Versioning](VERSIONING.md)
@@ -10,17 +10,17 @@ Code is annotated with [TypeDoc](https://typedoc.org/), which then can be used t
Please follow these guidelines to reduce redundance:
* The purpose of inline documentation is to explain what the line of code actually does without explaining syntax or external references. Example:
- The purpose of inline documentation is to explain what the line of code actually does without explaining syntax or external references. Example:
```typescript
// extend the template by the properties of the base template
templateBase.properties = mergeObjects(
templateBase.properties,
templates['base.template.json'].mappings._default_.properties
templates['base.template.json'].mappings._default_.properties,
);
```
* Follow the [recommendations](http://typedoc.org/guides/doccomments/) of `typedoc`, because it is used to generate documentation. Do not denote the types again in the documentation (`@param` and `@returns`), because they are already "documented" in the code itself. Example:
- Follow the [recommendations](http://typedoc.org/guides/doccomments/) of `typedoc`, because it is used to generate documentation. Do not denote the types again in the documentation (`@param` and `@returns`), because they are already "documented" in the code itself. Example:
```typescript
/**
@@ -39,8 +39,8 @@ async get<T>(key: string): Promise<T> {
### Inline Comments `//`
* Start inline comments with a lowercase letter and a space after the `//`
* Place the comment above the line that it is referencing
- Start inline comments with a lowercase letter and a space after the `//`
- Place the comment above the line that it is referencing
```typescript
// lorem ipsum
@@ -49,14 +49,14 @@ const lorem;
### Doc Comments `/**`
* Start with a capital letter
* Keep the first line short
* The first line should not end with a period, nor should it consist of multiple sentences
* The first line should be easily scannable
* If you want to comment more than one line, do a short summary in the first line, then continue after a blank line with the more detailed description
* Document all parameters in functions using `@param`
* `@param` must not contain a type annotation, just `@param name description`
* Do not include `@return`, as it is redundant information
- Start with a capital letter
- Keep the first line short
- The first line should not end with a period, nor should it consist of multiple sentences
- The first line should be easily scannable
- If you want to comment more than one line, do a short summary in the first line, then continue after a blank line with the more detailed description
- Document all parameters in functions using `@param`
- `@param` must not contain a type annotation, just `@param name description`
- Do not include `@return`, as it is redundant information
```typescript
/**
@@ -81,4 +81,4 @@ The path `.gitlab/issue_templates` can contain markdown files which act as templ
## Further resources
* [GitLab issue templates](https://gitlab.com/help/user/project/description_templates.md)
- [GitLab issue templates](https://gitlab.com/help/user/project/description_templates.md)
@@ -6,4 +6,4 @@ Issues keep a discussion of the topic, are related to a [branch](BRANCHING.md),
## Further resources
* [Always start with an issue](https://about.gitlab.com/2016/03/03/start-with-an-issue/)
- [Always start with an issue](https://about.gitlab.com/2016/03/03/start-with-an-issue/)
@@ -45,4 +45,4 @@ If the file is updated in a new year after its creation, the `<year>` should be
## Further resources
* [Coding style](CODING.md)
- [Coding style](CODING.md)
@@ -7,8 +7,8 @@ A merge request can also gather the work of multiple issues.
Merge requests are used to merge the changes to the main branches (`master`, `develop`). Every merge request needs to be reviewed/commented by at least 2 other developers before they can be accepted. This ensure that all guidelines are followed and that the scope of the issue is matched.
Before any merge of an `issue`-branch into the according `master`-branch, the commits of the `issue`-branch shall be tidied up.
Unstage your commits from the `issue`-branch (`git reset master`). Create your new commit(s) and push them to the remote repository (`git push --force`).
Unstage your commits from the `issue`-branch (`git reset master`). Create your new commit(s) and push them to the remote repository (`git push --force`).
## Further resources
* [Commits](COMMITS.md)
- [Commits](COMMITS.md)
@@ -33,5 +33,5 @@ For the contents and purpose of `.editorconfig`, `tsconfig.json` and `tslint.jso
## Further resources
* [Coding style](CODING.md)
* [Versioning](VERSIONING.md)
- [Coding style](CODING.md)
- [Versioning](VERSIONING.md)
@@ -2,7 +2,7 @@
## NPM
All projects that use the [OpenStApps configuration](https://gitlab.com/openstapps/configuration) and implement the automatic publishing via GitLab CI can simply be published to the NPM registry by using the appropriate job. It uses the `NPM_AUTH_TOKEN` that is a [protected variable](https://gitlab.com/groups/openstapps/-/settings/ci_cd) of the OpenStApps group. To trigger this job, a new tag has to be created (on the master branch):
All projects that use the [OpenStApps configuration](https://gitlab.com/openstapps/configuration) and implement the automatic publishing via GitLab CI can simply be published to the NPM registry by using the appropriate job. It uses the `NPM_AUTH_TOKEN` that is a [protected variable](https://gitlab.com/groups/openstapps/-/settings/ci_cd) of the OpenStApps group. To trigger this job, a new tag has to be created (on the master branch):
### Use current [master branch](BRANCHING.md)
@@ -19,8 +19,8 @@ npm version (major|minor|patch)
After these steps there should 2 new commits:
* A version commit
* A changelog commit
- A version commit
- A changelog commit
Also a new git tag should be created.
@@ -2,9 +2,9 @@
We use semantic version through `npm`.
* `npm version patch`: For fixes/patches
* `npm version minor`: For new features
* `npm version major`: For breaking changes in the API
- `npm version patch`: For fixes/patches
- `npm version minor`: For new features
- `npm version major`: For breaking changes in the API
Or directly with `git tag vMAJOR.MINOR.PATCH`.
@@ -12,4 +12,4 @@ This tag is set on the `develop`- (if present) or on the `master`-[branch](BRANC
## Further resources
* [Commit guidelines](COMMITS.md)
- [Commit guidelines](COMMITS.md)
+5 -11
View File
@@ -17,15 +17,15 @@
},
{
"matchUpdateTypes": ["major"],
"matchPackagePatterns": ["^@angular", "^@ionic", "^@types\/node$", "^got$"],
"matchPackagePatterns": ["^@angular", "^@ionic", "^@types/node$", "^got$"],
"enabled": false
},
{
"matchPackagePatterns": ["^@types\/geojson$"],
"matchPackagePatterns": ["^@types/geojson$"],
"allowedVersions": "1.0.6"
},
{
"matchPackagePatterns": ["^@elastic\/elasticsearch$"],
"matchPackagePatterns": ["^@elastic/elasticsearch$"],
"allowedVersions": "<6.0"
},
{
@@ -41,18 +41,12 @@
"allowedVersions": "<5.0"
},
{
"matchDepTypes": [
"peerDependencies"
],
"matchDepTypes": ["peerDependencies"],
"rangeStrategy": "replace"
}
],
"lockFileMaintenance": {
"enabled": true
},
"reviewers": [
"abcdev",
"jovankrunic",
"theaninova"
]
"reviewers": ["abcdev", "jovankrunic", "theaninova"]
}
+3 -44
View File
@@ -12,23 +12,9 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {asyncPool} from '@krlwlfrt/async-pool';
import {Api} from '@openstapps/gitlab-api';
import {Group, Project} from '@openstapps/gitlab-api/lib/types';
import {Project} from '@openstapps/gitlab-api/lib/types';
import {Logger} from '@openstapps/logger';
import {readFile, writeFile} from 'fs';
import {promisify} from 'util';
import {CONCURRENCY} from './configuration';
/**
* Promisified version of readFile
*/
export const readFilePromisified = promisify(readFile);
/**
* Promisified version of writeFile
*/
export const writeFilePromisified = promisify(writeFile);
/**
* Get projects for a list of groups
@@ -39,37 +25,10 @@ export const writeFilePromisified = promisify(writeFile);
export async function getProjects(api: Api, groups: number[]): Promise<Project[]> {
Logger.info(`Fetching all projects for specified groups (${groups.length})...`);
const projectResults = await asyncPool(CONCURRENCY, groups, async groupId => {
return api.getProjectsForGroup(groupId);
});
const projects = flatten2dArray(projectResults);
const projectResults = await Promise.all(groups.map(api.getProjectsForGroup));
const projects = projectResults.flat();
Logger.log(`Fetched ${projects.length} project(s).`);
return projects;
}
/**
* Get subgroups for a list of groups
*
* @param api GitLab API to make requests with
* @param groups List of groups
*/
export async function getSubGroups(api: Api, groups: number[]): Promise<Group[]> {
return flatten2dArray(
await asyncPool(CONCURRENCY, groups, async groupId => {
return api.getSubGroupsForGroup(groupId);
}),
);
}
/**
* Flatten 2d array
*
* @param array Flattened array
*/
export function flatten2dArray<T>(array: T[][]): T[] {
// eslint-disable-next-line unicorn/prefer-spread
return ([] as T[]).concat(...array);
}
@@ -13,7 +13,9 @@
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {Label} from '@openstapps/gitlab-api/lib/types';
import moment from 'moment';
import setHours from 'date-fns/setHours';
import nextThursday from 'date-fns/nextThursday';
import previousThursday from 'date-fns/previousThursday';
/**
* List of schools with their IDs
@@ -183,31 +185,11 @@ export const NOTE_PREFIX = '`openstapps/projectmanagement`';
*/
export const SLACK_CHANNEL = 'C762UG76Z';
/**
* Concurrency for async pool
*/
export const CONCURRENCY = 3;
/**
* Maximum depth for merge request reminders
*/
export const MAX_DEPTH_FOR_REMINDER = 2;
/**
* Next meeting
*/
export const NEXT_MEETING = moment()
.startOf('week')
// tslint:disable-next-line:no-magic-numbers
.hour(10)
// tslint:disable-next-line:no-magic-numbers
.day(3);
export const NEXT_MEETING = setHours(nextThursday(Date.now()), 10);
if (NEXT_MEETING.isBefore(moment())) {
NEXT_MEETING.add(1, 'week');
}
/**
* Last meeting
*/
export const LAST_MEETING = moment(NEXT_MEETING).subtract(1, 'week');
export const LAST_MEETING = setHours(previousThursday(Date.now()), 10);
@@ -14,7 +14,7 @@
*/
import {existsSync, PathLike} from 'fs';
import path from 'path';
import {readFilePromisified} from '../common';
import {readFile} from 'fs/promises';
/**
* Get used version of a dependency of a project referenced by a path
@@ -27,7 +27,7 @@ export async function getUsedVersion(directoryPath: PathLike, dependency: string
throw new Error(`'package.json' does not exist in '${directoryPath}'. Not a Node.js project?`);
}
const buffer = await readFilePromisified(path.join(directoryPath.toString(), 'package.json'));
const buffer = await readFile(path.join(directoryPath.toString(), 'package.json'));
const content = buffer.toString();
const packageJson = JSON.parse(content);
@@ -12,7 +12,6 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {asyncPool} from '@krlwlfrt/async-pool';
import {Api} from '@openstapps/gitlab-api';
import {
AccessLevel,
@@ -23,8 +22,8 @@ import {
User,
} from '@openstapps/gitlab-api/lib/types';
import {Logger} from '@openstapps/logger';
import {WebClient} from '@slack/client';
import {CONCURRENCY, GROUPS, MAX_DEPTH_FOR_REMINDER, NOTE_PREFIX, SLACK_CHANNEL} from '../configuration';
import {WebClient} from '@slack/web-api';
import {GROUPS, MAX_DEPTH_FOR_REMINDER, NOTE_PREFIX, SLACK_CHANNEL} from '../configuration';
/**
* Remind people of open merge requests
@@ -55,9 +54,9 @@ export async function remind(api: Api): Promise<void> {
// instantiate slack client
const client =
typeof process.env.SLACK_API_TOKEN !== 'undefined'
? new WebClient(process.env.SLACK_API_TOKEN)
: undefined;
typeof process.env.SLACK_API_TOKEN === 'undefined'
? undefined
: new WebClient(process.env.SLACK_API_TOKEN);
// get members of main group
const members = await api.getMembers(MembershipScope.GROUPS, GROUPS[0]);
@@ -75,115 +74,117 @@ export async function remind(api: Api): Promise<void> {
Logger.info(`Found ${maintainers.length} maintainer(s).`);
await asyncPool(CONCURRENCY, mergeRequests, async mergeRequest => {
// check if merge request is WIP
if (mergeRequest.work_in_progress) {
Logger.info(`Merge request '${mergeRequest.title}' is WIP.`);
await Promise.all(
mergeRequests.map(async mergeRequest => {
// check if merge request is WIP
if (mergeRequest.work_in_progress) {
Logger.info(`Merge request '${mergeRequest.title}' is WIP.`);
return;
}
// get merge request approval
const approval = await api.getMergeRequestApproval(mergeRequest.project_id, mergeRequest.iid);
// get merge request discussions
const discussions = await api.getMergeRequestDiscussions(mergeRequest.project_id, mergeRequest.iid);
// check if at least one of the discussions is unresolved
const hasUnresolvedDiscussions = discussions.some(discussion => {
return discussion.notes.some(note => {
return note.resolvable && (typeof note.resolved === 'undefined' || !note.resolved);
});
});
if (hasUnresolvedDiscussions) {
let recipient = mergeRequest.author.username;
if (typeof mergeRequest.assignee !== 'undefined' && mergeRequest.assignee !== null) {
recipient = mergeRequest.assignee.username;
return;
}
// create note in merge request
await api.createNote(
mergeRequest.project_id,
Scope.MERGE_REQUESTS,
mergeRequest.iid,
`${NOTE_PREFIX} Please resolve pending discussions, @${recipient}!`,
);
// get merge request approval
const approval = await api.getMergeRequestApproval(mergeRequest.project_id, mergeRequest.iid);
return;
}
// get merge request discussions
const discussions = await api.getMergeRequestDiscussions(mergeRequest.project_id, mergeRequest.iid);
if (approval.merge_status === MergeRequestMergeStatus.CAN_BE_MERGED) {
if (approval.approvals_left > 0) {
Logger.warn(`Merge request '${mergeRequest.title}' needs more approvals!`);
// get possible appropers, prefixed with '@' and joined with commas
const possibleApprovers = maintainerUsernames
.filter(username => {
if (mergeRequest.assignee.username === username) {
return false;
}
if (username.includes('openstapps') || username.includes('kphilipp')) {
return false;
}
if (approval.approved_by.length === 0) {
return true;
}
return approval.approved_by.find(
(approver: {
/**
* Possible approver
*/
user: User;
}) => {
return approver.user.username !== username;
},
);
})
.map(username => `@${username}`)
.join(' ');
// send message to slack
await client?.chat.postMessage({
channel: SLACK_CHANNEL,
text: `Merge request '${mergeRequest.title}' needs more approvals! See ${mergeRequest.web_url}!`,
// check if at least one of the discussions is unresolved
const hasUnresolvedDiscussions = discussions.some(discussion => {
return discussion.notes.some(note => {
return note.resolvable && (typeof note.resolved === 'undefined' || !note.resolved);
});
});
// assign reviewers
await api.createNote(
mergeRequest.project_id,
Scope.MERGE_REQUESTS,
mergeRequest.iid,
`/assign_reviewer ${possibleApprovers}`,
);
} else {
Logger.log(`Merge request '${mergeRequest.title}' is ready to be merged!`);
if (hasUnresolvedDiscussions) {
let recipient = mergeRequest.author.username;
// send message to slack
await client?.chat.postMessage({
channel: SLACK_CHANNEL,
text: `Merge request '${mergeRequest.title}' is ready to be merged! See ${mergeRequest.web_url}!`,
});
// prefix maintainers with '@' and join with commas
const possibleMergers = maintainerUsernames
.filter(username => {
return mergeRequest.assignee.username !== username;
})
.map(username => `@${username}`)
.join(', ');
if (typeof mergeRequest.assignee !== 'undefined' && mergeRequest.assignee !== null) {
recipient = mergeRequest.assignee.username;
}
// create note in merge request
await api.createNote(
mergeRequest.project_id,
Scope.MERGE_REQUESTS,
mergeRequest.iid,
`${NOTE_PREFIX} Merge request is ready to be merged, ${possibleMergers}!`,
`${NOTE_PREFIX} Please resolve pending discussions, @${recipient}!`,
);
return;
}
}
});
if (approval.merge_status === MergeRequestMergeStatus.CAN_BE_MERGED) {
if (approval.approvals_left > 0) {
Logger.warn(`Merge request '${mergeRequest.title}' needs more approvals!`);
// get possible appropers, prefixed with '@' and joined with commas
const possibleApprovers = maintainerUsernames
.filter(username => {
if (mergeRequest.assignee.username === username) {
return false;
}
if (username.includes('openstapps') || username.includes('kphilipp')) {
return false;
}
if (approval.approved_by.length === 0) {
return true;
}
return approval.approved_by.find(
(approver: {
/**
* Possible approver
*/
user: User;
}) => {
return approver.user.username !== username;
},
);
})
.map(username => `@${username}`)
.join(' ');
// send message to slack
await client?.chat.postMessage({
channel: SLACK_CHANNEL,
text: `Merge request '${mergeRequest.title}' needs more approvals! See ${mergeRequest.web_url}!`,
});
// assign reviewers
await api.createNote(
mergeRequest.project_id,
Scope.MERGE_REQUESTS,
mergeRequest.iid,
`/assign_reviewer ${possibleApprovers}`,
);
} else {
Logger.log(`Merge request '${mergeRequest.title}' is ready to be merged!`);
// send message to slack
await client?.chat.postMessage({
channel: SLACK_CHANNEL,
text: `Merge request '${mergeRequest.title}' is ready to be merged! See ${mergeRequest.web_url}!`,
});
// prefix maintainers with '@' and join with commas
const possibleMergers = maintainerUsernames
.filter(username => {
return mergeRequest.assignee.username !== username;
})
.map(username => `@${username}`)
.join(', ');
// create note in merge request
await api.createNote(
mergeRequest.project_id,
Scope.MERGE_REQUESTS,
mergeRequest.iid,
`${NOTE_PREFIX} Merge request is ready to be merged, ${possibleMergers}!`,
);
}
}
}),
);
}
@@ -12,7 +12,6 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {asyncPool} from '@krlwlfrt/async-pool';
import {Api} from '@openstapps/gitlab-api';
import {
Issue,
@@ -23,12 +22,16 @@ import {
User,
} from '@openstapps/gitlab-api/lib/types';
import {Logger} from '@openstapps/logger';
import moment from 'moment';
import {render} from 'mustache';
import path from 'path';
import {cwd} from 'process';
import {flatten2dArray, getProjects, readFilePromisified, writeFilePromisified} from '../common';
import {BOLD_LABELS, CONCURRENCY, GROUPS, LABEL_WEIGHTS, NEXT_MEETING} from '../configuration';
import {getProjects} from '../common';
import {BOLD_LABELS, GROUPS, LABEL_WEIGHTS, NEXT_MEETING} from '../configuration';
import differenceInWeeks from 'date-fns/differenceInWeeks';
import formatISO from 'date-fns/formatISO';
import format from 'date-fns/format';
import de from 'date-fns/locale/de';
import {readFile, writeFile} from 'fs/promises';
/**
* A structure for template compilation
@@ -188,13 +191,15 @@ export function getMergeRequestUrls(
* @param groups List of groups to get issues for
*/
export async function getIssues(api: Api, label: string, groups: number[]): Promise<Issue[]> {
const issueResults = await asyncPool(CONCURRENCY, groups, async groupId => {
return api.getIssues({
groupId: groupId,
});
});
const issueResults = await Promise.all(
groups.map(groupId =>
api.getIssues({
groupId: groupId,
}),
),
);
const issues = flatten2dArray(issueResults).filter(issue => {
const issues = issueResults.flat().filter(issue => {
return issue.labels.includes(label);
});
@@ -212,21 +217,23 @@ export async function getIssues(api: Api, label: string, groups: number[]): Prom
export async function getIssueBranches(api: Api, projects: Project[]): Promise<{[k: string]: number[]}> {
const projectBranches: {[k: string]: number[]} = {};
await asyncPool(CONCURRENCY, projects, async project => {
const branches = await api.getBranchesForProject(project.id);
await Promise.all(
projects.map(async project => {
const branches = await api.getBranchesForProject(project.id);
// extract issue number from branch
projectBranches[project.id] = branches
.map(branch => {
return branch.name.split('-')[0];
})
.filter(branchNameStart => {
return branchNameStart.match(/^[0-9]+$/);
})
.map(branchNameStart => {
return Number.parseInt(branchNameStart, 10);
});
});
// extract issue number from branch
projectBranches[project.id] = branches
.map(branch => {
return branch.name.split('-')[0];
})
.filter(branchNameStart => {
return branchNameStart.match(/^[0-9]+$/);
})
.map(branchNameStart => {
return Number.parseInt(branchNameStart, 10);
});
}),
);
return projectBranches;
}
@@ -240,14 +247,14 @@ export async function getIssueBranches(api: Api, projects: Project[]): Promise<{
export async function getIssuesGroupedByAssignees(api: Api, label: string): Promise<AssigneeWithIssues[]> {
const issuesByAssignee: IssuesGroupedByAssigneeId = {};
const groups = flatten2dArray(
await asyncPool(CONCURRENCY, GROUPS, async groupId => {
const groups = await Promise.all(
GROUPS.map(async groupId => {
const subGroups = await api.getSubGroupsForGroup(groupId);
return subGroups.map(group => {
return group.id;
});
}),
);
).then(it => it.flat());
groups.push(...groups, ...GROUPS);
const [issues, projects] = await Promise.all([getIssues(api, label, groups), getProjects(api, groups)]);
@@ -292,7 +299,7 @@ export async function getIssuesGroupedByAssignees(api: Api, label: string): Prom
}),
$mergeRequestUrl: getMergeRequestUrls(mergeRequests, issue.project_id, issue.iid)[0],
$project: issue.web_url.replace('https://gitlab.com/', '').split('/-/issues/')[0],
$weeksOpen: moment().diff(moment(issue.created_at), 'weeks'),
$weeksOpen: differenceInWeeks(Date.now(), new Date(issue.created_at)),
};
const issueWithMeta: IssueWithMeta = {
@@ -370,7 +377,7 @@ export async function getIssuesGroupedByAssignees(api: Api, label: string): Prom
* Get next meeting day
*/
export function getNextMeetingDay() {
const meetingDay = NEXT_MEETING.format('YYYY-MM-DD');
const meetingDay = formatISO(NEXT_MEETING, {representation: 'date'});
// log found meeting day
Logger.info(`Generating report for '${meetingDay}' of '${GROUPS.length}' group(s)...`);
@@ -388,35 +395,37 @@ export async function getMergeRequests(api: Api, projects: Project[]): Promise<M
const projectMergeRequests: MergeRequestsForProjects = {};
// iterate over projects
await asyncPool(CONCURRENCY, projects, async project => {
// check if project can have merge requests
if (!project.merge_requests_enabled) {
return;
}
await Promise.all(
projects.map(async project => {
// check if project can have merge requests
if (!project.merge_requests_enabled) {
return;
}
// get all merge requests for project
const mergeRequests = await api.getMergeRequests(
MembershipScope.PROJECTS,
project.id,
MergeRequestState.OPENED,
);
// get all merge requests for project
const mergeRequests = await api.getMergeRequests(
MembershipScope.PROJECTS,
project.id,
MergeRequestState.OPENED,
);
// extract issue number from merge request
projectMergeRequests[project.id] = mergeRequests
.map(mergeRequest => {
// keep information about web url too
return {issue_iid: mergeRequest.source_branch.split('-')[0], web_url: mergeRequest.web_url};
})
.filter(branchNameStartAndUrl => {
return branchNameStartAndUrl.issue_iid.match(/^[0-9]+$/);
})
.map(branchNameStartAndUrl => {
return {
issue_iid: Number.parseInt(branchNameStartAndUrl.issue_iid, 10),
web_url: branchNameStartAndUrl.web_url,
};
});
});
// extract issue number from merge request
projectMergeRequests[project.id] = mergeRequests
.map(mergeRequest => {
// keep information about web url too
return {issue_iid: mergeRequest.source_branch.split('-')[0], web_url: mergeRequest.web_url};
})
.filter(branchNameStartAndUrl => {
return branchNameStartAndUrl.issue_iid.match(/^[0-9]+$/);
})
.map(branchNameStartAndUrl => {
return {
issue_iid: Number.parseInt(branchNameStartAndUrl.issue_iid, 10),
web_url: branchNameStartAndUrl.web_url,
};
});
}),
);
return projectMergeRequests;
}
@@ -434,7 +443,7 @@ export async function generateReport(api: Api, label: string, template: string):
const structureForTemplate: StructureForTemplate = {
issuesByAssignee: issuesGroupedByAssignee,
meetingDay: getNextMeetingDay(),
timestamp: moment().format('LLL'),
timestamp: format(Date.now(), 'PPPPpp', {locale: de}),
};
return render(template, structureForTemplate);
@@ -449,7 +458,7 @@ export async function generateReport(api: Api, label: string, template: string):
export async function report(api: Api, label: string) {
const meetingDay = getNextMeetingDay();
const readReportFile = await readFilePromisified(
const readReportFile = await readFile(
// eslint-disable-next-line unicorn/prefer-module
path.resolve(__dirname, '..', '..', 'templates', 'report.md.mustache'),
);
@@ -462,7 +471,7 @@ export async function report(api: Api, label: string) {
filename = path.join(cwd(), 'reports', `${label}.md`);
}
await writeFilePromisified(filename, markdown);
await writeFile(filename, markdown);
Logger.ok(`Wrote file '${filename}'.`);
}
+217 -191
View File
@@ -12,7 +12,6 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {asyncPool} from '@krlwlfrt/async-pool';
import {Api} from '@openstapps/gitlab-api';
import {
AccessLevel,
@@ -24,9 +23,8 @@ import {
Scope,
} from '@openstapps/gitlab-api/lib/types';
import {Logger} from '@openstapps/logger';
import {flatten2dArray, getProjects} from '../common';
import {getProjects} from '../common';
import {
CONCURRENCY,
GROUPS,
NEEDED_LABELS,
NEEDED_MILESTONES,
@@ -44,51 +42,52 @@ import {
*/
export async function tidyIssuesWithoutMilestone(api: Api): Promise<void> {
// fetch issues without milestone from all groups
const issueResults = await asyncPool(CONCURRENCY, GROUPS, async groupId => {
return api.getIssues({
groupId: groupId,
milestone: 'No Milestone',
state: IssueState.OPENED,
});
});
// flatten structure, e.g. put all issues in one array
const issuesWithoutMilestone = flatten2dArray(issueResults);
const issuesWithoutMilestone = await Promise.all(
GROUPS.map(groupId =>
api.getIssues({
groupId: groupId,
milestone: 'No Milestone',
state: IssueState.OPENED,
}),
),
).then(it => it.flat());
Logger.info(`Found '${issuesWithoutMilestone.length}' issue(s) without milestone.`);
const milestoneCache: {[s: number]: Milestone[]} = {};
await asyncPool(CONCURRENCY, issuesWithoutMilestone, async issue => {
if (typeof milestoneCache[issue.project_id] === 'undefined') {
milestoneCache[issue.project_id] = await api.getMilestonesForProject(issue.project_id);
}
let milestoneId;
for (const milestone of milestoneCache[issue.project_id]) {
if (milestone.title === 'Meeting') {
milestoneId = milestone.id;
await Promise.all(
issuesWithoutMilestone.map(async issue => {
if (typeof milestoneCache[issue.project_id] === 'undefined') {
milestoneCache[issue.project_id] = await api.getMilestonesForProject(issue.project_id);
}
}
if (typeof milestoneId === 'undefined') {
Logger.warn(`Milestone 'Meeting' was not available for issue ${issue.title} (${issue.web_url}).`);
let milestoneId;
return;
}
for (const milestone of milestoneCache[issue.project_id]) {
if (milestone.title === 'Meeting') {
milestoneId = milestone.id;
}
}
await api.setMilestoneForIssue(issue, milestoneId);
if (typeof milestoneId === 'undefined') {
Logger.warn(`Milestone 'Meeting' was not available for issue ${issue.title} (${issue.web_url}).`);
Logger.log(`Milestone was set to 'Meeting' for issue ${issue.title} (${issue.web_url})`);
return;
}
await api.createNote(
issue.project_id,
Scope.ISSUES,
issue.iid,
`${NOTE_PREFIX} Milestone was set automatically to 'Meeting'.`,
);
});
await api.setMilestoneForIssue(issue, milestoneId);
Logger.log(`Milestone was set to 'Meeting' for issue ${issue.title} (${issue.web_url})`);
await api.createNote(
issue.project_id,
Scope.ISSUES,
issue.iid,
`${NOTE_PREFIX} Milestone was set automatically to 'Meeting'.`,
);
}),
);
Logger.ok('Tidied issues without milestones.');
}
@@ -102,15 +101,14 @@ export async function tidyIssuesWithoutMilestone(api: Api): Promise<void> {
*/
export async function tidyOpenIssuesWithoutMeetingLabel(api: Api): Promise<void> {
// fetch all open issues
const issueResults = await asyncPool(CONCURRENCY, GROUPS, async groupId => {
return api.getIssues({
groupId: groupId,
state: IssueState.OPENED,
});
});
// flatten structure, e.g. put all issues in one array
const openIssues = flatten2dArray(issueResults);
const openIssues = await Promise.all(
GROUPS.map(groupId =>
api.getIssues({
groupId: groupId,
state: IssueState.OPENED,
}),
),
).then(it => it.flat());
Logger.info(`Found ${openIssues.length} open issue(s).`);
@@ -121,20 +119,22 @@ export async function tidyOpenIssuesWithoutMeetingLabel(api: Api): Promise<void>
Logger.info(`Filtered ${openIssuesWithoutMeetingLabel.length} open issue(s) without label 'meeting'.`);
await asyncPool(CONCURRENCY, openIssuesWithoutMeetingLabel, async issue => {
if (issue.milestone !== null && issue.milestone.title === 'Backlog') {
Logger.info(`Skipping issue "${issue.title}" because it is in backlog.`);
await Promise.all(
openIssuesWithoutMeetingLabel.map(async issue => {
if (issue.milestone !== null && issue.milestone.title === 'Backlog') {
Logger.info(`Skipping issue "${issue.title}" because it is in backlog.`);
return;
}
return;
}
return api.createNote(
issue.project_id,
Scope.ISSUES,
issue.iid,
`${NOTE_PREFIX} Automatically adding label 'meeting'\n\n/label ~meeting`,
);
});
return api.createNote(
issue.project_id,
Scope.ISSUES,
issue.iid,
`${NOTE_PREFIX} Automatically adding label 'meeting'\n\n/label ~meeting`,
);
}),
);
Logger.ok(`Tidied open issues without label 'meeting'.`);
}
@@ -146,39 +146,43 @@ export async function tidyOpenIssuesWithoutMeetingLabel(api: Api): Promise<void>
* @param projects List of projects to tidy labels on
*/
export async function tidyLabels(api: Api, projects: Project[]): Promise<void> {
await asyncPool(CONCURRENCY, projects, async project => {
const labels = await api.getLabels(project.id);
await Promise.all(
projects.map(async project => {
const labels = await api.getLabels(project.id);
const neededLabels = [...NEEDED_LABELS];
// const extraneousLabels: Label[] = [];
const neededLabels = [...NEEDED_LABELS];
// const extraneousLabels: Label[] = [];
for (const label of labels) {
// let needed = false;
for (const label of labels) {
// let needed = false;
for (const [neededLabelIndex, neededLabel] of neededLabels.entries()) {
if (neededLabel.name.toLowerCase() === label.name.toLowerCase()) {
neededLabels.splice(neededLabelIndex, 1);
// needed = true;
for (const [neededLabelIndex, neededLabel] of neededLabels.entries()) {
if (neededLabel.name.toLowerCase() === label.name.toLowerCase()) {
neededLabels.splice(neededLabelIndex, 1);
// needed = true;
}
}
}
/* if (!needed) {
/* if (!needed) {
extraneousLabels.push(label);
} */
}
}
await asyncPool(CONCURRENCY, neededLabels, async neededLabel => {
await api.createLabel(project.id, neededLabel.name, neededLabel.description, neededLabel.color);
await Promise.all(
neededLabels.map(async neededLabel => {
await api.createLabel(project.id, neededLabel.name, neededLabel.description, neededLabel.color);
Logger.log(`Created label '${neededLabel.name}' in '${project.name_with_namespace}'.`);
});
Logger.log(`Created label '${neededLabel.name}' in '${project.name_with_namespace}'.`);
}),
);
// await asyncPool(2, extraneousLabels, async (extraneousLabel) => {
// await api.deleteLabel(project.id, extraneousLabel.name);
//
// Logger.log('Deleted label `' + extraneousLabel.name + '` from ' + project.name_with_namespace + '.');
// });
});
// await asyncPool(2, extraneousLabels, async (extraneousLabel) => {
// await api.deleteLabel(project.id, extraneousLabel.name);
//
// Logger.log('Deleted label `' + extraneousLabel.name + '` from ' + project.name_with_namespace + '.');
// });
}),
);
Logger.ok('Tidied labels.');
}
@@ -190,25 +194,29 @@ export async function tidyLabels(api: Api, projects: Project[]): Promise<void> {
* @param projects List of projects to tidy milestones on
*/
export async function tidyMilestones(api: Api, projects: Project[]): Promise<void> {
await asyncPool(CONCURRENCY, projects, async project => {
const milestones = await api.getMilestonesForProject(project.id);
const missingMilestones = [...NEEDED_MILESTONES];
await Promise.all(
projects.map(async project => {
const milestones = await api.getMilestonesForProject(project.id);
const missingMilestones = [...NEEDED_MILESTONES];
for (const milestone of milestones) {
const index = missingMilestones.indexOf(milestone.title);
for (const milestone of milestones) {
const index = missingMilestones.indexOf(milestone.title);
if (index >= 0) {
missingMilestones.splice(index, 1);
if (index >= 0) {
missingMilestones.splice(index, 1);
}
}
}
if (missingMilestones.length > 0 && !project.archived) {
await asyncPool(CONCURRENCY, missingMilestones, async milestone => {
await api.createMilestone(project.id, milestone);
Logger.log(`Created milestone '${milestone}' for project ${project.name_with_namespace}'.`);
});
}
});
if (missingMilestones.length > 0 && !project.archived) {
await Promise.all(
missingMilestones.map(async milestone => {
await api.createMilestone(project.id, milestone);
Logger.log(`Created milestone '${milestone}' for project ${project.name_with_namespace}'.`);
}),
);
}
}),
);
Logger.ok('Tidied milestones.');
}
@@ -220,23 +228,29 @@ export async function tidyMilestones(api: Api, projects: Project[]): Promise<voi
* @param projects List of projects to tidy milestones on
*/
export async function tidyProtectedBranches(api: Api, projects: Project[]): Promise<void> {
await asyncPool(CONCURRENCY, projects, async project => {
const branches = await api.getBranchesForProject(project.id);
await Promise.all(
projects.map(async project => {
const branches = await api.getBranchesForProject(project.id);
const protectableBranches = branches.filter(branch => {
return PROTECTED_BRANCHES.includes(branch.name);
});
const protectableBranches = branches.filter(branch => {
return PROTECTED_BRANCHES.includes(branch.name);
});
const unprotectedBranches = protectableBranches.filter(branch => {
return !branch.protected;
});
const unprotectedBranches = protectableBranches.filter(branch => {
return !branch.protected;
});
await asyncPool(CONCURRENCY, unprotectedBranches, async branch => {
await api.protectBranch(project.id, branch.name);
await Promise.all(
unprotectedBranches.map(async branch => {
await api.protectBranch(project.id, branch.name);
Logger.log(`Added protected branch '${branch.name}' in project '${project.name_with_namespace}'...`);
});
});
Logger.log(
`Added protected branch '${branch.name}' in project '${project.name_with_namespace}'...`,
);
}),
);
}),
);
Logger.ok('Tidied protected branches.');
}
@@ -248,44 +262,48 @@ export async function tidyProtectedBranches(api: Api, projects: Project[]): Prom
* @param projects List of projects to tidy protected tags on
*/
export async function tidyProtectedTags(api: Api, projects: Project[]): Promise<void> {
await asyncPool(CONCURRENCY, projects, async project => {
// TODO: move this to GitLab API
const protectedTags = (await api.makeGitLabAPIRequest(`projects/${project.id}/protected_tags`)) as Array<{
/**
* List of access levels to create a tag
*/
create_access_levels: Array<{
await Promise.all(
projects.map(async project => {
// TODO: move this to GitLab API
const protectedTags = (await api.makeGitLabAPIRequest(
`projects/${project.id}/protected_tags`,
)) as Array<{
/**
* Access level
* List of access levels to create a tag
*/
access_level: AccessLevel;
create_access_levels: Array<{
/**
* Access level
*/
access_level: AccessLevel;
/**
* Description of access level
*/
access_level_description: string;
}>;
/**
* Description of access level
* Name of the tag
*/
access_level_description: string;
name: string;
}>;
/**
* Name of the tag
*/
name: string;
}>;
if (
protectedTags.findIndex(protectedTag => {
return protectedTag.name === 'v*';
}) === -1
) {
await api.makeGitLabAPIRequest(`projects/${project.id}/protected_tags`, {
data: {
create_access_level: AccessLevel.Maintainer,
name: 'v*',
},
method: 'POST',
});
if (
protectedTags.findIndex(protectedTag => {
return protectedTag.name === 'v*';
}) === -1
) {
await api.makeGitLabAPIRequest(`projects/${project.id}/protected_tags`, {
data: {
create_access_level: AccessLevel.Maintainer,
name: 'v*',
},
method: 'POST',
});
Logger.log(`Added protected version tag in project '${project.name_with_namespace}'.`);
}
});
Logger.log(`Added protected version tag in project '${project.name_with_namespace}'.`);
}
}),
);
Logger.ok('Tidied protected tags.');
}
@@ -305,26 +323,32 @@ export async function tidySubGroupMembers(api: Api): Promise<void> {
groupIdsToSchool[SCHOOLS[school]] = school;
});
await asyncPool(CONCURRENCY, GROUPS.slice(1), async groupId => {
const members = await api.getMembers(MembershipScope.GROUPS, groupId);
const memberIds = new Set(members.map(member => member.id));
await Promise.all(
GROUPS.slice(1).map(async groupId => {
const members = await api.getMembers(MembershipScope.GROUPS, groupId);
const memberIds = new Set(members.map(member => member.id));
await asyncPool(CONCURRENCY, stappsMembers, async stappsMember => {
if (!memberIds.has(stappsMember.id)) {
await api.addMember(MembershipScope.GROUPS, groupId, stappsMember.id, AccessLevel.Developer);
await Promise.all(
stappsMembers.map(async stappsMember => {
if (!memberIds.has(stappsMember.id)) {
await api.addMember(MembershipScope.GROUPS, groupId, stappsMember.id, AccessLevel.Developer);
Logger.log(`Added '${stappsMember.name}' to group '${groupIdsToSchool[groupId]}'.`);
}
});
Logger.log(`Added '${stappsMember.name}' to group '${groupIdsToSchool[groupId]}'.`);
}
}),
);
await asyncPool(CONCURRENCY, members, async member => {
if (!stappsMemberIds.has(member.id)) {
await api.deleteMember(MembershipScope.GROUPS, groupId, member.id);
await Promise.all(
members.map(async member => {
if (!stappsMemberIds.has(member.id)) {
await api.deleteMember(MembershipScope.GROUPS, groupId, member.id);
Logger.log(`Deleted member '${member.name}' from group '${groupIdsToSchool[groupId]}'.`);
}
});
});
Logger.log(`Deleted member '${member.name}' from group '${groupIdsToSchool[groupId]}'.`);
}
}),
);
}),
);
Logger.ok(`Tidied 'sub' group members.`);
}
@@ -338,15 +362,14 @@ export async function tidySubGroupMembers(api: Api): Promise<void> {
*/
export async function tidyIssuesWithoutAssignee(api: Api): Promise<void> {
// fetch issues without milestone from all groups
const issueResults = await asyncPool(CONCURRENCY, GROUPS, async groupId => {
return api.getIssues({
groupId: groupId,
state: IssueState.OPENED,
});
});
// flatten structure, e.g. put all issues in one array
const issues = flatten2dArray(issueResults);
const issues = await Promise.all(
GROUPS.map(async groupId => {
return api.getIssues({
groupId: groupId,
state: IssueState.OPENED,
});
}),
).then(it => it.flat());
const issuesWithoutAssignee = issues.filter(issue => {
return issue.assignee === null;
@@ -354,18 +377,20 @@ export async function tidyIssuesWithoutAssignee(api: Api): Promise<void> {
Logger.info(`Found '${issuesWithoutAssignee.length}' issue(s) without assignee.`);
await asyncPool(CONCURRENCY, issuesWithoutAssignee, async issue => {
await api.setAssigneeForIssue(issue, issue.author.id);
await Promise.all(
issuesWithoutAssignee.map(async issue => {
await api.setAssigneeForIssue(issue, issue.author.id);
Logger.log(`Set assignee for '${issue.title}' to '${issue.author.name}'.`);
Logger.log(`Set assignee for '${issue.title}' to '${issue.author.name}'.`);
await api.createNote(
issue.project_id,
Scope.ISSUES,
issue.iid,
`${NOTE_PREFIX} Assignee was set automatically to author.`,
);
});
await api.createNote(
issue.project_id,
Scope.ISSUES,
issue.iid,
`${NOTE_PREFIX} Assignee was set automatically to author.`,
);
}),
);
Logger.ok('Tidied issues without assignee.');
}
@@ -378,12 +403,11 @@ export async function tidyIssuesWithoutAssignee(api: Api): Promise<void> {
* @param api GitLab API instance to use for the requests
*/
export async function tidyMergeRequestsWithoutAssignee(api: Api): Promise<void> {
const mergeRequestResults = await asyncPool(CONCURRENCY, GROUPS, async groupId => {
return api.getMergeRequests(MembershipScope.GROUPS, groupId, MergeRequestState.OPENED);
});
// flatten structure, e.g. put all issues in one array
const mergeRequests = flatten2dArray(mergeRequestResults);
const mergeRequests = await Promise.all(
GROUPS.map(async groupId => {
return api.getMergeRequests(MembershipScope.GROUPS, groupId, MergeRequestState.OPENED);
}),
).then(it => it.flat());
const mergeRequestsWithoutAssignee = mergeRequests.filter(mergeRequest => {
return mergeRequest.assignee === null;
@@ -391,18 +415,20 @@ export async function tidyMergeRequestsWithoutAssignee(api: Api): Promise<void>
Logger.info(`Found '${mergeRequestsWithoutAssignee.length}' merge requests without assignee.`);
await asyncPool(CONCURRENCY, mergeRequestsWithoutAssignee, async mergeRequest => {
await api.setAssigneeForMergeRequest(mergeRequest, mergeRequest.author.id);
await Promise.all(
mergeRequestsWithoutAssignee.map(async mergeRequest => {
await api.setAssigneeForMergeRequest(mergeRequest, mergeRequest.author.id);
Logger.log(`Set assignee for '${mergeRequest.title}' to '${mergeRequest.author.name}'.`);
Logger.log(`Set assignee for '${mergeRequest.title}' to '${mergeRequest.author.name}'.`);
await api.createNote(
mergeRequest.project_id,
Scope.MERGE_REQUESTS,
mergeRequest.iid,
`${NOTE_PREFIX} Assignee was set automatically to author.`,
);
});
await api.createNote(
mergeRequest.project_id,
Scope.MERGE_REQUESTS,
mergeRequest.iid,
`${NOTE_PREFIX} Assignee was set automatically to author.`,
);
}),
);
Logger.ok('Tidied merge requests without assignee.');
}
@@ -12,13 +12,11 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {asyncPool} from '@krlwlfrt/async-pool';
import {Api} from '@openstapps/gitlab-api';
import {IssueState, Scope} from '@openstapps/gitlab-api/lib/types';
import {Logger} from '@openstapps/logger';
import moment from 'moment';
import {flatten2dArray} from '../common';
import {CONCURRENCY, GROUPS, LAST_MEETING, NOTE_PREFIX} from '../configuration';
import {GROUPS, LAST_MEETING, NOTE_PREFIX} from '../configuration';
import isBefore from 'date-fns/isBefore';
/**
* Remove label `meeting` from closed issues
@@ -26,34 +24,38 @@ import {CONCURRENCY, GROUPS, LAST_MEETING, NOTE_PREFIX} from '../configuration';
* @param api Instance of GitLabAPI to send requests with
*/
export async function unlabel(api: Api) {
const issueResults = await asyncPool(CONCURRENCY, GROUPS, async groupId => {
return api.getIssues({
groupId: groupId,
state: IssueState.CLOSED,
});
});
const issues = flatten2dArray(issueResults);
const issues = await Promise.all(
GROUPS.map(async groupId => {
return api.getIssues({
groupId: groupId,
state: IssueState.CLOSED,
});
}),
).then(it => it.flat());
Logger.log(`Fetched ${issues.length} closed issue(s).`);
await asyncPool(CONCURRENCY, issues, async issue => {
if (
issue.labels.includes('meeting') &&
issue.closed_at !== null &&
moment(issue.closed_at).isBefore(LAST_MEETING)
) {
Logger.info(`Issue ${issue.title} is closed before last meeting and has label "meeting". Removing it.`);
await Promise.all(
issues.map(async issue => {
if (
issue.labels.includes('meeting') &&
issue.closed_at !== null &&
isBefore(new Date(issue.closed_at), LAST_MEETING)
) {
Logger.info(
`Issue ${issue.title} is closed before last meeting and has label "meeting". Removing it.`,
);
await api.createNote(
issue.project_id,
Scope.ISSUES,
issue.iid,
`${NOTE_PREFIX} Removed label \`meeting\` automatically.
await api.createNote(
issue.project_id,
Scope.ISSUES,
issue.iid,
`${NOTE_PREFIX} Removed label \`meeting\` automatically.
/unlabel ~meeting`,
);
}
});
);
}
}),
);
Logger.ok('Label `meeting` has been removed from closed issues.');
}
File diff suppressed because it is too large Load Diff
+27 -32
View File
@@ -1,60 +1,55 @@
{
"name": "@openstapps/minimal-connector",
"version": "0.2.0",
"description": "This is a minimal connector which serves as an example",
"repository": {
"type": "git",
"url": "git@gitlab.com:openstapps/minimal-connector.git"
},
"version": "2.1.0",
"license": "GPL-3.0-only",
"repository": "git@gitlab.com:openstapps/minimal-connector.git",
"author": "Anselm Stordeur <anselmstordeur@gmail.com>",
"contributors": [
"Jovan Krunić <jovan.krunic@gmail.com>",
"Karl-Philipp Wulfert <krlwlfrt@gmail.com>",
"Rainer Killinger <git@killinger.co>",
"Michel Jonathan Schmitz <michel.schmitz1992@gmail.com>"
"Michel Jonathan Schmitz <michel.schmitz1992@gmail.com>",
"Rainer Killinger <git@killinger.co>"
],
"main": "lib/cli.js",
"types": "lib/index.d.ts",
"scripts": {
"build": "npm run tslint && npm run compile",
"build": "npm run compile",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md && git commit -m 'docs: update changelog'",
"check-configuration": "openstapps-configuration",
"compile": "rimraf lib && tsc && prepend lib/cli.js '#!/usr/bin/env node\n'",
"compile": "rimraf lib && tsc",
"documentation": "typedoc --includeDeclarations --mode modules --out docs --readme README.md --listInvalidSymbolLinks src",
"lint": "tslint -p tsconfig.json -c tslint.json 'src/**/*.ts'",
"postversion": "npm run changelog",
"prepublishOnly": "npm ci && npm run build",
"preversion": "npm run prepublishOnly",
"push": "git push && git push origin \"v$npm_package_version\"",
"test": "nyc mocha --require ts-node/register --require source-map-support/register --recursive 'test/*.spec.ts'",
"tslint": "tslint -p tsconfig.json -c tslint.json 'src/**/*.ts'"
"test": "nyc mocha --require ts-node/register --require source-map-support/register --recursive 'test/*.spec.ts'"
},
"dependencies": {
"@openstapps/api": "0.28.0",
"@openstapps/core": "0.46.0",
"@openstapps/logger": "0.7.0",
"commander": "6.2.1"
"@openstapps/api": "workspace:*",
"@openstapps/core": "workspace:*",
"@openstapps/logger": "workspace:*",
"commander": "10.0.0"
},
"devDependencies": {
"@openstapps/configuration": "0.27.0",
"@openstapps/core-tools": "0.21.0",
"@testdeck/mocha": "0.1.2",
"@types/chai": "4.2.18",
"@types/chai-as-promised": "7.1.4",
"@types/mocha": "8.2.2",
"@types/node": "14.17.1",
"chai": "4.3.4",
"@openstapps/configuration": "workspace:*",
"@openstapps/core-tools": "workspace:*",
"@testdeck/mocha": "0.3.3",
"@types/chai": "4.3.4",
"@types/chai-as-promised": "7.1.5",
"@types/mocha": "10.0.1",
"@types/node": "18.15.3",
"chai": "4.3.7",
"chai-as-promised": "7.1.1",
"conventional-changelog-cli": "2.1.1",
"mocha": "8.4.0",
"nock": "13.1.0",
"conventional-changelog-cli": "2.2.2",
"mocha": "10.2.0",
"nock": "13.3.0",
"nyc": "15.1.0",
"prepend-file-cli": "1.0.6",
"rimraf": "3.0.2",
"ts-node": "9.1.1",
"tslint": "6.1.3",
"typedoc": "0.18.0",
"typescript": "3.8.3"
"rimraf": "4.4.0",
"ts-node": "10.9.1",
"typedoc": "0.22.18",
"typescript": "4.4.4"
},
"nyc": {
"all": true,
+2
View File
@@ -1,3 +1,5 @@
#!/usr/bin/env node
/*
* Copyright (C) 2018, 2019 StApps
* This program is free software: you can redistribute it and/or modify it
+1 -1
View File
@@ -49,7 +49,7 @@ export abstract class Connector<T extends SCThings> {
*
* Implementation according to your schools requirements
*/
protected abstract async fetchItems(): Promise<T[]>;
protected abstract fetchItems(): Promise<T[]>;
/**
* Creates a remote origin with the current date-time
@@ -53,6 +53,7 @@ export class MinimalConnector extends Connector<SCMessage> {
const importedItems: SCMessage[] = [
{
audiences: ['students', 'employees'],
categories: [],
description: 'Some description 1',
messageBody: 'Some message 1',
name: 'Some name 1',
@@ -62,6 +63,7 @@ export class MinimalConnector extends Connector<SCMessage> {
},
{
audiences: ['students', 'employees'],
categories: [],
description: 'Some description 2',
messageBody: 'Some message 2',
name: 'Some name 2',
@@ -71,6 +73,7 @@ export class MinimalConnector extends Connector<SCMessage> {
},
{
audiences: ['students', 'employees'],
categories: [],
description: 'Some description 3',
messageBody: 'Some message 3',
name: 'Some name 3',
-3
View File
@@ -1,3 +0,0 @@
{
"extends": "./node_modules/@openstapps/configuration/tslint.json"
}
File diff suppressed because it is too large Load Diff
+22 -24
View File
@@ -1,44 +1,42 @@
{
"name": "@openstapps/minimal-plugin",
"version": "0.0.1",
"description": "Minimal Plugin",
"version": "2.1.0",
"license": "GPL-3.0-only",
"author": "Wieland Schöbl",
"author": "Thea Schöbl",
"contributors": [
"Jovan Krunić <jovan.krunic@gmail.com>",
"Rainer Killinger <mail-openstapps@killinger.co>"
],
"scripts": {
"build": "npm run tslint && npm run compile",
"compile": "rimraf lib && tsc && prepend lib/cli.js '#!/usr/bin/env node\n'",
"build": "npm run compile",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md && git commit -m 'docs: update changelog'",
"check-configuration": "openstapps-configuration",
"compile": "rimraf lib && tsc",
"documentation": "typedoc --includeVersion --out docs src",
"start": "node lib/cli.js",
"tslint": "tslint -p tsconfig.json -c tslint.json 'src/**/*.ts'",
"prepublishOnly": "npm ci && npm run build",
"lint": "tslint -p tsconfig.json -c tslint.json 'src/**/*.ts'",
"postversion": "npm run changelog",
"prepublishOnly": "npm ci && npm run build",
"preversion": "npm run prepublishOnly",
"push": "git push && git push origin \"v$npm_package_version\""
"push": "git push && git push origin \"v$npm_package_version\"",
"start": "node lib/cli.js"
},
"dependencies": {
"@openstapps/api": "0.33.0",
"@openstapps/core": "0.52.0",
"@openstapps/core-tools": "0.25.0",
"@openstapps/logger": "0.7.0",
"commander": "8.2.0",
"express": "4.17.1",
"ts-node": "10.2.1"
"@openstapps/api": "workspace:*",
"@openstapps/core": "workspace:*",
"@openstapps/core-tools": "workspace:*",
"@openstapps/logger": "workspace:*",
"commander": "10.0.0",
"express": "4.18.2",
"ts-node": "10.9.1"
},
"devDependencies": {
"@openstapps/configuration": "0.28.1",
"@types/express": "4.17.13",
"@types/node": "14.17.12",
"conventional-changelog-cli": "2.1.1",
"prepend-file-cli": "1.0.6",
"rimraf": "3.0.2",
"tslint": "6.1.3",
"typedoc": "0.22.4",
"typescript": "4.4.3"
"@openstapps/configuration": "workspace:*",
"@types/express": "4.17.16",
"@types/node": "18.15.3",
"conventional-changelog-cli": "2.2.2",
"rimraf": "4.4.0",
"typedoc": "0.22.18",
"typescript": "4.4.4"
}
}
+2
View File
@@ -1,3 +1,5 @@
#!/usr/bin/env node
/*
* Copyright (C) 2019-2021 StApps
* This program is free software: you can redistribute it and/or modify it
@@ -1,3 +1,3 @@
{
"extends": "./node_modules/@openstapps/configuration/tsconfig.json"
"extends": "../../../node_modules/@openstapps/configuration/tsconfig.json"
}
-18376
View File
File diff suppressed because it is too large Load Diff
+24 -25
View File
@@ -1,7 +1,7 @@
{
"name": "@openstapps/app",
"version": "2.1.1",
"description": "The generic app tailored to fulfill needs of German universities, written using Ionic Framework.",
"version": "2.1.0",
"license": "GPL-3.0-only",
"author": "Karl-Philipp Wulfert <krlwlfrt@gmail.com>",
"contributors": [
@@ -21,6 +21,7 @@
"build:stats": "ng build --configuration=production --stats-json",
"changelog": "conventional-changelog -p angular -i src/assets/about/CHANGELOG.md -s -r 0",
"check-configuration": "openstapps-configuration",
"check-icons": "ts-node scripts/check-icon-correctness.ts",
"cypress:open": "cypress open",
"cypress:run": "cypress run",
"docker:build": "sudo docker run -p 8100:8100 -p 35729:35729 -p 53703:53703 -v $PWD:/app -it registry.gitlab.com/openstapps/app bash -c \"npm install && npm run build\"",
@@ -31,16 +32,14 @@
"docker:serve": "sudo docker run -p 8100:8100 -p 35729:35729 -p 53703:53703 -v $PWD:/app -it registry.gitlab.com/openstapps/app bash -c \"npm run start:external\"",
"documentation": "compodoc -p tsconfig.json -d docs",
"e2e": "ng e2e",
"licenses": "license-checker --json > src/assets/about/licenses.json && ts-node ./scripts/accumulate-licenses.ts",
"minify-icons": "ts-node scripts/minify-icon-font.ts",
"check-icons": "ts-node scripts/check-icon-correctness.ts",
"format:check": "prettier --check .",
"format:fix": "prettier --write .",
"licenses": "license-checker --json > src/assets/about/licenses.json && ts-node ./scripts/accumulate-licenses.ts && git add src/assets/about/licenses.json",
"lint": "ng lint",
"lint:fix": "eslint --fix -c .eslintrc.json --ignore-path .eslintignore --ext .ts,.html src/",
"minify-icons": "ts-node scripts/minify-icon-font.ts",
"ng": "ng",
"postinstall": "npx jetify",
"version": "npm run changelog && npm run licenses && npm run format:fix && git add src/assets/about/CHANGELOG.md && git add src/assets/about/licenses.json",
"prepublishOnly": "npm ci && npm run build && npm run lint && npm run format:check",
"preversion": "npm run prepublishOnly",
"push": "git push && git push origin \"v$npm_package_version\"",
@@ -50,7 +49,8 @@
"start": "ionic serve",
"start:external": "ionic serve --external",
"start:prod": "ionic serve -- --configuration=production",
"test": "ng test"
"test": "ng test",
"version": "npm run changelog && npm run licenses && npm run format:fix"
},
"dependencies": {
"@angular/animations": "13.3.11",
@@ -83,16 +83,18 @@
"@hugotomazi/capacitor-navigation-bar": "2.0.0",
"@ionic-native/core": "5.36.0",
"@ionic/angular": "6.3.9",
"@ionic/core": "6.6.1",
"@ionic/storage-angular": "3.0.6",
"@ngx-translate/core": "14.0.0",
"@ngx-translate/http-loader": "7.0.0",
"@openstapps/api": "1.0.1",
"@openstapps/configuration": "0.34.0",
"@openstapps/core": "1.0.1",
"@openid/appauth": "1.3.1",
"@openstapps/api": "workspace:*",
"@openstapps/configuration": "workspace:*",
"@openstapps/core": "workspace:*",
"@transistorsoft/capacitor-background-fetch": "1.0.2",
"capacitor-secure-storage-plugin": "0.8.1",
"cordova-plugin-calendar": "5.1.6",
"deepmerge": "4.2.2",
"deepmerge": "4.3.0",
"form-data": "4.0.0",
"geojson": "0.5.0",
"ionic-appauth": "0.9.0",
@@ -131,27 +133,28 @@
"@cypress/schematic": "1.7.0",
"@ionic/angular-toolkit": "6.1.0",
"@ionic/cli": "6.20.4",
"@openstapps/prettier-config": "1.0.0",
"@openstapps/prettier-config": "workspace:*",
"@types/fontkit": "1.8.0",
"@types/glob": "7.2.0",
"@types/geojson": "1.0.6",
"@types/glob": "8.0.1",
"@types/jasmine": "4.3.1",
"@types/jasminewd2": "2.0.10",
"@types/jsonpath": "0.2.0",
"@types/leaflet": "1.9.0",
"@types/leaflet.markercluster": "1.5.1",
"@types/node": "14.18.24",
"@typescript-eslint/eslint-plugin": "5.45.1",
"@typescript-eslint/parser": "5.45.1",
"@types/node": "18.15.3",
"@typescript-eslint/eslint-plugin": "5.49.0",
"@typescript-eslint/parser": "5.49.0",
"conventional-changelog-cli": "2.2.2",
"cordova-res": "0.15.4",
"cypress": "12.0.1",
"eslint": "8.29.0",
"eslint-config-prettier": "8.5.0",
"eslint-plugin-jsdoc": "39.6.4",
"eslint": "8.33.0",
"eslint-config-prettier": "8.6.0",
"eslint-plugin-jsdoc": "39.7.4",
"eslint-plugin-prettier": "4.2.1",
"eslint-plugin-unicorn": "43.0.2",
"eslint-plugin-unicorn": "45.0.2",
"fontkit": "2.0.2",
"glob": "8.0.3",
"glob": "8.1.0",
"is-docker": "2.2.1",
"jasmine-core": "4.5.0",
"jasmine-spec-reporter": "7.0.0",
@@ -163,17 +166,13 @@
"karma-jasmine-html-reporter": "2.0.0",
"karma-mocha-reporter": "2.2.5",
"license-checker": "25.0.1",
"prettier": "2.7.1",
"prettier": "2.8.3",
"protractor": "7.0.0",
"surge": "0.23.1",
"ts-node": "10.9.1",
"typescript": "4.4.4",
"webpack-bundle-analyzer": "4.7.0"
},
"engines": {
"node": "^14.20.0",
"npm": "^6.14.17"
},
"cordova": {
"plugins": {},
"platforms": [
+1 -1
View File
@@ -130,7 +130,7 @@ export class AppComponent implements AfterContentInit {
}
private async showMessage(message?: string) {
if (typeof message === 'undefined') {
if (message === undefined) {
return;
}
const toast = await this.toastController.create({
@@ -58,12 +58,14 @@ export class AuthHelperService {
public getAuthMessage(provider: SCAuthorizationProviderType, action: IAuthAction | IPAIAAuthAction) {
let message: string | undefined;
switch (action.action) {
case AuthActions.SignInSuccess:
case AuthActions.SignInSuccess: {
message = this.translateService.instant(`auth.messages.${provider}.logged_in_success`);
break;
case AuthActions.SignOutSuccess:
}
case AuthActions.SignOutSuccess: {
message = this.translateService.instant(`auth.messages.${provider}.logged_out_success`);
break;
}
}
return message;
}
@@ -166,10 +166,10 @@ export abstract class AuthService implements IAuthService {
});
}
if (this._configuration != undefined) {
return Promise.resolve(this._configuration);
} else {
if (this._configuration == undefined) {
throw new Error('Unable To Obtain Server Configuration');
} else {
return Promise.resolve(this._configuration);
}
}
@@ -186,36 +186,43 @@ export abstract class AuthService implements IAuthService {
case AuthActions.RefreshFailed:
case AuthActions.SignInFailed:
case AuthActions.SignOutSuccess:
case AuthActions.SignOutFailed:
case AuthActions.SignOutFailed: {
this._tokenSubject.next(undefined);
this._userSubject.next(undefined);
this._authenticatedSubject.next(false);
break;
case AuthActions.LoadTokenFromStorageFailed:
}
case AuthActions.LoadTokenFromStorageFailed: {
this._tokenSubject.next(undefined);
this._userSubject.next(undefined);
this._authenticatedSubject.next(false);
this._initComplete.next(true);
break;
}
case AuthActions.SignInSuccess:
case AuthActions.RefreshSuccess:
case AuthActions.RefreshSuccess: {
this._tokenSubject.next(action.tokenResponse);
this._authenticatedSubject.next(true);
break;
case AuthActions.LoadTokenFromStorageSuccess:
}
case AuthActions.LoadTokenFromStorageSuccess: {
this._tokenSubject.next(action.tokenResponse);
this._authenticatedSubject.next((action.tokenResponse as TokenResponse).isValid(0));
this._initComplete.next(true);
break;
case AuthActions.RevokeTokensSuccess:
}
case AuthActions.RevokeTokensSuccess: {
this._tokenSubject.next(undefined);
break;
case AuthActions.LoadUserInfoSuccess:
}
case AuthActions.LoadUserInfoSuccess: {
this._userSubject.next(action.user);
break;
case AuthActions.LoadUserInfoFailed:
}
case AuthActions.LoadUserInfoFailed: {
this._userSubject.next(undefined);
break;
}
}
this._authSubjectV2.next(action);
@@ -240,10 +247,10 @@ export abstract class AuthService implements IAuthService {
if (response != undefined) {
this.requestAccessToken(response.code, codeVerifier);
} else if (error != undefined) {
throw new Error(error.errorDescription);
} else {
} else if (error == undefined) {
throw new Error('Unknown Error With Authentication');
} else {
throw new Error(error.errorDescription);
}
}
@@ -260,7 +267,10 @@ export abstract class AuthService implements IAuthService {
}
protected async performEndSessionRequest(state?: string): Promise<void> {
if (this._tokenSubject.value != undefined) {
if (this._tokenSubject.value == undefined) {
//if user has no token they should not be logged in in the first place
this.endSessionCallback();
} else {
const requestJson: EndSessionRequestJson = {
postLogoutRedirectURI: this.authConfig.end_session_redirect_url,
idTokenHint: this._tokenSubject.value.idToken || '',
@@ -277,9 +287,6 @@ export abstract class AuthService implements IAuthService {
if (returnedUrl != undefined) {
this.endSessionCallback();
}
} else {
//if user has no token they should not be logged in in the first place
this.endSessionCallback();
}
}
@@ -460,13 +467,13 @@ export abstract class AuthService implements IAuthService {
public async getValidToken(buffer: number = AUTH_EXPIRY_BUFFER): Promise<TokenResponse> {
if (this._tokenSubject.value) {
if (!this._tokenSubject.value.isValid(buffer)) {
if (this._tokenSubject.value.isValid(buffer)) {
return this._tokenSubject.value;
} else {
await this.refreshToken();
if (this._tokenSubject.value) {
return this._tokenSubject.value;
}
} else {
return this._tokenSubject.value;
}
}
@@ -28,14 +28,18 @@ export class CapacitorRequestor extends Requestor {
if (!settings.method) settings.method = 'GET';
switch (settings.method) {
case 'GET':
case 'GET': {
return this.get(settings.url, settings.headers);
case 'POST':
}
case 'POST': {
return this.post(settings.url, settings.data, settings.headers);
case 'PUT':
}
case 'PUT': {
return this.put(settings.url, settings.data, settings.headers);
case 'DELETE':
}
case 'DELETE': {
return this.delete(settings.url, settings.headers);
}
}
}
@@ -33,26 +33,30 @@ export class NgHttpService implements Requestor {
let observable: Observable<T>;
switch (settings.method) {
case 'GET':
case 'GET': {
observable = this.http.get<T>(settings.url, {
headers: this.getHeaders(settings.headers),
});
break;
case 'POST':
}
case 'POST': {
observable = this.http.post<T>(settings.url, settings.data, {
headers: this.getHeaders(settings.headers),
});
break;
case 'PUT':
}
case 'PUT': {
observable = this.http.put<T>(settings.url, settings.data, {
headers: this.getHeaders(settings.headers),
});
break;
case 'DELETE':
}
case 'DELETE': {
observable = this.http.delete<T>(settings.url, {
headers: this.getHeaders(settings.headers),
});
break;
}
}
return firstValueFrom(observable);
@@ -60,7 +60,7 @@ export class PAIAAuthorizationRequestHandler {
const returnedUrl: string | undefined = await this.browser.showWindow(url, request.redirectUri);
// callback may come from showWindow or via another method
if (typeof returnedUrl !== 'undefined') {
if (returnedUrl !== undefined) {
await this.storage.setItem(AUTHORIZATION_RESPONSE_KEY, returnedUrl);
await this.completeAuthorizationRequestIfPossible();
}
@@ -88,7 +88,7 @@ export class PAIAAuthorizationRequestHandler {
return <PAIAAuthorizationRequestResponse>{
request: request, // request
response: !error ? this.getAuthorizationResponse(queryParameters) : undefined,
response: error ? undefined : this.getAuthorizationResponse(queryParameters),
error: error ? this.getAuthorizationError(queryParameters) : undefined,
};
}
@@ -128,14 +128,14 @@ export class PAIAAuthorizationRequestHandler {
}
private getQueryParams(authResponse: string | null): StringMap {
if (authResponse != undefined) {
if (authResponse == undefined) {
return {};
} else {
const querySide: string = authResponse.split('#')[0];
const parts: string[] = querySide.split('?');
if (parts.length !== 2) throw new Error('Invalid auth response string');
const hash = parts[1];
return this.utils.parseQueryString(hash);
} else {
return {};
}
}
@@ -166,35 +166,42 @@ export class PAIAAuthService {
switch (action.action) {
case AuthActions.SignInFailed:
case AuthActions.SignOutSuccess:
case AuthActions.SignOutFailed:
case AuthActions.SignOutFailed: {
this._tokenSubject.next(undefined);
this._userSubject.next(undefined);
this._authenticatedSubject.next(false);
break;
case AuthActions.LoadTokenFromStorageFailed:
}
case AuthActions.LoadTokenFromStorageFailed: {
this._tokenSubject.next(undefined);
this._userSubject.next(undefined);
this._authenticatedSubject.next(false);
this._initComplete.next(true);
break;
case AuthActions.SignInSuccess:
}
case AuthActions.SignInSuccess: {
this._tokenSubject.next(action.tokenResponse);
this._authenticatedSubject.next(true);
break;
case AuthActions.LoadTokenFromStorageSuccess:
}
case AuthActions.LoadTokenFromStorageSuccess: {
this._tokenSubject.next(action.tokenResponse);
this._authenticatedSubject.next((action.tokenResponse as TokenResponse).isValid(0));
this._initComplete.next(true);
break;
case AuthActions.RevokeTokensSuccess:
}
case AuthActions.RevokeTokensSuccess: {
this._tokenSubject.next(undefined);
break;
case AuthActions.LoadUserInfoSuccess:
}
case AuthActions.LoadUserInfoSuccess: {
this._userSubject.next(action.user);
break;
case AuthActions.LoadUserInfoFailed:
}
case AuthActions.LoadUserInfoFailed: {
this._userSubject.next(undefined);
break;
}
}
this._authSubjectV2.next(action);
@@ -219,10 +226,10 @@ export class PAIAAuthService {
if (response != undefined) {
this.requestAccessToken(response.code, response.patron, codeVerifier);
} else if (error != undefined) {
throw new Error(error.errorDescription);
} else {
} else if (error == undefined) {
throw new Error('Unknown Error With Authentication');
} else {
throw new Error(error.errorDescription);
}
}
@@ -93,7 +93,11 @@ export class ScheduleSyncService implements OnDestroy {
},
);
if (status !== BackgroundFetch.STATUS_AVAILABLE) {
if (status === BackgroundFetch.STATUS_AVAILABLE) {
console.info('Starting background fetch.');
await BackgroundFetch.start();
} else {
if (status === BackgroundFetch.STATUS_DENIED) {
console.error(
'The user explicitly disabled background behavior for this app or for the whole system.',
@@ -101,10 +105,6 @@ export class ScheduleSyncService implements OnDestroy {
} else if (status === BackgroundFetch.STATUS_RESTRICTED) {
console.error('Background updates are unavailable and the user cannot enable them again.');
}
} else {
console.info('Starting background fetch.');
await BackgroundFetch.start();
}
}
}
@@ -94,7 +94,7 @@ export class ConfigProvider {
* @param attribute requested attribute from app configuration
*/
public getValue(attribute: keyof SCAppConfiguration) {
if (typeof this.config.app[attribute] !== 'undefined') {
if (this.config.app[attribute] !== undefined) {
return this.config.app[attribute];
}
throw new ConfigValueNotAvailable(attribute);
@@ -106,7 +106,7 @@ export class ConfigProvider {
* @param attribute requested attribute from the configuration
*/
public getAnyValue(attribute: keyof SCIndexResponse) {
if (typeof this.config[attribute] !== 'undefined') {
if (this.config[attribute] !== undefined) {
return this.config[attribute];
}
throw new ConfigValueNotAvailable(attribute);
@@ -141,13 +141,13 @@ export class ConfigProvider {
fetchError = error;
}
// check for occurred errors and throw them
if (typeof loadError !== 'undefined' && typeof fetchError !== 'undefined') {
if (loadError !== undefined && fetchError !== undefined) {
throw new ConfigInitError();
}
if (typeof loadError !== 'undefined') {
if (loadError !== undefined) {
this.logger.warn(loadError);
}
if (typeof fetchError !== 'undefined') {
if (fetchError !== undefined) {
this.logger.warn(fetchError);
}
}
@@ -67,7 +67,7 @@ export class DashboardProvider {
from: from,
};
if (typeof filters !== 'undefined') {
if (filters !== undefined) {
for (const filter of filters) {
((query.filter as SCSearchBooleanFilter).arguments as SCBooleanFilterArguments).filters.push(filter);
}
@@ -189,15 +189,18 @@ export class AddEventActionChipComponent implements OnDestroy {
return;
}
switch (associatedDateSeries.map(it => it.uid).filter(it => !this.uuids.includes(it)).length) {
case 0:
case 0: {
this.applyState(AddEventStates.ADDED_ALL);
break;
case associatedDateSeries.length:
}
case associatedDateSeries.length: {
this.applyState(AddEventStates.REMOVED_ALL);
break;
default:
}
default: {
this.applyState(AddEventStates.ADDED_SOME);
break;
}
}
});
}
@@ -34,11 +34,7 @@ export class DataFacetsProvider {
// eslint-disable-next-line class-methods-use-this
addBuckets(bucketsMap: {[key: string]: number}, fields: string[]): {[key: string]: number} {
for (const field of fields) {
if (typeof bucketsMap[field] !== 'undefined') {
bucketsMap[field] = bucketsMap[field] + 1;
} else {
bucketsMap[field] = 1;
}
bucketsMap[field] = bucketsMap[field] === undefined ? 1 : bucketsMap[field] + 1;
}
return bucketsMap;
@@ -82,13 +78,13 @@ export class DataFacetsProvider {
for (const item of items) {
for (const aggregation of aggregations) {
let fieldValues = item[aggregation.fieldName as keyof SCThing] as string | string[] | undefined;
if (typeof fieldValues === 'undefined') {
if (fieldValues === undefined) {
continue;
}
if (typeof fieldValues === 'string') {
fieldValues = [fieldValues];
}
if (typeof aggregation.onlyOnTypes === 'undefined') {
if (aggregation.onlyOnTypes === undefined) {
combinedFacetsMap[aggregation.fieldName] = this.addBuckets(
combinedFacetsMap[aggregation.fieldName] || {},
fieldValues,
@@ -133,7 +133,7 @@ export class DataProvider {
for (const item of items) {
const value =
typeof bucketMap.get(item.type) === 'undefined' ? 1 : (bucketMap.get(item.type) as number) + 1;
bucketMap.get(item.type) === undefined ? 1 : (bucketMap.get(item.type) as number) + 1;
bucketMap.set(item.type, value);
}
@@ -169,7 +169,7 @@ export class DataProvider {
created: new Date().toISOString(),
type: SCThingOriginType.User,
},
type: typeof type === 'undefined' ? item.type : type,
type: type === undefined ? item.type : type,
uid: item.uid,
};
}
@@ -81,7 +81,7 @@ export class DataDetailComponent implements ViewWillEnter {
* Type guard for SCSavableThing
*/
static isSCSavableThing(thing: SCThings | SCSaveableThing): thing is SCSaveableThing {
return typeof (thing as SCSaveableThing).data !== 'undefined';
return (thing as SCSaveableThing).data !== undefined;
}
/**
@@ -126,12 +126,13 @@ export class DataDetailComponent implements ViewWillEnter {
)
: this.dataProvider.get(uid, DataScope.Remote)));
this.item = !item
this.item = item
? // eslint-disable-next-line unicorn/no-null
null
: DataDetailComponent.isSCSavableThing(item)
DataDetailComponent.isSCSavableThing(item)
? item.data
: item;
: item
// eslint-disable-next-line unicorn/no-null
: null;
} catch {
// eslint-disable-next-line unicorn/no-null
this.item = null;
@@ -150,7 +151,7 @@ export class DataDetailComponent implements ViewWillEnter {
.get(uid)
.pipe(take(1))
.subscribe(item => {
if (typeof item !== 'undefined') {
if (item !== undefined) {
this.item = item.data;
}
});
@@ -41,7 +41,7 @@ export class FavoriteButtonComponent {
this._item = item;
this.isFavorite$ = this.favoritesService.get(this.item.uid).pipe(
map(favorite => {
return typeof favorite !== 'undefined';
return favorite !== undefined;
}),
);
}
@@ -60,7 +60,7 @@ export class TitleCardComponent implements OnInit, OnChanges {
@HostListener('window:resize', ['$event'])
checkTextElipsis() {
if (typeof this.accordionTextArea === 'undefined') {
if (this.accordionTextArea === undefined) {
return;
}
const element = this.accordionTextArea.nativeElement as HTMLElement;
@@ -106,7 +106,7 @@ export class DataListComponent implements OnChanges, OnInit, OnDestroy {
}
ngOnChanges(changes: SimpleChanges): void {
if (Array.isArray(this.items) && typeof changes.items !== 'undefined') {
if (Array.isArray(this.items) && changes.items !== undefined) {
this.itemStream.next(this.items);
this.infiniteScroll.complete();
}
@@ -120,7 +120,7 @@ export class DataListComponent implements OnChanges, OnInit, OnDestroy {
ngOnInit(): void {
this.calcSkeletonItems();
if (typeof this.resetToTop !== 'undefined') {
if (this.resetToTop !== undefined) {
this.subscriptions.push(
this.resetToTop.subscribe(() => {
// this.viewPort.scrollToIndex(0);
@@ -90,10 +90,10 @@ export class ScThingListItemVirtualScrollStrategy implements VirtualScrollStrate
for (const node of renderedItems) {
const [item, group] = this.getItemByNode(node, renderedItems);
if (!this.heights.has(item)) {
this.intersectionObserver.observe(node);
} else {
if (this.heights.has(item)) {
node.style.height = `${this.getHeight(item, group)}px`;
} else {
this.intersectionObserver.observe(node);
}
}
});
@@ -202,7 +202,7 @@ export class SearchPageComponent implements OnInit, OnDestroy {
}
for (const filter of [this.forcedFilter, this.filterQuery]) {
if (typeof filter !== 'undefined') {
if (filter !== undefined) {
filters.push(filter);
}
}
@@ -324,7 +324,7 @@ export class SearchPageComponent implements OnInit, OnDestroy {
this.filterQuery = query[1];
this.sortQuery = query[2];
this.from = 0;
if (typeof this.filterQuery !== 'undefined' || this.queryText?.length > 0 || this.showDefaultData) {
if (this.filterQuery !== undefined || this.queryText?.length > 0 || this.showDefaultData) {
await this.fetchAndUpdateItems();
this.queryChanged.next();
}
@@ -50,7 +50,7 @@ export class PlaceDetailContentComponent implements OnInit, OnDestroy {
* @param item TODO
*/
hasCategories(item: SCThings): item is SCThings & {categories: string[]} {
return typeof (item as {categories: string[]}).categories !== 'undefined';
return (item as {categories: string[]}).categories !== undefined;
}
/**
@@ -92,7 +92,7 @@ export class FavoritesPageComponent extends SearchPageComponent implements OnIni
this.filterQuery = query[1];
this.sortQuery = query[2];
this.from = 0;
if (typeof this.filterQuery !== 'undefined' || this.queryText?.length > 0 || this.showDefaultData) {
if (this.filterQuery !== undefined || this.queryText?.length > 0 || this.showDefaultData) {
await this.fetchAndUpdateItems();
this.queryChanged.next();
}
@@ -187,7 +187,7 @@ export class FavoritesService {
return this.favoritesChanged$.pipe(
map(favoritesMap => {
let items = [...favoritesMap.values()].map(favorite => favorite.data);
if (typeof queryText !== 'undefined') {
if (queryText !== undefined) {
const textFilteredItems: SCIndexableThings[] = [];
for (const item of items) {
if (
@@ -199,7 +199,7 @@ export class FavoritesService {
items = textFilteredItems;
}
if (typeof filterQuery !== 'undefined') {
if (filterQuery !== undefined) {
const filterType = FavoritesService.getFilterType(
filterQuery as SCSearchBooleanFilter | SCSearchValueFilter,
);
@@ -212,7 +212,7 @@ export class FavoritesService {
items = filteredItems;
}
if (typeof sortQuery !== 'undefined') {
if (sortQuery !== undefined) {
items = this.sortItems(items, sortQuery[0].arguments.field as 'name' | 'type', sortQuery[0].order);
}
@@ -74,7 +74,7 @@ export class DaiaAvailabilityComponent extends DataDetailComponent implements On
*/
async getAvailability(uid: SCUuid) {
this.daiaDataProvider.getAvailability(uid).then(holdings => {
if (typeof holdings !== 'undefined') {
if (holdings !== undefined) {
this.holdings = holdings;
this.holdingsByDepartments = groupByStable(holdings, holding => holding.department.id);
}
@@ -66,7 +66,7 @@ export class DaiaDataProvider {
}
async getAvailability(id: string): Promise<DaiaHolding[] | undefined> {
if (typeof this.daiaServiceUrl === 'undefined') {
if (this.daiaServiceUrl === undefined) {
try {
const features = this.configProvider.getValue('features') as SCFeatureConfiguration;
if (features.extern?.daia?.url) {
@@ -134,7 +134,7 @@ export class DaiaDataProvider {
dueDate: dueDate,
online:
Array.isArray(available) &&
typeof available.find(item => item.service === 'remote') !== 'undefined',
available.find(item => item.service === 'remote') !== undefined,
available:
(Array.isArray(available) &&
available.find(item =>
@@ -171,7 +171,7 @@ export class DaiaDataProvider {
}
getHoldingLink(holding: DaiaHolding, open = false) {
if (typeof this.hebisProxyUrl === 'undefined') {
if (this.hebisProxyUrl === undefined) {
this.logger.error('HeBIS proxy url undefined');
return;
@@ -194,7 +194,7 @@ export class DaiaDataProvider {
unavailable: unavailable.findIndex(item => item.service === 'presentation'),
};
if (loan.unavailable !== -1 && typeof unavailable[loan.unavailable].expected !== 'undefined') {
if (loan.unavailable !== -1 && unavailable[loan.unavailable].expected !== undefined) {
return 'checked_out';
}
@@ -83,7 +83,7 @@ export class HebisDataProvider extends DataProvider {
let page: number | undefined = searchRequest.page;
if (typeof page === 'undefined') {
if (page === undefined) {
const preFlightResponse = await this.client.invokeRoute<HebisSearchResponse>(
this.hebisSearchRoute,
undefined,
@@ -122,7 +122,7 @@ export class LibraryAccountService {
}
async getDocumentFromHDS(edition: string) {
if (typeof edition === 'undefined') {
if (edition === undefined) {
return;
}
@@ -166,11 +166,13 @@ export class LibraryAccountService {
return new Promise(async resolve => {
const handleDocument = () => {
switch (documentAction.action) {
case 'cancel':
case 'cancel': {
return this.cancelReservation(documentAction.doc);
break;
case 'renew':
}
case 'renew': {
return this.renewLending(documentAction.doc);
}
}
};
const alert = await this.alertController.create({
@@ -75,8 +75,13 @@ export class MapProvider {
icon: divIcon({
className: className,
html:
typeof position.heading !== 'undefined'
position.heading === undefined
? `<span
name="${SCIcon`person_pin_circle`}"
class="material-symbols-rounded map-location-pin"
style="font-size: ${iconSize}px; color: var(--ion-color-primary);"
>${SCIcon`person_pin_circle`}</span>`
: `<span
class="material-symbols-rounded map-location-pin"
style="
transform-origin: center;
@@ -84,12 +89,7 @@ export class MapProvider {
font-size: ${iconSize}px;
color: var(--ion-color-primary);
"
>${SCIcon`navigation`}</span>`
: `<span
name="${SCIcon`person_pin_circle`}"
class="material-symbols-rounded map-location-pin"
style="font-size: ${iconSize}px; color: var(--ion-color-primary);"
>${SCIcon`person_pin_circle`}</span>`,
>${SCIcon`navigation`}</span>`,
iconSize: [iconSize, iconSize],
}),
zIndexOffset: 1000,
@@ -202,7 +202,7 @@ export class MapProvider {
let filter = baseFilter;
if (typeof contextFilter !== 'undefined') {
if (contextFilter !== undefined) {
filter = {
arguments: {
operation: 'and',
@@ -154,7 +154,7 @@ export class MapPageComponent {
* @param latLng Coordinates to animate to
*/
private focus(latLng?: LatLng) {
if (typeof latLng !== 'undefined') {
if (latLng !== undefined) {
this.map.flyTo(latLng, this.MAX_ZOOM);
return;
@@ -173,7 +173,7 @@ export class MapPageComponent {
this.removeAll();
}
const addSCPlace = (place: SCPlace): Layer | Marker => {
if (typeof place.geo.polygon !== 'undefined') {
if (place.geo.polygon !== undefined) {
const polygonLayer = geoJSON(place.geo.polygon, {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
@@ -190,7 +190,7 @@ export class MapPageComponent {
items.map(thing => {
// IMPORTANT: change this to support inPlace.geo when there is a need to show floors (the building of the floor)
if (typeof thing.geo !== 'undefined') {
if (thing.geo !== undefined) {
this.layers.push(addSCPlace(thing as SCPlace));
}
});
@@ -233,7 +233,7 @@ export class MapPageComponent {
this.items = result.data as SCPlace[];
this.addToMap(result.data as Array<SCBuilding | SCRoom>, true, animate);
// update filter options if result contains facets
if (typeof result.facets !== 'undefined') {
if (result.facets !== undefined) {
this.contextMenuService.updateContextFilter(result.facets);
}
} catch (error) {
@@ -313,9 +313,9 @@ export class MapPageComponent {
);
const uid = this.route.snapshot.paramMap.get('uid');
const response = await (uid !== null
? this.mapProvider.searchPlace(uid)
: this.mapProvider.searchPlaces());
const response = await (uid === null
? this.mapProvider.searchPlaces()
: this.mapProvider.searchPlace(uid));
if (response.data.length === 0) {
return;
@@ -345,9 +345,9 @@ export class MapPageComponent {
return;
}
this.locationStatus = await (!Capacitor.isNativePlatform()
? Geolocation.checkPermissions()
: Geolocation.requestPermissions());
this.locationStatus = await (Capacitor.isNativePlatform()
? Geolocation.requestPermissions()
: Geolocation.checkPermissions());
this.translateService
.get(['map.page.geolocation', 'app.errors.UNKNOWN'])
@@ -362,9 +362,9 @@ export class MapPageComponent {
message: `${
this.locationStatus?.location === 'denied'
? location.NOT_ALLOWED
: this.locationStatus?.location !== 'granted'
? location.NOT_ENABLED
: unknownError
: this.locationStatus?.location === 'granted'
? unknownError
: location.NOT_ENABLED
}`,
buttons: ['OK'],
})
@@ -54,7 +54,7 @@ export class MapListModalComponent implements OnInit {
*/
ngOnInit() {
let geofencedFilter: SCSearchBooleanFilter | undefined;
if (typeof this.mapBounds !== 'undefined') {
if (this.mapBounds !== undefined) {
geofencedFilter = {
arguments: {
operation: 'and',
@@ -77,7 +77,7 @@ export class MapListModalComponent implements OnInit {
},
type: 'boolean',
};
if (typeof this.filterQuery !== 'undefined') {
if (this.filterQuery !== undefined) {
geofencedFilter.arguments.filters.push(this.filterQuery);
}
}

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