Compare commits
295 Commits
update
...
formatter-
Author | SHA1 | Date | |
---|---|---|---|
![]() |
0b8e33f96d | ||
![]() |
c193f9334f | ||
![]() |
6e682dc752 | ||
![]() |
da86fe56bd | ||
![]() |
45865d701a | ||
![]() |
a66a31b474 | ||
![]() |
2661e7102f | ||
![]() |
224965b91e | ||
![]() |
a9c7375534 | ||
![]() |
e77f7ee0bf | ||
![]() |
ae5dd0cad6 | ||
![]() |
a128907a4e | ||
![]() |
d6453a8ed0 | ||
![]() |
dd1e8240b8 | ||
![]() |
b12f39916f | ||
![]() |
aae88fe1ad | ||
![]() |
83bb400df1 | ||
![]() |
8ea8067788 | ||
![]() |
9fbc9d59f5 | ||
![]() |
b96ba69a72 | ||
![]() |
c4ccab6a5d | ||
![]() |
f84f27bb56 | ||
![]() |
416cc0ffa9 | ||
![]() |
1fd5ec4db6 | ||
![]() |
4795c35c68 | ||
![]() |
25ce63b86d | ||
![]() |
5271033d34 | ||
![]() |
6ba8f33399 | ||
![]() |
7ab79bd815 | ||
![]() |
04a0a847c7 | ||
![]() |
436fa9af69 | ||
![]() |
ca0bbb0f08 | ||
![]() |
88996144a5 | ||
![]() |
44d5eee99e | ||
![]() |
0d1ff6074f | ||
![]() |
d63757634a | ||
![]() |
fd61cf3388 | ||
![]() |
a6a6b63e5a | ||
![]() |
c02c2def29 | ||
![]() |
ff66548462 | ||
![]() |
c9f292e252 | ||
![]() |
18cef5f3bd | ||
![]() |
e19340f1e0 | ||
![]() |
feb613cb6d | ||
![]() |
afa6bdfa44 | ||
![]() |
200e6d9905 | ||
![]() |
70772c49bd | ||
![]() |
762ea97e8b | ||
![]() |
8156b8b356 | ||
![]() |
3a2cbae0a0 | ||
![]() |
0ad8da097b | ||
![]() |
e2dcdd2811 | ||
![]() |
8074f9146b | ||
![]() |
df24bac913 | ||
![]() |
4d4091adcc | ||
![]() |
cac54c41a1 | ||
![]() |
130931d7af | ||
![]() |
d35b08b35e | ||
![]() |
82031da6a6 | ||
![]() |
9df5ee7b11 | ||
![]() |
2ed1a57cd9 | ||
![]() |
101450cba6 | ||
![]() |
6bab5b3f7c | ||
![]() |
ca3c0e00a7 | ||
![]() |
6d64daf324 | ||
![]() |
9ae4578e19 | ||
![]() |
e06b7ab87a | ||
![]() |
1e2adedcbf | ||
![]() |
adf763c1b0 | ||
![]() |
36ee0df256 | ||
![]() |
823d85b24a | ||
![]() |
a3b3038709 | ||
![]() |
ddeb18f626 | ||
![]() |
90cd11bd38 | ||
![]() |
e9ba37b8de | ||
![]() |
d5e4a1b1ad | ||
![]() |
129e6d60e5 | ||
![]() |
4b77f2f590 | ||
![]() |
a909966562 | ||
![]() |
fd184239d6 | ||
![]() |
52bc49dc6a | ||
![]() |
b9352ccc06 | ||
![]() |
525b2baf06 | ||
![]() |
a8edeb2459 | ||
![]() |
e3830d64e0 | ||
![]() |
91f3e2c2b4 | ||
![]() |
77b4408416 | ||
![]() |
cede96f018 | ||
![]() |
8e0a28d238 | ||
![]() |
da5d594428 | ||
![]() |
9f9ee0bb58 | ||
![]() |
163aca6179 | ||
![]() |
cb06d3b0ae | ||
![]() |
dbe18dd100 | ||
![]() |
217970667a | ||
![]() |
dace794167 | ||
![]() |
590780a539 | ||
![]() |
cbd1f47e87 | ||
![]() |
f89cff4e4a | ||
![]() |
cb08e0bf9f | ||
![]() |
3b54b29a99 | ||
![]() |
25983e046c | ||
![]() |
a6a124d2e6 | ||
![]() |
c7e1d30553 | ||
![]() |
6cc8c45634 | ||
![]() |
ee9a9114b7 | ||
![]() |
11f00f866c | ||
![]() |
03ea61ba81 | ||
![]() |
f6c500c998 | ||
![]() |
b590f0f98f | ||
![]() |
ef9359b208 | ||
![]() |
efd243a340 | ||
![]() |
bafb8b86db | ||
![]() |
84b701747f | ||
![]() |
ec42446daa | ||
![]() |
5046c4c911 | ||
![]() |
ce8c9906cb | ||
![]() |
6fb5482bba | ||
![]() |
58189963f5 | ||
![]() |
f488a71304 | ||
![]() |
4b706e004d | ||
![]() |
40e10cc270 | ||
![]() |
41db227eb3 | ||
![]() |
43eea965c5 | ||
![]() |
8101c9f0bc | ||
![]() |
b4cda90338 | ||
![]() |
7ca37c412e | ||
![]() |
e4e3356dc9 | ||
![]() |
0deaa03218 | ||
![]() |
a7104c41a2 | ||
![]() |
5176b8c322 | ||
![]() |
c37c70446d | ||
![]() |
63abc8a2c8 | ||
![]() |
ba5c038e3b | ||
![]() |
a6669415f5 | ||
![]() |
4086fad867 | ||
![]() |
8a71c13078 | ||
![]() |
5d77f64e76 | ||
![]() |
0d092b977f | ||
![]() |
69582ff83d | ||
![]() |
a5c7da331a | ||
![]() |
8e842296b7 | ||
![]() |
7db14d1df7 | ||
![]() |
067ec2eb9c | ||
![]() |
2d332b32d9 | ||
![]() |
1d9ad2ba86 | ||
![]() |
a28e2177f7 | ||
![]() |
18fe0df691 | ||
![]() |
8e21a06d99 | ||
![]() |
2daf5473bb | ||
![]() |
928ff53adf | ||
![]() |
a71e95e6e5 | ||
![]() |
cb4a54b5cc | ||
![]() |
37e4524156 | ||
![]() |
9ac24ee051 | ||
![]() |
f28ccd559a | ||
![]() |
8e84a93d8e | ||
![]() |
d871dec1b7 | ||
![]() |
b133e1a197 | ||
![]() |
9346a037b9 | ||
![]() |
89facbcddd | ||
![]() |
53fef35638 | ||
![]() |
bfe496a09b | ||
![]() |
ff774c2e8e | ||
![]() |
08a6d1078c | ||
![]() |
e9bcc919bf | ||
![]() |
04f4693c85 | ||
![]() |
2a58a0a4c4 | ||
![]() |
d911843648 | ||
![]() |
c80d178410 | ||
![]() |
9fb4dca39b | ||
![]() |
0dd444d50b | ||
![]() |
f3bf418997 | ||
![]() |
676027245f | ||
![]() |
6c5039f1ba | ||
![]() |
807be59f25 | ||
![]() |
8e9896ec2e | ||
![]() |
110c2dbac8 | ||
![]() |
f55ec4bd8a | ||
![]() |
06c9bf420e | ||
![]() |
3c9bc53a79 | ||
![]() |
de7a35dfe9 | ||
![]() |
92638c2e97 | ||
![]() |
63251e6a9a | ||
![]() |
59844c33fd | ||
![]() |
d36dd2ece1 | ||
![]() |
1fdb94739b | ||
![]() |
8a18f4c44f | ||
![]() |
c9c47c5519 | ||
![]() |
6be8b55daa | ||
![]() |
f2dc2f5530 | ||
![]() |
42842e7aec | ||
![]() |
49d9f77d1b | ||
![]() |
d06a89564f | ||
![]() |
58a8510d49 | ||
![]() |
8055d6555e | ||
![]() |
39620d3510 | ||
![]() |
6d19711926 | ||
![]() |
0b362dd435 | ||
![]() |
9485731e7d | ||
![]() |
1449fb0f84 | ||
![]() |
e548dd49ca | ||
![]() |
35863ee6e9 | ||
![]() |
0784a2d4d0 | ||
![]() |
75d5c0e356 | ||
![]() |
a2dd6d76a8 | ||
![]() |
bdc6b59857 | ||
![]() |
34e95f1e89 | ||
![]() |
6a92cfc573 | ||
![]() |
9f759d70b6 | ||
![]() |
43e957e8d3 | ||
![]() |
ae316f60e4 | ||
![]() |
1ac423ba56 | ||
![]() |
b43490dd76 | ||
![]() |
f586e81dd1 | ||
![]() |
8a6d8a7d8c | ||
![]() |
45d607f1a0 | ||
![]() |
d84abaa229 | ||
![]() |
3fd1d4d9b3 | ||
![]() |
078b8efb56 | ||
![]() |
5066995f72 | ||
![]() |
577fe3dba8 | ||
![]() |
d96f4999bc | ||
![]() |
6e80ff4eb6 | ||
![]() |
3f8f022d48 | ||
![]() |
93a2e2151e | ||
![]() |
663a1ed9d4 | ||
![]() |
4f46c55c85 | ||
![]() |
9701c98af9 | ||
![]() |
aabf2a1c79 | ||
![]() |
29539b090e | ||
![]() |
1c80677ac3 | ||
![]() |
ad419855e9 | ||
![]() |
30b75943f3 | ||
![]() |
41a67b402d | ||
![]() |
caa104b1cc | ||
![]() |
94085f2bc8 | ||
![]() |
d39c962314 | ||
![]() |
706fb0f063 | ||
![]() |
b9d89b040f | ||
![]() |
41421b849a | ||
![]() |
324375da93 | ||
![]() |
536446faf6 | ||
![]() |
d026ac09f3 | ||
![]() |
88c93ac992 | ||
![]() |
d540322d8b | ||
![]() |
ad4db5e936 | ||
![]() |
25cb4d90f3 | ||
![]() |
6c14a353ef | ||
![]() |
74d7d1aa98 | ||
![]() |
43b0d9ed29 | ||
![]() |
3572e6f65a | ||
![]() |
d23d5d2da0 | ||
![]() |
183b9b0d88 | ||
![]() |
7a1af268ae | ||
![]() |
f879b3c5b0 | ||
![]() |
40be72cf65 | ||
![]() |
a8886571d1 | ||
![]() |
1fcd51ea26 | ||
![]() |
89752138be | ||
![]() |
f29ccace2a | ||
![]() |
0c8343e76f | ||
![]() |
9776c9f5a4 | ||
![]() |
a5dbac9817 | ||
![]() |
bad5e0b855 | ||
![]() |
8e4ca55560 | ||
![]() |
f52afc1fe0 | ||
![]() |
815e64302e | ||
![]() |
07b2b18a4e | ||
![]() |
69eca33de7 | ||
![]() |
ec76a480d0 | ||
![]() |
a8823c3ed0 | ||
![]() |
1f1b3a341c | ||
![]() |
8c164a3852 | ||
![]() |
dcf526d810 | ||
![]() |
2fc6d680a0 | ||
![]() |
f414972f33 | ||
![]() |
69d192d989 | ||
![]() |
6c8769e598 | ||
![]() |
c12703422c | ||
![]() |
c0171e1cd1 | ||
![]() |
920a983146 | ||
![]() |
7ec86bfef1 | ||
![]() |
d8bc318688 | ||
![]() |
600ea1848f | ||
![]() |
a3ce9c7662 | ||
![]() |
44ce7577c6 | ||
![]() |
8c3e42f7eb | ||
![]() |
b8887c506c | ||
![]() |
6c4228b7b8 | ||
![]() |
9b1da98386 | ||
![]() |
1615169a3d | ||
![]() |
df83aa4d15 | ||
![]() |
142b96beb0 | ||
![]() |
18d07dd3b9 |
@@ -29,7 +29,6 @@ rm -rf .env
|
||||
echo "
|
||||
PORT=$WEB_PORT
|
||||
REACT_APP_GRAPHQL_URL=http://localhost:$BACKEND_PORT/graphql
|
||||
REACT_APP_NOTIFICATIONS_URL=https://notifications.automatisch.io
|
||||
" >> .env
|
||||
cd $CURRENT_DIR
|
||||
|
||||
|
@@ -33,7 +33,32 @@ services:
|
||||
- '6379:6379'
|
||||
expose:
|
||||
- 6379
|
||||
keycloak:
|
||||
image: quay.io/keycloak/keycloak:21.1
|
||||
restart: always
|
||||
container_name: keycloak
|
||||
environment:
|
||||
- KEYCLOAK_ADMIN=admin
|
||||
- KEYCLOAK_ADMIN_PASSWORD=admin
|
||||
- KC_DB=postgres
|
||||
- KC_DB_URL_HOST=postgres
|
||||
- KC_DB_URL_DATABASE=keycloak
|
||||
- KC_DB_USERNAME=automatisch_user
|
||||
- KC_DB_PASSWORD=automatisch_password
|
||||
- KC_HEALTH_ENABLED=true
|
||||
ports:
|
||||
- "8080:8080"
|
||||
command: start-dev
|
||||
depends_on:
|
||||
- postgres
|
||||
healthcheck:
|
||||
test: "curl -f http://localhost:8080/health/ready || exit 1"
|
||||
volumes:
|
||||
- keycloak:/opt/keycloak/data/
|
||||
expose:
|
||||
- 8080
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
redis_data:
|
||||
keycloak:
|
||||
|
8
.dockerignore
Normal file
8
.dockerignore
Normal file
@@ -0,0 +1,8 @@
|
||||
**/node_modules/
|
||||
**/dist/
|
||||
**/logs/
|
||||
**/.devcontainer
|
||||
**/.github
|
||||
**/.vscode
|
||||
packages/docs
|
||||
packages/e2e-test
|
8
.github/workflows/ci.yml
vendored
8
.github/workflows/ci.yml
vendored
@@ -1,5 +1,11 @@
|
||||
name: Automatisch CI
|
||||
on: [push]
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
linter:
|
||||
runs-on: ubuntu-latest
|
||||
|
88
.github/workflows/playwright.yml
vendored
Normal file
88
.github/workflows/playwright.yml
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
name: Automatisch UI Tests
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
ENCRYPTION_KEY: sample_encryption_key
|
||||
WEBHOOK_SECRET_KEY: sample_webhook_secret_key
|
||||
APP_SECRET_KEY: sample_app_secret_key
|
||||
POSTGRES_HOST: localhost
|
||||
POSTGRES_DATABASE: automatisch
|
||||
POSTGRES_PORT: 5432
|
||||
POSTGRES_USERNAME: automatisch_user
|
||||
POSTGRES_PASSWORD: automatisch_password
|
||||
REDIS_HOST: localhost
|
||||
APP_ENV: production
|
||||
LICENSE_KEY: ${{ secrets.E2E_LICENSE_KEY }}
|
||||
|
||||
jobs:
|
||||
test:
|
||||
timeout-minutes: 60
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:14.5-alpine
|
||||
env:
|
||||
POSTGRES_DB: automatisch
|
||||
POSTGRES_USER: automatisch_user
|
||||
POSTGRES_PASSWORD: automatisch_password
|
||||
options: >-
|
||||
--health-cmd "pg_isready -U automatisch_user -d automatisch"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 5432:5432
|
||||
redis:
|
||||
image: redis:7.0.4-alpine
|
||||
options: >-
|
||||
--health-cmd "redis-cli ping"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 6379:6379
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
- name: Install dependencies
|
||||
run: yarn && yarn lerna bootstrap
|
||||
- name: Install Playwright Browsers
|
||||
run: yarn playwright install --with-deps
|
||||
- name: Build Automatisch
|
||||
run: yarn lerna run --scope=@*/{web,backend,cli} build
|
||||
env:
|
||||
# Keep this until we clean up warnings in build processes
|
||||
CI: false
|
||||
- name: Migrate database
|
||||
working-directory: ./packages/backend
|
||||
run: yarn db:migrate --migrations-directory ./dist/src/db/migrations
|
||||
- name: Seed user
|
||||
working-directory: ./packages/backend
|
||||
run: yarn db:seed:user &
|
||||
- name: Run Automatisch
|
||||
run: yarn start &
|
||||
working-directory: ./packages/backend
|
||||
- name: Run Automatisch worker
|
||||
run: node dist/src/worker.js &
|
||||
working-directory: ./packages/backend
|
||||
- name: Run Playwright tests
|
||||
working-directory: ./packages/e2e-tests
|
||||
env:
|
||||
LOGIN_EMAIL: user@automatisch.io
|
||||
LOGIN_PASSWORD: sample
|
||||
BASE_URL: http://localhost:3000
|
||||
run: yarn test
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: playwright-report
|
||||
path: ./packages/e2e-tests/test-results/**/*
|
||||
retention-days: 30
|
3
.gitignore
vendored
3
.gitignore
vendored
@@ -125,3 +125,6 @@ dist
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
# MacOS finder preferences
|
||||
.DS_store
|
||||
|
1
.node-version
Normal file
1
.node-version
Normal file
@@ -0,0 +1 @@
|
||||
16.15.0
|
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -1,4 +1,7 @@
|
||||
{
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
The Automatisch Enterprise license (the “Enterprise License”)
|
||||
Copyright (c) 2023 Ömer Faruk Aydın, Ali Barın.
|
||||
Copyright (c) 2023-present AB Software GmbH.
|
||||
|
||||
With regard to the Automatisch Software:
|
||||
|
||||
|
@@ -4,7 +4,7 @@ WORKDIR /automatisch
|
||||
|
||||
RUN \
|
||||
apk --no-cache add --virtual build-dependencies python3 build-base && \
|
||||
yarn global add @automatisch/cli@0.5.0 --network-timeout 1000000 && \
|
||||
yarn global add @automatisch/cli@0.9.3 --network-timeout 1000000 && \
|
||||
rm -rf /usr/local/share/.cache/ && \
|
||||
apk del build-dependencies
|
||||
|
||||
|
19
docker/Dockerfile.cloud
Normal file
19
docker/Dockerfile.cloud
Normal file
@@ -0,0 +1,19 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM node:16-alpine
|
||||
WORKDIR /automatisch
|
||||
|
||||
ENV PORT 3000
|
||||
|
||||
RUN ls -lna
|
||||
|
||||
# copy the app, note .dockerignore
|
||||
COPY . ./
|
||||
|
||||
RUN yarn
|
||||
RUN yarn lerna bootstrap
|
||||
RUN yarn lerna run --scope=@*/{web,backend,cli} build
|
||||
|
||||
COPY ./docker/entrypoint-cloud.sh /entrypoint-cloud.sh
|
||||
|
||||
EXPOSE 3000
|
||||
ENTRYPOINT ["sh", "/entrypoint-cloud.sh"]
|
@@ -1,5 +1,5 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM automatischio/automatisch:0.5.0
|
||||
FROM automatischio/automatisch:0.9.3
|
||||
WORKDIR /automatisch
|
||||
|
||||
RUN apk add --no-cache openssl dos2unix
|
||||
|
9
docker/entrypoint-cloud.sh
Executable file
9
docker/entrypoint-cloud.sh
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
if [ -n "$WORKER" ]; then
|
||||
yarn automatisch start-worker
|
||||
else
|
||||
yarn automatisch start
|
||||
fi
|
@@ -2,7 +2,7 @@
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"version": "0.5.0",
|
||||
"version": "0.9.3",
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true,
|
||||
"command": {
|
||||
|
16
packages/backend/.env-example.test
Normal file
16
packages/backend/.env-example.test
Normal file
@@ -0,0 +1,16 @@
|
||||
APP_ENV=test
|
||||
HOST=localhost
|
||||
PROTOCOL=http
|
||||
PORT=3000
|
||||
LOG_LEVEL=debug
|
||||
WEBHOOK_SECRET_KEY=secret
|
||||
POSTGRES_DATABASE=automatisch_test
|
||||
POSTGRES_PORT=5432
|
||||
POSTGRES_HOST=localhost
|
||||
POSTGRES_USERNAME=automatisch_test_user
|
||||
POSTGRES_PASSWORD=
|
||||
POSTGRES_ENABLE_SSL=false
|
||||
ENCRYPTION_KEY=secret
|
||||
APP_SECRET_KEY=secret
|
||||
REDIS_PORT=6379
|
||||
REDIS_HOST=127.0.0.1
|
5
packages/backend/ava.config.mjs
Normal file
5
packages/backend/ava.config.mjs
Normal file
@@ -0,0 +1,5 @@
|
||||
export default {
|
||||
require: ['ts-node/register', './src/config/app.ts'],
|
||||
files: ['**/*.test.ts'],
|
||||
extensions: ['ts'],
|
||||
};
|
@@ -2,18 +2,33 @@ import appConfig from '../../src/config/app';
|
||||
import logger from '../../src/helpers/logger';
|
||||
import client from './client';
|
||||
import User from '../../src/models/user';
|
||||
import Role from '../../src/models/role';
|
||||
import '../../src/config/orm';
|
||||
|
||||
async function fetchAdminRole() {
|
||||
const role = await Role
|
||||
.query()
|
||||
.where({
|
||||
key: 'admin'
|
||||
})
|
||||
.limit(1)
|
||||
.first();
|
||||
|
||||
return role;
|
||||
}
|
||||
|
||||
export async function createUser(
|
||||
email = 'user@automatisch.io',
|
||||
password = 'sample'
|
||||
) {
|
||||
const UNIQUE_VIOLATION_CODE = '23505';
|
||||
|
||||
const role = await fetchAdminRole();
|
||||
const userParams = {
|
||||
email,
|
||||
password,
|
||||
fullName: 'Initial admin',
|
||||
role: 'admin',
|
||||
roleId: role.id,
|
||||
};
|
||||
|
||||
try {
|
||||
|
@@ -12,6 +12,8 @@ const knexConfig = {
|
||||
database: appConfig.postgresDatabase,
|
||||
ssl: appConfig.postgresEnableSsl,
|
||||
},
|
||||
asyncStackTraces: appConfig.isDev,
|
||||
searchPath: [appConfig.postgresSchema],
|
||||
pool: { min: 0, max: 20 },
|
||||
migrations: {
|
||||
directory: __dirname + '/src/db/migrations',
|
||||
|
@@ -1,15 +1,16 @@
|
||||
{
|
||||
"name": "@automatisch/backend",
|
||||
"version": "0.5.0",
|
||||
"version": "0.9.3",
|
||||
"license": "See LICENSE file",
|
||||
"description": "The open source Zapier alternative. Build workflow automation without spending time and money.",
|
||||
"scripts": {
|
||||
"dev": "ts-node-dev --exit-child src/server.ts",
|
||||
"dev": "ts-node-dev --watch 'src/graphql/schema.graphql' --exit-child src/server.ts",
|
||||
"worker": "nodemon --watch 'src/**/*.ts' --exec 'ts-node' src/worker.ts",
|
||||
"build": "tsc && yarn copy-statics",
|
||||
"build:watch": "nodemon --watch 'src/**/*.ts' --watch 'bin/**/*.ts' --exec yarn build --ext ts",
|
||||
"start": "node dist/src/server.js",
|
||||
"test": "ava",
|
||||
"pretest": "APP_ENV=test ts-node ./test/setup/prepare-test-env.ts",
|
||||
"test": "APP_ENV=test ava",
|
||||
"lint": "eslint . --ignore-path ../../.eslintignore",
|
||||
"db:create": "ts-node ./bin/database/create.ts",
|
||||
"db:seed:user": "ts-node ./bin/database/seed-user.ts",
|
||||
@@ -17,19 +18,25 @@
|
||||
"db:migration:create": "knex migrate:make",
|
||||
"db:rollback": "knex migrate:rollback",
|
||||
"db:migrate": "knex migrate:latest",
|
||||
"copy-statics": "copyfiles src/**/*.{graphql,json,svg} dist",
|
||||
"copy-statics": "copyfiles src/**/*.{graphql,json,svg,hbs} dist",
|
||||
"prepack": "yarn build",
|
||||
"prebuild": "rm -rf ./dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@automatisch/web": "^0.5.0",
|
||||
"@automatisch/web": "^0.9.3",
|
||||
"@bull-board/express": "^3.10.1",
|
||||
"@casl/ability": "^6.5.0",
|
||||
"@graphql-tools/graphql-file-loader": "^7.3.4",
|
||||
"@graphql-tools/load": "^7.5.2",
|
||||
"@node-saml/passport-saml": "^4.0.4",
|
||||
"@rudderstack/rudder-sdk-node": "^1.1.2",
|
||||
"@sentry/node": "^7.42.0",
|
||||
"@sentry/tracing": "^7.42.0",
|
||||
"@types/accounting": "^0.4.2",
|
||||
"@types/luxon": "^2.3.1",
|
||||
"@types/passport": "^1.0.12",
|
||||
"@types/xmlrpc": "^1.3.7",
|
||||
"accounting": "^0.4.1",
|
||||
"ajv-formats": "^2.1.1",
|
||||
"axios": "0.24.0",
|
||||
"bcrypt": "^5.0.1",
|
||||
@@ -49,6 +56,8 @@
|
||||
"graphql-type-json": "^0.3.2",
|
||||
"handlebars": "^4.7.7",
|
||||
"http-errors": "~1.6.3",
|
||||
"http-proxy-agent": "^7.0.0",
|
||||
"https-proxy-agent": "^7.0.1",
|
||||
"jsonwebtoken": "^9.0.0",
|
||||
"knex": "^2.4.0",
|
||||
"lodash.get": "^4.4.2",
|
||||
@@ -56,13 +65,18 @@
|
||||
"memory-cache": "^0.2.0",
|
||||
"morgan": "^1.10.0",
|
||||
"multer": "1.4.5-lts.1",
|
||||
"node-html-markdown": "^1.3.0",
|
||||
"nodemailer": "6.7.0",
|
||||
"oauth-1.0a": "^2.2.6",
|
||||
"objection": "^3.0.0",
|
||||
"passport": "^0.6.0",
|
||||
"pg": "^8.7.1",
|
||||
"php-serialize": "^4.0.2",
|
||||
"pluralize": "^8.0.0",
|
||||
"showdown": "^2.1.0",
|
||||
"stripe": "^11.13.0",
|
||||
"winston": "^3.7.1"
|
||||
"winston": "^3.7.1",
|
||||
"xmlrpc": "^1.3.2"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
@@ -100,7 +114,7 @@
|
||||
"url": "https://github.com/automatisch/automatisch/issues"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@automatisch/types": "^0.5.0",
|
||||
"@automatisch/types": "^0.9.3",
|
||||
"@types/bcrypt": "^5.0.0",
|
||||
"@types/bull": "^3.15.8",
|
||||
"@types/cors": "^2.8.12",
|
||||
@@ -116,23 +130,14 @@
|
||||
"@types/nodemailer": "^6.4.4",
|
||||
"@types/pg": "^8.6.1",
|
||||
"@types/pino": "^7.0.5",
|
||||
"ava": "^3.15.0",
|
||||
"@types/pluralize": "^0.0.30",
|
||||
"@types/showdown": "^2.0.1",
|
||||
"ava": "^5.3.1",
|
||||
"nodemon": "^2.0.13",
|
||||
"sinon": "^11.1.2",
|
||||
"ts-node": "^10.2.1",
|
||||
"ts-node-dev": "^1.1.8"
|
||||
},
|
||||
"ava": {
|
||||
"files": [
|
||||
"test/**/*"
|
||||
],
|
||||
"extensions": [
|
||||
"ts"
|
||||
],
|
||||
"require": [
|
||||
"ts-node/register"
|
||||
]
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
|
@@ -17,6 +17,7 @@ import {
|
||||
} from './helpers/create-bull-board-handler';
|
||||
import injectBullBoardHandler from './helpers/inject-bull-board-handler';
|
||||
import router from './routes';
|
||||
import configurePassport from './helpers/passport';
|
||||
|
||||
createBullBoardHandler(serverAdapter);
|
||||
|
||||
@@ -50,6 +51,9 @@ app.use(
|
||||
})
|
||||
);
|
||||
app.use(cors(corsOptions));
|
||||
|
||||
configurePassport(app);
|
||||
|
||||
app.use('/', router);
|
||||
|
||||
webUIHandler(app);
|
||||
|
@@ -2,7 +2,7 @@ import qs from 'qs';
|
||||
import defineAction from '../../../../helpers/define-action';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Translate Text',
|
||||
name: 'Translate text',
|
||||
key: 'translateText',
|
||||
description: 'Translates text from one language to another.',
|
||||
arguments: [
|
||||
@@ -20,7 +20,7 @@ export default defineAction({
|
||||
type: 'dropdown' as const,
|
||||
required: true,
|
||||
description: 'Language to translate the text to.',
|
||||
variables: false,
|
||||
variables: true,
|
||||
value: '',
|
||||
options: [
|
||||
{ label: 'Bulgarian', value: 'BG' },
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import defineAction from '../../../../helpers/define-action';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Delay For',
|
||||
name: 'Delay for',
|
||||
key: 'delayFor',
|
||||
description:
|
||||
'Delays the execution of the next action by a specified amount of time.',
|
||||
@@ -13,7 +13,7 @@ export default defineAction({
|
||||
required: true,
|
||||
value: null,
|
||||
description: 'Delay for unit, e.g. minutes, hours, days, weeks.',
|
||||
variables: false,
|
||||
variables: true,
|
||||
options: [
|
||||
{
|
||||
label: 'Minutes',
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import defineAction from '../../../../helpers/define-action';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Delay Until',
|
||||
name: 'Delay until',
|
||||
key: 'delayUntil',
|
||||
description:
|
||||
'Delays the execution of the next action until a specified date.',
|
||||
|
@@ -11,7 +11,7 @@ export default defineAction({
|
||||
type: 'dropdown' as const,
|
||||
required: true,
|
||||
description: 'Pick a channel to send the message to.',
|
||||
variables: false,
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
|
@@ -19,8 +19,8 @@ export default {
|
||||
|
||||
channels.data = response.data
|
||||
.filter((channel: IJSONObject) => {
|
||||
// filter in text channels only
|
||||
return channel.type === 0;
|
||||
// filter in text channels and announcement channels only
|
||||
return channel.type === 0 || channel.type === 5;
|
||||
})
|
||||
.map((channel: IJSONObject) => {
|
||||
return {
|
||||
|
@@ -10,7 +10,7 @@ type TGroupItem = {
|
||||
type TGroup = Record<'and', TGroupItem[]>;
|
||||
|
||||
const isEqual = (a: string, b: string) => a === b;
|
||||
const isNotEqual = (a: string, b: string) => !isEqual(a, b)
|
||||
const isNotEqual = (a: string, b: string) => !isEqual(a, b);
|
||||
const isGreaterThan = (a: string, b: string) => Number(a) > Number(b);
|
||||
const isLessThan = (a: string, b: string) => Number(a) < Number(b);
|
||||
const isGreaterThanOrEqual = (a: string, b: string) => Number(a) >= Number(b);
|
||||
@@ -18,6 +18,36 @@ const isLessThanOrEqual = (a: string, b: string) => Number(a) <= Number(b);
|
||||
const contains = (a: string, b: string) => a.includes(b);
|
||||
const doesNotContain = (a: string, b: string) => !contains(a, b);
|
||||
|
||||
const shouldContinue = (orGroups: TGroup[]) => {
|
||||
let atLeastOneGroupMatches = false;
|
||||
|
||||
for (const group of orGroups) {
|
||||
let groupMatches = true;
|
||||
|
||||
for (const condition of group.and) {
|
||||
const conditionMatches = operate(
|
||||
condition.operator,
|
||||
condition.key,
|
||||
condition.value
|
||||
);
|
||||
|
||||
if (!conditionMatches) {
|
||||
groupMatches = false;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (groupMatches) {
|
||||
atLeastOneGroupMatches = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return atLeastOneGroupMatches;
|
||||
}
|
||||
|
||||
type TOperatorFunc = (a: string, b: string) => boolean;
|
||||
|
||||
type TOperators = {
|
||||
@@ -66,7 +96,7 @@ export default defineAction({
|
||||
return groups;
|
||||
}, []);
|
||||
|
||||
if (matchingGroups.length === 0) {
|
||||
if (!shouldContinue(orGroups)) {
|
||||
$.execution.exit();
|
||||
}
|
||||
|
||||
|
@@ -20,12 +20,14 @@ export default defineTrigger({
|
||||
],
|
||||
|
||||
async testRun($) {
|
||||
if (!isEmpty($.lastExecutionStep?.dataOut)) {
|
||||
const lastExecutionStep = await $.getLastExecutionStep();
|
||||
|
||||
if (!isEmpty(lastExecutionStep?.dataOut)) {
|
||||
$.pushTriggerItem({
|
||||
raw: $.lastExecutionStep.dataOut,
|
||||
raw: lastExecutionStep.dataOut,
|
||||
meta: {
|
||||
internalId: '',
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -35,20 +37,15 @@ export default defineTrigger({
|
||||
name: $.flow.id,
|
||||
type: 'POST',
|
||||
url: $.webhookUrl,
|
||||
filters: [$.step.parameters.filters]
|
||||
filters: [$.step.parameters.filters],
|
||||
};
|
||||
|
||||
const { data } = await $.http.post(
|
||||
`/v2/public/api/webhooks`,
|
||||
payload
|
||||
);
|
||||
const { data } = await $.http.post(`/v2/public/api/webhooks`, payload);
|
||||
|
||||
await $.flow.setRemoteWebhookId(data.id);
|
||||
},
|
||||
|
||||
async unregisterHook($) {
|
||||
await $.http.delete(
|
||||
`/v2/public/api/webhooks/${$.flow.remoteWebhookId}`
|
||||
);
|
||||
await $.http.delete(`/v2/public/api/webhooks/${$.flow.remoteWebhookId}`);
|
||||
},
|
||||
});
|
||||
|
@@ -0,0 +1,49 @@
|
||||
import defineAction from '../../../../helpers/define-action';
|
||||
|
||||
import formatDateTime from './transformers/format-date-time';
|
||||
|
||||
const transformers = {
|
||||
formatDateTime,
|
||||
};
|
||||
|
||||
export default defineAction({
|
||||
name: 'Date / Time',
|
||||
key: 'date-time',
|
||||
description: 'Perform date and time related transformations on your data.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Transform',
|
||||
key: 'transform',
|
||||
type: 'dropdown' as const,
|
||||
required: true,
|
||||
variables: true,
|
||||
options: [{ label: 'Format Date / Time', value: 'formatDateTime' }],
|
||||
additionalFields: {
|
||||
type: 'query',
|
||||
name: 'getDynamicFields',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listTransformOptions',
|
||||
},
|
||||
{
|
||||
name: 'parameters.transform',
|
||||
value: '{parameters.transform}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const transformerName = $.step.parameters
|
||||
.transform as keyof typeof transformers;
|
||||
const output = transformers[transformerName]($);
|
||||
|
||||
$.setActionItem({
|
||||
raw: {
|
||||
output,
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
@@ -0,0 +1,23 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
const formatDateTime = ($: IGlobalVariable) => {
|
||||
const input = $.step.parameters.input as string;
|
||||
|
||||
const fromFormat = $.step.parameters.fromFormat as string;
|
||||
const fromTimezone = $.step.parameters.fromTimezone as string;
|
||||
|
||||
const inputDateTime = DateTime.fromFormat(input, fromFormat, {
|
||||
zone: fromTimezone,
|
||||
setZone: true,
|
||||
});
|
||||
|
||||
const toFormat = $.step.parameters.toFormat as string;
|
||||
const toTimezone = $.step.parameters.toTimezone as string;
|
||||
|
||||
const outputDateTime = inputDateTime.setZone(toTimezone).toFormat(toFormat);
|
||||
|
||||
return outputDateTime;
|
||||
};
|
||||
|
||||
export default formatDateTime;
|
6
packages/backend/src/apps/formatter/actions/index.ts
Normal file
6
packages/backend/src/apps/formatter/actions/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import text from './text';
|
||||
import numbers from './numbers';
|
||||
import dateTime from './date-time';
|
||||
import utilities from './utilities';
|
||||
|
||||
export default [text, numbers, dateTime, utilities];
|
58
packages/backend/src/apps/formatter/actions/numbers/index.ts
Normal file
58
packages/backend/src/apps/formatter/actions/numbers/index.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import defineAction from '../../../../helpers/define-action';
|
||||
|
||||
import performMathOperation from './transformers/perform-math-operation';
|
||||
import randomNumber from './transformers/random-number';
|
||||
import formatNumber from './transformers/format-number';
|
||||
|
||||
const transformers = {
|
||||
performMathOperation,
|
||||
randomNumber,
|
||||
formatNumber,
|
||||
};
|
||||
|
||||
export default defineAction({
|
||||
name: 'Numbers',
|
||||
key: 'numbers',
|
||||
description:
|
||||
'Transform numbers to perform math operations, generate random numbers, format numbers, and much more.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Transform',
|
||||
key: 'transform',
|
||||
type: 'dropdown' as const,
|
||||
required: true,
|
||||
variables: true,
|
||||
options: [
|
||||
{ label: 'Perform Math Operation', value: 'performMathOperation' },
|
||||
{ label: 'Random Number', value: 'randomNumber' },
|
||||
{ label: 'Format Number', value: 'formatNumber' },
|
||||
],
|
||||
additionalFields: {
|
||||
type: 'query',
|
||||
name: 'getDynamicFields',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listTransformOptions',
|
||||
},
|
||||
{
|
||||
name: 'parameters.transform',
|
||||
value: '{parameters.transform}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const transformerName = $.step.parameters
|
||||
.transform as keyof typeof transformers;
|
||||
const output = transformers[transformerName]($);
|
||||
|
||||
$.setActionItem({
|
||||
raw: {
|
||||
output,
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
@@ -0,0 +1,28 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
import accounting from 'accounting';
|
||||
|
||||
const formatNumber = ($: IGlobalVariable) => {
|
||||
const input = $.step.parameters.input as string;
|
||||
const inputDecimalMark = $.step.parameters.inputDecimalMark as string;
|
||||
const toFormat = $.step.parameters.toFormat as string;
|
||||
|
||||
const normalizedNumber = accounting.unformat(input, inputDecimalMark);
|
||||
const decimalPart = normalizedNumber.toString().split('.')[1];
|
||||
const precision = decimalPart ? decimalPart.length : 0;
|
||||
|
||||
if (toFormat === '0') {
|
||||
// Comma for grouping & period for decimal
|
||||
return accounting.formatNumber(normalizedNumber, precision, ',', '.');
|
||||
} else if (toFormat === '1') {
|
||||
// Period for grouping & comma for decimal
|
||||
return accounting.formatNumber(normalizedNumber, precision, '.', ',');
|
||||
} else if (toFormat === '2') {
|
||||
// Space for grouping & period for decimal
|
||||
return accounting.formatNumber(normalizedNumber, precision, ' ', '.');
|
||||
} else if (toFormat === '3') {
|
||||
// Space for grouping & comma for decimal
|
||||
return accounting.formatNumber(normalizedNumber, precision, ' ', ',');
|
||||
}
|
||||
};
|
||||
|
||||
export default formatNumber;
|
@@ -0,0 +1,23 @@
|
||||
import { IGlobalVariable, IJSONObject } from '@automatisch/types';
|
||||
import { add, divide, multiply, subtract } from 'lodash';
|
||||
|
||||
const mathOperation = ($: IGlobalVariable) => {
|
||||
const mathOperation = $.step.parameters.mathOperation as string;
|
||||
const values = ($.step.parameters.values as IJSONObject[]).map((value) =>
|
||||
Number(value.input)
|
||||
) as number[];
|
||||
|
||||
if (mathOperation === 'add') {
|
||||
return values.reduce((acc, curr) => add(acc, curr), 0);
|
||||
} else if (mathOperation === 'divide') {
|
||||
return values.reduce((acc, curr) => divide(acc, curr));
|
||||
} else if (mathOperation === 'makeNegative') {
|
||||
return values.map((value) => -value);
|
||||
} else if (mathOperation === 'multiply') {
|
||||
return values.reduce((acc, curr) => multiply(acc, curr), 1);
|
||||
} else if (mathOperation === 'subtract') {
|
||||
return values.reduce((acc, curr) => subtract(acc, curr));
|
||||
}
|
||||
};
|
||||
|
||||
export default mathOperation;
|
@@ -0,0 +1,15 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
|
||||
const randomNumber = ($: IGlobalVariable) => {
|
||||
const lowerRange = Number($.step.parameters.lowerRange);
|
||||
const upperRange = Number($.step.parameters.upperRange);
|
||||
const decimalPoints = Number($.step.parameters.decimalPoints) || 0;
|
||||
|
||||
return Number(
|
||||
(Math.random() * (upperRange - lowerRange) + lowerRange).toFixed(
|
||||
decimalPoints
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
export default randomNumber;
|
79
packages/backend/src/apps/formatter/actions/text/index.ts
Normal file
79
packages/backend/src/apps/formatter/actions/text/index.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import defineAction from '../../../../helpers/define-action';
|
||||
|
||||
import capitalize from './transformers/capitalize';
|
||||
import extractEmailAddress from './transformers/extract-email-address';
|
||||
import extractNumber from './transformers/extract-number';
|
||||
import htmlToMarkdown from './transformers/html-to-markdown';
|
||||
import lowercase from './transformers/lowercase';
|
||||
import markdownToHtml from './transformers/markdown-to-html';
|
||||
import pluralize from './transformers/pluralize';
|
||||
import replace from './transformers/replace';
|
||||
import trimWhitespace from './transformers/trim-whitespace';
|
||||
import useDefaultValue from './transformers/use-default-value';
|
||||
|
||||
const transformers = {
|
||||
capitalize,
|
||||
extractEmailAddress,
|
||||
extractNumber,
|
||||
htmlToMarkdown,
|
||||
lowercase,
|
||||
markdownToHtml,
|
||||
pluralize,
|
||||
replace,
|
||||
trimWhitespace,
|
||||
useDefaultValue,
|
||||
};
|
||||
|
||||
export default defineAction({
|
||||
name: 'Text',
|
||||
key: 'text',
|
||||
description:
|
||||
'Transform text data to capitalize, extract emails, apply default value, and much more.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Transform',
|
||||
key: 'transform',
|
||||
type: 'dropdown' as const,
|
||||
required: true,
|
||||
variables: true,
|
||||
options: [
|
||||
{ label: 'Capitalize', value: 'capitalize' },
|
||||
{ label: 'Convert HTML to Markdown', value: 'htmlToMarkdown' },
|
||||
{ label: 'Convert Markdown to HTML', value: 'markdownToHtml' },
|
||||
{ label: 'Extract Email Address', value: 'extractEmailAddress' },
|
||||
{ label: 'Extract Number', value: 'extractNumber' },
|
||||
{ label: 'Lowercase', value: 'lowercase' },
|
||||
{ label: 'Pluralize', value: 'pluralize' },
|
||||
{ label: 'Replace', value: 'replace' },
|
||||
{ label: 'Trim Whitespace', value: 'trimWhitespace' },
|
||||
{ label: 'Use Default Value', value: 'useDefaultValue' },
|
||||
],
|
||||
additionalFields: {
|
||||
type: 'query',
|
||||
name: 'getDynamicFields',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listTransformOptions',
|
||||
},
|
||||
{
|
||||
name: 'parameters.transform',
|
||||
value: '{parameters.transform}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const transformerName = $.step.parameters
|
||||
.transform as keyof typeof transformers;
|
||||
const output = transformers[transformerName]($);
|
||||
|
||||
$.setActionItem({
|
||||
raw: {
|
||||
output,
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
@@ -0,0 +1,11 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
import { capitalize as lodashCapitalize } from 'lodash';
|
||||
|
||||
const capitalize = ($: IGlobalVariable) => {
|
||||
const input = $.step.parameters.input as string;
|
||||
const capitalizedInput = input.replace(/\w+/g, lodashCapitalize);
|
||||
|
||||
return capitalizedInput;
|
||||
};
|
||||
|
||||
export default capitalize;
|
@@ -0,0 +1,12 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
|
||||
const extractEmailAddress = ($: IGlobalVariable) => {
|
||||
const input = $.step.parameters.input as string;
|
||||
const emailRegexp =
|
||||
/[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/;
|
||||
|
||||
const email = input.match(emailRegexp);
|
||||
return email ? email[0] : '';
|
||||
};
|
||||
|
||||
export default extractEmailAddress;
|
@@ -0,0 +1,26 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
|
||||
const extractNumber = ($: IGlobalVariable) => {
|
||||
const input = $.step.parameters.input as string;
|
||||
|
||||
// Example numbers that's supported:
|
||||
// 123
|
||||
// -123
|
||||
// 123456
|
||||
// -123456
|
||||
// 121,234
|
||||
// -121,234
|
||||
// 121.234
|
||||
// -121.234
|
||||
// 1,234,567.89
|
||||
// -1,234,567.89
|
||||
// 1.234.567,89
|
||||
// -1.234.567,89
|
||||
|
||||
const numberRegexp = /-?((\d{1,3})+\.?,?)+/g;
|
||||
|
||||
const numbers = input.match(numberRegexp);
|
||||
return numbers ? numbers[0] : '';
|
||||
};
|
||||
|
||||
export default extractNumber;
|
@@ -0,0 +1,11 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
import { NodeHtmlMarkdown } from 'node-html-markdown';
|
||||
|
||||
const htmlToMarkdown = ($: IGlobalVariable) => {
|
||||
const input = $.step.parameters.input as string;
|
||||
|
||||
const markdown = NodeHtmlMarkdown.translate(input);
|
||||
return markdown;
|
||||
};
|
||||
|
||||
export default htmlToMarkdown;
|
@@ -0,0 +1,8 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
|
||||
const lowercase = ($: IGlobalVariable) => {
|
||||
const input = $.step.parameters.input as string;
|
||||
return input.toLowerCase();
|
||||
};
|
||||
|
||||
export default lowercase;
|
@@ -0,0 +1,13 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
import showdown from 'showdown';
|
||||
|
||||
const converter = new showdown.Converter();
|
||||
|
||||
const markdownToHtml = ($: IGlobalVariable) => {
|
||||
const input = $.step.parameters.input as string;
|
||||
|
||||
const html = converter.makeHtml(input);
|
||||
return html;
|
||||
};
|
||||
|
||||
export default markdownToHtml;
|
@@ -0,0 +1,9 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
import pluralizeLibrary from 'pluralize';
|
||||
|
||||
const pluralize = ($: IGlobalVariable) => {
|
||||
const input = $.step.parameters.input as string;
|
||||
return pluralizeLibrary(input);
|
||||
};
|
||||
|
||||
export default pluralize;
|
@@ -0,0 +1,12 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
|
||||
const replace = ($: IGlobalVariable) => {
|
||||
const input = $.step.parameters.input as string;
|
||||
|
||||
const find = $.step.parameters.find as string;
|
||||
const replace = $.step.parameters.replace as string;
|
||||
|
||||
return input.replaceAll(find, replace);
|
||||
};
|
||||
|
||||
export default replace;
|
@@ -0,0 +1,8 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
|
||||
const trimWhitespace = ($: IGlobalVariable) => {
|
||||
const input = $.step.parameters.input as string;
|
||||
return input.trim();
|
||||
};
|
||||
|
||||
export default trimWhitespace;
|
@@ -0,0 +1,13 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
|
||||
const useDefaultValue = ($: IGlobalVariable) => {
|
||||
const input = $.step.parameters.input as string;
|
||||
|
||||
if (input && input.trim().length > 0) {
|
||||
return input;
|
||||
}
|
||||
|
||||
return $.step.parameters.defaultValue as string;
|
||||
};
|
||||
|
||||
export default useDefaultValue;
|
@@ -0,0 +1,54 @@
|
||||
import defineAction from '../../../../helpers/define-action';
|
||||
|
||||
import findArrayItemByProperty from './transformers/find-array-item-by-property';
|
||||
|
||||
const transformers = {
|
||||
findArrayItemByProperty,
|
||||
};
|
||||
|
||||
export default defineAction({
|
||||
name: 'Utilities',
|
||||
key: 'utilities',
|
||||
description: 'Specific utilities to help you transform your data.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Transform',
|
||||
key: 'transform',
|
||||
type: 'dropdown' as const,
|
||||
required: true,
|
||||
variables: true,
|
||||
options: [
|
||||
{
|
||||
label: 'Find Array Item By Property',
|
||||
value: 'findArrayItemByProperty',
|
||||
},
|
||||
],
|
||||
additionalFields: {
|
||||
type: 'query',
|
||||
name: 'getDynamicFields',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listTransformOptions',
|
||||
},
|
||||
{
|
||||
name: 'parameters.transform',
|
||||
value: '{parameters.transform}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const transformerName = $.step.parameters
|
||||
.transform as keyof typeof transformers;
|
||||
const output = transformers[transformerName]($);
|
||||
|
||||
$.setActionItem({
|
||||
raw: {
|
||||
output,
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
@@ -0,0 +1,13 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
import { find } from 'lodash';
|
||||
|
||||
const findArrayItemByProperty = ($: IGlobalVariable) => {
|
||||
const value = JSON.parse($.step.parameters.value as string);
|
||||
const propertyName = $.step.parameters.propertyName as string;
|
||||
const propertyValue = $.step.parameters.propertyValue as string;
|
||||
|
||||
const foundItem = find(value, { [propertyName]: propertyValue });
|
||||
return foundItem;
|
||||
};
|
||||
|
||||
export default findArrayItemByProperty;
|
3
packages/backend/src/apps/formatter/assets/favicon.svg
Normal file
3
packages/backend/src/apps/formatter/assets/favicon.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4 4H20M4 12H20M4 20H20M4 8H14M4 16H14" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 243 B |
@@ -0,0 +1,3 @@
|
||||
import listTransformOptions from './list-transform-options';
|
||||
|
||||
export default [listTransformOptions];
|
@@ -0,0 +1,51 @@
|
||||
import formatOptions from './options/format';
|
||||
import timezoneOptions from './options/timezone';
|
||||
|
||||
const formatDateTime = [
|
||||
{
|
||||
label: 'Input',
|
||||
key: 'input',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: 'The datetime you want to format.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'From Format',
|
||||
key: 'fromFormat',
|
||||
type: 'dropdown' as const,
|
||||
required: true,
|
||||
description: 'The format of the input.',
|
||||
variables: true,
|
||||
options: formatOptions,
|
||||
},
|
||||
{
|
||||
label: 'From Timezone',
|
||||
key: 'fromTimezone',
|
||||
type: 'dropdown' as const,
|
||||
required: true,
|
||||
description: 'The timezone of the input.',
|
||||
variables: true,
|
||||
options: timezoneOptions,
|
||||
},
|
||||
{
|
||||
label: 'To Format',
|
||||
key: 'toFormat',
|
||||
type: 'dropdown' as const,
|
||||
required: true,
|
||||
description: 'The format of the output.',
|
||||
variables: true,
|
||||
options: formatOptions,
|
||||
},
|
||||
{
|
||||
label: 'To Timezone',
|
||||
key: 'toTimezone',
|
||||
type: 'dropdown' as const,
|
||||
required: true,
|
||||
description: 'The timezone of the output.',
|
||||
variables: true,
|
||||
options: timezoneOptions,
|
||||
},
|
||||
];
|
||||
|
||||
export default formatDateTime;
|
@@ -0,0 +1,64 @@
|
||||
const formatOptions = [
|
||||
{
|
||||
label: 'ccc MMM dd HH:mm:ssZZZ yyyy (Wed Aug 23 12:25:36-0000 2023)',
|
||||
value: 'ccc MMM dd HH:mm:ssZZZ yyyy',
|
||||
},
|
||||
{
|
||||
label: 'MMMM dd yyyy HH:mm:ss (August 23 2023 12:25:36)',
|
||||
value: 'MMMM dd yyyy HH:mm:ss',
|
||||
},
|
||||
{
|
||||
label: 'MMMM dd yyyy (August 23 2023)',
|
||||
value: 'MMMM dd yyyy',
|
||||
},
|
||||
{
|
||||
label: 'MMM dd yyyy (Aug 23 2023)',
|
||||
value: 'MMM dd yyyy',
|
||||
},
|
||||
{
|
||||
label: 'yyyy-MM-dd HH:mm:ss ZZZ (2023-08-23 12:25:36 -0000)',
|
||||
value: 'yyyy-MM-dd HH:mm:ss ZZZ',
|
||||
},
|
||||
{
|
||||
label: 'yyyy-MM-dd (2023-08-23)',
|
||||
value: 'yyyy-MM-dd',
|
||||
},
|
||||
{
|
||||
label: 'MM-dd-yyyy (08-23-2023)',
|
||||
value: 'MM-dd-yyyy',
|
||||
},
|
||||
{
|
||||
label: 'MM/dd/yyyy (08/23/2023)',
|
||||
value: 'MM/dd/yyyy',
|
||||
},
|
||||
{
|
||||
label: 'MM/dd/yy (08/23/23)',
|
||||
value: 'MM/dd/yy',
|
||||
},
|
||||
{
|
||||
label: 'dd-MM-yyyy (23-08-2023)',
|
||||
value: 'dd-MM-yyyy',
|
||||
},
|
||||
{
|
||||
label: 'dd/MM/yyyy (23/08/2023)',
|
||||
value: 'dd/MM/yyyy',
|
||||
},
|
||||
{
|
||||
label: 'dd/MM/yy (23/08/23)',
|
||||
value: 'dd/MM/yy',
|
||||
},
|
||||
{
|
||||
label: 'MM-yyyy (08-2023)',
|
||||
value: 'MM-yyyy',
|
||||
},
|
||||
{
|
||||
label: 'Unix timestamp in seconds (1694008283)',
|
||||
value: 'X',
|
||||
},
|
||||
{
|
||||
label: 'Unix timestamp in milliseconds (1694008306315)',
|
||||
value: 'x',
|
||||
},
|
||||
];
|
||||
|
||||
export default formatOptions;
|
@@ -0,0 +1,449 @@
|
||||
// The list from Intl.supportedValuesOf('timeZone') which is used by Luxon.
|
||||
|
||||
const timezoneOptions = [
|
||||
{ label: 'Africa/Abidjan', value: 'Africa/Abidjan' },
|
||||
{ label: 'Africa/Accra', value: 'Africa/Accra' },
|
||||
{ label: 'Africa/Addis_Ababa', value: 'Africa/Addis_Ababa' },
|
||||
{ label: 'Africa/Algiers', value: 'Africa/Algiers' },
|
||||
{ label: 'Africa/Asmera', value: 'Africa/Asmera' },
|
||||
{ label: 'Africa/Bamako', value: 'Africa/Bamako' },
|
||||
{ label: 'Africa/Bangui', value: 'Africa/Bangui' },
|
||||
{ label: 'Africa/Banjul', value: 'Africa/Banjul' },
|
||||
{ label: 'Africa/Bissau', value: 'Africa/Bissau' },
|
||||
{ label: 'Africa/Blantyre', value: 'Africa/Blantyre' },
|
||||
{ label: 'Africa/Brazzaville', value: 'Africa/Brazzaville' },
|
||||
{ label: 'Africa/Bujumbura', value: 'Africa/Bujumbura' },
|
||||
{ label: 'Africa/Cairo', value: 'Africa/Cairo' },
|
||||
{ label: 'Africa/Casablanca', value: 'Africa/Casablanca' },
|
||||
{ label: 'Africa/Ceuta', value: 'Africa/Ceuta' },
|
||||
{ label: 'Africa/Conakry', value: 'Africa/Conakry' },
|
||||
{ label: 'Africa/Dakar', value: 'Africa/Dakar' },
|
||||
{ label: 'Africa/Dar_es_Salaam', value: 'Africa/Dar_es_Salaam' },
|
||||
{ label: 'Africa/Djibouti', value: 'Africa/Djibouti' },
|
||||
{ label: 'Africa/Douala', value: 'Africa/Douala' },
|
||||
{ label: 'Africa/El_Aaiun', value: 'Africa/El_Aaiun' },
|
||||
{ label: 'Africa/Freetown', value: 'Africa/Freetown' },
|
||||
{ label: 'Africa/Gaborone', value: 'Africa/Gaborone' },
|
||||
{ label: 'Africa/Harare', value: 'Africa/Harare' },
|
||||
{ label: 'Africa/Johannesburg', value: 'Africa/Johannesburg' },
|
||||
{ label: 'Africa/Juba', value: 'Africa/Juba' },
|
||||
{ label: 'Africa/Kampala', value: 'Africa/Kampala' },
|
||||
{ label: 'Africa/Khartoum', value: 'Africa/Khartoum' },
|
||||
{ label: 'Africa/Kigali', value: 'Africa/Kigali' },
|
||||
{ label: 'Africa/Kinshasa', value: 'Africa/Kinshasa' },
|
||||
{ label: 'Africa/Lagos', value: 'Africa/Lagos' },
|
||||
{ label: 'Africa/Libreville', value: 'Africa/Libreville' },
|
||||
{ label: 'Africa/Lome', value: 'Africa/Lome' },
|
||||
{ label: 'Africa/Luanda', value: 'Africa/Luanda' },
|
||||
{ label: 'Africa/Lubumbashi', value: 'Africa/Lubumbashi' },
|
||||
{ label: 'Africa/Lusaka', value: 'Africa/Lusaka' },
|
||||
{ label: 'Africa/Malabo', value: 'Africa/Malabo' },
|
||||
{ label: 'Africa/Maputo', value: 'Africa/Maputo' },
|
||||
{ label: 'Africa/Maseru', value: 'Africa/Maseru' },
|
||||
{ label: 'Africa/Mbabane', value: 'Africa/Mbabane' },
|
||||
{ label: 'Africa/Mogadishu', value: 'Africa/Mogadishu' },
|
||||
{ label: 'Africa/Monrovia', value: 'Africa/Monrovia' },
|
||||
{ label: 'Africa/Nairobi', value: 'Africa/Nairobi' },
|
||||
{ label: 'Africa/Ndjamena', value: 'Africa/Ndjamena' },
|
||||
{ label: 'Africa/Niamey', value: 'Africa/Niamey' },
|
||||
{ label: 'Africa/Nouakchott', value: 'Africa/Nouakchott' },
|
||||
{ label: 'Africa/Ouagadougou', value: 'Africa/Ouagadougou' },
|
||||
{ label: 'Africa/Porto-Novo', value: 'Africa/Porto-Novo' },
|
||||
{ label: 'Africa/Sao_Tome', value: 'Africa/Sao_Tome' },
|
||||
{ label: 'Africa/Tripoli', value: 'Africa/Tripoli' },
|
||||
{ label: 'Africa/Tunis', value: 'Africa/Tunis' },
|
||||
{ label: 'Africa/Windhoek', value: 'Africa/Windhoek' },
|
||||
{ label: 'America/Adak', value: 'America/Adak' },
|
||||
{ label: 'America/Anchorage', value: 'America/Anchorage' },
|
||||
{ label: 'America/Anguilla', value: 'America/Anguilla' },
|
||||
{ label: 'America/Antigua', value: 'America/Antigua' },
|
||||
{ label: 'America/Araguaina', value: 'America/Araguaina' },
|
||||
{ label: 'America/Argentina/La_Rioja', value: 'America/Argentina/La_Rioja' },
|
||||
{
|
||||
label: 'America/Argentina/Rio_Gallegos',
|
||||
value: 'America/Argentina/Rio_Gallegos',
|
||||
},
|
||||
{ label: 'America/Argentina/Salta', value: 'America/Argentina/Salta' },
|
||||
{ label: 'America/Argentina/San_Juan', value: 'America/Argentina/San_Juan' },
|
||||
{ label: 'America/Argentina/San_Luis', value: 'America/Argentina/San_Luis' },
|
||||
{ label: 'America/Argentina/Tucuman', value: 'America/Argentina/Tucuman' },
|
||||
{ label: 'America/Argentina/Ushuaia', value: 'America/Argentina/Ushuaia' },
|
||||
{ label: 'America/Aruba', value: 'America/Aruba' },
|
||||
{ label: 'America/Asuncion', value: 'America/Asuncion' },
|
||||
{ label: 'America/Bahia', value: 'America/Bahia' },
|
||||
{ label: 'America/Bahia_Banderas', value: 'America/Bahia_Banderas' },
|
||||
{ label: 'America/Barbados', value: 'America/Barbados' },
|
||||
{ label: 'America/Belem', value: 'America/Belem' },
|
||||
{ label: 'America/Belize', value: 'America/Belize' },
|
||||
{ label: 'America/Blanc-Sablon', value: 'America/Blanc-Sablon' },
|
||||
{ label: 'America/Boa_Vista', value: 'America/Boa_Vista' },
|
||||
{ label: 'America/Bogota', value: 'America/Bogota' },
|
||||
{ label: 'America/Boise', value: 'America/Boise' },
|
||||
{ label: 'America/Buenos_Aires', value: 'America/Buenos_Aires' },
|
||||
{ label: 'America/Cambridge_Bay', value: 'America/Cambridge_Bay' },
|
||||
{ label: 'America/Campo_Grande', value: 'America/Campo_Grande' },
|
||||
{ label: 'America/Cancun', value: 'America/Cancun' },
|
||||
{ label: 'America/Caracas', value: 'America/Caracas' },
|
||||
{ label: 'America/Catamarca', value: 'America/Catamarca' },
|
||||
{ label: 'America/Cayenne', value: 'America/Cayenne' },
|
||||
{ label: 'America/Cayman', value: 'America/Cayman' },
|
||||
{ label: 'America/Chicago', value: 'America/Chicago' },
|
||||
{ label: 'America/Chihuahua', value: 'America/Chihuahua' },
|
||||
{ label: 'America/Ciudad_Juarez', value: 'America/Ciudad_Juarez' },
|
||||
{ label: 'America/Coral_Harbour', value: 'America/Coral_Harbour' },
|
||||
{ label: 'America/Cordoba', value: 'America/Cordoba' },
|
||||
{ label: 'America/Costa_Rica', value: 'America/Costa_Rica' },
|
||||
{ label: 'America/Creston', value: 'America/Creston' },
|
||||
{ label: 'America/Cuiaba', value: 'America/Cuiaba' },
|
||||
{ label: 'America/Curacao', value: 'America/Curacao' },
|
||||
{ label: 'America/Danmarkshavn', value: 'America/Danmarkshavn' },
|
||||
{ label: 'America/Dawson', value: 'America/Dawson' },
|
||||
{ label: 'America/Dawson_Creek', value: 'America/Dawson_Creek' },
|
||||
{ label: 'America/Denver', value: 'America/Denver' },
|
||||
{ label: 'America/Detroit', value: 'America/Detroit' },
|
||||
{ label: 'America/Dominica', value: 'America/Dominica' },
|
||||
{ label: 'America/Edmonton', value: 'America/Edmonton' },
|
||||
{ label: 'America/Eirunepe', value: 'America/Eirunepe' },
|
||||
{ label: 'America/El_Salvador', value: 'America/El_Salvador' },
|
||||
{ label: 'America/Fort_Nelson', value: 'America/Fort_Nelson' },
|
||||
{ label: 'America/Fortaleza', value: 'America/Fortaleza' },
|
||||
{ label: 'America/Glace_Bay', value: 'America/Glace_Bay' },
|
||||
{ label: 'America/Godthab', value: 'America/Godthab' },
|
||||
{ label: 'America/Goose_Bay', value: 'America/Goose_Bay' },
|
||||
{ label: 'America/Grand_Turk', value: 'America/Grand_Turk' },
|
||||
{ label: 'America/Grenada', value: 'America/Grenada' },
|
||||
{ label: 'America/Guadeloupe', value: 'America/Guadeloupe' },
|
||||
{ label: 'America/Guatemala', value: 'America/Guatemala' },
|
||||
{ label: 'America/Guayaquil', value: 'America/Guayaquil' },
|
||||
{ label: 'America/Guyana', value: 'America/Guyana' },
|
||||
{ label: 'America/Halifax', value: 'America/Halifax' },
|
||||
{ label: 'America/Havana', value: 'America/Havana' },
|
||||
{ label: 'America/Hermosillo', value: 'America/Hermosillo' },
|
||||
{ label: 'America/Indiana/Knox', value: 'America/Indiana/Knox' },
|
||||
{ label: 'America/Indiana/Marengo', value: 'America/Indiana/Marengo' },
|
||||
{ label: 'America/Indiana/Petersburg', value: 'America/Indiana/Petersburg' },
|
||||
{ label: 'America/Indiana/Tell_City', value: 'America/Indiana/Tell_City' },
|
||||
{ label: 'America/Indiana/Vevay', value: 'America/Indiana/Vevay' },
|
||||
{ label: 'America/Indiana/Vincennes', value: 'America/Indiana/Vincennes' },
|
||||
{ label: 'America/Indiana/Winamac', value: 'America/Indiana/Winamac' },
|
||||
{ label: 'America/Indianapolis', value: 'America/Indianapolis' },
|
||||
{ label: 'America/Inuvik', value: 'America/Inuvik' },
|
||||
{ label: 'America/Iqaluit', value: 'America/Iqaluit' },
|
||||
{ label: 'America/Jamaica', value: 'America/Jamaica' },
|
||||
{ label: 'America/Jujuy', value: 'America/Jujuy' },
|
||||
{ label: 'America/Juneau', value: 'America/Juneau' },
|
||||
{
|
||||
label: 'America/Kentucky/Monticello',
|
||||
value: 'America/Kentucky/Monticello',
|
||||
},
|
||||
{ label: 'America/Kralendijk', value: 'America/Kralendijk' },
|
||||
{ label: 'America/La_Paz', value: 'America/La_Paz' },
|
||||
{ label: 'America/Lima', value: 'America/Lima' },
|
||||
{ label: 'America/Los_Angeles', value: 'America/Los_Angeles' },
|
||||
{ label: 'America/Louisville', value: 'America/Louisville' },
|
||||
{ label: 'America/Lower_Princes', value: 'America/Lower_Princes' },
|
||||
{ label: 'America/Maceio', value: 'America/Maceio' },
|
||||
{ label: 'America/Managua', value: 'America/Managua' },
|
||||
{ label: 'America/Manaus', value: 'America/Manaus' },
|
||||
{ label: 'America/Marigot', value: 'America/Marigot' },
|
||||
{ label: 'America/Martinique', value: 'America/Martinique' },
|
||||
{ label: 'America/Matamoros', value: 'America/Matamoros' },
|
||||
{ label: 'America/Mazatlan', value: 'America/Mazatlan' },
|
||||
{ label: 'America/Mendoza', value: 'America/Mendoza' },
|
||||
{ label: 'America/Menominee', value: 'America/Menominee' },
|
||||
{ label: 'America/Merida', value: 'America/Merida' },
|
||||
{ label: 'America/Metlakatla', value: 'America/Metlakatla' },
|
||||
{ label: 'America/Mexico_City', value: 'America/Mexico_City' },
|
||||
{ label: 'America/Miquelon', value: 'America/Miquelon' },
|
||||
{ label: 'America/Moncton', value: 'America/Moncton' },
|
||||
{ label: 'America/Monterrey', value: 'America/Monterrey' },
|
||||
{ label: 'America/Montevideo', value: 'America/Montevideo' },
|
||||
{ label: 'America/Montserrat', value: 'America/Montserrat' },
|
||||
{ label: 'America/Nassau', value: 'America/Nassau' },
|
||||
{ label: 'America/New_York', value: 'America/New_York' },
|
||||
{ label: 'America/Nipigon', value: 'America/Nipigon' },
|
||||
{ label: 'America/Nome', value: 'America/Nome' },
|
||||
{ label: 'America/Noronha', value: 'America/Noronha' },
|
||||
{
|
||||
label: 'America/North_Dakota/Beulah',
|
||||
value: 'America/North_Dakota/Beulah',
|
||||
},
|
||||
{
|
||||
label: 'America/North_Dakota/Center',
|
||||
value: 'America/North_Dakota/Center',
|
||||
},
|
||||
{
|
||||
label: 'America/North_Dakota/New_Salem',
|
||||
value: 'America/North_Dakota/New_Salem',
|
||||
},
|
||||
{ label: 'America/Ojinaga', value: 'America/Ojinaga' },
|
||||
{ label: 'America/Panama', value: 'America/Panama' },
|
||||
{ label: 'America/Pangnirtung', value: 'America/Pangnirtung' },
|
||||
{ label: 'America/Paramaribo', value: 'America/Paramaribo' },
|
||||
{ label: 'America/Phoenix', value: 'America/Phoenix' },
|
||||
{ label: 'America/Port-au-Prince', value: 'America/Port-au-Prince' },
|
||||
{ label: 'America/Port_of_Spain', value: 'America/Port_of_Spain' },
|
||||
{ label: 'America/Porto_Velho', value: 'America/Porto_Velho' },
|
||||
{ label: 'America/Puerto_Rico', value: 'America/Puerto_Rico' },
|
||||
{ label: 'America/Punta_Arenas', value: 'America/Punta_Arenas' },
|
||||
{ label: 'America/Rainy_River', value: 'America/Rainy_River' },
|
||||
{ label: 'America/Rankin_Inlet', value: 'America/Rankin_Inlet' },
|
||||
{ label: 'America/Recife', value: 'America/Recife' },
|
||||
{ label: 'America/Regina', value: 'America/Regina' },
|
||||
{ label: 'America/Resolute', value: 'America/Resolute' },
|
||||
{ label: 'America/Rio_Branco', value: 'America/Rio_Branco' },
|
||||
{ label: 'America/Santa_Isabel', value: 'America/Santa_Isabel' },
|
||||
{ label: 'America/Santarem', value: 'America/Santarem' },
|
||||
{ label: 'America/Santiago', value: 'America/Santiago' },
|
||||
{ label: 'America/Santo_Domingo', value: 'America/Santo_Domingo' },
|
||||
{ label: 'America/Sao_Paulo', value: 'America/Sao_Paulo' },
|
||||
{ label: 'America/Scoresbysund', value: 'America/Scoresbysund' },
|
||||
{ label: 'America/Sitka', value: 'America/Sitka' },
|
||||
{ label: 'America/St_Barthelemy', value: 'America/St_Barthelemy' },
|
||||
{ label: 'America/St_Johns', value: 'America/St_Johns' },
|
||||
{ label: 'America/St_Kitts', value: 'America/St_Kitts' },
|
||||
{ label: 'America/St_Lucia', value: 'America/St_Lucia' },
|
||||
{ label: 'America/St_Thomas', value: 'America/St_Thomas' },
|
||||
{ label: 'America/St_Vincent', value: 'America/St_Vincent' },
|
||||
{ label: 'America/Swift_Current', value: 'America/Swift_Current' },
|
||||
{ label: 'America/Tegucigalpa', value: 'America/Tegucigalpa' },
|
||||
{ label: 'America/Thule', value: 'America/Thule' },
|
||||
{ label: 'America/Thunder_Bay', value: 'America/Thunder_Bay' },
|
||||
{ label: 'America/Tijuana', value: 'America/Tijuana' },
|
||||
{ label: 'America/Toronto', value: 'America/Toronto' },
|
||||
{ label: 'America/Tortola', value: 'America/Tortola' },
|
||||
{ label: 'America/Vancouver', value: 'America/Vancouver' },
|
||||
{ label: 'America/Whitehorse', value: 'America/Whitehorse' },
|
||||
{ label: 'America/Winnipeg', value: 'America/Winnipeg' },
|
||||
{ label: 'America/Yakutat', value: 'America/Yakutat' },
|
||||
{ label: 'America/Yellowknife', value: 'America/Yellowknife' },
|
||||
{ label: 'Antarctica/Casey', value: 'Antarctica/Casey' },
|
||||
{ label: 'Antarctica/Davis', value: 'Antarctica/Davis' },
|
||||
{ label: 'Antarctica/DumontDUrville', value: 'Antarctica/DumontDUrville' },
|
||||
{ label: 'Antarctica/Macquarie', value: 'Antarctica/Macquarie' },
|
||||
{ label: 'Antarctica/Mawson', value: 'Antarctica/Mawson' },
|
||||
{ label: 'Antarctica/McMurdo', value: 'Antarctica/McMurdo' },
|
||||
{ label: 'Antarctica/Palmer', value: 'Antarctica/Palmer' },
|
||||
{ label: 'Antarctica/Rothera', value: 'Antarctica/Rothera' },
|
||||
{ label: 'Antarctica/Syowa', value: 'Antarctica/Syowa' },
|
||||
{ label: 'Antarctica/Troll', value: 'Antarctica/Troll' },
|
||||
{ label: 'Antarctica/Vostok', value: 'Antarctica/Vostok' },
|
||||
{ label: 'Arctic/Longyearbyen', value: 'Arctic/Longyearbyen' },
|
||||
{ label: 'Asia/Aden', value: 'Asia/Aden' },
|
||||
{ label: 'Asia/Almaty', value: 'Asia/Almaty' },
|
||||
{ label: 'Asia/Amman', value: 'Asia/Amman' },
|
||||
{ label: 'Asia/Anadyr', value: 'Asia/Anadyr' },
|
||||
{ label: 'Asia/Aqtau', value: 'Asia/Aqtau' },
|
||||
{ label: 'Asia/Aqtobe', value: 'Asia/Aqtobe' },
|
||||
{ label: 'Asia/Ashgabat', value: 'Asia/Ashgabat' },
|
||||
{ label: 'Asia/Atyrau', value: 'Asia/Atyrau' },
|
||||
{ label: 'Asia/Baghdad', value: 'Asia/Baghdad' },
|
||||
{ label: 'Asia/Bahrain', value: 'Asia/Bahrain' },
|
||||
{ label: 'Asia/Baku', value: 'Asia/Baku' },
|
||||
{ label: 'Asia/Bangkok', value: 'Asia/Bangkok' },
|
||||
{ label: 'Asia/Barnaul', value: 'Asia/Barnaul' },
|
||||
{ label: 'Asia/Beirut', value: 'Asia/Beirut' },
|
||||
{ label: 'Asia/Bishkek', value: 'Asia/Bishkek' },
|
||||
{ label: 'Asia/Brunei', value: 'Asia/Brunei' },
|
||||
{ label: 'Asia/Calcutta', value: 'Asia/Calcutta' },
|
||||
{ label: 'Asia/Chita', value: 'Asia/Chita' },
|
||||
{ label: 'Asia/Choibalsan', value: 'Asia/Choibalsan' },
|
||||
{ label: 'Asia/Colombo', value: 'Asia/Colombo' },
|
||||
{ label: 'Asia/Damascus', value: 'Asia/Damascus' },
|
||||
{ label: 'Asia/Dhaka', value: 'Asia/Dhaka' },
|
||||
{ label: 'Asia/Dili', value: 'Asia/Dili' },
|
||||
{ label: 'Asia/Dubai', value: 'Asia/Dubai' },
|
||||
{ label: 'Asia/Dushanbe', value: 'Asia/Dushanbe' },
|
||||
{ label: 'Asia/Famagusta', value: 'Asia/Famagusta' },
|
||||
{ label: 'Asia/Gaza', value: 'Asia/Gaza' },
|
||||
{ label: 'Asia/Hebron', value: 'Asia/Hebron' },
|
||||
{ label: 'Asia/Hong_Kong', value: 'Asia/Hong_Kong' },
|
||||
{ label: 'Asia/Hovd', value: 'Asia/Hovd' },
|
||||
{ label: 'Asia/Irkutsk', value: 'Asia/Irkutsk' },
|
||||
{ label: 'Asia/Jakarta', value: 'Asia/Jakarta' },
|
||||
{ label: 'Asia/Jayapura', value: 'Asia/Jayapura' },
|
||||
{ label: 'Asia/Jerusalem', value: 'Asia/Jerusalem' },
|
||||
{ label: 'Asia/Kabul', value: 'Asia/Kabul' },
|
||||
{ label: 'Asia/Kamchatka', value: 'Asia/Kamchatka' },
|
||||
{ label: 'Asia/Karachi', value: 'Asia/Karachi' },
|
||||
{ label: 'Asia/Katmandu', value: 'Asia/Katmandu' },
|
||||
{ label: 'Asia/Khandyga', value: 'Asia/Khandyga' },
|
||||
{ label: 'Asia/Krasnoyarsk', value: 'Asia/Krasnoyarsk' },
|
||||
{ label: 'Asia/Kuala_Lumpur', value: 'Asia/Kuala_Lumpur' },
|
||||
{ label: 'Asia/Kuching', value: 'Asia/Kuching' },
|
||||
{ label: 'Asia/Kuwait', value: 'Asia/Kuwait' },
|
||||
{ label: 'Asia/Macau', value: 'Asia/Macau' },
|
||||
{ label: 'Asia/Magadan', value: 'Asia/Magadan' },
|
||||
{ label: 'Asia/Makassar', value: 'Asia/Makassar' },
|
||||
{ label: 'Asia/Manila', value: 'Asia/Manila' },
|
||||
{ label: 'Asia/Muscat', value: 'Asia/Muscat' },
|
||||
{ label: 'Asia/Nicosia', value: 'Asia/Nicosia' },
|
||||
{ label: 'Asia/Novokuznetsk', value: 'Asia/Novokuznetsk' },
|
||||
{ label: 'Asia/Novosibirsk', value: 'Asia/Novosibirsk' },
|
||||
{ label: 'Asia/Omsk', value: 'Asia/Omsk' },
|
||||
{ label: 'Asia/Oral', value: 'Asia/Oral' },
|
||||
{ label: 'Asia/Phnom_Penh', value: 'Asia/Phnom_Penh' },
|
||||
{ label: 'Asia/Pontianak', value: 'Asia/Pontianak' },
|
||||
{ label: 'Asia/Pyongyang', value: 'Asia/Pyongyang' },
|
||||
{ label: 'Asia/Qatar', value: 'Asia/Qatar' },
|
||||
{ label: 'Asia/Qostanay', value: 'Asia/Qostanay' },
|
||||
{ label: 'Asia/Qyzylorda', value: 'Asia/Qyzylorda' },
|
||||
{ label: 'Asia/Rangoon', value: 'Asia/Rangoon' },
|
||||
{ label: 'Asia/Riyadh', value: 'Asia/Riyadh' },
|
||||
{ label: 'Asia/Saigon', value: 'Asia/Saigon' },
|
||||
{ label: 'Asia/Sakhalin', value: 'Asia/Sakhalin' },
|
||||
{ label: 'Asia/Samarkand', value: 'Asia/Samarkand' },
|
||||
{ label: 'Asia/Seoul', value: 'Asia/Seoul' },
|
||||
{ label: 'Asia/Shanghai', value: 'Asia/Shanghai' },
|
||||
{ label: 'Asia/Singapore', value: 'Asia/Singapore' },
|
||||
{ label: 'Asia/Srednekolymsk', value: 'Asia/Srednekolymsk' },
|
||||
{ label: 'Asia/Taipei', value: 'Asia/Taipei' },
|
||||
{ label: 'Asia/Tashkent', value: 'Asia/Tashkent' },
|
||||
{ label: 'Asia/Tbilisi', value: 'Asia/Tbilisi' },
|
||||
{ label: 'Asia/Tehran', value: 'Asia/Tehran' },
|
||||
{ label: 'Asia/Thimphu', value: 'Asia/Thimphu' },
|
||||
{ label: 'Asia/Tokyo', value: 'Asia/Tokyo' },
|
||||
{ label: 'Asia/Tomsk', value: 'Asia/Tomsk' },
|
||||
{ label: 'Asia/Ulaanbaatar', value: 'Asia/Ulaanbaatar' },
|
||||
{ label: 'Asia/Urumqi', value: 'Asia/Urumqi' },
|
||||
{ label: 'Asia/Ust-Nera', value: 'Asia/Ust-Nera' },
|
||||
{ label: 'Asia/Vientiane', value: 'Asia/Vientiane' },
|
||||
{ label: 'Asia/Vladivostok', value: 'Asia/Vladivostok' },
|
||||
{ label: 'Asia/Yakutsk', value: 'Asia/Yakutsk' },
|
||||
{ label: 'Asia/Yekaterinburg', value: 'Asia/Yekaterinburg' },
|
||||
{ label: 'Asia/Yerevan', value: 'Asia/Yerevan' },
|
||||
{ label: 'Atlantic/Azores', value: 'Atlantic/Azores' },
|
||||
{ label: 'Atlantic/Bermuda', value: 'Atlantic/Bermuda' },
|
||||
{ label: 'Atlantic/Canary', value: 'Atlantic/Canary' },
|
||||
{ label: 'Atlantic/Cape_Verde', value: 'Atlantic/Cape_Verde' },
|
||||
{ label: 'Atlantic/Faeroe', value: 'Atlantic/Faeroe' },
|
||||
{ label: 'Atlantic/Madeira', value: 'Atlantic/Madeira' },
|
||||
{ label: 'Atlantic/Reykjavik', value: 'Atlantic/Reykjavik' },
|
||||
{ label: 'Atlantic/South_Georgia', value: 'Atlantic/South_Georgia' },
|
||||
{ label: 'Atlantic/St_Helena', value: 'Atlantic/St_Helena' },
|
||||
{ label: 'Atlantic/Stanley', value: 'Atlantic/Stanley' },
|
||||
{ label: 'Australia/Adelaide', value: 'Australia/Adelaide' },
|
||||
{ label: 'Australia/Brisbane', value: 'Australia/Brisbane' },
|
||||
{ label: 'Australia/Broken_Hill', value: 'Australia/Broken_Hill' },
|
||||
{ label: 'Australia/Currie', value: 'Australia/Currie' },
|
||||
{ label: 'Australia/Darwin', value: 'Australia/Darwin' },
|
||||
{ label: 'Australia/Eucla', value: 'Australia/Eucla' },
|
||||
{ label: 'Australia/Hobart', value: 'Australia/Hobart' },
|
||||
{ label: 'Australia/Lindeman', value: 'Australia/Lindeman' },
|
||||
{ label: 'Australia/Lord_Howe', value: 'Australia/Lord_Howe' },
|
||||
{ label: 'Australia/Melbourne', value: 'Australia/Melbourne' },
|
||||
{ label: 'Australia/Perth', value: 'Australia/Perth' },
|
||||
{ label: 'Australia/Sydney', value: 'Australia/Sydney' },
|
||||
{ label: 'Europe/Amsterdam', value: 'Europe/Amsterdam' },
|
||||
{ label: 'Europe/Andorra', value: 'Europe/Andorra' },
|
||||
{ label: 'Europe/Astrakhan', value: 'Europe/Astrakhan' },
|
||||
{ label: 'Europe/Athens', value: 'Europe/Athens' },
|
||||
{ label: 'Europe/Belgrade', value: 'Europe/Belgrade' },
|
||||
{ label: 'Europe/Berlin', value: 'Europe/Berlin' },
|
||||
{ label: 'Europe/Bratislava', value: 'Europe/Bratislava' },
|
||||
{ label: 'Europe/Brussels', value: 'Europe/Brussels' },
|
||||
{ label: 'Europe/Bucharest', value: 'Europe/Bucharest' },
|
||||
{ label: 'Europe/Budapest', value: 'Europe/Budapest' },
|
||||
{ label: 'Europe/Busingen', value: 'Europe/Busingen' },
|
||||
{ label: 'Europe/Chisinau', value: 'Europe/Chisinau' },
|
||||
{ label: 'Europe/Copenhagen', value: 'Europe/Copenhagen' },
|
||||
{ label: 'Europe/Dublin', value: 'Europe/Dublin' },
|
||||
{ label: 'Europe/Gibraltar', value: 'Europe/Gibraltar' },
|
||||
{ label: 'Europe/Guernsey', value: 'Europe/Guernsey' },
|
||||
{ label: 'Europe/Helsinki', value: 'Europe/Helsinki' },
|
||||
{ label: 'Europe/Isle_of_Man', value: 'Europe/Isle_of_Man' },
|
||||
{ label: 'Europe/Istanbul', value: 'Europe/Istanbul' },
|
||||
{ label: 'Europe/Jersey', value: 'Europe/Jersey' },
|
||||
{ label: 'Europe/Kaliningrad', value: 'Europe/Kaliningrad' },
|
||||
{ label: 'Europe/Kiev', value: 'Europe/Kiev' },
|
||||
{ label: 'Europe/Kirov', value: 'Europe/Kirov' },
|
||||
{ label: 'Europe/Lisbon', value: 'Europe/Lisbon' },
|
||||
{ label: 'Europe/Ljubljana', value: 'Europe/Ljubljana' },
|
||||
{ label: 'Europe/London', value: 'Europe/London' },
|
||||
{ label: 'Europe/Luxembourg', value: 'Europe/Luxembourg' },
|
||||
{ label: 'Europe/Madrid', value: 'Europe/Madrid' },
|
||||
{ label: 'Europe/Malta', value: 'Europe/Malta' },
|
||||
{ label: 'Europe/Mariehamn', value: 'Europe/Mariehamn' },
|
||||
{ label: 'Europe/Minsk', value: 'Europe/Minsk' },
|
||||
{ label: 'Europe/Monaco', value: 'Europe/Monaco' },
|
||||
{ label: 'Europe/Moscow', value: 'Europe/Moscow' },
|
||||
{ label: 'Europe/Oslo', value: 'Europe/Oslo' },
|
||||
{ label: 'Europe/Paris', value: 'Europe/Paris' },
|
||||
{ label: 'Europe/Podgorica', value: 'Europe/Podgorica' },
|
||||
{ label: 'Europe/Prague', value: 'Europe/Prague' },
|
||||
{ label: 'Europe/Riga', value: 'Europe/Riga' },
|
||||
{ label: 'Europe/Rome', value: 'Europe/Rome' },
|
||||
{ label: 'Europe/Samara', value: 'Europe/Samara' },
|
||||
{ label: 'Europe/San_Marino', value: 'Europe/San_Marino' },
|
||||
{ label: 'Europe/Sarajevo', value: 'Europe/Sarajevo' },
|
||||
{ label: 'Europe/Saratov', value: 'Europe/Saratov' },
|
||||
{ label: 'Europe/Simferopol', value: 'Europe/Simferopol' },
|
||||
{ label: 'Europe/Skopje', value: 'Europe/Skopje' },
|
||||
{ label: 'Europe/Sofia', value: 'Europe/Sofia' },
|
||||
{ label: 'Europe/Stockholm', value: 'Europe/Stockholm' },
|
||||
{ label: 'Europe/Tallinn', value: 'Europe/Tallinn' },
|
||||
{ label: 'Europe/Tirane', value: 'Europe/Tirane' },
|
||||
{ label: 'Europe/Ulyanovsk', value: 'Europe/Ulyanovsk' },
|
||||
{ label: 'Europe/Uzhgorod', value: 'Europe/Uzhgorod' },
|
||||
{ label: 'Europe/Vaduz', value: 'Europe/Vaduz' },
|
||||
{ label: 'Europe/Vatican', value: 'Europe/Vatican' },
|
||||
{ label: 'Europe/Vienna', value: 'Europe/Vienna' },
|
||||
{ label: 'Europe/Vilnius', value: 'Europe/Vilnius' },
|
||||
{ label: 'Europe/Volgograd', value: 'Europe/Volgograd' },
|
||||
{ label: 'Europe/Warsaw', value: 'Europe/Warsaw' },
|
||||
{ label: 'Europe/Zagreb', value: 'Europe/Zagreb' },
|
||||
{ label: 'Europe/Zaporozhye', value: 'Europe/Zaporozhye' },
|
||||
{ label: 'Europe/Zurich', value: 'Europe/Zurich' },
|
||||
{ label: 'Indian/Antananarivo', value: 'Indian/Antananarivo' },
|
||||
{ label: 'Indian/Chagos', value: 'Indian/Chagos' },
|
||||
{ label: 'Indian/Christmas', value: 'Indian/Christmas' },
|
||||
{ label: 'Indian/Cocos', value: 'Indian/Cocos' },
|
||||
{ label: 'Indian/Comoro', value: 'Indian/Comoro' },
|
||||
{ label: 'Indian/Kerguelen', value: 'Indian/Kerguelen' },
|
||||
{ label: 'Indian/Mahe', value: 'Indian/Mahe' },
|
||||
{ label: 'Indian/Maldives', value: 'Indian/Maldives' },
|
||||
{ label: 'Indian/Mauritius', value: 'Indian/Mauritius' },
|
||||
{ label: 'Indian/Mayotte', value: 'Indian/Mayotte' },
|
||||
{ label: 'Indian/Reunion', value: 'Indian/Reunion' },
|
||||
{ label: 'Pacific/Apia', value: 'Pacific/Apia' },
|
||||
{ label: 'Pacific/Auckland', value: 'Pacific/Auckland' },
|
||||
{ label: 'Pacific/Bougainville', value: 'Pacific/Bougainville' },
|
||||
{ label: 'Pacific/Chatham', value: 'Pacific/Chatham' },
|
||||
{ label: 'Pacific/Easter', value: 'Pacific/Easter' },
|
||||
{ label: 'Pacific/Efate', value: 'Pacific/Efate' },
|
||||
{ label: 'Pacific/Enderbury', value: 'Pacific/Enderbury' },
|
||||
{ label: 'Pacific/Fakaofo', value: 'Pacific/Fakaofo' },
|
||||
{ label: 'Pacific/Fiji', value: 'Pacific/Fiji' },
|
||||
{ label: 'Pacific/Funafuti', value: 'Pacific/Funafuti' },
|
||||
{ label: 'Pacific/Galapagos', value: 'Pacific/Galapagos' },
|
||||
{ label: 'Pacific/Gambier', value: 'Pacific/Gambier' },
|
||||
{ label: 'Pacific/Guadalcanal', value: 'Pacific/Guadalcanal' },
|
||||
{ label: 'Pacific/Guam', value: 'Pacific/Guam' },
|
||||
{ label: 'Pacific/Honolulu', value: 'Pacific/Honolulu' },
|
||||
{ label: 'Pacific/Johnston', value: 'Pacific/Johnston' },
|
||||
{ label: 'Pacific/Kiritimati', value: 'Pacific/Kiritimati' },
|
||||
{ label: 'Pacific/Kosrae', value: 'Pacific/Kosrae' },
|
||||
{ label: 'Pacific/Kwajalein', value: 'Pacific/Kwajalein' },
|
||||
{ label: 'Pacific/Majuro', value: 'Pacific/Majuro' },
|
||||
{ label: 'Pacific/Marquesas', value: 'Pacific/Marquesas' },
|
||||
{ label: 'Pacific/Midway', value: 'Pacific/Midway' },
|
||||
{ label: 'Pacific/Nauru', value: 'Pacific/Nauru' },
|
||||
{ label: 'Pacific/Niue', value: 'Pacific/Niue' },
|
||||
{ label: 'Pacific/Norfolk', value: 'Pacific/Norfolk' },
|
||||
{ label: 'Pacific/Noumea', value: 'Pacific/Noumea' },
|
||||
{ label: 'Pacific/Pago_Pago', value: 'Pacific/Pago_Pago' },
|
||||
{ label: 'Pacific/Palau', value: 'Pacific/Palau' },
|
||||
{ label: 'Pacific/Pitcairn', value: 'Pacific/Pitcairn' },
|
||||
{ label: 'Pacific/Ponape', value: 'Pacific/Ponape' },
|
||||
{ label: 'Pacific/Port_Moresby', value: 'Pacific/Port_Moresby' },
|
||||
{ label: 'Pacific/Rarotonga', value: 'Pacific/Rarotonga' },
|
||||
{ label: 'Pacific/Saipan', value: 'Pacific/Saipan' },
|
||||
{ label: 'Pacific/Tahiti', value: 'Pacific/Tahiti' },
|
||||
{ label: 'Pacific/Tarawa', value: 'Pacific/Tarawa' },
|
||||
{ label: 'Pacific/Tongatapu', value: 'Pacific/Tongatapu' },
|
||||
{ label: 'Pacific/Truk', value: 'Pacific/Truk' },
|
||||
{ label: 'Pacific/Wake', value: 'Pacific/Wake' },
|
||||
{ label: 'Pacific/Wallis', value: 'Pacific/Wallis' },
|
||||
];
|
||||
|
||||
export default timezoneOptions;
|
@@ -0,0 +1,43 @@
|
||||
import { IGlobalVariable, IJSONObject } from '@automatisch/types';
|
||||
import capitalize from './text/capitalize';
|
||||
import extractEmailAddress from './text/extract-email-address';
|
||||
import extractNumber from './text/extract-number';
|
||||
import findArrayItemByProperty from './utilities/find-array-item-by-property';
|
||||
import formatDateTime from './date-time/format-date-time';
|
||||
import formatNumber from './numbers/format-number';
|
||||
import htmlToMarkdown from './text/html-to-markdown';
|
||||
import lowercase from './text/lowercase';
|
||||
import markdownToHtml from './text/markdown-to-html';
|
||||
import performMathOperation from './numbers/perform-math-operation';
|
||||
import pluralize from './text/pluralize';
|
||||
import randomNumber from './numbers/random-number';
|
||||
import replace from './text/replace';
|
||||
import trimWhitespace from './text/trim-whitespace';
|
||||
import useDefaultValue from './text/use-default-value';
|
||||
|
||||
const options: IJSONObject = {
|
||||
capitalize,
|
||||
extractEmailAddress,
|
||||
extractNumber,
|
||||
findArrayItemByProperty,
|
||||
formatDateTime,
|
||||
formatNumber,
|
||||
htmlToMarkdown,
|
||||
lowercase,
|
||||
markdownToHtml,
|
||||
performMathOperation,
|
||||
pluralize,
|
||||
randomNumber,
|
||||
replace,
|
||||
trimWhitespace,
|
||||
useDefaultValue,
|
||||
};
|
||||
|
||||
export default {
|
||||
name: 'List fields after transform',
|
||||
key: 'listTransformOptions',
|
||||
|
||||
async run($: IGlobalVariable) {
|
||||
return options[$.step.parameters.transform as string];
|
||||
},
|
||||
};
|
@@ -0,0 +1,38 @@
|
||||
const formatNumber = [
|
||||
{
|
||||
label: 'Input',
|
||||
key: 'input',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: 'The number you want to format.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Input Decimal Mark',
|
||||
key: 'inputDecimalMark',
|
||||
type: 'dropdown' as const,
|
||||
required: true,
|
||||
description: 'The decimal mark of the input number.',
|
||||
variables: true,
|
||||
options: [
|
||||
{ label: 'Comma', value: ',' },
|
||||
{ label: 'Period', value: '.' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'To Format',
|
||||
key: 'toFormat',
|
||||
type: 'dropdown' as const,
|
||||
required: true,
|
||||
description: 'The format you want to convert the number to.',
|
||||
variables: true,
|
||||
options: [
|
||||
{ label: 'Comma for grouping & period for decimal', value: '0' },
|
||||
{ label: 'Period for grouping & comma for decimal', value: '1' },
|
||||
{ label: 'Space for grouping & period for decimal', value: '2' },
|
||||
{ label: 'Space for grouping & comma for decimal', value: '3' },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export default formatNumber;
|
@@ -0,0 +1,36 @@
|
||||
const performMathOperation = [
|
||||
{
|
||||
label: 'Math Operation',
|
||||
key: 'mathOperation',
|
||||
type: 'dropdown' as const,
|
||||
required: true,
|
||||
description: 'The math operation to perform.',
|
||||
variables: true,
|
||||
options: [
|
||||
{ label: 'Add', value: 'add' },
|
||||
{ label: 'Divide', value: 'divide' },
|
||||
{ label: 'Make Negative', value: 'makeNegative' },
|
||||
{ label: 'Multiply', value: 'multiply' },
|
||||
{ label: 'Subtract', value: 'subtract' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Values',
|
||||
key: 'values',
|
||||
type: 'dynamic' as const,
|
||||
required: false,
|
||||
description: 'Add or remove numbers as needed.',
|
||||
fields: [
|
||||
{
|
||||
label: 'Input',
|
||||
key: 'input',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: 'The number to perform the math operation on.',
|
||||
variables: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export default performMathOperation;
|
@@ -0,0 +1,29 @@
|
||||
const randomNumber = [
|
||||
{
|
||||
label: 'Lower range',
|
||||
key: 'lowerRange',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: 'The lowest number to generate.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Upper range',
|
||||
key: 'upperRange',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: 'The highest number to generate.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Decimal points',
|
||||
key: 'decimalPoints',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description:
|
||||
'The number of digits after the decimal point. It can be an integer between 0 and 15.',
|
||||
variables: true,
|
||||
},
|
||||
];
|
||||
|
||||
export default randomNumber;
|
@@ -0,0 +1,12 @@
|
||||
const capitalize = [
|
||||
{
|
||||
label: 'Input',
|
||||
key: 'input',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: 'Text that will be capitalized.',
|
||||
variables: true,
|
||||
},
|
||||
];
|
||||
|
||||
export default capitalize;
|
@@ -0,0 +1,12 @@
|
||||
const extractEmailAddress = [
|
||||
{
|
||||
label: 'Input',
|
||||
key: 'input',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: 'Text that will be searched for an email address.',
|
||||
variables: true,
|
||||
},
|
||||
];
|
||||
|
||||
export default extractEmailAddress;
|
@@ -0,0 +1,12 @@
|
||||
const extractNumber = [
|
||||
{
|
||||
label: 'Input',
|
||||
key: 'input',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: 'Text that will be searched for a number.',
|
||||
variables: true,
|
||||
},
|
||||
];
|
||||
|
||||
export default extractNumber;
|
@@ -0,0 +1,12 @@
|
||||
const htmlToMarkdown = [
|
||||
{
|
||||
label: 'Input',
|
||||
key: 'input',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: 'HTML that will be converted to Markdown.',
|
||||
variables: true,
|
||||
},
|
||||
];
|
||||
|
||||
export default htmlToMarkdown;
|
@@ -0,0 +1,12 @@
|
||||
const lowercase = [
|
||||
{
|
||||
label: 'Input',
|
||||
key: 'input',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: 'Text that will be lowercased.',
|
||||
variables: true,
|
||||
},
|
||||
];
|
||||
|
||||
export default lowercase;
|
@@ -0,0 +1,12 @@
|
||||
const markdownToHtml = [
|
||||
{
|
||||
label: 'Input',
|
||||
key: 'input',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: 'Markdown text that will be converted to HTML.',
|
||||
variables: true,
|
||||
},
|
||||
];
|
||||
|
||||
export default markdownToHtml;
|
@@ -0,0 +1,12 @@
|
||||
const pluralize = [
|
||||
{
|
||||
label: 'Input',
|
||||
key: 'input',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: 'Text that will be pluralized.',
|
||||
variables: true,
|
||||
},
|
||||
];
|
||||
|
||||
export default pluralize;
|
@@ -0,0 +1,28 @@
|
||||
const replace = [
|
||||
{
|
||||
label: 'Input',
|
||||
key: 'input',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: 'Text that you want to search for and replace values.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Find',
|
||||
key: 'find',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: 'Text that will be searched for.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Replace',
|
||||
key: 'replace',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
description: 'Text that will replace the found text.',
|
||||
variables: true,
|
||||
},
|
||||
];
|
||||
|
||||
export default replace;
|
@@ -0,0 +1,12 @@
|
||||
const trimWhitespace = [
|
||||
{
|
||||
label: 'Input',
|
||||
key: 'input',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: 'Text you want to remove leading and trailing spaces.',
|
||||
variables: true,
|
||||
},
|
||||
];
|
||||
|
||||
export default trimWhitespace;
|
@@ -0,0 +1,21 @@
|
||||
const useDefaultValue = [
|
||||
{
|
||||
label: 'Input',
|
||||
key: 'input',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: 'Text you want to check whether it is empty or not.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Default Value',
|
||||
key: 'defaultValue',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description:
|
||||
'Text that will be used as a default value if the input is empty.',
|
||||
variables: true,
|
||||
},
|
||||
];
|
||||
|
||||
export default useDefaultValue;
|
@@ -0,0 +1,28 @@
|
||||
const findArrayItemByProperty = [
|
||||
{
|
||||
label: 'Value',
|
||||
key: 'value',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: 'Array of objects that will be searched.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Property Name',
|
||||
key: 'propertyName',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: 'Property name that will be searched.',
|
||||
variables: true,
|
||||
},
|
||||
{
|
||||
label: 'Property Value',
|
||||
key: 'propertyValue',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
description: 'Property value that will be matched.',
|
||||
variables: true,
|
||||
},
|
||||
];
|
||||
|
||||
export default findArrayItemByProperty;
|
0
packages/backend/src/apps/formatter/index.d.ts
vendored
Normal file
0
packages/backend/src/apps/formatter/index.d.ts
vendored
Normal file
16
packages/backend/src/apps/formatter/index.ts
Normal file
16
packages/backend/src/apps/formatter/index.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import defineApp from '../../helpers/define-app';
|
||||
import actions from './actions';
|
||||
import dynamicFields from './dynamic-fields';
|
||||
|
||||
export default defineApp({
|
||||
name: 'Formatter',
|
||||
key: 'formatter',
|
||||
iconUrl: '{BASE_URL}/apps/formatter/assets/favicon.svg',
|
||||
authDocUrl: 'https://automatisch.io/docs/apps/formatter/connection',
|
||||
supportsConnections: false,
|
||||
baseUrl: '',
|
||||
apiBaseUrl: '',
|
||||
primaryColor: '001F52',
|
||||
actions,
|
||||
dynamicFields,
|
||||
});
|
@@ -11,7 +11,7 @@ export default defineAction({
|
||||
key: 'repo',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
variables: false,
|
||||
variables: true,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
|
@@ -6,7 +6,7 @@ import actions from './actions';
|
||||
import dynamicData from './dynamic-data';
|
||||
|
||||
export default defineApp({
|
||||
name: 'Github',
|
||||
name: 'GitHub',
|
||||
key: 'github',
|
||||
baseUrl: 'https://github.com',
|
||||
apiBaseUrl: 'https://api.github.com',
|
||||
|
2
packages/backend/src/apps/gitlab/assets/favicon.svg
Normal file
2
packages/backend/src/apps/gitlab/assets/favicon.svg
Normal file
@@ -0,0 +1,2 @@
|
||||
<!-- https://about.gitlab.com/images/press/logo/svg/gitlab-logo-500.svg -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 380 380"><defs><style>.cls-1{fill:#e24329;}.cls-2{fill:#fc6d26;}.cls-3{fill:#fca326;}</style></defs><g id="LOGO"><path class="cls-1" d="M282.83,170.73l-.27-.69-26.14-68.22a6.81,6.81,0,0,0-2.69-3.24,7,7,0,0,0-8,.43,7,7,0,0,0-2.32,3.52l-17.65,54H154.29l-17.65-54A6.86,6.86,0,0,0,134.32,99a7,7,0,0,0-8-.43,6.87,6.87,0,0,0-2.69,3.24L97.44,170l-.26.69a48.54,48.54,0,0,0,16.1,56.1l.09.07.24.17,39.82,29.82,19.7,14.91,12,9.06a8.07,8.07,0,0,0,9.76,0l12-9.06,19.7-14.91,40.06-30,.1-.08A48.56,48.56,0,0,0,282.83,170.73Z"/><path class="cls-2" d="M282.83,170.73l-.27-.69a88.3,88.3,0,0,0-35.15,15.8L190,229.25c19.55,14.79,36.57,27.64,36.57,27.64l40.06-30,.1-.08A48.56,48.56,0,0,0,282.83,170.73Z"/><path class="cls-3" d="M153.43,256.89l19.7,14.91,12,9.06a8.07,8.07,0,0,0,9.76,0l12-9.06,19.7-14.91S209.55,244,190,229.25C170.45,244,153.43,256.89,153.43,256.89Z"/><path class="cls-2" d="M132.58,185.84A88.19,88.19,0,0,0,97.44,170l-.26.69a48.54,48.54,0,0,0,16.1,56.1l.09.07.24.17,39.82,29.82s17-12.85,36.57-27.64Z"/></g></svg>
|
After Width: | Height: | Size: 1.1 KiB |
24
packages/backend/src/apps/gitlab/auth/generate-auth-url.ts
Normal file
24
packages/backend/src/apps/gitlab/auth/generate-auth-url.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
import { URL, URLSearchParams } from 'url';
|
||||
import getBaseUrl from '../common/get-base-url';
|
||||
|
||||
export default async function generateAuthUrl($: IGlobalVariable) {
|
||||
// ref: https://docs.gitlab.com/ee/api/oauth2.html#authorization-code-flow
|
||||
|
||||
const scopes = ['api', 'read_user'];
|
||||
|
||||
const searchParams = new URLSearchParams({
|
||||
client_id: $.auth.data.clientId as string,
|
||||
redirect_uri: $.auth.data.oAuthRedirectUrl as string,
|
||||
scope: scopes.join(' '),
|
||||
response_type: 'code',
|
||||
state: Date.now().toString(),
|
||||
});
|
||||
|
||||
const baseUrl = getBaseUrl($);
|
||||
const path = `/oauth/authorize?${searchParams.toString()}`;
|
||||
|
||||
await $.auth.set({
|
||||
url: new URL(path, baseUrl).toString(),
|
||||
});
|
||||
}
|
63
packages/backend/src/apps/gitlab/auth/index.ts
Normal file
63
packages/backend/src/apps/gitlab/auth/index.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import generateAuthUrl from './generate-auth-url';
|
||||
import verifyCredentials from './verify-credentials';
|
||||
import isStillVerified from './is-still-verified';
|
||||
import refreshToken from './refresh-token';
|
||||
|
||||
export default {
|
||||
fields: [
|
||||
{
|
||||
key: 'oAuthRedirectUrl',
|
||||
label: 'OAuth Redirect URL',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
readOnly: true,
|
||||
value: '{WEB_APP_URL}/app/gitlab/connections/add',
|
||||
placeholder: null,
|
||||
description:
|
||||
'When asked to input an OAuth callback or redirect URL in Gitlab OAuth, enter the URL above.',
|
||||
docUrl: 'https://automatisch.io/docs/gitlab#oauth-redirect-url',
|
||||
clickToCopy: true,
|
||||
},
|
||||
{
|
||||
key: 'instanceUrl',
|
||||
label: 'Gitlab instance URL',
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
readOnly: false,
|
||||
value: 'https://gitlab.com',
|
||||
placeholder: 'https://gitlab.com',
|
||||
description: 'Your Gitlab instance URL. Default is https://gitlab.com.',
|
||||
docUrl: 'https://automatisch.io/docs/gitlab#oauth-redirect-url',
|
||||
clickToCopy: true,
|
||||
},
|
||||
{
|
||||
key: 'clientId',
|
||||
label: 'Client ID',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
readOnly: false,
|
||||
value: null,
|
||||
placeholder: null,
|
||||
description: null,
|
||||
docUrl: 'https://automatisch.io/docs/gitlab#client-id',
|
||||
clickToCopy: false,
|
||||
},
|
||||
{
|
||||
key: 'clientSecret',
|
||||
label: 'Client Secret',
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
readOnly: false,
|
||||
value: null,
|
||||
placeholder: null,
|
||||
description: null,
|
||||
docUrl: 'https://automatisch.io/docs/gitlab#client-secret',
|
||||
clickToCopy: false,
|
||||
},
|
||||
],
|
||||
|
||||
generateAuthUrl,
|
||||
refreshToken,
|
||||
verifyCredentials,
|
||||
isStillVerified,
|
||||
};
|
@@ -0,0 +1,9 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
import getCurrentUser from '../common/get-current-user';
|
||||
|
||||
const isStillVerified = async ($: IGlobalVariable) => {
|
||||
const user = await getCurrentUser($);
|
||||
return !!user.id;
|
||||
};
|
||||
|
||||
export default isStillVerified;
|
24
packages/backend/src/apps/gitlab/auth/refresh-token.ts
Normal file
24
packages/backend/src/apps/gitlab/auth/refresh-token.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
import { URLSearchParams } from 'url';
|
||||
|
||||
const refreshToken = async ($: IGlobalVariable) => {
|
||||
// ref: https://docs.gitlab.com/ee/api/oauth2.html#authorization-code-flow
|
||||
|
||||
const params = new URLSearchParams({
|
||||
grant_type: 'refresh_token',
|
||||
client_id: $.auth.data.clientId as string,
|
||||
client_secret: $.auth.data.clientSecret as string,
|
||||
refresh_token: $.auth.data.refreshToken as string,
|
||||
});
|
||||
|
||||
const { data } = await $.http.post('/oauth/token', params.toString());
|
||||
|
||||
await $.auth.set({
|
||||
accessToken: data.access_token,
|
||||
expiresIn: data.expires_in,
|
||||
tokenType: data.token_type,
|
||||
refreshToken: data.refresh_token,
|
||||
});
|
||||
};
|
||||
|
||||
export default refreshToken;
|
47
packages/backend/src/apps/gitlab/auth/verify-credentials.ts
Normal file
47
packages/backend/src/apps/gitlab/auth/verify-credentials.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
import getCurrentUser from '../common/get-current-user';
|
||||
|
||||
const verifyCredentials = async ($: IGlobalVariable) => {
|
||||
// ref: https://docs.gitlab.com/ee/api/oauth2.html#authorization-code-flow
|
||||
|
||||
const response = await $.http.post(
|
||||
'/oauth/token',
|
||||
{
|
||||
client_id: $.auth.data.clientId,
|
||||
client_secret: $.auth.data.clientSecret,
|
||||
code: $.auth.data.code,
|
||||
grant_type: 'authorization_code',
|
||||
redirect_uri: $.auth.data.oAuthRedirectUrl,
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const data = response.data;
|
||||
|
||||
$.auth.data.accessToken = data.access_token;
|
||||
|
||||
const currentUser = await getCurrentUser($);
|
||||
const screenName = [
|
||||
currentUser.username,
|
||||
$.auth.data.instanceUrl,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(' @ ');
|
||||
|
||||
await $.auth.set({
|
||||
clientId: $.auth.data.clientId,
|
||||
clientSecret: $.auth.data.clientSecret,
|
||||
accessToken: data.access_token,
|
||||
refreshToken: data.refresh_token,
|
||||
scope: data.scope,
|
||||
tokenType: data.token_type,
|
||||
userId: currentUser.id,
|
||||
screenName,
|
||||
});
|
||||
};
|
||||
|
||||
export default verifyCredentials;
|
11
packages/backend/src/apps/gitlab/common/add-auth-header.ts
Normal file
11
packages/backend/src/apps/gitlab/common/add-auth-header.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { TBeforeRequest } from '@automatisch/types';
|
||||
|
||||
const addAuthHeader: TBeforeRequest = ($, requestConfig) => {
|
||||
if ($.auth.data?.accessToken) {
|
||||
requestConfig.headers = requestConfig.headers || {};
|
||||
requestConfig.headers.Authorization = `Bearer ${$.auth.data.accessToken}`;
|
||||
}
|
||||
return requestConfig;
|
||||
};
|
||||
|
||||
export default addAuthHeader;
|
15
packages/backend/src/apps/gitlab/common/get-base-url.ts
Normal file
15
packages/backend/src/apps/gitlab/common/get-base-url.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
|
||||
const getBaseUrl = ($: IGlobalVariable): string => {
|
||||
if ($.auth.data.instanceUrl) {
|
||||
return $.auth.data.instanceUrl as string;
|
||||
}
|
||||
|
||||
if ($.app.apiBaseUrl) {
|
||||
return $.app.apiBaseUrl;
|
||||
}
|
||||
|
||||
return $.app.baseUrl;
|
||||
};
|
||||
|
||||
export default getBaseUrl;
|
11
packages/backend/src/apps/gitlab/common/get-current-user.ts
Normal file
11
packages/backend/src/apps/gitlab/common/get-current-user.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { IGlobalVariable, IJSONObject } from '@automatisch/types';
|
||||
|
||||
const getCurrentUser = async ($: IGlobalVariable): Promise<IJSONObject> => {
|
||||
// ref: https://docs.gitlab.com/ee/api/users.html#list-current-user
|
||||
|
||||
const response = await $.http.get('/api/v4/user');
|
||||
const currentUser = response.data;
|
||||
return currentUser;
|
||||
};
|
||||
|
||||
export default getCurrentUser;
|
33
packages/backend/src/apps/gitlab/common/paginate-all.ts
Normal file
33
packages/backend/src/apps/gitlab/common/paginate-all.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { IGlobalVariable, IJSONObject } from '@automatisch/types';
|
||||
import type { AxiosResponse } from 'axios';
|
||||
import parseLinkHeader from '../../../helpers/parse-header-link';
|
||||
|
||||
type TResponse = {
|
||||
data: IJSONObject[];
|
||||
error?: IJSONObject;
|
||||
};
|
||||
|
||||
export default async function paginateAll(
|
||||
$: IGlobalVariable,
|
||||
request: Promise<AxiosResponse>
|
||||
) {
|
||||
const response = await request;
|
||||
|
||||
const aggregatedResponse: TResponse = {
|
||||
data: [...response.data],
|
||||
};
|
||||
|
||||
let links = parseLinkHeader(response.headers.link);
|
||||
|
||||
while (links.next) {
|
||||
const nextPageResponse = await $.http.request({
|
||||
...response.config,
|
||||
url: links.next.uri,
|
||||
});
|
||||
|
||||
aggregatedResponse.data.push(...nextPageResponse.data);
|
||||
links = parseLinkHeader(nextPageResponse.headers.link);
|
||||
}
|
||||
|
||||
return aggregatedResponse;
|
||||
}
|
13
packages/backend/src/apps/gitlab/common/set-base-url.ts
Normal file
13
packages/backend/src/apps/gitlab/common/set-base-url.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { TBeforeRequest } from '@automatisch/types';
|
||||
|
||||
const setBaseUrl: TBeforeRequest = ($, requestConfig) => {
|
||||
if ($.auth.data.instanceUrl) {
|
||||
requestConfig.baseURL = $.auth.data.instanceUrl as string;
|
||||
} else if ($.app.apiBaseUrl) {
|
||||
requestConfig.baseURL = $.app.apiBaseUrl as string;
|
||||
}
|
||||
|
||||
return requestConfig;
|
||||
};
|
||||
|
||||
export default setBaseUrl;
|
3
packages/backend/src/apps/gitlab/dynamic-data/index.ts
Normal file
3
packages/backend/src/apps/gitlab/dynamic-data/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import listProjects from './list-projects';
|
||||
|
||||
export default [listProjects];
|
@@ -0,0 +1,33 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
import paginateAll from '../../common/paginate-all';
|
||||
|
||||
export default {
|
||||
name: 'List projects',
|
||||
key: 'listProjects',
|
||||
|
||||
async run($: IGlobalVariable) {
|
||||
// ref:
|
||||
// - https://docs.gitlab.com/ee/api/projects.html#list-all-projects
|
||||
// - https://docs.gitlab.com/ee/api/rest/index.html#keyset-based-pagination
|
||||
const firstPageRequest = $.http.get('/api/v4/projects', {
|
||||
params: {
|
||||
simple: true,
|
||||
pagination: 'keyset',
|
||||
membership: true,
|
||||
order_by: 'id',
|
||||
sort: 'asc',
|
||||
},
|
||||
});
|
||||
|
||||
const response = await paginateAll($, firstPageRequest);
|
||||
|
||||
response.data = response.data.map((repo: { name: string; id: number }) => {
|
||||
return {
|
||||
value: repo.id,
|
||||
name: repo.name,
|
||||
};
|
||||
});
|
||||
|
||||
return response;
|
||||
},
|
||||
};
|
1
packages/backend/src/apps/gitlab/index.d.ts
vendored
Normal file
1
packages/backend/src/apps/gitlab/index.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
|
21
packages/backend/src/apps/gitlab/index.ts
Normal file
21
packages/backend/src/apps/gitlab/index.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import defineApp from '../../helpers/define-app';
|
||||
import addAuthHeader from './common/add-auth-header';
|
||||
import setBaseUrl from './common/set-base-url';
|
||||
import auth from './auth';
|
||||
import triggers from './triggers';
|
||||
import dynamicData from './dynamic-data';
|
||||
|
||||
export default defineApp({
|
||||
name: 'GitLab',
|
||||
key: 'gitlab',
|
||||
baseUrl: 'https://gitlab.com',
|
||||
apiBaseUrl: 'https://gitlab.com',
|
||||
iconUrl: '{BASE_URL}/apps/gitlab/assets/favicon.svg',
|
||||
authDocUrl: 'https://automatisch.io/docs/apps/gitlab/connection',
|
||||
primaryColor: 'FC6D26',
|
||||
supportsConnections: true,
|
||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||
auth,
|
||||
triggers,
|
||||
dynamicData,
|
||||
});
|
@@ -0,0 +1,27 @@
|
||||
import { IRawTrigger } from '@automatisch/types';
|
||||
import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import { GITLAB_EVENT_TYPE } from '../types';
|
||||
import {
|
||||
getRegisterHookFn,
|
||||
getTestRunFn,
|
||||
projectArgumentDescriptor,
|
||||
unregisterHook,
|
||||
} from '../lib';
|
||||
|
||||
// confidential_issues_events has the same event data as issues_events
|
||||
import data from './issue_event';
|
||||
|
||||
export const triggerDescriptor: IRawTrigger = {
|
||||
name: 'Confidential issue event',
|
||||
description:
|
||||
'Confidential issue event (triggered when a new confidential issue is created or an existing issue is updated, closed, or reopened)',
|
||||
// info: 'https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#issue-events',
|
||||
key: GITLAB_EVENT_TYPE.confidential_issues_events,
|
||||
type: 'webhook',
|
||||
arguments: [projectArgumentDescriptor],
|
||||
testRun: getTestRunFn(data),
|
||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.confidential_issues_events),
|
||||
unregisterHook,
|
||||
};
|
||||
|
||||
export default defineTrigger(triggerDescriptor);
|
@@ -0,0 +1,159 @@
|
||||
// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#issue-events
|
||||
|
||||
export default {
|
||||
object_kind: 'issue',
|
||||
event_type: 'issue',
|
||||
user: {
|
||||
id: 1,
|
||||
name: 'Administrator',
|
||||
username: 'root',
|
||||
avatar_url:
|
||||
'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon',
|
||||
email: 'admin@example.com',
|
||||
},
|
||||
project: {
|
||||
id: 1,
|
||||
name: 'Gitlab Test',
|
||||
description: 'Aut reprehenderit ut est.',
|
||||
web_url: 'http://example.com/gitlabhq/gitlab-test',
|
||||
avatar_url: null,
|
||||
git_ssh_url: 'git@example.com:gitlabhq/gitlab-test.git',
|
||||
git_http_url: 'http://example.com/gitlabhq/gitlab-test.git',
|
||||
namespace: 'GitlabHQ',
|
||||
visibility_level: 20,
|
||||
path_with_namespace: 'gitlabhq/gitlab-test',
|
||||
default_branch: 'master',
|
||||
ci_config_path: null,
|
||||
homepage: 'http://example.com/gitlabhq/gitlab-test',
|
||||
url: 'http://example.com/gitlabhq/gitlab-test.git',
|
||||
ssh_url: 'git@example.com:gitlabhq/gitlab-test.git',
|
||||
http_url: 'http://example.com/gitlabhq/gitlab-test.git',
|
||||
},
|
||||
object_attributes: {
|
||||
id: 301,
|
||||
title: 'New API: create/update/delete file',
|
||||
assignee_ids: [51],
|
||||
assignee_id: 51,
|
||||
author_id: 51,
|
||||
project_id: 14,
|
||||
created_at: '2013-12-03T17:15:43Z',
|
||||
updated_at: '2013-12-03T17:15:43Z',
|
||||
updated_by_id: 1,
|
||||
last_edited_at: null,
|
||||
last_edited_by_id: null,
|
||||
relative_position: 0,
|
||||
description: 'Create new API for manipulations with repository',
|
||||
milestone_id: null,
|
||||
state_id: 1,
|
||||
confidential: false,
|
||||
discussion_locked: true,
|
||||
due_date: null,
|
||||
moved_to_id: null,
|
||||
duplicated_to_id: null,
|
||||
time_estimate: 0,
|
||||
total_time_spent: 0,
|
||||
time_change: 0,
|
||||
human_total_time_spent: null,
|
||||
human_time_estimate: null,
|
||||
human_time_change: null,
|
||||
weight: null,
|
||||
iid: 23,
|
||||
url: 'http://example.com/diaspora/issues/23',
|
||||
state: 'opened',
|
||||
action: 'open',
|
||||
severity: 'high',
|
||||
escalation_status: 'triggered',
|
||||
escalation_policy: {
|
||||
id: 18,
|
||||
name: 'Engineering On-call',
|
||||
},
|
||||
labels: [
|
||||
{
|
||||
id: 206,
|
||||
title: 'API',
|
||||
color: '#ffffff',
|
||||
project_id: 14,
|
||||
created_at: '2013-12-03T17:15:43Z',
|
||||
updated_at: '2013-12-03T17:15:43Z',
|
||||
template: false,
|
||||
description: 'API related issues',
|
||||
type: 'ProjectLabel',
|
||||
group_id: 41,
|
||||
},
|
||||
],
|
||||
},
|
||||
repository: {
|
||||
name: 'Gitlab Test',
|
||||
url: 'http://example.com/gitlabhq/gitlab-test.git',
|
||||
description: 'Aut reprehenderit ut est.',
|
||||
homepage: 'http://example.com/gitlabhq/gitlab-test',
|
||||
},
|
||||
assignees: [
|
||||
{
|
||||
name: 'User1',
|
||||
username: 'user1',
|
||||
avatar_url:
|
||||
'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon',
|
||||
},
|
||||
],
|
||||
assignee: {
|
||||
name: 'User1',
|
||||
username: 'user1',
|
||||
avatar_url:
|
||||
'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon',
|
||||
},
|
||||
labels: [
|
||||
{
|
||||
id: 206,
|
||||
title: 'API',
|
||||
color: '#ffffff',
|
||||
project_id: 14,
|
||||
created_at: '2013-12-03T17:15:43Z',
|
||||
updated_at: '2013-12-03T17:15:43Z',
|
||||
template: false,
|
||||
description: 'API related issues',
|
||||
type: 'ProjectLabel',
|
||||
group_id: 41,
|
||||
},
|
||||
],
|
||||
changes: {
|
||||
updated_by_id: {
|
||||
previous: null,
|
||||
current: 1,
|
||||
},
|
||||
updated_at: {
|
||||
previous: '2017-09-15 16:50:55 UTC',
|
||||
current: '2017-09-15 16:52:00 UTC',
|
||||
},
|
||||
labels: {
|
||||
previous: [
|
||||
{
|
||||
id: 206,
|
||||
title: 'API',
|
||||
color: '#ffffff',
|
||||
project_id: 14,
|
||||
created_at: '2013-12-03T17:15:43Z',
|
||||
updated_at: '2013-12-03T17:15:43Z',
|
||||
template: false,
|
||||
description: 'API related issues',
|
||||
type: 'ProjectLabel',
|
||||
group_id: 41,
|
||||
},
|
||||
],
|
||||
current: [
|
||||
{
|
||||
id: 205,
|
||||
title: 'Platform',
|
||||
color: '#123123',
|
||||
project_id: 14,
|
||||
created_at: '2013-12-03T17:15:43Z',
|
||||
updated_at: '2013-12-03T17:15:43Z',
|
||||
template: false,
|
||||
description: 'Platform related issues',
|
||||
type: 'ProjectLabel',
|
||||
group_id: 41,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
@@ -0,0 +1,27 @@
|
||||
import { IRawTrigger } from '@automatisch/types';
|
||||
import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import { GITLAB_EVENT_TYPE } from '../types';
|
||||
import {
|
||||
getRegisterHookFn,
|
||||
getTestRunFn,
|
||||
projectArgumentDescriptor,
|
||||
unregisterHook,
|
||||
} from '../lib';
|
||||
|
||||
// confidential_note_events has the same event data as note_events
|
||||
import data from './note_event';
|
||||
|
||||
export const triggerDescriptor: IRawTrigger = {
|
||||
name: 'Confidential comment event',
|
||||
description:
|
||||
'Confidential comment event (triggered when a new confidential comment is made on commits, merge requests, issues, and code snippets)',
|
||||
// info: 'https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#comment-events',
|
||||
key: GITLAB_EVENT_TYPE.confidential_note_events,
|
||||
type: 'webhook',
|
||||
arguments: [projectArgumentDescriptor],
|
||||
testRun: getTestRunFn(data),
|
||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.confidential_note_events),
|
||||
unregisterHook,
|
||||
};
|
||||
|
||||
export default defineTrigger(triggerDescriptor);
|
@@ -0,0 +1,74 @@
|
||||
// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#comment-events
|
||||
|
||||
export default {
|
||||
object_kind: 'note',
|
||||
event_type: 'note',
|
||||
user: {
|
||||
id: 1,
|
||||
name: 'Administrator',
|
||||
username: 'root',
|
||||
avatar_url:
|
||||
'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon',
|
||||
email: 'admin@example.com',
|
||||
},
|
||||
project_id: 5,
|
||||
project: {
|
||||
id: 5,
|
||||
name: 'Gitlab Test',
|
||||
description: 'Aut reprehenderit ut est.',
|
||||
web_url: 'http://example.com/gitlabhq/gitlab-test',
|
||||
avatar_url: null,
|
||||
git_ssh_url: 'git@example.com:gitlabhq/gitlab-test.git',
|
||||
git_http_url: 'http://example.com/gitlabhq/gitlab-test.git',
|
||||
namespace: 'GitlabHQ',
|
||||
visibility_level: 20,
|
||||
path_with_namespace: 'gitlabhq/gitlab-test',
|
||||
default_branch: 'master',
|
||||
homepage: 'http://example.com/gitlabhq/gitlab-test',
|
||||
url: 'http://example.com/gitlabhq/gitlab-test.git',
|
||||
ssh_url: 'git@example.com:gitlabhq/gitlab-test.git',
|
||||
http_url: 'http://example.com/gitlabhq/gitlab-test.git',
|
||||
},
|
||||
repository: {
|
||||
name: 'Gitlab Test',
|
||||
url: 'http://example.com/gitlab-org/gitlab-test.git',
|
||||
description: 'Aut reprehenderit ut est.',
|
||||
homepage: 'http://example.com/gitlab-org/gitlab-test',
|
||||
},
|
||||
object_attributes: {
|
||||
id: 1243,
|
||||
note: 'This is a commit comment. How does this work?',
|
||||
noteable_type: 'Commit',
|
||||
author_id: 1,
|
||||
created_at: '2015-05-17 18:08:09 UTC',
|
||||
updated_at: '2015-05-17 18:08:09 UTC',
|
||||
project_id: 5,
|
||||
attachment: null,
|
||||
line_code: 'bec9703f7a456cd2b4ab5fb3220ae016e3e394e3_0_1',
|
||||
commit_id: 'cfe32cf61b73a0d5e9f13e774abde7ff789b1660',
|
||||
noteable_id: null,
|
||||
system: false,
|
||||
st_diff: {
|
||||
diff: '--- /dev/null\n+++ b/six\n@@ -0,0 +1 @@\n+Subproject commit 409f37c4f05865e4fb208c771485f211a22c4c2d\n',
|
||||
new_path: 'six',
|
||||
old_path: 'six',
|
||||
a_mode: '0',
|
||||
b_mode: '160000',
|
||||
new_file: true,
|
||||
renamed_file: false,
|
||||
deleted_file: false,
|
||||
},
|
||||
url: 'http://example.com/gitlab-org/gitlab-test/commit/cfe32cf61b73a0d5e9f13e774abde7ff789b1660#note_1243',
|
||||
},
|
||||
commit: {
|
||||
id: 'cfe32cf61b73a0d5e9f13e774abde7ff789b1660',
|
||||
message:
|
||||
'Add submodule\n\nSigned-off-by: Example User \u003cuser@example.com.com\u003e\n',
|
||||
timestamp: '2014-02-27T10:06:20+02:00',
|
||||
url: 'http://example.com/gitlab-org/gitlab-test/commit/cfe32cf61b73a0d5e9f13e774abde7ff789b1660',
|
||||
author: {
|
||||
name: 'Example User',
|
||||
email: 'user@example.com',
|
||||
},
|
||||
},
|
||||
};
|
@@ -0,0 +1,45 @@
|
||||
// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#deployment-events
|
||||
|
||||
export default {
|
||||
object_kind: 'deployment',
|
||||
status: 'success',
|
||||
status_changed_at: '2021-04-28 21:50:00 +0200',
|
||||
deployment_id: 15,
|
||||
deployable_id: 796,
|
||||
deployable_url:
|
||||
'http://10.126.0.2:3000/root/test-deployment-webhooks/-/jobs/796',
|
||||
environment: 'staging',
|
||||
environment_slug: 'staging',
|
||||
environment_external_url: 'https://staging.example.com',
|
||||
project: {
|
||||
id: 30,
|
||||
name: 'test-deployment-webhooks',
|
||||
description: '',
|
||||
web_url: 'http://10.126.0.2:3000/root/test-deployment-webhooks',
|
||||
avatar_url: null,
|
||||
git_ssh_url: 'ssh://vlad@10.126.0.2:2222/root/test-deployment-webhooks.git',
|
||||
git_http_url: 'http://10.126.0.2:3000/root/test-deployment-webhooks.git',
|
||||
namespace: 'Administrator',
|
||||
visibility_level: 0,
|
||||
path_with_namespace: 'root/test-deployment-webhooks',
|
||||
default_branch: 'master',
|
||||
ci_config_path: '',
|
||||
homepage: 'http://10.126.0.2:3000/root/test-deployment-webhooks',
|
||||
url: 'ssh://vlad@10.126.0.2:2222/root/test-deployment-webhooks.git',
|
||||
ssh_url: 'ssh://vlad@10.126.0.2:2222/root/test-deployment-webhooks.git',
|
||||
http_url: 'http://10.126.0.2:3000/root/test-deployment-webhooks.git',
|
||||
},
|
||||
short_sha: '279484c0',
|
||||
user: {
|
||||
id: 1,
|
||||
name: 'Administrator',
|
||||
username: 'root',
|
||||
avatar_url:
|
||||
'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
|
||||
email: 'admin@example.com',
|
||||
},
|
||||
user_url: 'http://10.126.0.2:3000/root',
|
||||
commit_url:
|
||||
'http://10.126.0.2:3000/root/test-deployment-webhooks/-/commit/279484c09fbe69ededfced8c1bb6e6d24616b468',
|
||||
commit_title: 'Add new file',
|
||||
};
|
@@ -0,0 +1,26 @@
|
||||
import { IRawTrigger } from '@automatisch/types';
|
||||
import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import { GITLAB_EVENT_TYPE } from '../types';
|
||||
import {
|
||||
getRegisterHookFn,
|
||||
getTestRunFn,
|
||||
projectArgumentDescriptor,
|
||||
unregisterHook,
|
||||
} from '../lib';
|
||||
|
||||
import data from './deployment_event';
|
||||
|
||||
export const triggerDescriptor: IRawTrigger = {
|
||||
name: 'Deployment event',
|
||||
description:
|
||||
'Deployment event (triggered when a deployment starts, succeeds, fails or is canceled)',
|
||||
// info: 'https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#deployment-events',
|
||||
key: GITLAB_EVENT_TYPE.deployment_events,
|
||||
type: 'webhook',
|
||||
arguments: [projectArgumentDescriptor],
|
||||
testRun: getTestRunFn(data),
|
||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.deployment_events),
|
||||
unregisterHook,
|
||||
};
|
||||
|
||||
export default defineTrigger(triggerDescriptor);
|
@@ -0,0 +1,38 @@
|
||||
// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#feature-flag-events
|
||||
|
||||
export default {
|
||||
object_kind: 'feature_flag',
|
||||
project: {
|
||||
id: 1,
|
||||
name: 'Gitlab Test',
|
||||
description: 'Aut reprehenderit ut est.',
|
||||
web_url: 'http://example.com/gitlabhq/gitlab-test',
|
||||
avatar_url: null,
|
||||
git_ssh_url: 'git@example.com:gitlabhq/gitlab-test.git',
|
||||
git_http_url: 'http://example.com/gitlabhq/gitlab-test.git',
|
||||
namespace: 'GitlabHQ',
|
||||
visibility_level: 20,
|
||||
path_with_namespace: 'gitlabhq/gitlab-test',
|
||||
default_branch: 'master',
|
||||
ci_config_path: null,
|
||||
homepage: 'http://example.com/gitlabhq/gitlab-test',
|
||||
url: 'http://example.com/gitlabhq/gitlab-test.git',
|
||||
ssh_url: 'git@example.com:gitlabhq/gitlab-test.git',
|
||||
http_url: 'http://example.com/gitlabhq/gitlab-test.git',
|
||||
},
|
||||
user: {
|
||||
id: 1,
|
||||
name: 'Administrator',
|
||||
username: 'root',
|
||||
avatar_url:
|
||||
'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
|
||||
email: 'admin@example.com',
|
||||
},
|
||||
user_url: 'http://example.com/root',
|
||||
object_attributes: {
|
||||
id: 6,
|
||||
name: 'test-feature-flag',
|
||||
description: 'test-feature-flag-description',
|
||||
active: true,
|
||||
},
|
||||
};
|
@@ -0,0 +1,26 @@
|
||||
import { IRawTrigger } from '@automatisch/types';
|
||||
import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import { GITLAB_EVENT_TYPE } from '../types';
|
||||
import {
|
||||
getRegisterHookFn,
|
||||
getTestRunFn,
|
||||
projectArgumentDescriptor,
|
||||
unregisterHook,
|
||||
} from '../lib';
|
||||
|
||||
import data from './feature_flag_event';
|
||||
|
||||
export const triggerDescriptor: IRawTrigger = {
|
||||
name: 'Feature flag event',
|
||||
description:
|
||||
'Feature flag event (triggered when a feature flag is turned on or off)',
|
||||
// info: 'https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#feature-flag-events',
|
||||
key: GITLAB_EVENT_TYPE.feature_flag_events,
|
||||
type: 'webhook',
|
||||
arguments: [projectArgumentDescriptor],
|
||||
testRun: getTestRunFn(data),
|
||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.feature_flag_events),
|
||||
unregisterHook,
|
||||
};
|
||||
|
||||
export default defineTrigger(triggerDescriptor);
|
29
packages/backend/src/apps/gitlab/triggers/index.ts
Normal file
29
packages/backend/src/apps/gitlab/triggers/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import confidentialIssueEvent from './confidential-issue-event';
|
||||
import confidentialNoteEvent from './confidential-note-event';
|
||||
import deploymentEvent from './deployment-event';
|
||||
import featureFlagEvent from './feature-flag-event';
|
||||
import issueEvent from './issue-event';
|
||||
import jobEvent from './job-event';
|
||||
import mergeRequestEvent from './merge-request-event';
|
||||
import noteEvent from './note-event';
|
||||
import pipelineEvent from './pipeline-event';
|
||||
import pushEvent from './push-event';
|
||||
import releaseEvent from './release-event';
|
||||
import tagPushEvent from './tag-push-event';
|
||||
import wikiPageEvent from './wiki-page-event';
|
||||
|
||||
export default [
|
||||
confidentialIssueEvent,
|
||||
confidentialNoteEvent,
|
||||
deploymentEvent,
|
||||
featureFlagEvent,
|
||||
issueEvent,
|
||||
jobEvent,
|
||||
mergeRequestEvent,
|
||||
noteEvent,
|
||||
pipelineEvent,
|
||||
pushEvent,
|
||||
releaseEvent,
|
||||
tagPushEvent,
|
||||
wikiPageEvent,
|
||||
];
|
@@ -0,0 +1,26 @@
|
||||
import { IRawTrigger } from '@automatisch/types';
|
||||
import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import { GITLAB_EVENT_TYPE } from '../types';
|
||||
import {
|
||||
getRegisterHookFn,
|
||||
getTestRunFn,
|
||||
projectArgumentDescriptor,
|
||||
unregisterHook,
|
||||
} from '../lib';
|
||||
|
||||
import data from './issue_event';
|
||||
|
||||
export const triggerDescriptor: IRawTrigger = {
|
||||
name: 'Issue event',
|
||||
description:
|
||||
'Issue event (triggered when a new issue is created or an existing issue is updated, closed, or reopened)',
|
||||
// info: 'https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#issue-events',
|
||||
key: GITLAB_EVENT_TYPE.issues_events,
|
||||
type: 'webhook',
|
||||
arguments: [projectArgumentDescriptor],
|
||||
testRun: getTestRunFn(data),
|
||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.issues_events),
|
||||
unregisterHook,
|
||||
};
|
||||
|
||||
export default defineTrigger(triggerDescriptor);
|
@@ -0,0 +1,159 @@
|
||||
// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#issue-events
|
||||
|
||||
export default {
|
||||
object_kind: 'issue',
|
||||
event_type: 'issue',
|
||||
user: {
|
||||
id: 1,
|
||||
name: 'Administrator',
|
||||
username: 'root',
|
||||
avatar_url:
|
||||
'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon',
|
||||
email: 'admin@example.com',
|
||||
},
|
||||
project: {
|
||||
id: 1,
|
||||
name: 'Gitlab Test',
|
||||
description: 'Aut reprehenderit ut est.',
|
||||
web_url: 'http://example.com/gitlabhq/gitlab-test',
|
||||
avatar_url: null,
|
||||
git_ssh_url: 'git@example.com:gitlabhq/gitlab-test.git',
|
||||
git_http_url: 'http://example.com/gitlabhq/gitlab-test.git',
|
||||
namespace: 'GitlabHQ',
|
||||
visibility_level: 20,
|
||||
path_with_namespace: 'gitlabhq/gitlab-test',
|
||||
default_branch: 'master',
|
||||
ci_config_path: null,
|
||||
homepage: 'http://example.com/gitlabhq/gitlab-test',
|
||||
url: 'http://example.com/gitlabhq/gitlab-test.git',
|
||||
ssh_url: 'git@example.com:gitlabhq/gitlab-test.git',
|
||||
http_url: 'http://example.com/gitlabhq/gitlab-test.git',
|
||||
},
|
||||
object_attributes: {
|
||||
id: 301,
|
||||
title: 'New API: create/update/delete file',
|
||||
assignee_ids: [51],
|
||||
assignee_id: 51,
|
||||
author_id: 51,
|
||||
project_id: 14,
|
||||
created_at: '2013-12-03T17:15:43Z',
|
||||
updated_at: '2013-12-03T17:15:43Z',
|
||||
updated_by_id: 1,
|
||||
last_edited_at: null,
|
||||
last_edited_by_id: null,
|
||||
relative_position: 0,
|
||||
description: 'Create new API for manipulations with repository',
|
||||
milestone_id: null,
|
||||
state_id: 1,
|
||||
confidential: false,
|
||||
discussion_locked: true,
|
||||
due_date: null,
|
||||
moved_to_id: null,
|
||||
duplicated_to_id: null,
|
||||
time_estimate: 0,
|
||||
total_time_spent: 0,
|
||||
time_change: 0,
|
||||
human_total_time_spent: null,
|
||||
human_time_estimate: null,
|
||||
human_time_change: null,
|
||||
weight: null,
|
||||
iid: 23,
|
||||
url: 'http://example.com/diaspora/issues/23',
|
||||
state: 'opened',
|
||||
action: 'open',
|
||||
severity: 'high',
|
||||
escalation_status: 'triggered',
|
||||
escalation_policy: {
|
||||
id: 18,
|
||||
name: 'Engineering On-call',
|
||||
},
|
||||
labels: [
|
||||
{
|
||||
id: 206,
|
||||
title: 'API',
|
||||
color: '#ffffff',
|
||||
project_id: 14,
|
||||
created_at: '2013-12-03T17:15:43Z',
|
||||
updated_at: '2013-12-03T17:15:43Z',
|
||||
template: false,
|
||||
description: 'API related issues',
|
||||
type: 'ProjectLabel',
|
||||
group_id: 41,
|
||||
},
|
||||
],
|
||||
},
|
||||
repository: {
|
||||
name: 'Gitlab Test',
|
||||
url: 'http://example.com/gitlabhq/gitlab-test.git',
|
||||
description: 'Aut reprehenderit ut est.',
|
||||
homepage: 'http://example.com/gitlabhq/gitlab-test',
|
||||
},
|
||||
assignees: [
|
||||
{
|
||||
name: 'User1',
|
||||
username: 'user1',
|
||||
avatar_url:
|
||||
'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon',
|
||||
},
|
||||
],
|
||||
assignee: {
|
||||
name: 'User1',
|
||||
username: 'user1',
|
||||
avatar_url:
|
||||
'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon',
|
||||
},
|
||||
labels: [
|
||||
{
|
||||
id: 206,
|
||||
title: 'API',
|
||||
color: '#ffffff',
|
||||
project_id: 14,
|
||||
created_at: '2013-12-03T17:15:43Z',
|
||||
updated_at: '2013-12-03T17:15:43Z',
|
||||
template: false,
|
||||
description: 'API related issues',
|
||||
type: 'ProjectLabel',
|
||||
group_id: 41,
|
||||
},
|
||||
],
|
||||
changes: {
|
||||
updated_by_id: {
|
||||
previous: null,
|
||||
current: 1,
|
||||
},
|
||||
updated_at: {
|
||||
previous: '2017-09-15 16:50:55 UTC',
|
||||
current: '2017-09-15 16:52:00 UTC',
|
||||
},
|
||||
labels: {
|
||||
previous: [
|
||||
{
|
||||
id: 206,
|
||||
title: 'API',
|
||||
color: '#ffffff',
|
||||
project_id: 14,
|
||||
created_at: '2013-12-03T17:15:43Z',
|
||||
updated_at: '2013-12-03T17:15:43Z',
|
||||
template: false,
|
||||
description: 'API related issues',
|
||||
type: 'ProjectLabel',
|
||||
group_id: 41,
|
||||
},
|
||||
],
|
||||
current: [
|
||||
{
|
||||
id: 205,
|
||||
title: 'Platform',
|
||||
color: '#123123',
|
||||
project_id: 14,
|
||||
created_at: '2013-12-03T17:15:43Z',
|
||||
updated_at: '2013-12-03T17:15:43Z',
|
||||
template: false,
|
||||
description: 'Platform related issues',
|
||||
type: 'ProjectLabel',
|
||||
group_id: 41,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
25
packages/backend/src/apps/gitlab/triggers/job-event/index.ts
Normal file
25
packages/backend/src/apps/gitlab/triggers/job-event/index.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { IRawTrigger } from '@automatisch/types';
|
||||
import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import { GITLAB_EVENT_TYPE } from '../types';
|
||||
import {
|
||||
getRegisterHookFn,
|
||||
getTestRunFn,
|
||||
projectArgumentDescriptor,
|
||||
unregisterHook,
|
||||
} from '../lib';
|
||||
|
||||
import data from './job_event';
|
||||
|
||||
export const triggerDescriptor: IRawTrigger = {
|
||||
name: 'Job event',
|
||||
description: 'Job event (triggered when the status of a job changes)',
|
||||
// info: 'https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#job-events',
|
||||
key: GITLAB_EVENT_TYPE.job_events,
|
||||
type: 'webhook',
|
||||
arguments: [projectArgumentDescriptor],
|
||||
testRun: getTestRunFn(data),
|
||||
registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.job_events),
|
||||
unregisterHook,
|
||||
};
|
||||
|
||||
export default defineTrigger(triggerDescriptor);
|
@@ -0,0 +1,60 @@
|
||||
// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#job-events
|
||||
|
||||
export default {
|
||||
object_kind: 'build',
|
||||
ref: 'gitlab-script-trigger',
|
||||
tag: false,
|
||||
before_sha: '2293ada6b400935a1378653304eaf6221e0fdb8f',
|
||||
sha: '2293ada6b400935a1378653304eaf6221e0fdb8f',
|
||||
build_id: 1977,
|
||||
build_name: 'test',
|
||||
build_stage: 'test',
|
||||
build_status: 'created',
|
||||
build_created_at: '2021-02-23T02:41:37.886Z',
|
||||
build_started_at: null,
|
||||
build_finished_at: null,
|
||||
build_duration: null,
|
||||
build_queued_duration: 1095.588715, // duration in seconds
|
||||
build_allow_failure: false,
|
||||
build_failure_reason: 'script_failure',
|
||||
retries_count: 2, // the second retry of this job
|
||||
pipeline_id: 2366,
|
||||
project_id: 380,
|
||||
project_name: 'gitlab-org/gitlab-test',
|
||||
user: {
|
||||
id: 3,
|
||||
name: 'User',
|
||||
email: 'user@gitlab.com',
|
||||
avatar_url:
|
||||
'http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon',
|
||||
},
|
||||
commit: {
|
||||
id: 2366,
|
||||
name: 'Build pipeline',
|
||||
sha: '2293ada6b400935a1378653304eaf6221e0fdb8f',
|
||||
message: 'test\n',
|
||||
author_name: 'User',
|
||||
author_email: 'user@gitlab.com',
|
||||
status: 'created',
|
||||
duration: null,
|
||||
started_at: null,
|
||||
finished_at: null,
|
||||
},
|
||||
repository: {
|
||||
name: 'gitlab_test',
|
||||
description: 'Atque in sunt eos similique dolores voluptatem.',
|
||||
homepage: 'http://192.168.64.1:3005/gitlab-org/gitlab-test',
|
||||
git_ssh_url: 'git@192.168.64.1:gitlab-org/gitlab-test.git',
|
||||
git_http_url: 'http://192.168.64.1:3005/gitlab-org/gitlab-test.git',
|
||||
visibility_level: 20,
|
||||
},
|
||||
runner: {
|
||||
active: true,
|
||||
runner_type: 'project_type',
|
||||
is_shared: false,
|
||||
id: 380987,
|
||||
description: 'shared-runners-manager-6.gitlab.com',
|
||||
tags: ['linux', 'docker'],
|
||||
},
|
||||
environment: null,
|
||||
};
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user