Compare commits
94 Commits
Author | SHA1 | Date | |
---|---|---|---|
61d5301de8 | |||
72fa7f790c | |||
dcc087c04d | |||
c8556355c0 | |||
9cfc41ace8 | |||
2827a1676b | |||
424ad80b60 | |||
682a0c53ce | |||
4fc09af779 | |||
f73d973383 | |||
d87a942ab3 | |||
60e8657467 | |||
5215be946e | |||
b9c67666fa | |||
4b0fb073e6 | |||
fc458b6827 | |||
f27b9f8143 | |||
38058aba57 | |||
ba38dae64f | |||
69e862a6cf | |||
4562ac355b | |||
b029dc191e | |||
2640275d04 | |||
7bbcc91300 | |||
da39d52975 | |||
307469312f | |||
0f3ff2b611 | |||
bce82d49b6 | |||
0b10913995 | |||
7048585702 | |||
92697bad82 | |||
e1475a3342 | |||
e3c58e7fc0 | |||
32d60fff0d | |||
f33b64d625 | |||
6ee70ecafa | |||
6f3700adc0 | |||
3648f12358 | |||
c239eaa9d5 | |||
75bd7a9175 | |||
be9b47e73b | |||
966d953aff | |||
7f73664970 | |||
71452a293f | |||
c5e60d804a | |||
c5d52013e6 | |||
64195e4c78 | |||
01b5b3dc1a | |||
b34d7faec2 | |||
7c98e19988 | |||
608669ec44 | |||
a7b14cd383 | |||
21dc933302 | |||
4e7455fa26 | |||
c424d589ea | |||
9435796333 | |||
12d7310b90 | |||
9fc4db1e35 | |||
895464115e | |||
00f22f9651 | |||
278b35c9c5 | |||
da78da27e5 | |||
a8aeeaaa6c | |||
f9f6975b87 | |||
b9a6f1d5b0 | |||
489ad9284b | |||
6fdf0d9955 | |||
499a1893f9 | |||
2754447aae | |||
544277cb8a | |||
9a23960d21 | |||
23cca6cce3 | |||
2a9e58cc35 | |||
7d6a9921b5 | |||
3ee46a31f7 | |||
d72310ce10 | |||
1e14166ddb | |||
be38e91548 | |||
6c2057b119 | |||
08d7224016 | |||
bfa3330eb6 | |||
644fa2a49d | |||
c0dad3a977 | |||
a921033cc4 | |||
21e4712b04 | |||
df43bc2974 | |||
564988185d | |||
8442f3570f | |||
196357c878 | |||
bc187b7e41 | |||
0e54bf889f | |||
4c211bc82e | |||
a1be281670 | |||
1a44d2027c |
66
.gitea/workflows/default_nottags.yaml
Normal file
66
.gitea/workflows/default_nottags.yaml
Normal file
@ -0,0 +1,66 @@
|
||||
name: Default (not tags)
|
||||
|
||||
on:
|
||||
push:
|
||||
tags-ignore:
|
||||
- '**'
|
||||
|
||||
env:
|
||||
IMAGE: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
||||
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@gitea.lossless.digital/${{gitea.repository}}.git
|
||||
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
|
||||
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
|
||||
NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
|
||||
NPMCI_URL_CLOUDLY: ${{secrets.NPMCI_URL_CLOUDLY}}
|
||||
|
||||
jobs:
|
||||
security:
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
container:
|
||||
image: ${{ env.IMAGE }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install pnpm and npmci
|
||||
run: |
|
||||
pnpm install -g pnpm
|
||||
pnpm install -g @shipzone/npmci
|
||||
|
||||
- name: Run npm prepare
|
||||
run: npmci npm prepare
|
||||
|
||||
- name: Audit production dependencies
|
||||
run: |
|
||||
npmci command npm config set registry https://registry.npmjs.org
|
||||
npmci command pnpm audit --audit-level=high --prod
|
||||
continue-on-error: true
|
||||
|
||||
- name: Audit development dependencies
|
||||
run: |
|
||||
npmci command npm config set registry https://registry.npmjs.org
|
||||
npmci command pnpm audit --audit-level=high --dev
|
||||
continue-on-error: true
|
||||
|
||||
test:
|
||||
if: ${{ always() }}
|
||||
needs: security
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: ${{ env.IMAGE }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Test stable
|
||||
run: |
|
||||
npmci node install stable
|
||||
npmci npm install
|
||||
npmci npm test
|
||||
|
||||
- name: Test build
|
||||
run: |
|
||||
npmci node install stable
|
||||
npmci npm install
|
||||
npmci npm build
|
124
.gitea/workflows/default_tags.yaml
Normal file
124
.gitea/workflows/default_tags.yaml
Normal file
@ -0,0 +1,124 @@
|
||||
name: Default (tags)
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
|
||||
env:
|
||||
IMAGE: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
||||
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@gitea.lossless.digital/${{gitea.repository}}.git
|
||||
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
|
||||
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
|
||||
NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
|
||||
NPMCI_URL_CLOUDLY: ${{secrets.NPMCI_URL_CLOUDLY}}
|
||||
|
||||
jobs:
|
||||
security:
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
container:
|
||||
image: ${{ env.IMAGE }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Prepare
|
||||
run: |
|
||||
pnpm install -g pnpm
|
||||
pnpm install -g @shipzone/npmci
|
||||
npmci npm prepare
|
||||
|
||||
- name: Audit production dependencies
|
||||
run: |
|
||||
npmci command npm config set registry https://registry.npmjs.org
|
||||
npmci command pnpm audit --audit-level=high --prod
|
||||
continue-on-error: true
|
||||
|
||||
- name: Audit development dependencies
|
||||
run: |
|
||||
npmci command npm config set registry https://registry.npmjs.org
|
||||
npmci command pnpm audit --audit-level=high --dev
|
||||
continue-on-error: true
|
||||
|
||||
test:
|
||||
if: ${{ always() }}
|
||||
needs: security
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: ${{ env.IMAGE }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Prepare
|
||||
run: |
|
||||
pnpm install -g pnpm
|
||||
pnpm install -g @shipzone/npmci
|
||||
npmci npm prepare
|
||||
|
||||
- name: Test stable
|
||||
run: |
|
||||
npmci node install stable
|
||||
npmci npm install
|
||||
npmci npm test
|
||||
|
||||
- name: Test build
|
||||
run: |
|
||||
npmci node install stable
|
||||
npmci npm install
|
||||
npmci npm build
|
||||
|
||||
release:
|
||||
needs: test
|
||||
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: ${{ env.IMAGE }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Prepare
|
||||
run: |
|
||||
pnpm install -g pnpm
|
||||
pnpm install -g @shipzone/npmci
|
||||
npmci npm prepare
|
||||
|
||||
- name: Release
|
||||
run: |
|
||||
npmci node install stable
|
||||
npmci npm publish
|
||||
|
||||
metadata:
|
||||
needs: test
|
||||
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: ${{ env.IMAGE }}
|
||||
continue-on-error: true
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Prepare
|
||||
run: |
|
||||
pnpm install -g pnpm
|
||||
pnpm install -g @shipzone/npmci
|
||||
npmci npm prepare
|
||||
|
||||
- name: Code quality
|
||||
run: |
|
||||
npmci command npm install -g typescript
|
||||
npmci npm install
|
||||
|
||||
- name: Trigger
|
||||
run: npmci trigger
|
||||
|
||||
- name: Build docs and upload artifacts
|
||||
run: |
|
||||
npmci node install stable
|
||||
npmci npm install
|
||||
pnpm install -g @gitzone/tsdoc
|
||||
npmci command tsdoc
|
||||
continue-on-error: true
|
137
.gitlab-ci.yml
137
.gitlab-ci.yml
@ -1,137 +0,0 @@
|
||||
# gitzone ci_default
|
||||
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
||||
|
||||
cache:
|
||||
paths:
|
||||
- .npmci_cache/
|
||||
key: '$CI_BUILD_STAGE'
|
||||
|
||||
stages:
|
||||
- security
|
||||
- test
|
||||
- release
|
||||
- metadata
|
||||
|
||||
# ====================
|
||||
# security stage
|
||||
# ====================
|
||||
mirror:
|
||||
stage: security
|
||||
script:
|
||||
- npmci git mirror
|
||||
only:
|
||||
- tags
|
||||
tags:
|
||||
- lossless
|
||||
- docker
|
||||
- notpriv
|
||||
|
||||
auditProductionDependencies:
|
||||
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
||||
stage: security
|
||||
script:
|
||||
- npmci npm prepare
|
||||
- npmci command npm install --production --ignore-scripts
|
||||
- npmci command npm config set registry https://registry.npmjs.org
|
||||
- npmci command npm audit --audit-level=high --only=prod --production
|
||||
tags:
|
||||
- docker
|
||||
|
||||
auditDevDependencies:
|
||||
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
||||
stage: security
|
||||
script:
|
||||
- npmci npm prepare
|
||||
- npmci command npm install --ignore-scripts
|
||||
- npmci command npm config set registry https://registry.npmjs.org
|
||||
- npmci command npm audit --audit-level=high --only=dev
|
||||
tags:
|
||||
- docker
|
||||
allow_failure: true
|
||||
|
||||
# ====================
|
||||
# test stage
|
||||
# ====================
|
||||
|
||||
testStable:
|
||||
stage: test
|
||||
script:
|
||||
- npmci npm prepare
|
||||
- npmci node install stable
|
||||
- npmci npm install
|
||||
- npmci npm test
|
||||
coverage: /\d+.?\d+?\%\s*coverage/
|
||||
tags:
|
||||
- docker
|
||||
|
||||
testBuild:
|
||||
stage: test
|
||||
script:
|
||||
- npmci npm prepare
|
||||
- npmci node install stable
|
||||
- npmci npm install
|
||||
- npmci command npm run build
|
||||
coverage: /\d+.?\d+?\%\s*coverage/
|
||||
tags:
|
||||
- docker
|
||||
|
||||
release:
|
||||
stage: release
|
||||
script:
|
||||
- npmci node install stable
|
||||
- npmci npm publish
|
||||
only:
|
||||
- tags
|
||||
tags:
|
||||
- lossless
|
||||
- docker
|
||||
- notpriv
|
||||
|
||||
# ====================
|
||||
# metadata stage
|
||||
# ====================
|
||||
codequality:
|
||||
stage: metadata
|
||||
allow_failure: true
|
||||
only:
|
||||
- tags
|
||||
script:
|
||||
- npmci command npm install -g tslint typescript
|
||||
- npmci npm prepare
|
||||
- npmci npm install
|
||||
- npmci command "tslint -c tslint.json ./ts/**/*.ts"
|
||||
tags:
|
||||
- lossless
|
||||
- docker
|
||||
- priv
|
||||
|
||||
trigger:
|
||||
stage: metadata
|
||||
script:
|
||||
- npmci trigger
|
||||
only:
|
||||
- tags
|
||||
tags:
|
||||
- lossless
|
||||
- docker
|
||||
- notpriv
|
||||
|
||||
pages:
|
||||
stage: metadata
|
||||
script:
|
||||
- npmci node install lts
|
||||
- npmci command npm install -g @gitzone/tsdoc
|
||||
- npmci npm prepare
|
||||
- npmci npm install
|
||||
- npmci command tsdoc
|
||||
tags:
|
||||
- lossless
|
||||
- docker
|
||||
- notpriv
|
||||
only:
|
||||
- tags
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
paths:
|
||||
- public
|
||||
allow_failure: true
|
13
.snyk
13
.snyk
@ -1,13 +0,0 @@
|
||||
# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.
|
||||
version: v1.13.5
|
||||
# ignores vulnerabilities until expiry date; change duration by modifying expiry date
|
||||
ignore:
|
||||
SNYK-JS-JSYAML-173999:
|
||||
- '@pushrocks/smartexpress > @pushrocks/smartfile > js-yaml':
|
||||
reason: None given
|
||||
expires: '2019-05-24T15:16:11.291Z'
|
||||
SNYK-JS-JSYAML-174129:
|
||||
- '@pushrocks/smartexpress > @pushrocks/smartfile > js-yaml':
|
||||
reason: None given
|
||||
expires: '2019-05-24T15:16:11.291Z'
|
||||
patch: {}
|
24
.vscode/launch.json
vendored
24
.vscode/launch.json
vendored
@ -2,28 +2,10 @@
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "current file",
|
||||
"type": "node",
|
||||
"command": "npm test",
|
||||
"name": "Run npm test",
|
||||
"request": "launch",
|
||||
"args": [
|
||||
"${relativeFile}"
|
||||
],
|
||||
"runtimeArgs": ["-r", "@gitzone/tsrun"],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"protocol": "inspector",
|
||||
"internalConsoleOptions": "openOnSessionStart"
|
||||
},
|
||||
{
|
||||
"name": "test.ts",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"args": [
|
||||
"test/test.ts"
|
||||
],
|
||||
"runtimeArgs": ["-r", "@gitzone/tsrun"],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"protocol": "inspector",
|
||||
"internalConsoleOptions": "openOnSessionStart"
|
||||
"type": "node-terminal"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -3,10 +3,10 @@
|
||||
"projectType": "npm",
|
||||
"module": {
|
||||
"githost": "gitlab.com",
|
||||
"gitscope": "pushrocks",
|
||||
"gitscope": "push.rocks",
|
||||
"gitrepo": "smartsocket",
|
||||
"shortDescription": "easy and secure websocket communication",
|
||||
"npmPackagename": "@pushrocks/smartsocket",
|
||||
"description": "easy and secure websocket communication",
|
||||
"npmPackagename": "@push.rocks/smartsocket",
|
||||
"license": "MIT",
|
||||
"projectDomain": "push.rocks"
|
||||
}
|
||||
|
11315
package-lock.json
generated
11315
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
51
package.json
51
package.json
@ -1,12 +1,14 @@
|
||||
{
|
||||
"name": "@pushrocks/smartsocket",
|
||||
"version": "1.1.68",
|
||||
"name": "@push.rocks/smartsocket",
|
||||
"version": "2.0.21",
|
||||
"description": "easy and secure websocket communication",
|
||||
"main": "dist_ts/index.js",
|
||||
"typings": "dist_ts/index.d.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"test": "(tstest test/)",
|
||||
"build": "(tsbuild --web && tsbundle --from ./ts/index.ts --to dist_bundle/bundle.js)"
|
||||
"build": "(tsbuild --web --allowimplicitany && tsbundle --from ./ts/index.ts --to dist_bundle/bundle.js)",
|
||||
"buildDocs": "tsdoc"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -19,30 +21,29 @@
|
||||
},
|
||||
"homepage": "https://gitlab.com/pushrocks/smartsocket#README",
|
||||
"dependencies": {
|
||||
"@apiglobal/typedrequest-interfaces": "^1.0.15",
|
||||
"@pushrocks/isohash": "^1.0.2",
|
||||
"@pushrocks/isounique": "^1.0.4",
|
||||
"@pushrocks/lik": "^4.0.17",
|
||||
"@pushrocks/smartdelay": "^2.0.10",
|
||||
"@pushrocks/smartenv": "^4.0.15",
|
||||
"@pushrocks/smartexpress": "^3.0.76",
|
||||
"@pushrocks/smartlog": "^2.0.39",
|
||||
"@pushrocks/smartpromise": "^3.0.6",
|
||||
"@pushrocks/smartrx": "^2.0.19",
|
||||
"@pushrocks/smarttime": "^3.0.35",
|
||||
"@types/socket.io": "^2.1.11",
|
||||
"@types/socket.io-client": "^1.4.33",
|
||||
"socket.io": "^2.3.0",
|
||||
"socket.io-client": "^2.3.0"
|
||||
"@apiglobal/typedrequest-interfaces": "^2.0.1",
|
||||
"@apiglobal/typedserver": "^2.0.65",
|
||||
"@push.rocks/isohash": "^2.0.0",
|
||||
"@push.rocks/isounique": "^1.0.5",
|
||||
"@push.rocks/lik": "^6.0.3",
|
||||
"@push.rocks/smartdelay": "^3.0.5",
|
||||
"@push.rocks/smartenv": "^5.0.5",
|
||||
"@push.rocks/smartjson": "^5.0.1",
|
||||
"@push.rocks/smartlog": "^3.0.3",
|
||||
"@push.rocks/smartpromise": "^4.0.3",
|
||||
"@push.rocks/smartrx": "^3.0.6",
|
||||
"@push.rocks/smarttime": "^4.0.4",
|
||||
"engine.io": "6.3.1",
|
||||
"socket.io": "4.5.4",
|
||||
"socket.io-client": "4.5.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@gitzone/tsbuild": "^2.1.25",
|
||||
"@gitzone/tsrun": "^1.2.12",
|
||||
"@gitzone/tstest": "^1.0.48",
|
||||
"@pushrocks/tapbundle": "^3.2.9",
|
||||
"@types/node": "^14.11.2",
|
||||
"tslint": "^6.1.3",
|
||||
"tslint-config-prettier": "^1.18.0"
|
||||
"@gitzone/tsbuild": "^2.1.66",
|
||||
"@gitzone/tsbundle": "^2.0.8",
|
||||
"@gitzone/tsrun": "^1.2.44",
|
||||
"@gitzone/tstest": "^1.0.77",
|
||||
"@push.rocks/tapbundle": "^5.0.12",
|
||||
"@types/node": "^20.4.8"
|
||||
},
|
||||
"private": false,
|
||||
"files": [
|
||||
|
4596
pnpm-lock.yaml
generated
Normal file
4596
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
31
readme.md
31
readme.md
@ -1,27 +1,26 @@
|
||||
# @pushrocks/smartsocket
|
||||
# @push.rocks/smartsocket
|
||||
easy and secure websocket communication
|
||||
|
||||
## Availabililty and Links
|
||||
* [npmjs.org (npm package)](https://www.npmjs.com/package/@pushrocks/smartsocket)
|
||||
* [gitlab.com (source)](https://gitlab.com/pushrocks/smartsocket)
|
||||
* [github.com (source mirror)](https://github.com/pushrocks/smartsocket)
|
||||
* [docs (typedoc)](https://pushrocks.gitlab.io/smartsocket/)
|
||||
* [npmjs.org (npm package)](https://www.npmjs.com/package/@push.rocks/smartsocket)
|
||||
* [gitlab.com (source)](https://gitlab.com/push.rocks/smartsocket)
|
||||
* [github.com (source mirror)](https://github.com/push.rocks/smartsocket)
|
||||
* [docs (typedoc)](https://push.rocks.gitlab.io/smartsocket/)
|
||||
|
||||
## Status for master
|
||||
|
||||
Status Category | Status Badge
|
||||
-- | --
|
||||
GitLab Pipelines | [](https://lossless.cloud)
|
||||
GitLab Pipline Test Coverage | [](https://lossless.cloud)
|
||||
npm | [](https://lossless.cloud)
|
||||
Snyk | [](https://lossless.cloud)
|
||||
GitLab Pipelines | [](https://lossless.cloud)
|
||||
GitLab Pipline Test Coverage | [](https://lossless.cloud)
|
||||
npm | [](https://lossless.cloud)
|
||||
Snyk | [](https://lossless.cloud)
|
||||
TypeScript Support | [](https://lossless.cloud)
|
||||
node Support | [](https://nodejs.org/dist/latest-v10.x/docs/api/)
|
||||
Code Style | [](https://lossless.cloud)
|
||||
PackagePhobia (total standalone install weight) | [](https://lossless.cloud)
|
||||
PackagePhobia (package size on registry) | [](https://lossless.cloud)
|
||||
BundlePhobia (total size when bundled) | [](https://lossless.cloud)
|
||||
Platform support | [](https://lossless.cloud) [](https://lossless.cloud)
|
||||
PackagePhobia (total standalone install weight) | [](https://lossless.cloud)
|
||||
PackagePhobia (package size on registry) | [](https://lossless.cloud)
|
||||
BundlePhobia (total size when bundled) | [](https://lossless.cloud)
|
||||
|
||||
## Usage
|
||||
|
||||
@ -110,14 +109,12 @@ mySmartsocketClient.serverCall('function', functionCallData).then((functionRespo
|
||||
> `data` is always a js object that you can design for your specific needs.
|
||||
> It supports buffers for large binary data network exchange.
|
||||
|
||||
|
||||
## Contribution
|
||||
|
||||
We are always happy for code contributions. If you are not the code contributing type that is ok. Still, maintaining Open Source repositories takes considerable time and thought. If you like the quality of what we do and our modules are useful to you we would appreciate a little monthly contribution: You can [contribute one time](https://lossless.link/contribute-onetime) or [contribute monthly](https://lossless.link/contribute). :)
|
||||
|
||||
For further information read the linked docs at the top of this readme.
|
||||
|
||||
> MIT licensed | **©** [Lossless GmbH](https://lossless.gmbh)
|
||||
## Legal
|
||||
> MIT licensed | **©** [Task Venture Capital GmbH](https://task.vc)
|
||||
| By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy)
|
||||
|
||||
[](https://maintainedby.lossless.com)
|
||||
|
@ -1 +0,0 @@
|
||||
console.log('TODO');
|
@ -1,31 +1,28 @@
|
||||
// tslint:disable-next-line:no-implicit-dependencies
|
||||
import { expect, tap } from '@pushrocks/tapbundle';
|
||||
import { expect, expectAsync, tap } from '@push.rocks/tapbundle';
|
||||
|
||||
import * as smarthash from '@pushrocks/smarthash';
|
||||
import * as smartpromise from '@pushrocks/smartpromise';
|
||||
import * as smartexpress from '@pushrocks/smartexpress';
|
||||
import * as isohash from '@push.rocks/isohash';
|
||||
import * as smartexpress from '@apiglobal/typedserver';
|
||||
|
||||
import socketIoClient = require('socket.io-client');
|
||||
import smartsocket = require('../ts/index');
|
||||
import * as smartsocket from '../ts/index.js';
|
||||
|
||||
let testSmartsocket: smartsocket.Smartsocket;
|
||||
let testSmartsocketClient: smartsocket.SmartsocketClient;
|
||||
let testSocketRole1: smartsocket.SocketRole;
|
||||
let testSocketFunction1: smartsocket.SocketFunction<any>;
|
||||
let myseServer: smartexpress.Server;
|
||||
let myseServer: smartexpress.servertools.Server;
|
||||
|
||||
const testConfig = {
|
||||
port: 3005,
|
||||
port: 3000,
|
||||
};
|
||||
|
||||
// class smartsocket
|
||||
tap.test('should create a new smartsocket', async () => {
|
||||
testSmartsocket = new smartsocket.Smartsocket({ port: testConfig.port });
|
||||
expect(testSmartsocket).be.instanceOf(smartsocket.Smartsocket);
|
||||
testSmartsocket = new smartsocket.Smartsocket({ alias: 'testserver', port: testConfig.port });
|
||||
expect(testSmartsocket).toBeInstanceOf(smartsocket.Smartsocket);
|
||||
});
|
||||
|
||||
tap.test('Should accept an smartExpressServer as server', async () => {
|
||||
myseServer = new smartexpress.Server({
|
||||
myseServer = new smartexpress.servertools.Server({
|
||||
cors: true,
|
||||
forceSsl: false,
|
||||
port: testConfig.port,
|
||||
@ -36,19 +33,9 @@ tap.test('Should accept an smartExpressServer as server', async () => {
|
||||
await myseServer.start();
|
||||
});
|
||||
|
||||
// class socketrole
|
||||
tap.test('should add a socketrole', async () => {
|
||||
testSocketRole1 = new smartsocket.SocketRole({
|
||||
name: 'testRole1',
|
||||
passwordHash: smarthash.sha256FromStringSync('testPassword'),
|
||||
});
|
||||
testSmartsocket.addSocketRoles([testSocketRole1]);
|
||||
});
|
||||
|
||||
// class SocketFunction
|
||||
tap.test('should register a new Function', async () => {
|
||||
testSocketFunction1 = new smartsocket.SocketFunction({
|
||||
allowedRoles: [testSocketRole1],
|
||||
funcDef: async (dataArg, socketConnectionArg) => {
|
||||
return dataArg;
|
||||
},
|
||||
@ -67,12 +54,9 @@ tap.test('should react to a new websocket connection from client', async () => {
|
||||
testSmartsocketClient = new smartsocket.SmartsocketClient({
|
||||
port: testConfig.port,
|
||||
url: 'http://localhost',
|
||||
password: 'testPassword',
|
||||
alias: 'testClient1',
|
||||
role: 'testRole1',
|
||||
});
|
||||
testSmartsocketClient.addSocketFunction(testSocketFunction1);
|
||||
console.log(testSmartsocketClient.socketFunctions);
|
||||
await testSmartsocketClient.connect();
|
||||
});
|
||||
|
||||
@ -87,17 +71,23 @@ tap.test('2 clients should connect in parallel', async () => {
|
||||
});
|
||||
|
||||
tap.test('should be able to make a functionCall from client to server', async () => {
|
||||
const totalCycles = 20000
|
||||
const totalCycles = 20000;
|
||||
let counter = 0;
|
||||
let startTime = Date.now();
|
||||
while (counter < totalCycles) {
|
||||
const response = await testSmartsocketClient.serverCall('testFunction1', {
|
||||
value1: 'hello',
|
||||
const randomString = `hello ${Math.random()}`;
|
||||
const response: any = await testSmartsocketClient.serverCall('testFunction1', {
|
||||
value1: randomString,
|
||||
});
|
||||
expect(response.value1).toEqual(randomString);
|
||||
if (counter % 100 === 0) {
|
||||
console.log(`processed 100 more messages in ${Date.now() - startTime}ms. ${totalCycles - counter} messages to go.`);
|
||||
console.log(
|
||||
`processed 100 more messages in ${Date.now() - startTime}ms. ${
|
||||
totalCycles - counter
|
||||
} messages to go.`
|
||||
);
|
||||
startTime = Date.now();
|
||||
};
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
});
|
||||
|
152
test/test.reconnect.ts
Normal file
152
test/test.reconnect.ts
Normal file
@ -0,0 +1,152 @@
|
||||
// tslint:disable-next-line:no-implicit-dependencies
|
||||
import { expect, tap } from '@push.rocks/tapbundle';
|
||||
|
||||
import * as smartsocket from '../ts/index.js';
|
||||
|
||||
let testSmartsocket: smartsocket.Smartsocket;
|
||||
let testSmartsocketClient: smartsocket.SmartsocketClient;
|
||||
let testSocketFunctionForServer: smartsocket.SocketFunction<any>;
|
||||
let testSocketFunctionClient: smartsocket.SocketFunction<any>;
|
||||
|
||||
export interface IReqResClient {
|
||||
method: 'testFunction1';
|
||||
request: {
|
||||
value1: string;
|
||||
};
|
||||
response: {
|
||||
value1: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface IReqResServer {
|
||||
method: 'testFunction2';
|
||||
request: {
|
||||
hi: string;
|
||||
};
|
||||
response: {
|
||||
hi: string;
|
||||
};
|
||||
}
|
||||
|
||||
const testConfig = {
|
||||
port: 3000,
|
||||
};
|
||||
|
||||
// class smartsocket
|
||||
tap.test('should create a new smartsocket', async () => {
|
||||
testSmartsocket = new smartsocket.Smartsocket({ alias: 'testserver1', port: testConfig.port });
|
||||
await testSmartsocket.start();
|
||||
});
|
||||
|
||||
// class SocketFunction
|
||||
tap.test('should register a new Function', async () => {
|
||||
testSocketFunctionForServer = new smartsocket.SocketFunction({
|
||||
funcDef: async (dataArg, socketConnectionArg) => {
|
||||
return dataArg;
|
||||
},
|
||||
funcName: 'testFunction1',
|
||||
});
|
||||
testSmartsocket.addSocketFunction(testSocketFunctionForServer);
|
||||
|
||||
testSocketFunctionClient = new smartsocket.SocketFunction({
|
||||
funcDef: async (dataArg, socketConnectionArg) => {
|
||||
return dataArg;
|
||||
},
|
||||
funcName: 'testFunction2',
|
||||
});
|
||||
testSmartsocket.addSocketFunction(testSocketFunctionForServer);
|
||||
});
|
||||
|
||||
// class SmartsocketClient
|
||||
tap.test('should react to a new websocket connection from client', async () => {
|
||||
testSmartsocketClient = new smartsocket.SmartsocketClient({
|
||||
port: testConfig.port,
|
||||
url: 'http://localhost',
|
||||
alias: 'testClient1',
|
||||
autoReconnect: true,
|
||||
});
|
||||
testSmartsocketClient.addSocketFunction(testSocketFunctionClient);
|
||||
await testSmartsocketClient.connect();
|
||||
});
|
||||
|
||||
tap.test('should be able to tag a connection from client', async (tools) => {
|
||||
await testSmartsocketClient.addTag({
|
||||
id: 'awesome',
|
||||
payload: 'yes',
|
||||
});
|
||||
const tagOnServerSide = await testSmartsocket.socketConnections
|
||||
.findSync((socketConnection) => {
|
||||
return true;
|
||||
})
|
||||
.getTagById('awesome');
|
||||
expect(tagOnServerSide.payload).toEqual('yes');
|
||||
});
|
||||
|
||||
tap.test('should be able to tag a connection from server', async (tools) => {
|
||||
await testSmartsocket.socketConnections
|
||||
.findSync((socketConnection) => {
|
||||
return true;
|
||||
})
|
||||
.addTag({
|
||||
id: 'awesome2',
|
||||
payload: 'absolutely',
|
||||
});
|
||||
const tagOnClientSide = await testSmartsocketClient.socketConnection.getTagById('awesome2');
|
||||
expect(tagOnClientSide.payload).toEqual('absolutely');
|
||||
});
|
||||
|
||||
tap.test('should be able to make a functionCall from client to server', async () => {
|
||||
const response = await testSmartsocketClient.serverCall<IReqResClient>('testFunction1', {
|
||||
value1: 'hello',
|
||||
});
|
||||
console.log(response);
|
||||
expect(response.value1).toEqual('hello');
|
||||
});
|
||||
|
||||
tap.test('should be able to make a functionCall from server to client', async () => {
|
||||
const response = await testSmartsocket.clientCall<IReqResServer>(
|
||||
'testFunction2',
|
||||
{
|
||||
hi: 'hi there from server',
|
||||
},
|
||||
testSmartsocket.socketConnections.findSync((socketConnection) => {
|
||||
return true;
|
||||
})
|
||||
);
|
||||
console.log(response);
|
||||
expect(response.hi).toEqual('hi there from server');
|
||||
});
|
||||
|
||||
tap.test('client should disconnect and reconnect', async (toolsArg) => {
|
||||
await testSmartsocketClient.disconnect();
|
||||
await testSmartsocketClient.connect();
|
||||
await toolsArg.delayFor(2000);
|
||||
expect(testSmartsocket.socketConnections.getArray().length).toEqual(1);
|
||||
});
|
||||
|
||||
// class smartsocket
|
||||
tap.test('should be able to switch to a new server', async (toolsArg) => {
|
||||
await testSmartsocket.stop();
|
||||
testSmartsocket = new smartsocket.Smartsocket({ alias: 'testserver2', port: testConfig.port });
|
||||
await testSmartsocket.start();
|
||||
await toolsArg.delayFor(30000);
|
||||
});
|
||||
|
||||
tap.test('should be able to locate a connection tag after reconnect', async (tools) => {
|
||||
expect(testSmartsocket.socketConnections.getArray().length).toEqual(1);
|
||||
const tagOnServerSide = await testSmartsocket.socketConnections
|
||||
.findSync((socketConnection) => {
|
||||
return true;
|
||||
})
|
||||
.getTagById('awesome');
|
||||
expect(tagOnServerSide.payload).toEqual('yes');
|
||||
});
|
||||
|
||||
// terminate
|
||||
tap.test('should close the server', async (tools) => {
|
||||
await testSmartsocketClient.stop();
|
||||
await testSmartsocket.stop();
|
||||
tools.delayFor(1000).then(() => process.exit(0));
|
||||
});
|
||||
|
||||
tap.start();
|
@ -1,16 +1,10 @@
|
||||
// tslint:disable-next-line:no-implicit-dependencies
|
||||
import { expect, tap } from '@pushrocks/tapbundle';
|
||||
import { expect, tap } from '@push.rocks/tapbundle';
|
||||
|
||||
import * as smarthash from '@pushrocks/smarthash';
|
||||
import * as smartpromise from '@pushrocks/smartpromise';
|
||||
|
||||
import socketIoClient = require('socket.io-client');
|
||||
import smartsocket = require('../ts/index');
|
||||
import * as smartsocket from '../ts/index.js';
|
||||
|
||||
let testSmartsocket: smartsocket.Smartsocket;
|
||||
let testSmartsocketClient: smartsocket.SmartsocketClient;
|
||||
let testSocketConnection: smartsocket.SocketConnection;
|
||||
let testSocketRole1: smartsocket.SocketRole;
|
||||
let testSocketFunctionForServer: smartsocket.SocketFunction<any>;
|
||||
let testSocketFunctionClient: smartsocket.SocketFunction<any>;
|
||||
|
||||
@ -40,23 +34,13 @@ const testConfig = {
|
||||
|
||||
// class smartsocket
|
||||
tap.test('should create a new smartsocket', async () => {
|
||||
testSmartsocket = new smartsocket.Smartsocket({ port: testConfig.port });
|
||||
expect(testSmartsocket).be.instanceOf(smartsocket.Smartsocket);
|
||||
});
|
||||
|
||||
// class socketrole
|
||||
tap.test('should add a socketrole', async () => {
|
||||
testSocketRole1 = new smartsocket.SocketRole({
|
||||
name: 'testRole1',
|
||||
passwordHash: smarthash.sha256FromStringSync('testPassword'),
|
||||
});
|
||||
testSmartsocket.addSocketRoles([testSocketRole1]);
|
||||
testSmartsocket = new smartsocket.Smartsocket({ alias: 'testserver2', port: testConfig.port });
|
||||
expect(testSmartsocket).toBeInstanceOf(smartsocket.Smartsocket);
|
||||
});
|
||||
|
||||
// class SocketFunction
|
||||
tap.test('should register a new Function', async () => {
|
||||
testSocketFunctionForServer = new smartsocket.SocketFunction({
|
||||
allowedRoles: [testSocketRole1],
|
||||
funcDef: async (dataArg, socketConnectionArg) => {
|
||||
return dataArg;
|
||||
},
|
||||
@ -65,14 +49,12 @@ tap.test('should register a new Function', async () => {
|
||||
testSmartsocket.addSocketFunction(testSocketFunctionForServer);
|
||||
|
||||
testSocketFunctionClient = new smartsocket.SocketFunction({
|
||||
allowedRoles: [],
|
||||
funcDef: async (dataArg, socketConnectionArg) => {
|
||||
return dataArg;
|
||||
},
|
||||
funcName: 'testFunction2',
|
||||
});
|
||||
testSmartsocket.addSocketFunction(testSocketFunctionForServer);
|
||||
console.log(testSmartsocket.socketFunctions);
|
||||
});
|
||||
|
||||
tap.test('should start listening when .started is called', async () => {
|
||||
@ -84,15 +66,38 @@ tap.test('should react to a new websocket connection from client', async () => {
|
||||
testSmartsocketClient = new smartsocket.SmartsocketClient({
|
||||
port: testConfig.port,
|
||||
url: 'http://localhost',
|
||||
password: 'testPassword',
|
||||
alias: 'testClient1',
|
||||
role: 'testRole1',
|
||||
});
|
||||
testSmartsocketClient.addSocketFunction(testSocketFunctionClient);
|
||||
console.log(testSmartsocketClient.socketFunctions);
|
||||
await testSmartsocketClient.connect();
|
||||
});
|
||||
|
||||
tap.test('should be able to tag a connection from client', async (tools) => {
|
||||
await testSmartsocketClient.addTag({
|
||||
id: 'awesome',
|
||||
payload: 'yes',
|
||||
});
|
||||
const tagOnServerSide = await testSmartsocket.socketConnections
|
||||
.findSync((socketConnection) => {
|
||||
return true;
|
||||
})
|
||||
.getTagById('awesome');
|
||||
expect(tagOnServerSide.payload).toEqual('yes');
|
||||
});
|
||||
|
||||
tap.test('should be able to tag a connection from server', async (tools) => {
|
||||
await testSmartsocket.socketConnections
|
||||
.findSync((socketConnection) => {
|
||||
return true;
|
||||
})
|
||||
.addTag({
|
||||
id: 'awesome2',
|
||||
payload: 'absolutely',
|
||||
});
|
||||
const tagOnClientSide = await testSmartsocketClient.socketConnection.getTagById('awesome2');
|
||||
expect(tagOnClientSide.payload).toEqual('absolutely');
|
||||
});
|
||||
|
||||
tap.test('2 clients should connect in parallel', async () => {
|
||||
// TODO: implement parallel test
|
||||
});
|
||||
@ -102,7 +107,7 @@ tap.test('should be able to make a functionCall from client to server', async ()
|
||||
value1: 'hello',
|
||||
});
|
||||
console.log(response);
|
||||
expect(response.value1).to.equal('hello');
|
||||
expect(response.value1).toEqual('hello');
|
||||
});
|
||||
|
||||
tap.test('should be able to make a functionCall from server to client', async () => {
|
||||
@ -111,20 +116,29 @@ tap.test('should be able to make a functionCall from server to client', async ()
|
||||
{
|
||||
hi: 'hi there from server',
|
||||
},
|
||||
testSmartsocket.socketConnections.find((socketConnection) => {
|
||||
testSmartsocket.socketConnections.findSync((socketConnection) => {
|
||||
return true;
|
||||
})
|
||||
);
|
||||
console.log(response);
|
||||
expect(response.hi).to.equal('hi there from server');
|
||||
expect(response.hi).toEqual('hi there from server');
|
||||
});
|
||||
|
||||
tap.test('client should disconnect and reconnect', async (tools) => {
|
||||
await testSmartsocketClient.disconnect();
|
||||
await tools.delayFor(100);
|
||||
await testSmartsocketClient.connect();
|
||||
});
|
||||
|
||||
tap.test('should be able to locate a connection tag after reconnect', async (tools) => {
|
||||
console.log(testSmartsocket.socketConnections.getArray().length);
|
||||
const tagOnServerSide = await testSmartsocket.socketConnections
|
||||
.findSync((socketConnection) => {
|
||||
return true;
|
||||
})
|
||||
.getTagById('awesome');
|
||||
expect(tagOnServerSide.payload).toEqual('yes');
|
||||
});
|
||||
|
||||
// terminate
|
||||
tap.test('should close the server', async () => {
|
||||
await testSmartsocket.stop();
|
8
ts/00_commitinfo_data.ts
Normal file
8
ts/00_commitinfo_data.ts
Normal file
@ -0,0 +1,8 @@
|
||||
/**
|
||||
* autocreated commitinfo by @pushrocks/commitinfo
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@push.rocks/smartsocket',
|
||||
version: '2.0.21',
|
||||
description: 'easy and secure websocket communication'
|
||||
}
|
12
ts/index.ts
12
ts/index.ts
@ -1,8 +1,10 @@
|
||||
// export main classes
|
||||
export * from './smartsocket.classes.smartsocket';
|
||||
export * from './smartsocket.classes.smartsocketclient';
|
||||
export * from './smartsocket.classes.smartsocket.js';
|
||||
export * from './smartsocket.classes.smartsocketclient.js';
|
||||
|
||||
// export further classes and objects
|
||||
export * from './smartsocket.classes.socketfunction';
|
||||
export * from './smartsocket.classes.socketrole';
|
||||
export * from './smartsocket.classes.socketconnection';
|
||||
export * from './smartsocket.classes.socketfunction.js';
|
||||
export * from './smartsocket.classes.socketconnection.js';
|
||||
|
||||
// export types so they can be referred to
|
||||
export * from './interfaces/index.js';
|
@ -1,5 +1,5 @@
|
||||
export interface IRequestAuthPayload {
|
||||
serverShortId: string;
|
||||
serverAlias: string;
|
||||
}
|
||||
|
||||
export type TConnectionStatus =
|
||||
@ -7,4 +7,5 @@ export type TConnectionStatus =
|
||||
| 'connecting'
|
||||
| 'connected'
|
||||
| 'disconnecting'
|
||||
| 'disconnected';
|
||||
| 'disconnected'
|
||||
| 'timedOut';
|
||||
|
@ -1 +1,2 @@
|
||||
export * from './connection';
|
||||
export * from './connection.js';
|
||||
export * from './tag.js';
|
||||
|
6
ts/interfaces/tag.ts
Normal file
6
ts/interfaces/tag.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export interface ITag<T = any> {
|
||||
id: string;
|
||||
payload: T;
|
||||
}
|
||||
|
||||
export type TTagStore = { [key: string]: ITag };
|
@ -1,20 +1,21 @@
|
||||
import * as plugins from './smartsocket.plugins';
|
||||
import * as pluginsTyped from './smartsocket.pluginstyped';
|
||||
import * as plugins from './smartsocket.plugins.js';
|
||||
import * as pluginsTyped from './smartsocket.pluginstyped.js';
|
||||
import * as interfaces from './interfaces/index.js';
|
||||
|
||||
// classes
|
||||
import { SocketConnection } from './smartsocket.classes.socketconnection';
|
||||
import { SocketConnection } from './smartsocket.classes.socketconnection.js';
|
||||
import {
|
||||
ISocketFunctionCallDataRequest,
|
||||
type ISocketFunctionCallDataRequest,
|
||||
SocketFunction,
|
||||
ISocketFunctionCallDataResponse,
|
||||
} from './smartsocket.classes.socketfunction';
|
||||
import { SocketRequest } from './smartsocket.classes.socketrequest';
|
||||
import { SocketRole } from './smartsocket.classes.socketrole';
|
||||
import { SocketServer } from './smartsocket.classes.socketserver';
|
||||
type ISocketFunctionCallDataResponse,
|
||||
} from './smartsocket.classes.socketfunction.js';
|
||||
import { SocketRequest } from './smartsocket.classes.socketrequest.js';
|
||||
import { SocketServer } from './smartsocket.classes.socketserver.js';
|
||||
|
||||
import { logger } from './smartsocket.logging';
|
||||
import { logger } from './smartsocket.logging.js';
|
||||
|
||||
export interface ISmartsocketConstructorOptions {
|
||||
alias: string;
|
||||
port?: number;
|
||||
}
|
||||
|
||||
@ -22,22 +23,23 @@ export class Smartsocket {
|
||||
/**
|
||||
* a unique id to detect server restarts
|
||||
*/
|
||||
public shortId = plugins.isounique.uni();
|
||||
public alias: string;
|
||||
public smartenv = new plugins.smartenv.Smartenv();
|
||||
public options: ISmartsocketConstructorOptions;
|
||||
public io: pluginsTyped.socketIo.Server;
|
||||
public socketConnections = new plugins.lik.ObjectMap<SocketConnection>();
|
||||
public socketRoles = new plugins.lik.ObjectMap<SocketRole>();
|
||||
public socketFunctions = new plugins.lik.ObjectMap<SocketFunction<any>>();
|
||||
public socketRequests = new plugins.lik.ObjectMap<SocketRequest<any>>();
|
||||
|
||||
public eventSubject = new plugins.smartrx.rxjs.Subject<interfaces.TConnectionStatus>();
|
||||
|
||||
private socketServer = new SocketServer(this);
|
||||
|
||||
constructor(optionsArg: ISmartsocketConstructorOptions) {
|
||||
this.options = optionsArg;
|
||||
this.alias = plugins.isounique.uni(this.options.alias);
|
||||
}
|
||||
|
||||
// tslint:disable-next-line:member-ordering
|
||||
public async setExternalServer(serverType: 'smartexpress', serverArg: any) {
|
||||
await this.socketServer.setExternalServer(serverType, serverArg);
|
||||
}
|
||||
@ -46,8 +48,14 @@ export class Smartsocket {
|
||||
* starts smartsocket
|
||||
*/
|
||||
public async start() {
|
||||
const socketIoModule = this.smartenv.getSafeNodeModule('socket.io');
|
||||
this.io = socketIoModule(this.socketServer.getServerForSocketIo());
|
||||
const socketIoModule = await this.smartenv.getSafeNodeModule('socket.io');
|
||||
this.io = new socketIoModule.Server(await this.socketServer.getServerForSocketIo(), {
|
||||
cors: {
|
||||
allowedHeaders: '*',
|
||||
methods: '*',
|
||||
origin: '*',
|
||||
},
|
||||
});
|
||||
await this.socketServer.start();
|
||||
this.io.on('connection', (socketArg) => {
|
||||
this._handleSocketConnection(socketArg);
|
||||
@ -61,8 +69,11 @@ export class Smartsocket {
|
||||
await plugins.smartdelay.delayFor(1000);
|
||||
this.socketConnections.forEach((socketObjectArg: SocketConnection) => {
|
||||
if (socketObjectArg) {
|
||||
logger.log('info', `disconnect socket with >>alias ${socketObjectArg.alias}`);
|
||||
socketObjectArg.socket.disconnect();
|
||||
logger.log(
|
||||
'info',
|
||||
`disconnecting socket with >>alias ${socketObjectArg.alias} due to server stop...`
|
||||
);
|
||||
socketObjectArg.disconnect();
|
||||
}
|
||||
});
|
||||
this.socketConnections.wipe();
|
||||
@ -96,16 +107,6 @@ export class Smartsocket {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* adds socketRoles
|
||||
*/
|
||||
public addSocketRoles(socketRolesArray: SocketRole[]): void {
|
||||
for (const socketRole of socketRolesArray) {
|
||||
this.socketRoles.add(socketRole);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
public addSocketFunction(socketFunction: SocketFunction<any>) {
|
||||
this.socketFunctions.add(socketFunction);
|
||||
}
|
||||
@ -117,14 +118,20 @@ export class Smartsocket {
|
||||
const socketConnection: SocketConnection = new SocketConnection({
|
||||
alias: undefined,
|
||||
authenticated: false,
|
||||
role: undefined,
|
||||
side: 'server',
|
||||
smartsocketHost: this,
|
||||
socket: socketArg,
|
||||
});
|
||||
logger.log('info', 'Socket connected. Trying to authenticate...');
|
||||
this.socketConnections.add(socketConnection);
|
||||
const disconnectSubscription = socketConnection.eventSubject.subscribe((eventArg) => {
|
||||
if (eventArg === 'disconnected') {
|
||||
this.socketConnections.remove(socketConnection);
|
||||
disconnectSubscription.unsubscribe();
|
||||
}
|
||||
});
|
||||
await socketConnection.authenticate();
|
||||
await socketConnection.listenToFunctionRequests();
|
||||
await socketConnection.socket.emit('serverFullyReactive');
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,14 @@
|
||||
import * as plugins from './smartsocket.plugins';
|
||||
import * as pluginsTyped from './smartsocket.pluginstyped';
|
||||
import * as interfaces from './interfaces';
|
||||
import * as plugins from './smartsocket.plugins.js';
|
||||
import * as pluginsTyped from './smartsocket.pluginstyped.js';
|
||||
import * as interfaces from './interfaces/index.js';
|
||||
|
||||
import { SocketConnection } from './smartsocket.classes.socketconnection';
|
||||
import { SocketConnection } from './smartsocket.classes.socketconnection.js';
|
||||
import {
|
||||
ISocketFunctionCallDataRequest,
|
||||
type ISocketFunctionCallDataRequest,
|
||||
SocketFunction,
|
||||
} from './smartsocket.classes.socketfunction';
|
||||
import { ISocketRequestDataObject, SocketRequest } from './smartsocket.classes.socketrequest';
|
||||
import { SocketRole } from './smartsocket.classes.socketrole';
|
||||
import { logger } from './smartsocket.logging';
|
||||
} from './smartsocket.classes.socketfunction.js';
|
||||
import { type ISocketRequestDataObject, SocketRequest } from './smartsocket.classes.socketrequest.js';
|
||||
import { logger } from './smartsocket.logging.js';
|
||||
|
||||
/**
|
||||
* interface for class SmartsocketClient
|
||||
@ -18,8 +17,6 @@ export interface ISmartsocketClientOptions {
|
||||
port: number;
|
||||
url: string;
|
||||
alias: string; // an alias makes it easier to identify this client in a multo client environment
|
||||
role: string;
|
||||
password: string; // by setting a password access to functions can be limited
|
||||
autoReconnect?: boolean;
|
||||
}
|
||||
|
||||
@ -31,7 +28,6 @@ export class SmartsocketClient {
|
||||
public remoteShortId: string = null;
|
||||
|
||||
public alias: string;
|
||||
public socketRole: SocketRole;
|
||||
public socketConnection: SocketConnection;
|
||||
public serverUrl: string;
|
||||
public serverPort: number;
|
||||
@ -43,22 +39,50 @@ export class SmartsocketClient {
|
||||
|
||||
public socketFunctions = new plugins.lik.ObjectMap<SocketFunction<any>>();
|
||||
public socketRequests = new plugins.lik.ObjectMap<SocketRequest<any>>();
|
||||
public socketRoles = new plugins.lik.ObjectMap<SocketRole>();
|
||||
|
||||
// tagStore
|
||||
private tagStore: { [key: string]: interfaces.ITag } = {};
|
||||
private tagStoreSubscription: plugins.smartrx.rxjs.Subscription;
|
||||
|
||||
/**
|
||||
* adds a tag to a connection
|
||||
*/
|
||||
public async addTag(tagArg: interfaces.ITag) {
|
||||
if (this.socketConnection) {
|
||||
await this.socketConnection.addTag(tagArg);
|
||||
} else {
|
||||
this.tagStore[tagArg.id] = tagArg;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gets a tag by id
|
||||
* @param tagIdArg
|
||||
*/
|
||||
public async getTagById(tagIdArg: interfaces.ITag['id']) {
|
||||
return this.tagStore[tagIdArg];
|
||||
}
|
||||
|
||||
/**
|
||||
* removes a tag from a connection
|
||||
*/
|
||||
public async removeTagById(tagIdArg: interfaces.ITag['id']) {
|
||||
if (this.socketConnection) {
|
||||
this.socketConnection.removeTagById(tagIdArg);
|
||||
} else {
|
||||
delete this.tagStore[tagIdArg];
|
||||
}
|
||||
}
|
||||
|
||||
constructor(optionsArg: ISmartsocketClientOptions) {
|
||||
this.alias = optionsArg.alias;
|
||||
this.serverUrl = optionsArg.url;
|
||||
this.serverPort = optionsArg.port;
|
||||
this.socketRole = new SocketRole({
|
||||
name: optionsArg.role,
|
||||
passwordHash: optionsArg.password,
|
||||
});
|
||||
this.autoReconnect = optionsArg.autoReconnect;
|
||||
}
|
||||
|
||||
public addSocketFunction(socketFunction: SocketFunction<any>) {
|
||||
this.socketFunctions.add(socketFunction);
|
||||
this.socketRole.allowedFunctions.add(socketFunction);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -67,108 +91,146 @@ export class SmartsocketClient {
|
||||
public async connect() {
|
||||
const done = plugins.smartpromise.defer();
|
||||
const smartenvInstance = new plugins.smartenv.Smartenv();
|
||||
const socketIoClient = await smartenvInstance.getEnvAwareModule({
|
||||
const socketIoClient: any = await smartenvInstance.getEnvAwareModule({
|
||||
nodeModuleName: 'socket.io-client',
|
||||
webUrlArg: 'https://cdn.jsdelivr.net/npm/socket.io-client@2/dist/socket.io.js',
|
||||
webUrlArg: 'https://cdn.jsdelivr.net/npm/socket.io-client@4/dist/socket.io.js',
|
||||
getFunction: () => {
|
||||
return globalThis.io;
|
||||
const socketIoBrowserModule = (globalThis as any).io;
|
||||
// console.log('loaded socket.io for browser');
|
||||
return socketIoBrowserModule;
|
||||
},
|
||||
});
|
||||
// console.log(socketIoClient);
|
||||
logger.log('info', 'trying to connect...');
|
||||
const socketUrl = `${this.serverUrl}:${this.serverPort}`;
|
||||
this.socketConnection = new SocketConnection({
|
||||
alias: this.alias,
|
||||
authenticated: false,
|
||||
role: this.socketRole,
|
||||
side: 'client',
|
||||
smartsocketHost: this,
|
||||
socket: await socketIoClient.connect(socketUrl, {
|
||||
multiplex: false,
|
||||
reconnectionAttempts: 5,
|
||||
}),
|
||||
socket: await socketIoClient
|
||||
.connect(socketUrl, {
|
||||
multiplex: true,
|
||||
rememberUpgrade: true,
|
||||
autoConnect: false,
|
||||
reconnectionAttempts: 0,
|
||||
rejectUnauthorized: socketUrl.startsWith('https://localhost') ? false : true,
|
||||
})
|
||||
.open(),
|
||||
});
|
||||
|
||||
const timer = new plugins.smarttime.Timer(5000);
|
||||
timer.start();
|
||||
timer.completed.then(() => {
|
||||
this.updateStatus('timedOut');
|
||||
logger.log('warn', 'connection to server timed out.');
|
||||
this.disconnect();
|
||||
this.disconnect(true);
|
||||
});
|
||||
|
||||
// authentication flow
|
||||
this.socketConnection.socket.on(
|
||||
'requestAuth',
|
||||
(requestAuthPayload: interfaces.IRequestAuthPayload) => {
|
||||
timer.reset();
|
||||
logger.log('info', 'server requested authentication');
|
||||
this.socketConnection.socket.on('requestAuth', (dataArg: interfaces.IRequestAuthPayload) => {
|
||||
timer.reset();
|
||||
logger.log('info', `server ${dataArg.serverAlias} requested authentication`);
|
||||
|
||||
// lets register the authenticated event
|
||||
this.socketConnection.socket.on('authenticated', () => {
|
||||
this.remoteShortId = requestAuthPayload.serverShortId;
|
||||
logger.log('info', 'client is authenticated');
|
||||
this.socketConnection.authenticated = true;
|
||||
this.socketConnection.listenToFunctionRequests();
|
||||
done.resolve();
|
||||
});
|
||||
// lets register the authenticated event
|
||||
this.socketConnection.socket.on('authenticated', async () => {
|
||||
this.remoteShortId = dataArg.serverAlias;
|
||||
logger.log('info', 'client is authenticated');
|
||||
this.socketConnection.authenticated = true;
|
||||
await this.socketConnection.listenToFunctionRequests();
|
||||
});
|
||||
|
||||
// lets register the forbidden event
|
||||
this.socketConnection.socket.on('forbidden', async () => {
|
||||
logger.log('warn', `disconnecting due to being forbidden to use the ressource`);
|
||||
await this.disconnect();
|
||||
});
|
||||
this.socketConnection.socket.on('serverFullyReactive', async () => {
|
||||
// lets take care of retagging
|
||||
const oldTagStore = this.tagStore;
|
||||
this.tagStoreSubscription?.unsubscribe();
|
||||
for (const keyArg of Object.keys(this.tagStore)) {
|
||||
this.socketConnection.addTag(this.tagStore[keyArg]);
|
||||
}
|
||||
this.tagStoreSubscription = this.socketConnection.tagStoreObservable.subscribe(
|
||||
(tagStoreArg) => {
|
||||
this.tagStore = tagStoreArg;
|
||||
}
|
||||
);
|
||||
|
||||
// lets provide the actual auth data
|
||||
this.socketConnection.socket.emit('dataAuth', {
|
||||
role: this.socketRole.name,
|
||||
password: this.socketRole.passwordHash,
|
||||
alias: this.alias,
|
||||
});
|
||||
}
|
||||
);
|
||||
for (const tag of Object.keys(oldTagStore)) {
|
||||
await this.addTag(oldTagStore[tag]);
|
||||
}
|
||||
this.updateStatus('connected');
|
||||
done.resolve();
|
||||
});
|
||||
|
||||
// lets register the forbidden event
|
||||
this.socketConnection.socket.on('forbidden', async () => {
|
||||
logger.log('warn', `disconnecting due to being forbidden to use the ressource`);
|
||||
await this.disconnect();
|
||||
});
|
||||
|
||||
// lets provide the actual auth data
|
||||
this.socketConnection.socket.emit('dataAuth', {
|
||||
alias: this.alias,
|
||||
});
|
||||
});
|
||||
|
||||
// handle connection
|
||||
this.socketConnection.socket.on('connect', async () => {
|
||||
this.updateStatus('connected');
|
||||
});
|
||||
this.socketConnection.socket.on('connect', async () => {});
|
||||
|
||||
// handle disconnection and errors
|
||||
this.socketConnection.socket.on('disconnect', async () => {
|
||||
await this.disconnect();
|
||||
await this.disconnect(true);
|
||||
});
|
||||
|
||||
this.socketConnection.socket.on('reconnect_failed', async () => {
|
||||
await this.disconnect();
|
||||
await this.disconnect(true);
|
||||
});
|
||||
this.socketConnection.socket.on('connect_error', async () => {
|
||||
await this.disconnect();
|
||||
await this.disconnect(true);
|
||||
});
|
||||
return done.promise;
|
||||
}
|
||||
|
||||
private disconnectRunning = false;
|
||||
|
||||
/**
|
||||
* disconnect from the server
|
||||
*/
|
||||
public async disconnect() {
|
||||
public async disconnect(useAutoReconnectSetting = false) {
|
||||
if (this.disconnectRunning) {
|
||||
return;
|
||||
}
|
||||
this.disconnectRunning = true;
|
||||
this.updateStatus('disconnecting');
|
||||
this.tagStoreSubscription?.unsubscribe();
|
||||
if (this.socketConnection) {
|
||||
await this.socketConnection.disconnect();
|
||||
this.socketConnection = undefined;
|
||||
logger.log('ok', 'disconnected!');
|
||||
logger.log('ok', 'disconnected socket!');
|
||||
} else {
|
||||
this.disconnectRunning = false;
|
||||
logger.log('warn', 'tried to disconnect, without a SocketConnection');
|
||||
return;
|
||||
}
|
||||
|
||||
logger.log('warn', `disconnected from server ${this.remoteShortId}`);
|
||||
this.remoteShortId = null;
|
||||
this.updateStatus('disconnected');
|
||||
|
||||
if (this.autoReconnect) {
|
||||
this.tryDebouncedReconnect();
|
||||
if (this.autoReconnect && useAutoReconnectSetting && this.eventStatus !== 'connecting') {
|
||||
this.updateStatus('connecting');
|
||||
console.log('debounced reconnect!');
|
||||
await plugins.smartdelay.delayForRandom(10000, 20000);
|
||||
this.disconnectRunning = false;
|
||||
await this.connect();
|
||||
} else {
|
||||
this.disconnectRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* try a reconnection
|
||||
* stops the client completely
|
||||
*/
|
||||
public async tryDebouncedReconnect() {
|
||||
await plugins.smartdelay.delayForRandom(10000, 60000);
|
||||
await this.connect();
|
||||
public async stop() {
|
||||
this.autoReconnect = false;
|
||||
await this.disconnect();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,16 +1,15 @@
|
||||
import * as plugins from './smartsocket.plugins';
|
||||
import * as interfaces from './interfaces';
|
||||
import * as plugins from './smartsocket.plugins.js';
|
||||
import * as pluginsTyped from './smartsocket.pluginstyped.js';
|
||||
import * as interfaces from './interfaces/index.js';
|
||||
|
||||
// import classes
|
||||
import { Smartsocket } from './smartsocket.classes.smartsocket';
|
||||
import { SocketFunction } from './smartsocket.classes.socketfunction';
|
||||
import { SocketRequest, ISocketRequestDataObject } from './smartsocket.classes.socketrequest';
|
||||
import { SocketRole } from './smartsocket.classes.socketrole';
|
||||
import { Smartsocket } from './smartsocket.classes.smartsocket.js';
|
||||
import { SocketFunction } from './smartsocket.classes.socketfunction.js';
|
||||
import { SocketRequest, type ISocketRequestDataObject } from './smartsocket.classes.socketrequest.js';
|
||||
|
||||
// socket.io
|
||||
import * as SocketIO from 'socket.io';
|
||||
import { SmartsocketClient } from './smartsocket.classes.smartsocketclient';
|
||||
import { logger } from './smartsocket.logging';
|
||||
import { SmartsocketClient } from './smartsocket.classes.smartsocketclient.js';
|
||||
import { logger } from './smartsocket.logging.js';
|
||||
|
||||
// export interfaces
|
||||
|
||||
@ -25,19 +24,16 @@ export type TSocketConnectionSide = 'server' | 'client';
|
||||
export interface ISocketConnectionConstructorOptions {
|
||||
alias: string;
|
||||
authenticated: boolean;
|
||||
role: SocketRole;
|
||||
side: TSocketConnectionSide;
|
||||
smartsocketHost: Smartsocket | SmartsocketClient;
|
||||
socket: SocketIO.Socket | SocketIOClient.Socket;
|
||||
socket: pluginsTyped.socketIo.Socket | pluginsTyped.socketIoClient.Socket;
|
||||
}
|
||||
|
||||
/**
|
||||
* interface for authentication data
|
||||
*/
|
||||
export interface ISocketConnectionAuthenticationObject {
|
||||
role: 'coreflowContainer';
|
||||
password: 'somePassword';
|
||||
alias: 'coreflow1';
|
||||
alias: string;
|
||||
}
|
||||
|
||||
// export classes
|
||||
@ -50,17 +46,19 @@ export class SocketConnection {
|
||||
public alias: string;
|
||||
public side: TSocketConnectionSide;
|
||||
public authenticated: boolean = false;
|
||||
public role: SocketRole;
|
||||
public smartsocketRef: Smartsocket | SmartsocketClient;
|
||||
public socket: SocketIO.Socket | SocketIOClient.Socket;
|
||||
public socket: pluginsTyped.socketIo.Socket | pluginsTyped.socketIoClient.Socket;
|
||||
|
||||
public eventSubject = new plugins.smartrx.rxjs.Subject<interfaces.TConnectionStatus>();
|
||||
public eventStatus: interfaces.TConnectionStatus = 'new';
|
||||
|
||||
private tagStore: interfaces.TTagStore = {};
|
||||
public tagStoreObservable = new plugins.smartrx.rxjs.Subject<interfaces.TTagStore>();
|
||||
public remoteTagStoreObservable = new plugins.smartrx.rxjs.Subject<interfaces.TTagStore>();
|
||||
|
||||
constructor(optionsArg: ISocketConnectionConstructorOptions) {
|
||||
this.alias = optionsArg.alias;
|
||||
this.authenticated = optionsArg.authenticated;
|
||||
this.role = optionsArg.role;
|
||||
this.side = optionsArg.side;
|
||||
this.smartsocketRef = optionsArg.smartsocketHost;
|
||||
this.socket = optionsArg.socket;
|
||||
@ -79,9 +77,49 @@ export class SocketConnection {
|
||||
);
|
||||
await this.disconnect();
|
||||
allSocketConnections.remove(this);
|
||||
this.eventSubject.next('disconnected');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* adds a tag to a connection
|
||||
*/
|
||||
public async addTag(tagArg: interfaces.ITag) {
|
||||
const done = plugins.smartpromise.defer();
|
||||
this.tagStore[tagArg.id] = tagArg;
|
||||
this.tagStoreObservable.next(this.tagStore);
|
||||
const remoteSubscription = this.remoteTagStoreObservable.subscribe((remoteTagStore) => {
|
||||
if (!remoteTagStore[tagArg.id]) {
|
||||
return;
|
||||
}
|
||||
const localTagString = plugins.smartjson.stringify(tagArg);
|
||||
const remoteTagString = plugins.smartjson.stringify(remoteTagStore[tagArg.id]);
|
||||
if (localTagString === remoteTagString) {
|
||||
remoteSubscription.unsubscribe();
|
||||
done.resolve();
|
||||
}
|
||||
});
|
||||
this.socket.emit('updateTagStore', this.tagStore);
|
||||
await done.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets a tag by id
|
||||
* @param tagIdArg
|
||||
*/
|
||||
public async getTagById(tagIdArg: interfaces.ITag['id']) {
|
||||
return this.tagStore[tagIdArg];
|
||||
}
|
||||
|
||||
/**
|
||||
* removes a tag from a connection
|
||||
*/
|
||||
public async removeTagById(tagIdArg: interfaces.ITag['id']) {
|
||||
delete this.tagStore[tagIdArg];
|
||||
this.tagStoreObservable.next(this.tagStore);
|
||||
this.socket.emit('updateTagStore', this.tagStore);
|
||||
}
|
||||
|
||||
// authenticating --------------------------
|
||||
|
||||
/**
|
||||
@ -90,24 +128,23 @@ export class SocketConnection {
|
||||
public authenticate() {
|
||||
const done = plugins.smartpromise.defer();
|
||||
this.socket.on('dataAuth', async (dataArg: ISocketConnectionAuthenticationObject) => {
|
||||
logger.log('info', 'received authentication data. now hashing and comparing...');
|
||||
this.socket.removeListener('dataAuth', () => {});
|
||||
if (await SocketRole.checkPasswordForRole(dataArg, this.smartsocketRef)) {
|
||||
logger.log('info', 'received authentication data...');
|
||||
this.socket.removeAllListeners('dataAuth');
|
||||
if (dataArg.alias) {
|
||||
// TODO: authenticate password
|
||||
this.alias = dataArg.alias;
|
||||
this.authenticated = true;
|
||||
this.role = SocketRole.getSocketRoleByName(this.smartsocketRef, dataArg.role);
|
||||
this.socket.emit('authenticated');
|
||||
logger.log('ok', `socket with >>alias ${this.alias} >>role ${this.role} is authenticated!`);
|
||||
logger.log('ok', `socket with >>alias ${this.alias} is authenticated!`);
|
||||
done.resolve(this);
|
||||
} else {
|
||||
this.authenticated = false;
|
||||
await this.disconnect();
|
||||
done.reject('not authenticated');
|
||||
done.reject('a socket tried to connect, but could not authenticated.');
|
||||
}
|
||||
});
|
||||
const requestAuthPayload: interfaces.IRequestAuthPayload = {
|
||||
serverShortId: this.smartsocketRef.shortId,
|
||||
serverAlias: this.smartsocketRef.alias,
|
||||
};
|
||||
this.socket.emit('requestAuth', requestAuthPayload);
|
||||
return done.promise;
|
||||
@ -124,11 +161,10 @@ export class SocketConnection {
|
||||
this.socket.on('function', (dataArg: ISocketRequestDataObject<any>) => {
|
||||
// check if requested function is available to the socket's scope
|
||||
// logger.log('info', 'function request received');
|
||||
const referencedFunction: SocketFunction<any> = this.role.allowedFunctions.find(
|
||||
(socketFunctionArg) => {
|
||||
const referencedFunction: SocketFunction<any> =
|
||||
this.smartsocketRef.socketFunctions.findSync((socketFunctionArg) => {
|
||||
return socketFunctionArg.name === dataArg.funcCallData.funcName;
|
||||
}
|
||||
);
|
||||
});
|
||||
if (referencedFunction) {
|
||||
// logger.log('ok', 'function in access scope');
|
||||
const localSocketRequest = new SocketRequest(this.smartsocketRef, {
|
||||
@ -150,7 +186,20 @@ export class SocketConnection {
|
||||
);
|
||||
targetSocketRequest.handleResponse(dataArg);
|
||||
});
|
||||
logger.log('info', `now listening to function requests for ${this.alias}`);
|
||||
|
||||
this.socket.on('updateTagStore', async (tagStoreArg: interfaces.TTagStore) => {
|
||||
if (!plugins.smartjson.deepEqualObjects(this.tagStore, tagStoreArg)) {
|
||||
this.tagStore = tagStoreArg;
|
||||
this.socket.emit('updateTagStore', this.tagStore);
|
||||
this.tagStoreObservable.next(this.tagStore);
|
||||
}
|
||||
this.remoteTagStoreObservable.next(tagStoreArg);
|
||||
});
|
||||
|
||||
logger.log(
|
||||
'info',
|
||||
`now listening to function requests for ${this.alias} on side ${this.side}`
|
||||
);
|
||||
done.resolve(this);
|
||||
} else {
|
||||
const errMessage = 'socket needs to be authenticated first';
|
||||
|
@ -1,10 +1,9 @@
|
||||
import * as plugins from './smartsocket.plugins';
|
||||
import * as plugins from './smartsocket.plugins.js';
|
||||
|
||||
// import classes
|
||||
import { SocketRole } from './smartsocket.classes.socketrole';
|
||||
import { SocketConnection } from './smartsocket.classes.socketconnection';
|
||||
import { Smartsocket } from './smartsocket.classes.smartsocket';
|
||||
import { SmartsocketClient } from './smartsocket.classes.smartsocketclient';
|
||||
import { SocketConnection } from './smartsocket.classes.socketconnection.js';
|
||||
import { Smartsocket } from './smartsocket.classes.smartsocket.js';
|
||||
import { SmartsocketClient } from './smartsocket.classes.smartsocketclient.js';
|
||||
|
||||
// export interfaces
|
||||
|
||||
@ -16,7 +15,6 @@ export interface ISocketFunctionConstructorOptions<
|
||||
> {
|
||||
funcName: T['method'];
|
||||
funcDef: TFuncDef<T>;
|
||||
allowedRoles: SocketRole[]; // all roles that are allowed to execute a SocketFunction
|
||||
}
|
||||
|
||||
/**
|
||||
@ -58,7 +56,7 @@ export class SocketFunction<T extends plugins.typedrequestInterfaces.ITypedReque
|
||||
smartsocketRefArg: Smartsocket | SmartsocketClient,
|
||||
functionNameArg: string
|
||||
): SocketFunction<Q> {
|
||||
return smartsocketRefArg.socketFunctions.find((socketFunctionArg) => {
|
||||
return smartsocketRefArg.socketFunctions.findSync((socketFunctionArg) => {
|
||||
return socketFunctionArg.name === functionNameArg;
|
||||
});
|
||||
}
|
||||
@ -66,7 +64,6 @@ export class SocketFunction<T extends plugins.typedrequestInterfaces.ITypedReque
|
||||
// INSTANCE
|
||||
public name: string;
|
||||
public funcDef: TFuncDef<T>;
|
||||
public roles: SocketRole[];
|
||||
|
||||
/**
|
||||
* the constructor for SocketFunction
|
||||
@ -74,10 +71,6 @@ export class SocketFunction<T extends plugins.typedrequestInterfaces.ITypedReque
|
||||
constructor(optionsArg: ISocketFunctionConstructorOptions<T>) {
|
||||
this.name = optionsArg.funcName;
|
||||
this.funcDef = optionsArg.funcDef;
|
||||
this.roles = optionsArg.allowedRoles;
|
||||
for (const socketRoleArg of this.roles) {
|
||||
this._notifyRole(socketRoleArg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -97,11 +90,4 @@ export class SocketFunction<T extends plugins.typedrequestInterfaces.ITypedReque
|
||||
throw new Error("SocketFunction.name does not match the data argument's .name!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* notifies a role about access to this SocketFunction
|
||||
*/
|
||||
private _notifyRole(socketRoleArg: SocketRole) {
|
||||
socketRoleArg.addSocketFunction(this);
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,17 @@
|
||||
import * as plugins from './smartsocket.plugins';
|
||||
import * as plugins from './smartsocket.plugins.js';
|
||||
|
||||
// import interfaces
|
||||
import {
|
||||
SocketFunction,
|
||||
ISocketFunctionCallDataRequest,
|
||||
ISocketFunctionCallDataResponse,
|
||||
} from './smartsocket.classes.socketfunction';
|
||||
type ISocketFunctionCallDataRequest,
|
||||
type ISocketFunctionCallDataResponse,
|
||||
} from './smartsocket.classes.socketfunction.js';
|
||||
|
||||
// import classes
|
||||
import { SocketConnection } from './smartsocket.classes.socketconnection';
|
||||
import { logger } from './smartsocket.logging';
|
||||
import { Smartsocket } from './smartsocket.classes.smartsocket';
|
||||
import { SmartsocketClient } from './smartsocket.classes.smartsocketclient';
|
||||
import { SocketConnection } from './smartsocket.classes.socketconnection.js';
|
||||
import { logger } from './smartsocket.logging.js';
|
||||
import { Smartsocket } from './smartsocket.classes.smartsocket.js';
|
||||
import { SmartsocketClient } from './smartsocket.classes.smartsocketclient.js';
|
||||
|
||||
// export interfaces
|
||||
export type TSocketRequestStatus = 'new' | 'pending' | 'finished';
|
||||
@ -45,7 +45,7 @@ export class SocketRequest<T extends plugins.typedrequestInterfaces.ITypedReques
|
||||
smartsocketRef: Smartsocket | SmartsocketClient,
|
||||
shortIdArg: string
|
||||
): SocketRequest<any> {
|
||||
return smartsocketRef.socketRequests.find((socketRequestArg) => {
|
||||
return smartsocketRef.socketRequests.findSync((socketRequestArg) => {
|
||||
return socketRequestArg.shortid === shortIdArg;
|
||||
});
|
||||
}
|
||||
|
@ -1,57 +0,0 @@
|
||||
import * as plugins from './smartsocket.plugins';
|
||||
|
||||
// import classes
|
||||
import { SocketFunction } from './smartsocket.classes.socketfunction';
|
||||
import { Smartsocket } from './smartsocket.classes.smartsocket';
|
||||
import { SmartsocketClient } from './smartsocket.classes.smartsocketclient';
|
||||
import { ISocketConnectionAuthenticationObject } from './smartsocket.classes.socketconnection';
|
||||
|
||||
/**
|
||||
* interface for class SocketRole
|
||||
*/
|
||||
export interface ISocketRoleOptions {
|
||||
name: string;
|
||||
passwordHash: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* A socketrole defines access to certain routines.
|
||||
*/
|
||||
export class SocketRole {
|
||||
// STATIC
|
||||
public static getSocketRoleByName(
|
||||
referenceSmartsocket: Smartsocket | SmartsocketClient,
|
||||
socketRoleNameArg: string
|
||||
): SocketRole {
|
||||
return referenceSmartsocket.socketRoles.find((socketRoleArg) => {
|
||||
return socketRoleArg.name === socketRoleNameArg;
|
||||
});
|
||||
}
|
||||
|
||||
public static async checkPasswordForRole(
|
||||
dataArg: ISocketConnectionAuthenticationObject,
|
||||
referenceSmartsocket: Smartsocket | SmartsocketClient
|
||||
): Promise<boolean> {
|
||||
const targetPasswordHash = SocketRole.getSocketRoleByName(referenceSmartsocket, dataArg.role)
|
||||
.passwordHash;
|
||||
const computedCompareHash = await plugins.isohash.sha256FromString(dataArg.password);
|
||||
return targetPasswordHash === computedCompareHash;
|
||||
}
|
||||
|
||||
// INSTANCE
|
||||
public name: string;
|
||||
public passwordHash: string;
|
||||
public allowedFunctions = new plugins.lik.ObjectMap<SocketFunction<any>>();
|
||||
constructor(optionsArg: ISocketRoleOptions) {
|
||||
this.name = optionsArg.name;
|
||||
this.passwordHash = optionsArg.passwordHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* adds the socketfunction to the socketrole
|
||||
* @param socketFunctionArg
|
||||
*/
|
||||
public addSocketFunction(socketFunctionArg: SocketFunction<any>) {
|
||||
this.allowedFunctions.add(socketFunctionArg);
|
||||
}
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
import * as plugins from './smartsocket.plugins';
|
||||
import * as pluginsTyped from './smartsocket.pluginstyped';
|
||||
import * as plugins from './smartsocket.plugins.js';
|
||||
import * as pluginsTyped from './smartsocket.pluginstyped.js';
|
||||
|
||||
// used in case no other server is supplied
|
||||
import { Smartsocket } from './smartsocket.classes.smartsocket';
|
||||
import { logger } from './smartsocket.logging';
|
||||
import { Smartsocket } from './smartsocket.classes.smartsocket.js';
|
||||
import { logger } from './smartsocket.logging.js';
|
||||
|
||||
/**
|
||||
* class socketServer
|
||||
@ -11,8 +11,12 @@ import { logger } from './smartsocket.logging';
|
||||
*/
|
||||
export class SocketServer {
|
||||
private smartsocket: Smartsocket;
|
||||
private httpServerDeferred: plugins.smartpromise.Deferred<any>;
|
||||
private httpServer: pluginsTyped.http.Server | pluginsTyped.https.Server;
|
||||
// wether httpServer is standalone
|
||||
|
||||
/**
|
||||
* wether httpServer is standalone
|
||||
*/
|
||||
private standaloneServer = false;
|
||||
|
||||
constructor(smartSocketInstance: Smartsocket) {
|
||||
@ -25,20 +29,25 @@ export class SocketServer {
|
||||
*/
|
||||
public async setExternalServer(
|
||||
serverType: 'smartexpress',
|
||||
serverArg: pluginsTyped.smartexpress.Server
|
||||
serverArg: pluginsTyped.typedserver.servertools.Server
|
||||
) {
|
||||
this.httpServerDeferred = plugins.smartpromise.defer();
|
||||
await serverArg.startedPromise;
|
||||
this.httpServer = serverArg.httpServer;
|
||||
this.httpServerDeferred.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the server for socket.io
|
||||
*/
|
||||
public getServerForSocketIo() {
|
||||
public async getServerForSocketIo() {
|
||||
if (this.httpServerDeferred) {
|
||||
await this.httpServerDeferred.promise;
|
||||
}
|
||||
if (this.httpServer) {
|
||||
return this.httpServer;
|
||||
} else {
|
||||
const httpModule = this.smartsocket.smartenv.getSafeNodeModule('http');
|
||||
const httpModule = await this.smartsocket.smartenv.getSafeNodeModule('http');
|
||||
this.httpServer = new httpModule.Server();
|
||||
this.standaloneServer = true;
|
||||
return this.httpServer;
|
||||
@ -77,5 +86,9 @@ export class SocketServer {
|
||||
/**
|
||||
* closes the server
|
||||
*/
|
||||
public async stop() {}
|
||||
public async stop() {
|
||||
if (this.httpServer) {
|
||||
this.httpServer.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +0,0 @@
|
||||
import * as plugins from './smartsocket.plugins';
|
||||
|
||||
export class SocketStats {}
|
@ -1,3 +1,3 @@
|
||||
import * as plugins from './smartsocket.plugins';
|
||||
import * as plugins from './smartsocket.plugins.js';
|
||||
|
||||
export const logger = new plugins.smartlog.ConsoleLog();
|
||||
|
@ -4,21 +4,23 @@ import * as typedrequestInterfaces from '@apiglobal/typedrequest-interfaces';
|
||||
export { typedrequestInterfaces };
|
||||
|
||||
// pushrocks scope
|
||||
import * as isohash from '@pushrocks/isohash';
|
||||
import * as isounique from '@pushrocks/isounique';
|
||||
import * as lik from '@pushrocks/lik';
|
||||
import * as smartenv from '@pushrocks/smartenv';
|
||||
import * as smartlog from '@pushrocks/smartlog';
|
||||
import * as smartdelay from '@pushrocks/smartdelay';
|
||||
import * as smartpromise from '@pushrocks/smartpromise';
|
||||
import * as smarttime from '@pushrocks/smarttime';
|
||||
import * as smartrx from '@pushrocks/smartrx';
|
||||
import * as isohash from '@push.rocks/isohash';
|
||||
import * as isounique from '@push.rocks/isounique';
|
||||
import * as lik from '@push.rocks/lik';
|
||||
import * as smartenv from '@push.rocks/smartenv';
|
||||
import * as smartjson from '@push.rocks/smartjson';
|
||||
import * as smartlog from '@push.rocks/smartlog';
|
||||
import * as smartdelay from '@push.rocks/smartdelay';
|
||||
import * as smartpromise from '@push.rocks/smartpromise';
|
||||
import * as smarttime from '@push.rocks/smarttime';
|
||||
import * as smartrx from '@push.rocks/smartrx';
|
||||
|
||||
export {
|
||||
isohash,
|
||||
isounique,
|
||||
lik,
|
||||
smartenv,
|
||||
smartjson,
|
||||
smartlog,
|
||||
smartdelay,
|
||||
smartpromise,
|
||||
|
@ -1,16 +1,23 @@
|
||||
// node native
|
||||
import type http from 'http';
|
||||
import type https from 'https';
|
||||
import type * as http from 'http';
|
||||
import type * as https from 'https';
|
||||
|
||||
export { http, https };
|
||||
export type { http, https };
|
||||
|
||||
// pushrocks scope
|
||||
import type * as smartexpress from '@pushrocks/smartexpress';
|
||||
import type * as typedserver from '@apiglobal/typedserver';
|
||||
|
||||
export { smartexpress };
|
||||
export type { typedserver };
|
||||
|
||||
// third party scope
|
||||
import type socketIo from 'socket.io';
|
||||
import type socketIoClient from 'socket.io-client';
|
||||
import type { Socket as ServerSocket, Server as ServerServer } from 'socket.io';
|
||||
import type { Socket as ClientSocket, connect as ClientIo } from 'socket.io-client';
|
||||
|
||||
export { socketIo, socketIoClient };
|
||||
export namespace socketIo {
|
||||
export type Socket = ServerSocket;
|
||||
export type Server = ServerServer;
|
||||
}
|
||||
export namespace socketIoClient {
|
||||
export type Socket = ClientSocket;
|
||||
export type connect = typeof ClientIo;
|
||||
}
|
||||
|
11
tsconfig.json
Normal file
11
tsconfig.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"experimentalDecorators": true,
|
||||
"useDefineForClassFields": false,
|
||||
"target": "ES2022",
|
||||
"module": "ES2022",
|
||||
"moduleResolution": "nodenext",
|
||||
"esModuleInterop": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
}
|
||||
}
|
17
tslint.json
17
tslint.json
@ -1,17 +0,0 @@
|
||||
{
|
||||
"extends": ["tslint:latest", "tslint-config-prettier"],
|
||||
"rules": {
|
||||
"semicolon": [true, "always"],
|
||||
"no-console": false,
|
||||
"ordered-imports": false,
|
||||
"object-literal-sort-keys": false,
|
||||
"member-ordering": {
|
||||
"options":{
|
||||
"order": [
|
||||
"static-method"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultSeverity": "warning"
|
||||
}
|
Reference in New Issue
Block a user