diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000000..ff08c12b59
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,22 @@
+{
+ // Use IntelliSense to learn about possible attributes.
+ // Hover to view descriptions of existing attributes.
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Debug server",
+ "type": "node",
+ "request": "launch",
+ "args": ["src/__start.ts"],
+ "env": {
+ "ELASTIC_URL": "http://localhost:9200",
+ "MONGO_URL": "mongodb://localhost:27017"
+ },
+ "runtimeArgs": ["--nolazy", "-r", "ts-node/register"],
+ "sourceMaps": true,
+ "cwd": "${workspaceRoot}/server/server",
+ "protocol": "inspector"
+ }
+ ]
+}
diff --git a/README.md b/README.md
index 728095b24b..711bf028c1 100644
--- a/README.md
+++ b/README.md
@@ -12,8 +12,40 @@ You need Microsoft's [rush](https://rushjs.io) to install application. Install [
cd dev/prod
rushx dev
```
+
Then go to http://localhost:8080/login:component:LoginApp and use following credentials to login into the system:
-* login: rosamund@hc.engineering
-* pass: 1111
-* workspace: trx40
+- login: rosamund@hc.engineering
+- pass: 1111
+- workspace: trx40
+
+To connect to running local server `dev-server` command should be used instead.
+
+## Build and run inside docker
+
+It is possible to setup all environment required with local docker containers.
+Supported both amd64 and armv8 containers.
+
+```bash
+rush build # Will build all required packages.
+rush bundle # Will prepare bundles.
+rush docker:build # Will build docker containers for all applications.
+cd ./dev/
+docker-compose up -d --force-recreate # Will setup all containers
+
+# we a few seconds delay, to be sure elastic is up and running.
+./deploy/setup-es-attachment-pipeline.sh # Setup elastic search plugin configuration.
+```
+
+By default docker volumes `dev_db` `dev_elastic` `dev_files` will be created for mongo/elastic/minio instances.
+
+Before we could start we need to create workspace/account and associate it with workspace.
+
+```bash
+cd ./dev/tools
+rushx run-local create-workspace ws1 -o DevWorkspace # Create workspace
+rushx run-local create-account user1 -p 1234 -f John -l Appleseed # Create account
+rushx run-local assign-workspace user1 ws1 # Assign worksapce to user
+```
+
+Following URL http://localhost:8081/login:component:LoginApp will lead us to app.
diff --git a/common/config/rush/command-line.json b/common/config/rush/command-line.json
index 2418864902..ab83d5b996 100644
--- a/common/config/rush/command-line.json
+++ b/common/config/rush/command-line.json
@@ -207,6 +207,27 @@
"ignoreDependencyOrder": false,
"ignoreMissingScript": true
},
+
+ {
+ "commandKind": "bulk",
+ "name": "docker:build",
+ "summary": "docker:build",
+ "description": "Build and make docker containers",
+ "enableParallelism": true,
+ "incremental": true,
+ "ignoreDependencyOrder": false,
+ "ignoreMissingScript": true
+ },
+ {
+ "commandKind": "bulk",
+ "name": "bundle",
+ "summary": "bundle",
+ "description": "Build bundles",
+ "enableParallelism": true,
+ "incremental": true,
+ "ignoreDependencyOrder": false,
+ "ignoreMissingScript": true
+ },
],
/**
diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml
index eee29f61b3..4c62446880 100644
--- a/common/config/rush/pnpm-lock.yaml
+++ b/common/config/rush/pnpm-lock.yaml
@@ -101,6 +101,7 @@ specifiers:
'@types/ws': ^7.4.7
autoprefixer: ^10.2.6
commander: ^8.1.0
+ compression-webpack-plugin: ~9.0.0
cors: ^2.8.5
cross-env: ^7.0.3
css-loader: ^5.2.1
@@ -241,6 +242,7 @@ dependencies:
'@types/ws': 7.4.7
autoprefixer: 10.3.7_postcss@8.3.9
commander: 8.2.0
+ compression-webpack-plugin: 9.0.1_webpack@5.57.1
cors: 2.8.5
cross-env: 7.0.3
css-loader: 5.2.7_webpack@5.57.1
@@ -2226,6 +2228,15 @@ packages:
ajv: 6.12.6
dev: false
+ /ajv-formats/2.1.1:
+ resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==}
+ peerDependenciesMeta:
+ ajv:
+ optional: true
+ dependencies:
+ ajv: 8.8.1
+ dev: false
+
/ajv-keywords/3.5.2_ajv@6.12.6:
resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==}
peerDependencies:
@@ -2234,6 +2245,15 @@ packages:
ajv: 6.12.6
dev: false
+ /ajv-keywords/5.0.0_ajv@8.8.1:
+ resolution: {integrity: sha512-ULd1QMjRoH6JDNUQIfDLrlE+OgZlFaxyYCjzt58uNuUQtKXt8/U+vK/8Ql0gyn/C5mqZzUWtKMqr/4YquvTrWA==}
+ peerDependencies:
+ ajv: ^8.0.0
+ dependencies:
+ ajv: 8.8.1
+ fast-deep-equal: 3.1.3
+ dev: false
+
/ajv/6.12.6:
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
dependencies:
@@ -2252,6 +2272,15 @@ packages:
uri-js: 4.4.1
dev: false
+ /ajv/8.8.1:
+ resolution: {integrity: sha512-6CiMNDrzv0ZR916u2T+iRunnD60uWmNn8SkdB44/6stVORUg0aAkWO7PkOhpCmjmW8f2I/G/xnowD66fxGyQJg==}
+ dependencies:
+ fast-deep-equal: 3.1.3
+ json-schema-traverse: 1.0.0
+ require-from-string: 2.0.2
+ uri-js: 4.4.1
+ dev: false
+
/ansi-colors/3.2.4:
resolution: {integrity: sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==}
engines: {node: '>=6'}
@@ -3013,6 +3042,17 @@ packages:
mime-db: 1.50.0
dev: false
+ /compression-webpack-plugin/9.0.1_webpack@5.57.1:
+ resolution: {integrity: sha512-vqlhZIPSyCpy6eaYWy8iPhteLWpARKotRiN5B/jr7lLowJv1GVc98Snn1Dcxe0+SKbfydLu7qZcnNuP+AyG19Q==}
+ engines: {node: '>= 12.13.0'}
+ peerDependencies:
+ webpack: ^5.1.0
+ dependencies:
+ schema-utils: 4.0.0
+ serialize-javascript: 6.0.0
+ webpack: 5.57.1_webpack-cli@4.8.0
+ dev: false
+
/compression/1.7.4:
resolution: {integrity: sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==}
engines: {node: '>= 0.8.0'}
@@ -7674,6 +7714,16 @@ packages:
ajv-keywords: 3.5.2_ajv@6.12.6
dev: false
+ /schema-utils/4.0.0:
+ resolution: {integrity: sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==}
+ engines: {node: '>= 12.13.0'}
+ dependencies:
+ '@types/json-schema': 7.0.9
+ ajv: 8.8.1
+ ajv-formats: 2.1.1
+ ajv-keywords: 5.0.0_ajv@8.8.1
+ dev: false
+
/secure-json-parse/2.4.0:
resolution: {integrity: sha512-Q5Z/97nbON5t/L/sH6mY2EacfjVGwrCcSi5D3btRO2GZ8pf1K1UN7Z9H5J57hjVU2Qzxr1xO+FmBhOvEkzCMmg==}
dev: false
@@ -9832,7 +9882,7 @@ packages:
dev: false
file:projects/front.tgz_typescript@4.4.3:
- resolution: {integrity: sha512-qKmnx2yFt1hFJRZWJNaPPbb+p/Q0lnyA6u9AAgeqDbOjmWjp48NxqX6jIbiEyQi56IDHViE3w4/NQb0c/mp/rA==, tarball: file:projects/front.tgz}
+ resolution: {integrity: sha512-8DxO3cOzfmEfVPsjIfOfA0mT3OrRDlBCuobV2mlj5+NzofW4yjJicsGlU8jCZ/fG2CMqfpWK5Hdino0LTX+T7g==, tarball: file:projects/front.tgz}
id: file:projects/front.tgz
name: '@rush-temp/front'
version: 0.0.0
@@ -9844,20 +9894,21 @@ packages:
'@types/minio': 7.0.10
'@types/node': 16.10.3
'@types/uuid': 8.3.1
- '@typescript-eslint/eslint-plugin': 4.33.0_eslint@7.32.0+typescript@4.4.3
+ '@typescript-eslint/eslint-plugin': 5.4.0_87dbf04088b125598d0271706532eaf3
+ '@typescript-eslint/parser': 5.4.0_eslint@7.32.0+typescript@4.4.3
cors: 2.8.5
esbuild: 0.12.29
eslint: 7.32.0
+ eslint-config-standard-with-typescript: 21.0.1_05a8ea1454e6ca4c9f98b94b8f3abf9c
eslint-plugin-import: 2.25.3_eslint@7.32.0
eslint-plugin-node: 11.1.0_eslint@7.32.0
- eslint-plugin-promise: 4.3.1
+ eslint-plugin-promise: 5.1.1_eslint@7.32.0
express: 4.17.1
express-fileupload: 1.2.1
jwt-simple: 0.5.6
minio: 7.0.19
uuid: 8.3.2
transitivePeerDependencies:
- - '@typescript-eslint/parser'
- supports-color
- typescript
dev: false
@@ -9999,7 +10050,7 @@ packages:
dev: false
file:projects/model-demo.tgz_typescript@4.4.3:
- resolution: {integrity: sha512-yo76yELzjfVH7a4Ba62J3M4cYP9yN/Xbe+O1jpwgVqRyqUHpowMrykgvrMDh9meuEsSsJ3NNFrClan9TEaY17A==, tarball: file:projects/model-demo.tgz}
+ resolution: {integrity: sha512-vXuP1gNtnqOBsOcxF7YtmkX2JFGlRRRxlCt7Jf/uLkAdU2h87nhkoRdllrvkGXPCqJYae47xLvpEpIxpgj6OBQ==, tarball: file:projects/model-demo.tgz}
id: file:projects/model-demo.tgz
name: '@rush-temp/model-demo'
version: 0.0.0
@@ -10330,13 +10381,14 @@ packages:
dev: false
file:projects/prod.tgz_sass@1.42.1+typescript@4.4.3:
- resolution: {integrity: sha512-BNsiZcy9EorJrRU+a1vLrsdXIWfjlSOKDzxwvsiORGg+DJhyBuWRPMl1ngR/JuiDMPIThzTp3DHhmcKDPvQfVw==, tarball: file:projects/prod.tgz}
+ resolution: {integrity: sha512-x7H3hwhd/DGstkIJ2QG1AJMUyFKeP//3BVCL24c8w4Z1xMD+fnfsg5pf3V1c/LkHk/e3D3YyPTqBOAt5+u1mJQ==, tarball: file:projects/prod.tgz}
id: file:projects/prod.tgz
name: '@rush-temp/prod'
version: 0.0.0
dependencies:
'@types/node': 14.17.21
autoprefixer: 10.3.7_postcss@8.3.9
+ compression-webpack-plugin: 9.0.1_webpack@5.57.1
cross-env: 7.0.3
css-loader: 5.2.7_webpack@5.57.1
dotenv-webpack: 7.0.3_webpack@5.57.1
diff --git a/dev/docker-compose.yaml b/dev/docker-compose.yaml
new file mode 100644
index 0000000000..26ad2eb6f6
--- /dev/null
+++ b/dev/docker-compose.yaml
@@ -0,0 +1,73 @@
+services:
+ mongodb:
+ image: mongo
+ container_name: mongodb
+ environment:
+ - PUID=1000
+ - PGID=1000
+ volumes:
+ - db:/data/db
+ ports:
+ - 27017:27017
+ restart: unless-stopped
+ minio:
+ image: 'minio/minio'
+ command: server /data --address ":9000" --console-address ":9001"
+ ports:
+ - 9000:9000
+ volumes:
+ - files:/data
+ elastic:
+ image: 'elasticsearch:7.14.0'
+ command: |
+ /bin/sh -c "./bin/elasticsearch-plugin list | grep -q ingest-attachment || yes | ./bin/elasticsearch-plugin install --silent ingest-attachment;
+ /usr/local/bin/docker-entrypoint.sh eswrapper"
+ volumes:
+ - elastic:/usr/share/elasticsearch/data
+ ports:
+ - 9200:9200
+ environment:
+ - ELASTICSEARCH_PORT_NUMBER=9200
+ - BITNAMI_DEBUG=true
+ - discovery.type=single-node
+ account:
+ image: anticrm/account
+ links:
+ - mongodb
+ ports:
+ - 3000:3000
+ environment:
+ - MONGO_URL=mongodb://mongodb:27017
+ - TRANSACTOR_URL=ws://localhost:3333
+ front:
+ image: anticrm/front
+ links:
+ - mongodb
+ - minio
+ - elastic
+ - server
+ - upload
+ ports:
+ - 8081:8080
+ environment:
+ - ACCOUNTS_URL=http://localhost:3000
+ - UPLOAD_URL=/files
+ - TRANSACTOR_URL=ws://localhost:3333
+ - ELASTIC_URL=http://elastic:9200
+ - MINIO_ENDPOINT=minio
+ - MINIO_ACCESS_KEY=minioadmin
+ - MINIO_SECRET_KEY=minioadmin
+ transactor:
+ image: anticrm/transactor
+ links:
+ - mongodb
+ - elastic
+ ports:
+ - 3333:3333
+ environment:
+ - ELASTIC_URL=http://elastic:9200
+ - MONGO_URL=mongodb://mongodb:27017
+volumes:
+ db:
+ files:
+ elastic:
diff --git a/dev/prod/.env b/dev/prod/.env
index fbc8053278..ef5af27eab 100644
--- a/dev/prod/.env
+++ b/dev/prod/.env
@@ -1,7 +1,5 @@
-CLIENT_TYPE=dev
-ACCOUNTS_URL=/account
-UPLOAD_URL=/upload
-LOGIN_TOKEN=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6InJvc2FtdW5kQGhjLmVuZ2luZWVyaW5nIiwid29ya3NwYWNlIjoidHJ4NDAifQ.dYsCF2VRbuc-zmRt0yLAww1_--xtX4P1EqPFREEzCjQ
-# LOGIN_ENDPOINT=ws://localhost:3333
-LOGIN_ENDPOINT=wss://transactor.hc.engineering/
+LOGIN_ENDPOINT=ws://localhost:3333
+
+LOGIN_TOKEN_DEV=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6InJvc2FtdW5kQGhjLmVuZ2luZWVyaW5nIiwid29ya3NwYWNlIjoidHJ4NDAifQ.dYsCF2VRbuc-zmRt0yLAww1_--xtX4P1EqPFREEzCjQ
+LOGIN_ENDPOINT_DEV=wss://transactor.hc.engineering/
diff --git a/dev/prod/.env-prod b/dev/prod/.env-prod
index f169c875ee..e69de29bb2 100644
--- a/dev/prod/.env-prod
+++ b/dev/prod/.env-prod
@@ -1,5 +0,0 @@
-
-
-#ACCOUNTS_URL=https://ftwm71rwag.execute-api.us-west-2.amazonaws.com/stage/
-ACCOUNTS_URL=https://account.hc.engineering/
-UPLOAD_URL=/files
diff --git a/dev/prod/config.json b/dev/prod/config.json
new file mode 100644
index 0000000000..d915d990f8
--- /dev/null
+++ b/dev/prod/config.json
@@ -0,0 +1 @@
+{"ACCOUNTS_URL":"http://localhost:3000","UPLOAD_URL":"/files"}
\ No newline at end of file
diff --git a/dev/prod/package.json b/dev/prod/package.json
index 64c216dbbc..03cce49c38 100644
--- a/dev/prod/package.json
+++ b/dev/prod/package.json
@@ -3,11 +3,11 @@
"version": "1.0.1",
"license": "EPL-2.0",
"scripts": {
- "build": "cross-env NODE_ENV=production webpack --stats-error-details && echo 'done'",
+ "build": "cross-env NODE_ENV=development webpack --stats-error-details && echo 'done'",
"analyze": "cross-env NODE_ENV=production webpack --json > stats.json",
"show": "webpack-bundle-analyzer stats.json dist",
- "dev": "cross-env webpack serve --content-base public",
- "dev-server": "cross-env CLIENT=server webpack serve --content-base public",
+ "dev": "cross-env CLIENT_TYPE=dev webpack serve --content-base public",
+ "dev-server": "cross-env CLIENT_TYPE=dev-server webpack serve --content-base public",
"start": "cross-env NODE_ENV=production webpack serve --content-base public",
"preformat-svelte": "prettier -w src/**/*.svelte",
"lint": "eslint --max-warnings=0 src",
@@ -33,7 +33,8 @@
"autoprefixer": "^10.2.6",
"postcss": "^8.3.4",
"postcss-loader": "^6.1.0",
- "postcss-load-config": "^3.1.0"
+ "postcss-load-config": "^3.1.0",
+ "compression-webpack-plugin": "~9.0.0"
},
"dependencies": {
"@anticrm/platform": "~0.6.5",
diff --git a/dev/prod/public/config.json b/dev/prod/public/config.json
new file mode 100644
index 0000000000..72b566762d
--- /dev/null
+++ b/dev/prod/public/config.json
@@ -0,0 +1,4 @@
+{
+ "ACCOUNTS_URL":"/account",
+ "UPLOAD_URL":"/files"
+}
\ No newline at end of file
diff --git a/dev/prod/public/index.html b/dev/prod/public/index.html
index 1474b2b6f8..c7bf9124d2 100644
--- a/dev/prod/public/index.html
+++ b/dev/prod/public/index.html
@@ -12,6 +12,7 @@
+
diff --git a/dev/prod/src/main.ts b/dev/prod/src/main.ts
index 9dffc79f9e..c5647f645d 100644
--- a/dev/prod/src/main.ts
+++ b/dev/prod/src/main.ts
@@ -14,41 +14,9 @@
// limitations under the License.
//
-// import { setMetadata } from '@anticrm/platform'
import { createApp } from '@anticrm/ui'
-// import login from '@anticrm/login'
-// import pluginCore from '@anticrm/plugin-core'
-// import meetingPlugin from '@anticrm/meeting'
-
import { configurePlatform } from './platform'
configurePlatform()
-// const accountsUrl = process.env.APP_ACCOUNTS_URL
-// const appHost = process.env.APP_WSHOST
-// const appPort = process.env.APP_WSPORT
-// const appToken = process.env.APP_TOKEN
-// const meetingHost = process.env.MEETING_WSHOST
-// const meetingPort = process.env.MEETING_WSPORT
-
-// setMetadata(login.metadata.AccountsUrl, accountsUrl)
-// setMetadata(pluginCore.metadata.ClientUrl, `${appHost}:${appPort}/${appToken}`)
-// setMetadata(meetingPlugin.metadata.ClientUrl, `${meetingHost}:${meetingPort}`)
-// platform.setMetadata(core.metadata.WSHost, host)
-// platform.setMetadata(core.metadata.WSPort, port)
-
-// const loginInfo = currentAccount()
-// if (loginInfo) {
-// platform.setMetadata(core.metadata.WhoAmI, loginInfo.email)
-// platform.setMetadata(core.metadata.Token, loginInfo.token)
-// }
-
-// async function boot (): Promise {
-// uiService.createApp(document.body)
-// }
-
-// boot().catch(err => {
-// new ErrorPage({ target: document.body, props: { error: err.message } })
-// })
-
createApp(document.body)
diff --git a/dev/prod/src/platform.ts b/dev/prod/src/platform.ts
index 2ef08fa33d..1f8011dd30 100644
--- a/dev/prod/src/platform.ts
+++ b/dev/prod/src/platform.ts
@@ -38,20 +38,30 @@ import '@anticrm/recruit-assets'
import '@anticrm/activity-assets'
import { setMetadata } from '@anticrm/platform'
-
-export function configurePlatform() {
-
- setMetadata(login.metadata.AccountsUrl, process.env.ACCOUNTS_URL)
- setMetadata(login.metadata.UploadUrl, process.env.UPLOAD_URL)
- setMetadata(login.metadata.OverrideLoginToken, process.env.LOGIN_TOKEN)
+export function configurePlatform() {
+ fetch('/config.json').then(config => {
+ config.json().then(value => {
+ console.log('loading configuration', value)
+ setMetadata(login.metadata.AccountsUrl, value.ACCOUNTS_URL)
+ setMetadata(login.metadata.UploadUrl, value.UPLOAD_URL)
+ })
+ })
setMetadata(login.metadata.OverrideEndpoint, process.env.LOGIN_ENDPOINT)
if (process.env.CLIENT_TYPE === 'dev') {
+ setMetadata(login.metadata.OverrideLoginToken, process.env.LOGIN_TOKEN_DEV)
+ setMetadata(login.metadata.OverrideEndpoint, process.env.LOGIN_ENDPOINT_DEV)
+ console.log('Use DEV server')
addLocation(clientId, () => import(/* webpackChunkName: "client-dev" */ '@anticrm/dev-client-resources'))
addLocation(serverChunterId, () => import(/* webpackChunkName: "server-chunter" */ '@anticrm/dev-server-chunter-resources'))
addLocation(serverRecruitId, () => import(/* webpackChunkName: "server-recruit" */ '@anticrm/server-recruit-resources'))
addLocation(serverViewId, () => import(/* webpackChunkName: "server-view" */ '@anticrm/server-view-resources'))
} else {
+ if (process.env.CLIENT_TYPE === 'dev-server') {
+ console.log('Use Endpoint override:', process.env.LOGIN_ENDPOINT)
+ setMetadata(login.metadata.OverrideEndpoint, process.env.LOGIN_ENDPOINT)
+ }
+ console.log('Use server')
addLocation(clientId, () => import(/* webpackChunkName: "client" */ '@anticrm/client-resources'))
}
diff --git a/dev/prod/webpack.config.js b/dev/prod/webpack.config.js
index 808e0945c9..b9e225351e 100644
--- a/dev/prod/webpack.config.js
+++ b/dev/prod/webpack.config.js
@@ -17,9 +17,12 @@ const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const Dotenv = require('dotenv-webpack')
const path = require('path')
const autoprefixer = require('autoprefixer')
+const CompressionPlugin = require('compression-webpack-plugin')
+const DefinePlugin = require('webpack').DefinePlugin
const mode = process.env.NODE_ENV || 'development'
const prod = mode === 'production'
+const devServer = (process.env.CLIENT_TYPE ?? '') === 'dev-server'
module.exports = {
entry: {
@@ -42,6 +45,22 @@ module.exports = {
chunkFilename: '[name].[id].js',
publicPath: '/'
},
+ optimization: {
+ minimize: prod,
+ usedExports: prod,
+ splitChunks: {
+ chunks: 'all',
+ maxAsyncRequests: 5,
+ maxInitialRequests: 3,
+ cacheGroups: {
+ vendors: {
+ name: 'vendors',
+ test: /[\\/]node_modules[\\/]/,
+ priority: 20
+ }
+ }
+ }
+ },
module: {
rules: [
{
@@ -149,10 +168,14 @@ module.exports = {
},
mode,
plugins: [
+ ...(prod ? [new CompressionPlugin()] : []),
new MiniCssExtractPlugin({
filename: '[name].css'
}),
- new Dotenv({path: prod ? '.env-prod' : '.env'})
+ new Dotenv({path: prod ? '.env-prod' : '.env'}),
+ new DefinePlugin({
+ 'process.env.CLIENT_TYPE': JSON.stringify(process.env.CLIENT_TYPE)
+ })
],
devtool: prod ? false : 'source-map',
devServer: {
@@ -160,7 +183,19 @@ module.exports = {
historyApiFallback: {
disableDotRule: true
},
- proxy: {
+ proxy: devServer ? {
+ '/account': {
+ target: 'http://localhost:3000',
+ changeOrigin: true,
+ pathRewrite: { '^/account': '' },
+ logLevel: 'debug'
+ },
+ '/files': {
+ target: 'http://localhost:8081',
+ changeOrigin: true,
+ logLevel: 'debug'
+ },
+ } : {
'/account': {
// target: 'https://ftwm71rwag.execute-api.us-west-2.amazonaws.com/stage/',
target: 'https://account.hc.engineering/',
@@ -168,12 +203,12 @@ module.exports = {
pathRewrite: { '^/account': '' },
logLevel: 'debug'
},
- '/upload': {
+ '/files': {
// target: 'https://anticrm-upload.herokuapp.com/',
- // target: 'http://localhost:3000/',
+ // target: 'http://localhost:3000/',
target: 'https://front.hc.engineering/files',
changeOrigin: true,
- pathRewrite: { '^/upload': '' },
+ pathRewrite: { '^/files': '' },
logLevel: 'debug'
},
}
diff --git a/dev/tool/package.json b/dev/tool/package.json
index 8b4fc01968..51bd1648a3 100644
--- a/dev/tool/package.json
+++ b/dev/tool/package.json
@@ -9,9 +9,10 @@
"build:watch": "tsc",
"lint:fix": "eslint --fix src",
"start": "ts-node src/index.ts",
- "bundle": "esbuild src/index.ts --bundle --minify --platform=node > bundle.js",
+ "bundle": "esbuild src/index.ts --bundle --minify --platform=node > bundle.js",
"docker:build": "docker build -t anticrm/tool .",
- "docker:push": "docker push anticrm/tool"
+ "docker:push": "docker push anticrm/tool",
+ "run-local": "MINIO_ACCESS_KEY=minioadmin MINIO_SECRET_KEY=minioadmin MONGO_URL=mongodb://localhost:27017 TRANSACTOR_URL=ws:/localhost:3333 MINIO_ENDPOINT=localhost ts-node ./src/index.ts"
},
"devDependencies": {
"@anticrm/platform-rig":"~0.6.0",
diff --git a/pods/account/src/index.ts b/pods/account/src/index.ts
index a5ee211a22..cd3763fe11 100644
--- a/pods/account/src/index.ts
+++ b/pods/account/src/index.ts
@@ -14,15 +14,13 @@
// limitations under the License.
//
-import { ACCOUNT_DB, methods } from '@anticrm/account'
-import platform, { Response, Request, serialize, Status, Severity } from '@anticrm/platform'
-import { MongoClient, Db } from 'mongodb'
-
-import Koa from 'koa'
-import Router from 'koa-router'
-
-import bodyParser from 'koa-bodyparser'
+import accountPlugin, { ACCOUNT_DB, methods } from '@anticrm/account'
+import platform, { Request, Response, serialize, setMetadata, Severity, Status } from '@anticrm/platform'
import cors from '@koa/cors'
+import Koa from 'koa'
+import bodyParser from 'koa-bodyparser'
+import Router from 'koa-router'
+import { Db, MongoClient } from 'mongodb'
const dbUri = process.env.MONGO_URL
if (dbUri === undefined) {
@@ -30,6 +28,14 @@ if (dbUri === undefined) {
process.exit(1)
}
+const transactorUri = process.env.TRANSACTOR_URL
+if (dbUri === undefined) {
+ console.log('Please provide transactor url')
+ process.exit(1)
+}
+
+setMetadata(accountPlugin.metadata.Endpoint, transactorUri)
+
let client: MongoClient
const app = new Koa()
@@ -60,6 +66,13 @@ app.use(cors())
app.use(bodyParser())
app.use(router.routes()).use(router.allowedMethods())
-app.listen(3000, () => {
+const server = app.listen(3000, () => {
console.log('server started on port 3000')
})
+
+const close = (): void => {
+ server.close()
+}
+process.on('SIGINT', close)
+process.on('SIGTERM', close)
+process.on('exit', close)
diff --git a/server/account/src/index.ts b/server/account/src/index.ts
index 35c969da84..dc9c4482d1 100644
--- a/server/account/src/index.ts
+++ b/server/account/src/index.ts
@@ -14,18 +14,14 @@
// limitations under the License.
//
-import type { Plugin, StatusCode, Request, Response } from '@anticrm/platform'
-import { PlatformError, Severity, Status, plugin, unknownStatus } from '@anticrm/platform'
-import { Binary, Db, ObjectId } from 'mongodb'
+import { getMetadata, Metadata, Plugin, Request, Response, StatusCode, PlatformError, plugin, Severity, Status, unknownStatus } from '@anticrm/platform'
import { pbkdf2Sync, randomBytes } from 'crypto'
import { encode } from 'jwt-simple'
+import { Binary, Db, ObjectId } from 'mongodb'
const WORKSPACE_COLLECTION = 'workspace'
const ACCOUNT_COLLECTION = 'account'
-const endpoint = 'wss://transactor.hc.engineering/'
-const secret = 'secret'
-
/**
* @public
*/
@@ -40,6 +36,10 @@ export const accountId = 'account' as Plugin
* @public
*/
const accountPlugin = plugin(accountId, {
+ metadata: {
+ Endpoint: '' as Metadata,
+ Secret: '' as Metadata
+ },
status: {
AccountNotFound: '' as StatusCode<{account: string}>,
WorkspaceNotFound: '' as StatusCode<{workspace: string}>,
@@ -50,6 +50,14 @@ const accountPlugin = plugin(accountId, {
}
})
+const getSecret = (): string => {
+ return getMetadata(accountPlugin.metadata.Secret) ?? 'secret'
+}
+
+const getEndpoint = (): string => {
+ return getMetadata(accountPlugin.metadata.Endpoint) ?? 'wss://transactor.hc.engineering/'
+}
+
/**
* @public
*/
@@ -132,7 +140,7 @@ async function getAccountInfo (db: Db, email: string, password: string): Promise
}
function generateToken (email: string, workspace: string): string {
- return encode({ email, workspace }, secret)
+ return encode({ email, workspace }, getSecret())
}
/**
@@ -153,7 +161,7 @@ export async function login (db: Db, email: string, password: string, workspace:
for (const w of workspaces) {
if (w.equals(workspaceInfo._id)) {
const result = {
- endpoint,
+ endpoint: getEndpoint(),
email,
token: generateToken(email, workspace)
}
diff --git a/server/elastic/src/__init.ts b/server/elastic/src/__init.ts
index 8f541b474e..a5a16a4fae 100644
--- a/server/elastic/src/__init.ts
+++ b/server/elastic/src/__init.ts
@@ -22,7 +22,7 @@ if (url === undefined) {
process.exit(1)
}
-const client = new Client({ node: 'http://45.32.149.163:9200/' })
+const client = new Client({ node: url })
client.ingest.putPipeline({
id: 'anticrm-pipeline',
diff --git a/server/elastic/src/adapter.ts b/server/elastic/src/adapter.ts
index 0be44dee9e..897f010960 100644
--- a/server/elastic/src/adapter.ts
+++ b/server/elastic/src/adapter.ts
@@ -66,38 +66,51 @@ class ElasticAdapter implements FullTextAdapter {
async index (doc: IndexedDoc): Promise {
console.log('eastic: index', doc)
if (doc.data === undefined) {
- const resp = await this.client.index({
- index: this.db,
- id: doc.id,
- type: '_doc',
- body: doc
- })
- console.log('resp', resp)
- console.log('error', (resp.meta as any)?.body?.error)
+ try {
+ const resp = await this.client.index({
+ index: this.db,
+ id: doc.id,
+ type: '_doc',
+ body: doc
+ })
+ console.log('resp', resp)
+ console.log('error', (resp.meta as any)?.body?.error)
+ } catch (err: any) {
+ console.log('elastic-exception', err)
+ }
} else {
console.log('attachment pipeline')
- const resp = await this.client.index({
- index: this.db,
- id: doc.id,
- type: '_doc',
- pipeline: 'attachment',
- body: doc
- })
- console.log('resp', resp)
- console.log('error', (resp.meta as any)?.body?.error)
+ try {
+ const resp = await this.client.index({
+ index: this.db,
+ id: doc.id,
+ type: '_doc',
+ pipeline: 'attachment',
+ body: doc
+ })
+ console.log('resp', resp)
+ console.log('error', (resp.meta as any)?.body?.error)
+ } catch (err: any) {
+ console.log('elastic-exception', err)
+ }
}
return {}
}
async update (id: Ref, update: Record): Promise {
- const resp = await this.client.update({
- index: this.db,
- id,
- body: {
- doc: update
- }
- })
- console.log('update', resp)
+ try {
+ const resp = await this.client.update({
+ index: this.db,
+ id,
+ body: {
+ doc: update
+ }
+ })
+ console.log('update', resp)
+ } catch (err: any) {
+ console.log('elastic-exception', err)
+ }
+
return {}
}
}
diff --git a/server/front/kube/front.yml b/server/front/kube/front.yml
index 0eb6c3eadf..212767d173 100644
--- a/server/front/kube/front.yml
+++ b/server/front/kube/front.yml
@@ -20,6 +20,10 @@ spec:
- containerPort: 8080
imagePullPolicy: Always
env:
+ - name: ACCOUNTS_URL
+ value: https://account.hc.engineering/
+ - name: UPLOAD_URL
+ value: /files
- name: TRANSACTOR_URL
value: ws://transactor/
- name: ELASTIC_URL
diff --git a/server/front/package.json b/server/front/package.json
index 6df36221fd..67d9e5c141 100644
--- a/server/front/package.json
+++ b/server/front/package.json
@@ -8,7 +8,7 @@
"build": "heft build",
"build:watch": "tsc",
"lint:fix": "eslint --fix src",
- "bundle": "esbuild src/__start.ts --bundle --minify --platform=node > bundle.js & rm -rf ./dist && cp -r ../../dev/prod/dist . && cp -r ../../dev/prod/public/* ./dist/",
+ "bundle": "esbuild src/__start.ts --bundle --minify --platform=node > bundle.js & rm -rf ./dist && cp -r ../../dev/prod/dist . && cp -r ../../dev/prod/public/* ./dist/ && rm ./dist/config.json",
"docker:build": "docker build -t anticrm/front .",
"docker:push": "docker push anticrm/front"
},
@@ -16,11 +16,13 @@
"@anticrm/platform-rig":"~0.6.0",
"@types/heft-jest":"^1.0.2",
"@types/node": "^16.4.10",
- "@typescript-eslint/eslint-plugin":"4",
- "eslint-plugin-import":"2",
- "eslint-plugin-promise":"4",
- "eslint-plugin-node":"11",
- "eslint":"^7.32.0",
+ "@typescript-eslint/eslint-plugin": "^5.4.0",
+ "@typescript-eslint/parser": "^5.4.0",
+ "eslint-config-standard-with-typescript": "^21.0.1",
+ "eslint-plugin-import": "^2.25.3",
+ "eslint-plugin-node": "^11.1.0",
+ "eslint-plugin-promise": "^5.1.1",
+ "eslint": "^7.32.0",
"@types/express":"^4.17.13",
"@types/express-fileupload":"^1.1.7",
"@types/uuid":"^8.3.1",
diff --git a/server/front/run.sh b/server/front/run.sh
new file mode 100755
index 0000000000..3bf8911fef
--- /dev/null
+++ b/server/front/run.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+export ACCOUNTS_URL=http://localhost:3333
+export TRANSACTOR_URL=ws://localhost:3333
+export ELASTIC_URL=http://elastic:9200
+export MINIO_ENDPOINT=minio
+export MINIO_ACCESS_KEY=minioadmin
+export MINIO_SECRET_KEY=minioadmin
+node ./bundle.js
\ No newline at end of file
diff --git a/server/front/src/__start.ts b/server/front/src/__start.ts
index 7f9dacb089..11f6bf3b4e 100644
--- a/server/front/src/__start.ts
+++ b/server/front/src/__start.ts
@@ -17,8 +17,8 @@
import { start } from './app'
import { Client } from 'minio'
-const url = process.env.TRANSACTOR_URL
-if (url === undefined) {
+const transactorEndpoint = process.env.TRANSACTOR_URL
+if (transactorEndpoint === undefined) {
console.error('please provide transactor url')
process.exit(1)
}
@@ -55,4 +55,18 @@ const minio = new Client({
secretKey: minioSecretKey
})
-start(url, elasticUrl, minio, 8080)
+const accountsUrl = process.env.ACCOUNTS_URL
+if (accountsUrl === undefined) {
+ console.error('please provide accounts url')
+ process.exit(1)
+}
+
+const uploadUrl = process.env.UPLOAD_URL
+if (uploadUrl === undefined) {
+ console.error('please provide upload url')
+ process.exit(1)
+}
+
+const config = { transactorEndpoint, elasticUrl, minio, accountsUrl, uploadUrl }
+console.log('Starting Front service with', config)
+start(config, 8080)
diff --git a/server/front/src/app.ts b/server/front/src/app.ts
index 0a38f1b738..4ce1387955 100644
--- a/server/front/src/app.ts
+++ b/server/front/src/app.ts
@@ -79,12 +79,24 @@ async function minioUpload (minio: Client, workspace: string, file: UploadedFile
* @public
* @param port -
*/
-export function start (transactorEndpoint: string, elasticUrl: string, minio: Client, port: number): void {
+export function start (config: { transactorEndpoint: string, elasticUrl: string, minio: Client, accountsUrl: string, uploadUrl: string }, port: number): void {
const app = express()
app.use(cors())
app.use(fileUpload())
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
+ app.get('/config.json', async (req, res) => {
+ res.status(200)
+ res.set('Cache-Control', 'no-cache')
+ res.json(
+ {
+ ACCOUNTS_URL: config.accountsUrl,
+ UPLOAD_URL: config.uploadUrl
+ }
+ )
+ })
+
const dist = resolve(__dirname, 'dist')
console.log('serving static files from', dist)
app.use(express.static(dist, { maxAge: '10m' }))
@@ -96,8 +108,8 @@ export function start (transactorEndpoint: string, elasticUrl: string, minio: Cl
const payload = decode(token, 'secret', false) as Token
const uuid = req.query.file as string
- const stat = await minio.statObject(payload.workspace, uuid)
- minio.getObject(payload.workspace, uuid, function (err, dataStream) {
+ const stat = await config.minio.statObject(payload.workspace, uuid)
+ config.minio.getObject(payload.workspace, uuid, function (err, dataStream) {
if (err !== null) {
return console.log(err)
}
@@ -143,7 +155,7 @@ export function start (transactorEndpoint: string, elasticUrl: string, minio: Cl
const token = authHeader.split(' ')[1]
const payload = decode(token ?? '', 'secret', false) as Token
// const fileId = await awsUpload(file as UploadedFile)
- const uuid = await minioUpload(minio, payload.workspace, file)
+ const uuid = await minioUpload(config.minio, payload.workspace, file)
console.log('uploaded uuid', uuid)
const name = req.query.name as string
@@ -162,7 +174,7 @@ export function start (transactorEndpoint: string, elasticUrl: string, minio: Cl
// fileId
// )
- const elastic = await createElasticAdapter(elasticUrl, payload.workspace)
+ const elastic = await createElasticAdapter(config.elasticUrl, payload.workspace)
const indexedDoc: IndexedDoc = {
id: generateId() + '/attachments/' + name,
@@ -224,7 +236,7 @@ export function start (transactorEndpoint: string, elasticUrl: string, minio: Cl
}).on('end', function () {
const buffer = Buffer.concat(data)
// eslint-disable-next-line @typescript-eslint/no-misused-promises
- minio.putObject(payload.workspace, id, buffer, 0, meta, async (err, objInfo) => {
+ config.minio.putObject(payload.workspace, id, buffer, 0, meta, async (err, objInfo) => {
if (err !== null) {
console.log('minio putObject error', err)
res.status(500).send(err)
@@ -233,7 +245,7 @@ export function start (transactorEndpoint: string, elasticUrl: string, minio: Cl
if (attachedTo !== undefined) {
const space = req.query.space as Ref
- const elastic = await createElasticAdapter(elasticUrl, payload.workspace)
+ const elastic = await createElasticAdapter(config.elasticUrl, payload.workspace)
const indexedDoc: IndexedDoc = {
id: generateId() + '/attachments/' + 'Profile.pdf',
diff --git a/server/front/src/index.ts b/server/front/src/index.ts
index 8d7a5f6b3a..8844274b23 100644
--- a/server/front/src/index.ts
+++ b/server/front/src/index.ts
@@ -30,5 +30,12 @@ app.get('*', function (request, response) {
response.sendFile(join(dist, 'index.html'))
})
-app.listen(port)
+const server = app.listen(port)
console.log(`server started on port ${port}`)
+
+const close = (): void => {
+ server.close()
+}
+process.on('SIGINT', close)
+process.on('SIGTERM', close)
+process.on('exit', close)
diff --git a/server/server/src/__start.ts b/server/server/src/__start.ts
index 36c97f243a..58763c7a1a 100644
--- a/server/server/src/__start.ts
+++ b/server/server/src/__start.ts
@@ -29,4 +29,14 @@ if (elasticUrl === undefined) {
}
// eslint-disable-next-line @typescript-eslint/no-floating-promises
-start(url, elasticUrl, 3333)
+const shutdown = start(url, elasticUrl, 3333)
+
+const close = (): void => {
+ console.error(new Error().stack)
+ console.log('Shutdown request accepted')
+ shutdown()
+ process.exit(0)
+}
+process.on('SIGINT', close)
+process.on('SIGTERM', close)
+process.on('exit', close)
diff --git a/server/server/src/server.ts b/server/server/src/server.ts
index 407d8e9fd9..a5bbff27af 100644
--- a/server/server/src/server.ts
+++ b/server/server/src/server.ts
@@ -39,12 +39,12 @@ async function createNullAdapter (hierarchy: Hierarchy, url: string, db: string,
/**
* @public
*/
-export async function start (dbUrl: string, fullTextUrl: string, port: number, host?: string): Promise {
+export function start (dbUrl: string, fullTextUrl: string, port: number, host?: string): () => void {
addLocation(serverChunterId, () => import('@anticrm/server-chunter-resources'))
addLocation(serverRecruitId, () => import('@anticrm/server-recruit-resources'))
addLocation(serverViewId, () => import('@anticrm/server-view-resources'))
- startJsonRpc((workspace: string) => {
+ return startJsonRpc((workspace: string) => {
const conf: DbConfiguration = {
domains: {
[DOMAIN_TX]: 'MongoTx',
diff --git a/server/upload/src/__start.ts b/server/upload/src/__start.ts
index a5fd5bc507..ecafe9540f 100644
--- a/server/upload/src/__start.ts
+++ b/server/upload/src/__start.ts
@@ -55,4 +55,12 @@ const minio = new Client({
secretKey: minioSecretKey
})
-start(url, elasticUrl, minio, 3000)
+const shutdown = start(url, elasticUrl, minio, 3000)
+
+const close = (): void => {
+ shutdown()
+ process.exit(0)
+}
+process.on('SIGINT', close)
+process.on('SIGTERM', close)
+process.on('exit', close)
diff --git a/server/upload/src/app.ts b/server/upload/src/app.ts
index ee49264b4f..9572328526 100644
--- a/server/upload/src/app.ts
+++ b/server/upload/src/app.ts
@@ -77,7 +77,7 @@ async function minioUpload (minio: Client, workspace: string, file: UploadedFile
* @public
* @param port -
*/
-export function start (transactorEndpoint: string, elasticUrl: string, minio: Client, port: number): void {
+export function start (transactorEndpoint: string, elasticUrl: string, minio: Client, port: number): () => void {
const app = express()
app.use(cors())
@@ -177,5 +177,8 @@ export function start (transactorEndpoint: string, elasticUrl: string, minio: Cl
}
})
- app.listen(port)
+ const server = app.listen(port)
+ return () => {
+ server.close()
+ }
}
diff --git a/server/ws/src/server.ts b/server/ws/src/server.ts
index 5d5a7e3fb5..97d1bd0e9d 100644
--- a/server/ws/src/server.ts
+++ b/server/ws/src/server.ts
@@ -115,7 +115,7 @@ async function handleRequest (service: S, ws: WebSocket, msg: string): Promis
* @param port -
* @param host -
*/
-export function start (storageFactory: (workspace: string) => Promise, port: number, host?: string): void {
+export function start (storageFactory: (workspace: string) => Promise, port: number, host?: string): () => void {
console.log(`starting server on port ${port} ...`)
const sessions = new SessionManager()
@@ -151,4 +151,7 @@ export function start (storageFactory: (workspace: string) => Promise {
+ server.close()
+ }
}