Compare commits
No commits in common. "master" and "v1.1.60" have entirely different histories.
@ -1,66 +0,0 @@
|
|||||||
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
|
|
@ -1,124 +0,0 @@
|
|||||||
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 @git.zone/tsdoc
|
|
||||||
npmci command tsdoc
|
|
||||||
continue-on-error: true
|
|
137
.gitlab-ci.yml
Normal file
137
.gitlab-ci.yml
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
# 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
Normal file
13
.snyk
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# 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,10 +2,28 @@
|
|||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"command": "npm test",
|
"name": "current file",
|
||||||
"name": "Run npm test",
|
"type": "node",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"type": "node-terminal"
|
"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"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
111
README.md
Normal file
111
README.md
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
# @pushrocks/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/)
|
||||||
|
|
||||||
|
## Status for master
|
||||||
|
[](https://gitlab.com/pushrocks/smartsocket/commits/master)
|
||||||
|
[](https://gitlab.com/pushrocks/smartsocket/commits/master)
|
||||||
|
[](https://www.npmjs.com/package/@pushrocks/smartsocket)
|
||||||
|
[](https://snyk.io/test/npm/@pushrocks/smartsocket)
|
||||||
|
[](https://nodejs.org/dist/latest-v10.x/docs/api/)
|
||||||
|
[](https://nodejs.org/dist/latest-v10.x/docs/api/)
|
||||||
|
[](https://prettier.io/)
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Use TypeScript for best in class instellisense.
|
||||||
|
|
||||||
|
Under the hood we use socket.io and shortid for managed data exchange.
|
||||||
|
|
||||||
|
### Serverside
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import * as smartsocket from 'smartsocket';
|
||||||
|
import * as q from q; // q is a promise library
|
||||||
|
|
||||||
|
// The "Smartsocket" listens on a port and can receive new "SocketConnection" requests.
|
||||||
|
let mySmartsocket = new smartsocket.Smartsocket({
|
||||||
|
port: 3000 // the port smartsocket will listen on
|
||||||
|
});
|
||||||
|
|
||||||
|
// optional:
|
||||||
|
// run this with anothoer existing server like express
|
||||||
|
declare var someExpressServer; // read the express docs about how express actually works
|
||||||
|
mySmartsocket.setServer(someExpressServer);
|
||||||
|
|
||||||
|
// A "SocketRole" can be referenced by "SocketFunction"s.
|
||||||
|
// All "SocketRequest"s carry authentication data for a specific "SocketRole".
|
||||||
|
// "SocketFunction"s know which "SocketRole"s are allowed to execute them
|
||||||
|
let mySocketRole = new smartsocket.SocketRole({
|
||||||
|
name: 'someRoleName',
|
||||||
|
passwordHash: 'someHashedString'
|
||||||
|
});
|
||||||
|
|
||||||
|
// A "SocketFunction" executes a referenced function and passes in any data of the corresponding "SocketRequest".
|
||||||
|
// The referenced function must return a promise and resolve with data of type any.
|
||||||
|
// Any "SocketRequest" carries a unique identifier. If the referenced function's promise resolved any passed on argument will be returned to the requesting party
|
||||||
|
let testSocketFunction1 = new smartsocket.SocketFunction({
|
||||||
|
funcName: 'testSocketFunction1',
|
||||||
|
funcDef: data => {
|
||||||
|
console.log('testSocketFunction1 executed successfully!');
|
||||||
|
},
|
||||||
|
allowedRoles: [mySocketRole] // all roles that have access to a specific function
|
||||||
|
});
|
||||||
|
|
||||||
|
// A "Smartsocket" exposes a .clientCall() that gets
|
||||||
|
// 1. the name of the "SocketFunction" on the client side
|
||||||
|
// 2. the data to pass in
|
||||||
|
// 3. And a target "SocketConnection" (there can be multiple connections at once)
|
||||||
|
// any unique id association is done internally
|
||||||
|
mySmartsocket.clientCall('restart', data, someTargetConnection).then(responseData => {});
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Client side
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import * as smartsocket from 'smartsocket';
|
||||||
|
|
||||||
|
// A "SmartsocketClient" is different from a "Smartsocket" in that it doesn't expose any public address.
|
||||||
|
// Thus any new "SocketConnection"s must be innitiated from a "SmartsocketClient".
|
||||||
|
let testSmartsocketClient = new smartsocket.SmartsocketClient({
|
||||||
|
port: testConfig.port,
|
||||||
|
url: 'http://localhost',
|
||||||
|
password: 'testPassword',
|
||||||
|
alias: 'testClient1',
|
||||||
|
role: 'testRole1'
|
||||||
|
});
|
||||||
|
|
||||||
|
// You can .connect() and .disconnect() from a "Smartsocket"
|
||||||
|
testSmartsocketClient.connect().then(() => {
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
// The client can also specify "SocketFunction"s. It can also specify "SocketRole"s in case a client connects to multiple servers at once
|
||||||
|
let testSocketFunction2 = new smartsocket.SocketFunction({
|
||||||
|
funcName: 'testSocketFunction2',
|
||||||
|
funcDef: data => {}, // the function to execute, has to return promise
|
||||||
|
allowedRoles: []
|
||||||
|
});
|
||||||
|
|
||||||
|
// A "SmartsocketClient" can call functions on the serverside using .serverCall() analog to the "Smartsocket"'s .clientCall method.
|
||||||
|
mySmartsocketClient.serverCall('function', functionCallData).then(functionResponseData => {
|
||||||
|
// the functionResponseData comes from the server... awesome, right?
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
> **NOTE:**
|
||||||
|
> you can easily chain dependent requests on either the server or client side with promises.
|
||||||
|
> `data` is always a js object that you can design for your specific needs.
|
||||||
|
> It supports buffers for large binary data network exchange.
|
||||||
|
|
||||||
|
For further information read the linked docs at the top of this readme.
|
||||||
|
|
||||||
|
> MIT licensed | **©** [Lossless GmbH](https://lossless.gmbh)
|
||||||
|
| By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy)
|
||||||
|
|
||||||
|
[](https://maintainedby.lossless.com)
|
103
changelog.md
103
changelog.md
@ -1,103 +0,0 @@
|
|||||||
# Changelog
|
|
||||||
|
|
||||||
## 2025-03-10 - 2.1.0 - feat(SmartsocketClient)
|
|
||||||
Improve client reconnection logic with exponential backoff and jitter; update socket.io and @types/node dependencies
|
|
||||||
|
|
||||||
- Bump engine.io from 6.5.4 to 6.6.4, socket.io and socket.io-client from 4.7.5 to 4.8.1
|
|
||||||
- Bump @types/node from ^20.12.7 to ^22.13.10
|
|
||||||
- Add new optional reconnection parameters (maxRetries, initialBackoffDelay, maxBackoffDelay) to SmartsocketClient options
|
|
||||||
- Implement exponential backoff with jitter for auto-reconnect and reset reconnection state on successful connection
|
|
||||||
|
|
||||||
## 2024-05-29 - 2.0.27 - docs
|
|
||||||
update description
|
|
||||||
|
|
||||||
## 2024-04-26 to 2024-03-30 - 2.0.26 … 2.0.24 - core & configuration
|
|
||||||
A series of internal fixes and configuration tweaks.
|
|
||||||
- fix(core): update
|
|
||||||
- update tsconfig
|
|
||||||
- update npmextra.json: githost
|
|
||||||
|
|
||||||
## 2023-09-10 to 2023-07-21 - 2.0.23 … 2.0.20 - core
|
|
||||||
Multiple minor core fixes were applied in rapid succession.
|
|
||||||
- fix(core): update
|
|
||||||
|
|
||||||
## 2023-07-21 to 2023-03-20 - 2.0.19 … 2.0.15 - core
|
|
||||||
Routine internal updates addressing core functionality.
|
|
||||||
- fix(core): update
|
|
||||||
|
|
||||||
## 2023-02-07 to 2022-03-24 - 2.0.14 … 2.0.0 - core
|
|
||||||
Further minor core updates were rolled out over several versions.
|
|
||||||
- fix(core): update
|
|
||||||
|
|
||||||
## 2022-03-14 - 1.2.22 - esm
|
|
||||||
A breaking change was introduced to switch the module system.
|
|
||||||
- BREAKING CHANGE(switch to esm): update
|
|
||||||
|
|
||||||
## 2022-01-20 to 2021-01-23 - 1.2.21 … 1.2.0 - core
|
|
||||||
A range of minor core fixes.
|
|
||||||
- fix(core): update
|
|
||||||
|
|
||||||
## 2020-12-26 - 1.1.71 - SmartsocketClient
|
|
||||||
New functionality in the socket client was added.
|
|
||||||
- feat(SmartsocketClient): socket client can now be stopped with .stop() in addition to .reconnect()
|
|
||||||
|
|
||||||
## 2020-12-26 to 2020-09-24 - 1.1.70 … 1.1.58 - core & test
|
|
||||||
A group of updates addressing both core mechanics and tests.
|
|
||||||
- fix(core): update
|
|
||||||
- fix(test): use @pushrocks/isohash instead of @pushrocks/smarthash
|
|
||||||
|
|
||||||
## 2019-11-08 to 2019-04-23 - 1.1.57 … 1.1.27 - core
|
|
||||||
Numerous versions in this period included only internal core fixes.
|
|
||||||
- fix(core): update
|
|
||||||
|
|
||||||
## 2019-01-31 to 2019-01-30 - 1.1.26 … 1.1.19 - build, docs & configuration
|
|
||||||
Updates went beyond the core, affecting build tooling and package metadata.
|
|
||||||
- fix(build): now building with tsbuild
|
|
||||||
- fix(readme): update
|
|
||||||
- fix(npmextra): adjust access level
|
|
||||||
- fix(scope): switch to @pushrocks
|
|
||||||
- fix(package.json): private setting
|
|
||||||
- fix(snyk): add .snyk file
|
|
||||||
- fix(structure): update to latest standards
|
|
||||||
|
|
||||||
## 2018-03-19 to 2018-03-15 - 1.1.18 … 1.1.12 - core & docs
|
|
||||||
Several improvements touching both functionality and documentation.
|
|
||||||
- now working as expected
|
|
||||||
- start transitioning to better SocketFunction handling
|
|
||||||
- add @types/node
|
|
||||||
- format and update README
|
|
||||||
- update to latest standards
|
|
||||||
|
|
||||||
## 2017-10-09 to 2017-07-07 - 1.1.11 … 1.1.07 - core & docs
|
|
||||||
Updates in this range improved both the internal mechanics and the developer‐facing materials.
|
|
||||||
- allow setting of specific server
|
|
||||||
- fix not ending error correctly
|
|
||||||
- update to newest version
|
|
||||||
- update docs and tests
|
|
||||||
- remove taskbuffer
|
|
||||||
- update to latest standards
|
|
||||||
|
|
||||||
## 2016-09-25 to 2016-09-03 - 1.1.6 … 1.1.3 - docs & core
|
|
||||||
Minor improvements in documentation and code quality.
|
|
||||||
- improve README
|
|
||||||
- added docs
|
|
||||||
- fix scoping of socket roles and perform small syntax fixes
|
|
||||||
|
|
||||||
## 2016-09-02 to 2016-08-16 - 1.1.2 … 1.1.1 - dependencies & security
|
|
||||||
Several housekeeping tasks to update dependencies and improve security.
|
|
||||||
- updated dependencies and exported socketConnection
|
|
||||||
- now authenticating sockets by checking the password hash
|
|
||||||
|
|
||||||
## 2016-08-15 - 1.1.0 - docs
|
|
||||||
A documentation update was published.
|
|
||||||
- update README
|
|
||||||
|
|
||||||
## 2016-08-15 - 1.0.7 - networking
|
|
||||||
A key update made the socket client work bi-directionally, enabling mesh setups.
|
|
||||||
- now working in both directions so mesh setups work
|
|
||||||
|
|
||||||
## 2016-08-14 to 2016-08-07 - 1.0.6 … 1.0.0 - internal changes
|
|
||||||
From the initial release onward, several internal improvements were introduced:
|
|
||||||
- updated tests and structure
|
|
||||||
- reworked reconnection logic and added a request/response abstraction for transparent function calls
|
|
||||||
- initial release features with updated documentation and structure
|
|
5
dist_ts/index.d.ts
vendored
Normal file
5
dist_ts/index.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export * from './smartsocket.classes.smartsocket';
|
||||||
|
export * from './smartsocket.classes.smartsocketclient';
|
||||||
|
export * from './smartsocket.classes.socketfunction';
|
||||||
|
export * from './smartsocket.classes.socketrole';
|
||||||
|
export * from './smartsocket.classes.socketconnection';
|
20
dist_ts/index.js
Normal file
20
dist_ts/index.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
"use strict";
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||||
|
}) : (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
o[k2] = m[k];
|
||||||
|
}));
|
||||||
|
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||||
|
for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p);
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
// export main classes
|
||||||
|
__exportStar(require("./smartsocket.classes.smartsocket"), exports);
|
||||||
|
__exportStar(require("./smartsocket.classes.smartsocketclient"), exports);
|
||||||
|
// export further classes and objects
|
||||||
|
__exportStar(require("./smartsocket.classes.socketfunction"), exports);
|
||||||
|
__exportStar(require("./smartsocket.classes.socketrole"), exports);
|
||||||
|
__exportStar(require("./smartsocket.classes.socketconnection"), exports);
|
||||||
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7QUFBQSxzQkFBc0I7QUFDdEIsb0VBQWtEO0FBQ2xELDBFQUF3RDtBQUV4RCxxQ0FBcUM7QUFDckMsdUVBQXFEO0FBQ3JELG1FQUFpRDtBQUNqRCx5RUFBdUQifQ==
|
4
dist_ts/interfaces/connection.d.ts
vendored
Normal file
4
dist_ts/interfaces/connection.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export interface IRequestAuthPayload {
|
||||||
|
serverShortId: string;
|
||||||
|
}
|
||||||
|
export declare type TConnectionStatus = 'new' | 'connecting' | 'connected' | 'disconnecting' | 'disconnected';
|
3
dist_ts/interfaces/connection.js
Normal file
3
dist_ts/interfaces/connection.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29ubmVjdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2ludGVyZmFjZXMvY29ubmVjdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIn0=
|
1
dist_ts/interfaces/index.d.ts
vendored
Normal file
1
dist_ts/interfaces/index.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './connection';
|
14
dist_ts/interfaces/index.js
Normal file
14
dist_ts/interfaces/index.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
"use strict";
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||||
|
}) : (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
o[k2] = m[k];
|
||||||
|
}));
|
||||||
|
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||||
|
for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p);
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
__exportStar(require("./connection"), exports);
|
||||||
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9pbnRlcmZhY2VzL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7OztBQUFBLCtDQUE2QiJ9
|
45
dist_ts/smartsocket.classes.smartsocket.d.ts
vendored
Normal file
45
dist_ts/smartsocket.classes.smartsocket.d.ts
vendored
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import * as plugins from './smartsocket.plugins';
|
||||||
|
import { SocketConnection } from './smartsocket.classes.socketconnection';
|
||||||
|
import { SocketFunction } from './smartsocket.classes.socketfunction';
|
||||||
|
import { SocketRequest } from './smartsocket.classes.socketrequest';
|
||||||
|
import { SocketRole } from './smartsocket.classes.socketrole';
|
||||||
|
import * as SocketIO from 'socket.io';
|
||||||
|
export interface ISmartsocketConstructorOptions {
|
||||||
|
port?: number;
|
||||||
|
}
|
||||||
|
export declare class Smartsocket {
|
||||||
|
/**
|
||||||
|
* a unique id to detect server restarts
|
||||||
|
*/
|
||||||
|
shortId: string;
|
||||||
|
options: ISmartsocketConstructorOptions;
|
||||||
|
io: SocketIO.Server;
|
||||||
|
socketConnections: plugins.lik.ObjectMap<SocketConnection>;
|
||||||
|
socketRoles: plugins.lik.ObjectMap<SocketRole>;
|
||||||
|
socketFunctions: plugins.lik.ObjectMap<SocketFunction<any>>;
|
||||||
|
socketRequests: plugins.lik.ObjectMap<SocketRequest<any>>;
|
||||||
|
private socketServer;
|
||||||
|
constructor(optionsArg: ISmartsocketConstructorOptions);
|
||||||
|
setExternalServer(serverType: 'smartexpress', serverArg: any): Promise<void>;
|
||||||
|
/**
|
||||||
|
* starts smartsocket
|
||||||
|
*/
|
||||||
|
start(): Promise<void>;
|
||||||
|
/**
|
||||||
|
* stops smartsocket
|
||||||
|
*/
|
||||||
|
stop(): Promise<void>;
|
||||||
|
/**
|
||||||
|
* allows call to specific client.
|
||||||
|
*/
|
||||||
|
clientCall<T extends plugins.typedrequestInterfaces.ITypedRequest>(functionNameArg: T['method'], dataArg: T['request'], targetSocketConnectionArg: SocketConnection): Promise<T['response']>;
|
||||||
|
/**
|
||||||
|
* adds socketRoles
|
||||||
|
*/
|
||||||
|
addSocketRoles(socketRolesArray: SocketRole[]): void;
|
||||||
|
addSocketFunction(socketFunction: SocketFunction<any>): void;
|
||||||
|
/**
|
||||||
|
* the standard handler for new socket connections
|
||||||
|
*/
|
||||||
|
private _handleSocketConnection;
|
||||||
|
}
|
119
dist_ts/smartsocket.classes.smartsocket.js
Normal file
119
dist_ts/smartsocket.classes.smartsocket.js
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
"use strict";
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||||
|
}) : (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
o[k2] = m[k];
|
||||||
|
}));
|
||||||
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||||
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||||
|
}) : function(o, v) {
|
||||||
|
o["default"] = v;
|
||||||
|
});
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.Smartsocket = void 0;
|
||||||
|
const plugins = __importStar(require("./smartsocket.plugins"));
|
||||||
|
// classes
|
||||||
|
const smartsocket_classes_socketconnection_1 = require("./smartsocket.classes.socketconnection");
|
||||||
|
const smartsocket_classes_socketrequest_1 = require("./smartsocket.classes.socketrequest");
|
||||||
|
const smartsocket_classes_socketserver_1 = require("./smartsocket.classes.socketserver");
|
||||||
|
const smartsocket_logging_1 = require("./smartsocket.logging");
|
||||||
|
class Smartsocket {
|
||||||
|
constructor(optionsArg) {
|
||||||
|
/**
|
||||||
|
* a unique id to detect server restarts
|
||||||
|
*/
|
||||||
|
this.shortId = plugins.smartunique.shortId();
|
||||||
|
this.socketConnections = new plugins.lik.ObjectMap();
|
||||||
|
this.socketRoles = new plugins.lik.ObjectMap();
|
||||||
|
this.socketFunctions = new plugins.lik.ObjectMap();
|
||||||
|
this.socketRequests = new plugins.lik.ObjectMap();
|
||||||
|
this.socketServer = new smartsocket_classes_socketserver_1.SocketServer(this);
|
||||||
|
this.options = optionsArg;
|
||||||
|
}
|
||||||
|
// tslint:disable-next-line:member-ordering
|
||||||
|
async setExternalServer(serverType, serverArg) {
|
||||||
|
await this.socketServer.setExternalServer(serverType, serverArg);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* starts smartsocket
|
||||||
|
*/
|
||||||
|
async start() {
|
||||||
|
this.io = plugins.socketIo(this.socketServer.getServerForSocketIo());
|
||||||
|
await this.socketServer.start();
|
||||||
|
this.io.on('connection', socketArg => {
|
||||||
|
this._handleSocketConnection(socketArg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* stops smartsocket
|
||||||
|
*/
|
||||||
|
async stop() {
|
||||||
|
await plugins.smartdelay.delayFor(1000);
|
||||||
|
this.socketConnections.forEach((socketObjectArg) => {
|
||||||
|
smartsocket_logging_1.logger.log('info', `disconnect socket with >>alias ${socketObjectArg.alias}`);
|
||||||
|
socketObjectArg.socket.disconnect();
|
||||||
|
});
|
||||||
|
this.socketConnections.wipe();
|
||||||
|
this.io.close();
|
||||||
|
// stop the corresponging server
|
||||||
|
this.socketServer.stop();
|
||||||
|
}
|
||||||
|
// communication
|
||||||
|
/**
|
||||||
|
* allows call to specific client.
|
||||||
|
*/
|
||||||
|
async clientCall(functionNameArg, dataArg, targetSocketConnectionArg) {
|
||||||
|
const socketRequest = new smartsocket_classes_socketrequest_1.SocketRequest(this, {
|
||||||
|
funcCallData: {
|
||||||
|
funcDataArg: dataArg,
|
||||||
|
funcName: functionNameArg
|
||||||
|
},
|
||||||
|
originSocketConnection: targetSocketConnectionArg,
|
||||||
|
shortId: plugins.smartunique.shortId(),
|
||||||
|
side: 'requesting'
|
||||||
|
});
|
||||||
|
const response = await socketRequest.dispatch();
|
||||||
|
const result = response.funcDataArg;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* adds socketRoles
|
||||||
|
*/
|
||||||
|
addSocketRoles(socketRolesArray) {
|
||||||
|
for (const socketRole of socketRolesArray) {
|
||||||
|
this.socketRoles.add(socketRole);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
addSocketFunction(socketFunction) {
|
||||||
|
this.socketFunctions.add(socketFunction);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* the standard handler for new socket connections
|
||||||
|
*/
|
||||||
|
async _handleSocketConnection(socketArg) {
|
||||||
|
const socketConnection = new smartsocket_classes_socketconnection_1.SocketConnection({
|
||||||
|
alias: undefined,
|
||||||
|
authenticated: false,
|
||||||
|
role: undefined,
|
||||||
|
side: 'server',
|
||||||
|
smartsocketHost: this,
|
||||||
|
socket: socketArg
|
||||||
|
});
|
||||||
|
smartsocket_logging_1.logger.log('info', 'Socket connected. Trying to authenticate...');
|
||||||
|
this.socketConnections.add(socketConnection);
|
||||||
|
await socketConnection.authenticate();
|
||||||
|
await socketConnection.listenToFunctionRequests();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.Smartsocket = Smartsocket;
|
||||||
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRzb2NrZXQuY2xhc3Nlcy5zbWFydHNvY2tldC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3NtYXJ0c29ja2V0LmNsYXNzZXMuc21hcnRzb2NrZXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLCtEQUFpRDtBQUVqRCxVQUFVO0FBQ1YsaUdBQTBFO0FBRTFFLDJGQUFvRTtBQUVwRSx5RkFBa0U7QUFJbEUsK0RBQStDO0FBTS9DLE1BQWEsV0FBVztJQWN0QixZQUFZLFVBQTBDO1FBYnREOztXQUVHO1FBQ0ksWUFBTyxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsT0FBTyxFQUFFLENBQUM7UUFHeEMsc0JBQWlCLEdBQUcsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBb0IsQ0FBQztRQUNsRSxnQkFBVyxHQUFHLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxTQUFTLEVBQWMsQ0FBQztRQUN0RCxvQkFBZSxHQUFHLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxTQUFTLEVBQXVCLENBQUM7UUFDbkUsbUJBQWMsR0FBRyxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFzQixDQUFDO1FBRWhFLGlCQUFZLEdBQUcsSUFBSSwrQ0FBWSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRzVDLElBQUksQ0FBQyxPQUFPLEdBQUcsVUFBVSxDQUFDO0lBQzVCLENBQUM7SUFFRCwyQ0FBMkM7SUFDcEMsS0FBSyxDQUFDLGlCQUFpQixDQUFDLFVBQTBCLEVBQUUsU0FBYztRQUN2RSxNQUFNLElBQUksQ0FBQyxZQUFZLENBQUMsaUJBQWlCLENBQUMsVUFBVSxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQ25FLENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxLQUFLO1FBQ2hCLElBQUksQ0FBQyxFQUFFLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLG9CQUFvQixFQUFFLENBQUMsQ0FBQztRQUNyRSxNQUFNLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDaEMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsWUFBWSxFQUFFLFNBQVMsQ0FBQyxFQUFFO1lBQ25DLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUMxQyxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxJQUFJO1FBQ2YsTUFBTSxPQUFPLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN4QyxJQUFJLENBQUMsaUJBQWlCLENBQUMsT0FBTyxDQUFDLENBQUMsZUFBaUMsRUFBRSxFQUFFO1lBQ25FLDRCQUFNLENBQUMsR0FBRyxDQUNSLE1BQU0sRUFDTixrQ0FBa0MsZUFBZSxDQUFDLEtBQUssRUFBRSxDQUMxRCxDQUFDO1lBQ0YsZUFBZSxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUN0QyxDQUFDLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUM5QixJQUFJLENBQUMsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBRWhCLGdDQUFnQztRQUNoQyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQzNCLENBQUM7SUFFRCxnQkFBZ0I7SUFFaEI7O09BRUc7SUFDSSxLQUFLLENBQUMsVUFBVSxDQUNyQixlQUE0QixFQUM1QixPQUFxQixFQUNyQix5QkFBMkM7UUFFM0MsTUFBTSxhQUFhLEdBQUcsSUFBSSxpREFBYSxDQUFJLElBQUksRUFBRTtZQUMvQyxZQUFZLEVBQUU7Z0JBQ1osV0FBVyxFQUFFLE9BQU87Z0JBQ3BCLFFBQVEsRUFBRSxlQUFlO2FBQzFCO1lBQ0Qsc0JBQXNCLEVBQUUseUJBQXlCO1lBQ2pELE9BQU8sRUFBRSxPQUFPLENBQUMsV0FBVyxDQUFDLE9BQU8sRUFBRTtZQUN0QyxJQUFJLEVBQUUsWUFBWTtTQUNuQixDQUFDLENBQUM7UUFDSCxNQUFNLFFBQVEsR0FBdUMsTUFBTSxhQUFhLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDcEYsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLFdBQVcsQ0FBQztRQUNwQyxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDO0lBRUQ7O09BRUc7SUFDSSxjQUFjLENBQUMsZ0JBQThCO1FBQ2xELEtBQUssTUFBTSxVQUFVLElBQUksZ0JBQWdCLEVBQUU7WUFDekMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUM7U0FDbEM7UUFDRCxPQUFPO0lBQ1QsQ0FBQztJQUVNLGlCQUFpQixDQUFDLGNBQW1DO1FBQzFELElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxDQUFDO0lBQzNDLENBQUM7SUFFRDs7T0FFRztJQUNLLEtBQUssQ0FBQyx1QkFBdUIsQ0FBQyxTQUFrQztRQUN0RSxNQUFNLGdCQUFnQixHQUFxQixJQUFJLHVEQUFnQixDQUFDO1lBQzlELEtBQUssRUFBRSxTQUFTO1lBQ2hCLGFBQWEsRUFBRSxLQUFLO1lBQ3BCLElBQUksRUFBRSxTQUFTO1lBQ2YsSUFBSSxFQUFFLFFBQVE7WUFDZCxlQUFlLEVBQUUsSUFBSTtZQUNyQixNQUFNLEVBQUUsU0FBUztTQUNsQixDQUFDLENBQUM7UUFDSCw0QkFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsNkNBQTZDLENBQUMsQ0FBQztRQUNsRSxJQUFJLENBQUMsaUJBQWlCLENBQUMsR0FBRyxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDN0MsTUFBTSxnQkFBZ0IsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUN0QyxNQUFNLGdCQUFnQixDQUFDLHdCQUF3QixFQUFFLENBQUM7SUFDcEQsQ0FBQztDQUNGO0FBNUdELGtDQTRHQyJ9
|
53
dist_ts/smartsocket.classes.smartsocketclient.d.ts
vendored
Normal file
53
dist_ts/smartsocket.classes.smartsocketclient.d.ts
vendored
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import * as plugins from './smartsocket.plugins';
|
||||||
|
import * as interfaces from './interfaces';
|
||||||
|
import { SocketConnection } from './smartsocket.classes.socketconnection';
|
||||||
|
import { SocketFunction } from './smartsocket.classes.socketfunction';
|
||||||
|
import { SocketRequest } from './smartsocket.classes.socketrequest';
|
||||||
|
import { SocketRole } from './smartsocket.classes.socketrole';
|
||||||
|
/**
|
||||||
|
* interface for class SmartsocketClient
|
||||||
|
*/
|
||||||
|
export interface ISmartsocketClientOptions {
|
||||||
|
port: number;
|
||||||
|
url: string;
|
||||||
|
alias: string;
|
||||||
|
role: string;
|
||||||
|
password: string;
|
||||||
|
autoReconnect?: boolean;
|
||||||
|
}
|
||||||
|
export declare class SmartsocketClient {
|
||||||
|
shortId: string;
|
||||||
|
remoteShortId: string;
|
||||||
|
alias: string;
|
||||||
|
socketRole: SocketRole;
|
||||||
|
socketConnection: SocketConnection;
|
||||||
|
serverUrl: string;
|
||||||
|
serverPort: number;
|
||||||
|
autoReconnect: boolean;
|
||||||
|
eventSubject: plugins.smartrx.rxjs.Subject<interfaces.TConnectionStatus>;
|
||||||
|
eventStatus: interfaces.TConnectionStatus;
|
||||||
|
socketFunctions: plugins.lik.ObjectMap<SocketFunction<any>>;
|
||||||
|
socketRequests: plugins.lik.ObjectMap<SocketRequest<any>>;
|
||||||
|
socketRoles: plugins.lik.ObjectMap<SocketRole>;
|
||||||
|
constructor(optionsArg: ISmartsocketClientOptions);
|
||||||
|
addSocketFunction(socketFunction: SocketFunction<any>): void;
|
||||||
|
/**
|
||||||
|
* connect the client to the server
|
||||||
|
*/
|
||||||
|
connect(): Promise<unknown>;
|
||||||
|
/**
|
||||||
|
* disconnect from the server
|
||||||
|
*/
|
||||||
|
disconnect(): Promise<void>;
|
||||||
|
/**
|
||||||
|
* try a reconnection
|
||||||
|
*/
|
||||||
|
tryDebouncedReconnect(): Promise<void>;
|
||||||
|
/**
|
||||||
|
* dispatches a server call
|
||||||
|
* @param functionNameArg
|
||||||
|
* @param dataArg
|
||||||
|
*/
|
||||||
|
serverCall<T extends plugins.typedrequestInterfaces.ITypedRequest>(functionNameArg: T['method'], dataArg: T['request']): Promise<T['response']>;
|
||||||
|
private updateStatus;
|
||||||
|
}
|
168
dist_ts/smartsocket.classes.smartsocketclient.js
Normal file
168
dist_ts/smartsocket.classes.smartsocketclient.js
Normal file
File diff suppressed because one or more lines are too long
55
dist_ts/smartsocket.classes.socketconnection.d.ts
vendored
Normal file
55
dist_ts/smartsocket.classes.socketconnection.d.ts
vendored
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/// <reference types="socket.io-client" />
|
||||||
|
import * as plugins from './smartsocket.plugins';
|
||||||
|
import * as interfaces from './interfaces';
|
||||||
|
import { Smartsocket } from './smartsocket.classes.smartsocket';
|
||||||
|
import { SocketRole } from './smartsocket.classes.socketrole';
|
||||||
|
import * as SocketIO from 'socket.io';
|
||||||
|
import { SmartsocketClient } from './smartsocket.classes.smartsocketclient';
|
||||||
|
/**
|
||||||
|
* defines is a SocketConnection is server or client side. Important for mesh setups.
|
||||||
|
*/
|
||||||
|
export declare type TSocketConnectionSide = 'server' | 'client';
|
||||||
|
/**
|
||||||
|
* interface for constructor of class SocketConnection
|
||||||
|
*/
|
||||||
|
export interface ISocketConnectionConstructorOptions {
|
||||||
|
alias: string;
|
||||||
|
authenticated: boolean;
|
||||||
|
role: SocketRole;
|
||||||
|
side: TSocketConnectionSide;
|
||||||
|
smartsocketHost: Smartsocket | SmartsocketClient;
|
||||||
|
socket: SocketIO.Socket | SocketIOClient.Socket;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* interface for authentication data
|
||||||
|
*/
|
||||||
|
export interface ISocketConnectionAuthenticationObject {
|
||||||
|
role: 'coreflowContainer';
|
||||||
|
password: 'somePassword';
|
||||||
|
alias: 'coreflow1';
|
||||||
|
}
|
||||||
|
export declare let allSocketConnections: plugins.lik.ObjectMap<SocketConnection>;
|
||||||
|
/**
|
||||||
|
* class SocketConnection represents a websocket connection
|
||||||
|
*/
|
||||||
|
export declare class SocketConnection {
|
||||||
|
alias: string;
|
||||||
|
side: TSocketConnectionSide;
|
||||||
|
authenticated: boolean;
|
||||||
|
role: SocketRole;
|
||||||
|
smartsocketRef: Smartsocket | SmartsocketClient;
|
||||||
|
socket: SocketIO.Socket | SocketIOClient.Socket;
|
||||||
|
eventSubject: plugins.smartrx.rxjs.Subject<interfaces.TConnectionStatus>;
|
||||||
|
eventStatus: interfaces.TConnectionStatus;
|
||||||
|
constructor(optionsArg: ISocketConnectionConstructorOptions);
|
||||||
|
/**
|
||||||
|
* authenticate the socket
|
||||||
|
*/
|
||||||
|
authenticate(): Promise<unknown>;
|
||||||
|
/**
|
||||||
|
* listen to function requests
|
||||||
|
*/
|
||||||
|
listenToFunctionRequests(): Promise<unknown>;
|
||||||
|
disconnect(): Promise<void>;
|
||||||
|
private updateStatus;
|
||||||
|
}
|
140
dist_ts/smartsocket.classes.socketconnection.js
Normal file
140
dist_ts/smartsocket.classes.socketconnection.js
Normal file
File diff suppressed because one or more lines are too long
52
dist_ts/smartsocket.classes.socketfunction.d.ts
vendored
Normal file
52
dist_ts/smartsocket.classes.socketfunction.d.ts
vendored
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import * as plugins from './smartsocket.plugins';
|
||||||
|
import { SocketRole } from './smartsocket.classes.socketrole';
|
||||||
|
import { SocketConnection } from './smartsocket.classes.socketconnection';
|
||||||
|
import { Smartsocket } from './smartsocket.classes.smartsocket';
|
||||||
|
import { SmartsocketClient } from './smartsocket.classes.smartsocketclient';
|
||||||
|
/**
|
||||||
|
* interface of the contructor options of class SocketFunction
|
||||||
|
*/
|
||||||
|
export interface ISocketFunctionConstructorOptions<T extends plugins.typedrequestInterfaces.ITypedRequest> {
|
||||||
|
funcName: T['method'];
|
||||||
|
funcDef: TFuncDef<T>;
|
||||||
|
allowedRoles: SocketRole[];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* interface of the Socket Function call, in other words the object that routes a call to a function
|
||||||
|
*/
|
||||||
|
export interface ISocketFunctionCallDataRequest<T extends plugins.typedrequestInterfaces.ITypedRequest> {
|
||||||
|
funcName: T['method'];
|
||||||
|
funcDataArg: T['request'];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* interface of the Socket Function call, in other words the object that routes a call to a function
|
||||||
|
*/
|
||||||
|
export interface ISocketFunctionCallDataResponse<T extends plugins.typedrequestInterfaces.ITypedRequest> {
|
||||||
|
funcName: T['method'];
|
||||||
|
funcDataArg: T['response'];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* interface for function definition of SocketFunction
|
||||||
|
*/
|
||||||
|
export declare type TFuncDef<T extends plugins.typedrequestInterfaces.ITypedRequest> = (dataArg: T['request'], connectionArg: SocketConnection) => PromiseLike<T['response']>;
|
||||||
|
/**
|
||||||
|
* class that respresents a function that can be transparently called using a SocketConnection
|
||||||
|
*/
|
||||||
|
export declare class SocketFunction<T extends plugins.typedrequestInterfaces.ITypedRequest> {
|
||||||
|
static getSocketFunctionByName<Q extends plugins.typedrequestInterfaces.ITypedRequest>(smartsocketRefArg: Smartsocket | SmartsocketClient, functionNameArg: string): SocketFunction<Q>;
|
||||||
|
name: string;
|
||||||
|
funcDef: TFuncDef<T>;
|
||||||
|
roles: SocketRole[];
|
||||||
|
/**
|
||||||
|
* the constructor for SocketFunction
|
||||||
|
*/
|
||||||
|
constructor(optionsArg: ISocketFunctionConstructorOptions<T>);
|
||||||
|
/**
|
||||||
|
* invokes the function of this SocketFunction
|
||||||
|
*/
|
||||||
|
invoke(dataArg: ISocketFunctionCallDataRequest<T>, socketConnectionArg: SocketConnection): Promise<ISocketFunctionCallDataResponse<T>>;
|
||||||
|
/**
|
||||||
|
* notifies a role about access to this SocketFunction
|
||||||
|
*/
|
||||||
|
private _notifyRole;
|
||||||
|
}
|
49
dist_ts/smartsocket.classes.socketfunction.js
Normal file
49
dist_ts/smartsocket.classes.socketfunction.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.SocketFunction = void 0;
|
||||||
|
// export classes
|
||||||
|
/**
|
||||||
|
* class that respresents a function that can be transparently called using a SocketConnection
|
||||||
|
*/
|
||||||
|
class SocketFunction {
|
||||||
|
/**
|
||||||
|
* the constructor for SocketFunction
|
||||||
|
*/
|
||||||
|
constructor(optionsArg) {
|
||||||
|
this.name = optionsArg.funcName;
|
||||||
|
this.funcDef = optionsArg.funcDef;
|
||||||
|
this.roles = optionsArg.allowedRoles;
|
||||||
|
for (const socketRoleArg of this.roles) {
|
||||||
|
this._notifyRole(socketRoleArg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// STATIC
|
||||||
|
static getSocketFunctionByName(smartsocketRefArg, functionNameArg) {
|
||||||
|
return smartsocketRefArg.socketFunctions.find(socketFunctionArg => {
|
||||||
|
return socketFunctionArg.name === functionNameArg;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* invokes the function of this SocketFunction
|
||||||
|
*/
|
||||||
|
async invoke(dataArg, socketConnectionArg) {
|
||||||
|
if (dataArg.funcName === this.name) {
|
||||||
|
const funcResponseData = {
|
||||||
|
funcName: this.name,
|
||||||
|
funcDataArg: await this.funcDef(dataArg.funcDataArg, socketConnectionArg)
|
||||||
|
};
|
||||||
|
return funcResponseData;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new Error("SocketFunction.name does not match the data argument's .name!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* notifies a role about access to this SocketFunction
|
||||||
|
*/
|
||||||
|
_notifyRole(socketRoleArg) {
|
||||||
|
socketRoleArg.addSocketFunction(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.SocketFunction = SocketFunction;
|
||||||
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRzb2NrZXQuY2xhc3Nlcy5zb2NrZXRmdW5jdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3NtYXJ0c29ja2V0LmNsYXNzZXMuc29ja2V0ZnVuY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBd0NBLGlCQUFpQjtBQUVqQjs7R0FFRztBQUNILE1BQWEsY0FBYztJQWdCekI7O09BRUc7SUFDSCxZQUFZLFVBQWdEO1FBQzFELElBQUksQ0FBQyxJQUFJLEdBQUcsVUFBVSxDQUFDLFFBQVEsQ0FBQztRQUNoQyxJQUFJLENBQUMsT0FBTyxHQUFHLFVBQVUsQ0FBQyxPQUFPLENBQUM7UUFDbEMsSUFBSSxDQUFDLEtBQUssR0FBRyxVQUFVLENBQUMsWUFBWSxDQUFDO1FBQ3JDLEtBQUssTUFBTSxhQUFhLElBQUksSUFBSSxDQUFDLEtBQUssRUFBRTtZQUN0QyxJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1NBQ2pDO0lBQ0gsQ0FBQztJQXpCRCxTQUFTO0lBQ0YsTUFBTSxDQUFDLHVCQUF1QixDQUNuQyxpQkFBa0QsRUFDbEQsZUFBdUI7UUFFdkIsT0FBTyxpQkFBaUIsQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEVBQUU7WUFDaEUsT0FBTyxpQkFBaUIsQ0FBQyxJQUFJLEtBQUssZUFBZSxDQUFDO1FBQ3BELENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQW1CRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxNQUFNLENBQUMsT0FBMEMsRUFBRSxtQkFBcUM7UUFDbkcsSUFBSSxPQUFPLENBQUMsUUFBUSxLQUFLLElBQUksQ0FBQyxJQUFJLEVBQUU7WUFDbEMsTUFBTSxnQkFBZ0IsR0FBdUM7Z0JBQzNELFFBQVEsRUFBRSxJQUFJLENBQUMsSUFBSTtnQkFDbkIsV0FBVyxFQUFFLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFLG1CQUFtQixDQUFDO2FBQzFFLENBQUM7WUFDRixPQUFPLGdCQUFnQixDQUFDO1NBQ3pCO2FBQU07WUFDTCxNQUFNLElBQUksS0FBSyxDQUFDLCtEQUErRCxDQUFDLENBQUM7U0FDbEY7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSyxXQUFXLENBQUMsYUFBeUI7UUFDM0MsYUFBYSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3hDLENBQUM7Q0FDRjtBQWpERCx3Q0FpREMifQ==
|
47
dist_ts/smartsocket.classes.socketrequest.d.ts
vendored
Normal file
47
dist_ts/smartsocket.classes.socketrequest.d.ts
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import * as plugins from './smartsocket.plugins';
|
||||||
|
import { ISocketFunctionCallDataRequest, ISocketFunctionCallDataResponse } from './smartsocket.classes.socketfunction';
|
||||||
|
import { SocketConnection } from './smartsocket.classes.socketconnection';
|
||||||
|
import { Smartsocket } from './smartsocket.classes.smartsocket';
|
||||||
|
import { SmartsocketClient } from './smartsocket.classes.smartsocketclient';
|
||||||
|
export declare type TSocketRequestStatus = 'new' | 'pending' | 'finished';
|
||||||
|
export declare type TSocketRequestSide = 'requesting' | 'responding';
|
||||||
|
/**
|
||||||
|
* interface of constructor of class SocketRequest
|
||||||
|
*/
|
||||||
|
export interface ISocketRequestConstructorOptions<T extends plugins.typedrequestInterfaces.ITypedRequest> {
|
||||||
|
side: TSocketRequestSide;
|
||||||
|
originSocketConnection: SocketConnection;
|
||||||
|
shortId: string;
|
||||||
|
funcCallData?: ISocketFunctionCallDataRequest<T>;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* request object that is sent initially and may or may not receive a response
|
||||||
|
*/
|
||||||
|
export interface ISocketRequestDataObject<T extends plugins.typedrequestInterfaces.ITypedRequest> {
|
||||||
|
funcCallData: ISocketFunctionCallDataRequest<T> | ISocketFunctionCallDataResponse<T>;
|
||||||
|
shortId: string;
|
||||||
|
responseTimeout?: number;
|
||||||
|
}
|
||||||
|
export declare class SocketRequest<T extends plugins.typedrequestInterfaces.ITypedRequest> {
|
||||||
|
static getSocketRequestById(smartsocketRef: Smartsocket | SmartsocketClient, shortIdArg: string): SocketRequest<any>;
|
||||||
|
status: TSocketRequestStatus;
|
||||||
|
side: TSocketRequestSide;
|
||||||
|
shortid: string;
|
||||||
|
originSocketConnection: SocketConnection;
|
||||||
|
funcCallData: ISocketFunctionCallDataRequest<T>;
|
||||||
|
done: plugins.smartpromise.Deferred<ISocketFunctionCallDataResponse<T>>;
|
||||||
|
smartsocketRef: Smartsocket | SmartsocketClient;
|
||||||
|
constructor(smartsocketRefArg: Smartsocket | SmartsocketClient, optionsArg: ISocketRequestConstructorOptions<T>);
|
||||||
|
/**
|
||||||
|
* dispatches a socketrequest from the requesting to the receiving side
|
||||||
|
*/
|
||||||
|
dispatch(): Promise<ISocketFunctionCallDataResponse<T>>;
|
||||||
|
/**
|
||||||
|
* handles the response that is received by the requesting side
|
||||||
|
*/
|
||||||
|
handleResponse(responseDataArg: ISocketRequestDataObject<T>): Promise<void>;
|
||||||
|
/**
|
||||||
|
* creates the response on the responding side
|
||||||
|
*/
|
||||||
|
createResponse(): Promise<void>;
|
||||||
|
}
|
90
dist_ts/smartsocket.classes.socketrequest.js
Normal file
90
dist_ts/smartsocket.classes.socketrequest.js
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
"use strict";
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||||
|
}) : (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
o[k2] = m[k];
|
||||||
|
}));
|
||||||
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||||
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||||
|
}) : function(o, v) {
|
||||||
|
o["default"] = v;
|
||||||
|
});
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.SocketRequest = void 0;
|
||||||
|
const plugins = __importStar(require("./smartsocket.plugins"));
|
||||||
|
// import interfaces
|
||||||
|
const smartsocket_classes_socketfunction_1 = require("./smartsocket.classes.socketfunction");
|
||||||
|
const smartsocket_logging_1 = require("./smartsocket.logging");
|
||||||
|
// export classes
|
||||||
|
class SocketRequest {
|
||||||
|
constructor(smartsocketRefArg, optionsArg) {
|
||||||
|
// INSTANCE
|
||||||
|
this.status = 'new';
|
||||||
|
this.done = plugins.smartpromise.defer();
|
||||||
|
this.smartsocketRef = smartsocketRefArg;
|
||||||
|
this.side = optionsArg.side;
|
||||||
|
this.shortid = optionsArg.shortId;
|
||||||
|
this.funcCallData = optionsArg.funcCallData;
|
||||||
|
this.originSocketConnection = optionsArg.originSocketConnection;
|
||||||
|
this.smartsocketRef.socketRequests.add(this);
|
||||||
|
}
|
||||||
|
// STATIC
|
||||||
|
static getSocketRequestById(smartsocketRef, shortIdArg) {
|
||||||
|
return smartsocketRef.socketRequests.find(socketRequestArg => {
|
||||||
|
return socketRequestArg.shortid === shortIdArg;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// requesting --------------------------
|
||||||
|
/**
|
||||||
|
* dispatches a socketrequest from the requesting to the receiving side
|
||||||
|
*/
|
||||||
|
dispatch() {
|
||||||
|
const requestData = {
|
||||||
|
funcCallData: this.funcCallData,
|
||||||
|
shortId: this.shortid
|
||||||
|
};
|
||||||
|
this.originSocketConnection.socket.emit('function', requestData);
|
||||||
|
return this.done.promise;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* handles the response that is received by the requesting side
|
||||||
|
*/
|
||||||
|
async handleResponse(responseDataArg) {
|
||||||
|
smartsocket_logging_1.logger.log('info', 'handling response!');
|
||||||
|
this.done.resolve(responseDataArg.funcCallData);
|
||||||
|
this.smartsocketRef.socketRequests.remove(this);
|
||||||
|
}
|
||||||
|
// responding --------------------------
|
||||||
|
/**
|
||||||
|
* creates the response on the responding side
|
||||||
|
*/
|
||||||
|
async createResponse() {
|
||||||
|
const targetSocketFunction = smartsocket_classes_socketfunction_1.SocketFunction.getSocketFunctionByName(this.smartsocketRef, this.funcCallData.funcName);
|
||||||
|
if (!targetSocketFunction) {
|
||||||
|
smartsocket_logging_1.logger.log('warn', `There is no SocketFunction defined for ${this.funcCallData.funcName}`);
|
||||||
|
smartsocket_logging_1.logger.log('warn', `So now response is being sent.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
smartsocket_logging_1.logger.log('info', `invoking ${targetSocketFunction.name}`);
|
||||||
|
targetSocketFunction.invoke(this.funcCallData, this.originSocketConnection).then(resultData => {
|
||||||
|
smartsocket_logging_1.logger.log('info', 'got resultData. Sending it to requesting party.');
|
||||||
|
const responseData = {
|
||||||
|
funcCallData: resultData,
|
||||||
|
shortId: this.shortid
|
||||||
|
};
|
||||||
|
this.originSocketConnection.socket.emit('functionResponse', responseData);
|
||||||
|
this.smartsocketRef.socketRequests.remove(this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.SocketRequest = SocketRequest;
|
||||||
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRzb2NrZXQuY2xhc3Nlcy5zb2NrZXRyZXF1ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvc21hcnRzb2NrZXQuY2xhc3Nlcy5zb2NrZXRyZXF1ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSwrREFBaUQ7QUFFakQsb0JBQW9CO0FBQ3BCLDZGQUF1STtBQUl2SSwrREFBK0M7QUEyQi9DLGlCQUFpQjtBQUNqQixNQUFhLGFBQWE7SUFxQnhCLFlBQ0UsaUJBQWtELEVBQ2xELFVBQStDO1FBWmpELFdBQVc7UUFDSixXQUFNLEdBQXlCLEtBQUssQ0FBQztRQUtyQyxTQUFJLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQyxLQUFLLEVBQXNDLENBQUM7UUFRN0UsSUFBSSxDQUFDLGNBQWMsR0FBRyxpQkFBaUIsQ0FBQztRQUN4QyxJQUFJLENBQUMsSUFBSSxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUM7UUFDNUIsSUFBSSxDQUFDLE9BQU8sR0FBRyxVQUFVLENBQUMsT0FBTyxDQUFDO1FBQ2xDLElBQUksQ0FBQyxZQUFZLEdBQUcsVUFBVSxDQUFDLFlBQVksQ0FBQztRQUM1QyxJQUFJLENBQUMsc0JBQXNCLEdBQUcsVUFBVSxDQUFDLHNCQUFzQixDQUFDO1FBQ2hFLElBQUksQ0FBQyxjQUFjLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMvQyxDQUFDO0lBOUJELFNBQVM7SUFDRixNQUFNLENBQUMsb0JBQW9CLENBQ2hDLGNBQStDLEVBQy9DLFVBQWtCO1FBRWxCLE9BQU8sY0FBYyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsRUFBRTtZQUMzRCxPQUFPLGdCQUFnQixDQUFDLE9BQU8sS0FBSyxVQUFVLENBQUM7UUFDakQsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBd0JELHdDQUF3QztJQUV4Qzs7T0FFRztJQUNJLFFBQVE7UUFDYixNQUFNLFdBQVcsR0FBZ0M7WUFDL0MsWUFBWSxFQUFFLElBQUksQ0FBQyxZQUFZO1lBQy9CLE9BQU8sRUFBRSxJQUFJLENBQUMsT0FBTztTQUN0QixDQUFDO1FBQ0YsSUFBSSxDQUFDLHNCQUFzQixDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBQ2pFLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7SUFDM0IsQ0FBQztJQUVEOztPQUVHO0lBQ0ksS0FBSyxDQUFDLGNBQWMsQ0FBQyxlQUE0QztRQUN0RSw0QkFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsb0JBQW9CLENBQUMsQ0FBQztRQUN6QyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDaEQsSUFBSSxDQUFDLGNBQWMsQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2xELENBQUM7SUFFRCx3Q0FBd0M7SUFFeEM7O09BRUc7SUFDSSxLQUFLLENBQUMsY0FBYztRQUN6QixNQUFNLG9CQUFvQixHQUFzQixtREFBYyxDQUFDLHVCQUF1QixDQUNwRixJQUFJLENBQUMsY0FBYyxFQUNuQixJQUFJLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FDM0IsQ0FBQztRQUVGLElBQUksQ0FBQyxvQkFBb0IsRUFBRTtZQUN6Qiw0QkFBTSxDQUFDLEdBQUcsQ0FDUixNQUFNLEVBQ04sMENBQTBDLElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxFQUFFLENBQ3ZFLENBQUM7WUFDRiw0QkFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsZ0NBQWdDLENBQUMsQ0FBQztZQUNyRCxPQUFPO1NBQ1I7UUFDRCw0QkFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsWUFBWSxvQkFBb0IsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQzVELG9CQUFvQixDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsRUFBRTtZQUM1Riw0QkFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsaURBQWlELENBQUMsQ0FBQztZQUN0RSxNQUFNLFlBQVksR0FBZ0M7Z0JBQ2hELFlBQVksRUFBRSxVQUFVO2dCQUN4QixPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU87YUFDdEIsQ0FBQztZQUNGLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFLFlBQVksQ0FBQyxDQUFDO1lBQzFFLElBQUksQ0FBQyxjQUFjLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNsRCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRjtBQXRGRCxzQ0FzRkMifQ==
|
28
dist_ts/smartsocket.classes.socketrole.d.ts
vendored
Normal file
28
dist_ts/smartsocket.classes.socketrole.d.ts
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import * as plugins from './smartsocket.plugins';
|
||||||
|
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 declare class SocketRole {
|
||||||
|
static getSocketRoleByName(referenceSmartsocket: Smartsocket | SmartsocketClient, socketRoleNameArg: string): SocketRole;
|
||||||
|
static checkPasswordForRole(dataArg: ISocketConnectionAuthenticationObject, referenceSmartsocket: Smartsocket | SmartsocketClient): boolean;
|
||||||
|
name: string;
|
||||||
|
passwordHash: string;
|
||||||
|
allowedFunctions: plugins.lik.ObjectMap<SocketFunction<any>>;
|
||||||
|
constructor(optionsArg: ISocketRoleOptions);
|
||||||
|
/**
|
||||||
|
* adds the socketfunction to the socketrole
|
||||||
|
* @param socketFunctionArg
|
||||||
|
*/
|
||||||
|
addSocketFunction(socketFunctionArg: SocketFunction<any>): void;
|
||||||
|
}
|
54
dist_ts/smartsocket.classes.socketrole.js
Normal file
54
dist_ts/smartsocket.classes.socketrole.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
"use strict";
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||||
|
}) : (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
o[k2] = m[k];
|
||||||
|
}));
|
||||||
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||||
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||||
|
}) : function(o, v) {
|
||||||
|
o["default"] = v;
|
||||||
|
});
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.SocketRole = void 0;
|
||||||
|
const plugins = __importStar(require("./smartsocket.plugins"));
|
||||||
|
/**
|
||||||
|
* A socketrole defines access to certain routines.
|
||||||
|
*/
|
||||||
|
class SocketRole {
|
||||||
|
constructor(optionsArg) {
|
||||||
|
this.allowedFunctions = new plugins.lik.ObjectMap();
|
||||||
|
this.name = optionsArg.name;
|
||||||
|
this.passwordHash = optionsArg.passwordHash;
|
||||||
|
}
|
||||||
|
// STATIC
|
||||||
|
static getSocketRoleByName(referenceSmartsocket, socketRoleNameArg) {
|
||||||
|
return referenceSmartsocket.socketRoles.find(socketRoleArg => {
|
||||||
|
return socketRoleArg.name === socketRoleNameArg;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
static checkPasswordForRole(dataArg, referenceSmartsocket) {
|
||||||
|
const targetPasswordHash = SocketRole.getSocketRoleByName(referenceSmartsocket, dataArg.role)
|
||||||
|
.passwordHash;
|
||||||
|
const computedCompareHash = plugins.smarthash.sha256FromStringSync(dataArg.password);
|
||||||
|
return targetPasswordHash === computedCompareHash;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* adds the socketfunction to the socketrole
|
||||||
|
* @param socketFunctionArg
|
||||||
|
*/
|
||||||
|
addSocketFunction(socketFunctionArg) {
|
||||||
|
this.allowedFunctions.add(socketFunctionArg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.SocketRole = SocketRole;
|
||||||
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRzb2NrZXQuY2xhc3Nlcy5zb2NrZXRyb2xlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvc21hcnRzb2NrZXQuY2xhc3Nlcy5zb2NrZXRyb2xlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSwrREFBaUQ7QUFnQmpEOztHQUVHO0FBQ0gsTUFBYSxVQUFVO0lBeUJyQixZQUFZLFVBQThCO1FBRG5DLHFCQUFnQixHQUFHLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxTQUFTLEVBQXVCLENBQUM7UUFFekUsSUFBSSxDQUFDLElBQUksR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDO1FBQzVCLElBQUksQ0FBQyxZQUFZLEdBQUcsVUFBVSxDQUFDLFlBQVksQ0FBQztJQUM5QyxDQUFDO0lBM0JELFNBQVM7SUFDRixNQUFNLENBQUMsbUJBQW1CLENBQy9CLG9CQUFxRCxFQUNyRCxpQkFBeUI7UUFFekIsT0FBTyxvQkFBb0IsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxFQUFFO1lBQzNELE9BQU8sYUFBYSxDQUFDLElBQUksS0FBSyxpQkFBaUIsQ0FBQztRQUNsRCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTSxNQUFNLENBQUMsb0JBQW9CLENBQ2hDLE9BQThDLEVBQzlDLG9CQUFxRDtRQUVyRCxNQUFNLGtCQUFrQixHQUFHLFVBQVUsQ0FBQyxtQkFBbUIsQ0FBQyxvQkFBb0IsRUFBRSxPQUFPLENBQUMsSUFBSSxDQUFDO2FBQzFGLFlBQVksQ0FBQztRQUNoQixNQUFNLG1CQUFtQixHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsb0JBQW9CLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3JGLE9BQU8sa0JBQWtCLEtBQUssbUJBQW1CLENBQUM7SUFDcEQsQ0FBQztJQVdEOzs7T0FHRztJQUNJLGlCQUFpQixDQUFDLGlCQUFzQztRQUM3RCxJQUFJLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLENBQUM7SUFDL0MsQ0FBQztDQUNGO0FBckNELGdDQXFDQyJ9
|
33
dist_ts/smartsocket.classes.socketserver.d.ts
vendored
Normal file
33
dist_ts/smartsocket.classes.socketserver.d.ts
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/// <reference types="node" />
|
||||||
|
import * as plugins from './smartsocket.plugins';
|
||||||
|
import * as http from 'http';
|
||||||
|
import * as https from 'https';
|
||||||
|
import { Smartsocket } from './smartsocket.classes.smartsocket';
|
||||||
|
/**
|
||||||
|
* class socketServer
|
||||||
|
* handles the attachment of socketIo to whatever server is in play
|
||||||
|
*/
|
||||||
|
export declare class SocketServer {
|
||||||
|
private smartsocket;
|
||||||
|
private httpServer;
|
||||||
|
private standaloneServer;
|
||||||
|
private expressServer;
|
||||||
|
constructor(smartSocketInstance: Smartsocket);
|
||||||
|
/**
|
||||||
|
* starts the server with another server
|
||||||
|
* also works with an express style server
|
||||||
|
*/
|
||||||
|
setExternalServer(serverType: 'smartexpress', serverArg: plugins.smartexpress.Server): Promise<void>;
|
||||||
|
/**
|
||||||
|
* gets the server for socket.io
|
||||||
|
*/
|
||||||
|
getServerForSocketIo(): http.Server | https.Server;
|
||||||
|
/**
|
||||||
|
* starts listening to incoming sockets:
|
||||||
|
*/
|
||||||
|
start(): Promise<void>;
|
||||||
|
/**
|
||||||
|
* closes the server
|
||||||
|
*/
|
||||||
|
stop(): Promise<void>;
|
||||||
|
}
|
88
dist_ts/smartsocket.classes.socketserver.js
Normal file
88
dist_ts/smartsocket.classes.socketserver.js
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
"use strict";
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||||
|
}) : (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
o[k2] = m[k];
|
||||||
|
}));
|
||||||
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||||
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||||
|
}) : function(o, v) {
|
||||||
|
o["default"] = v;
|
||||||
|
});
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.SocketServer = void 0;
|
||||||
|
const plugins = __importStar(require("./smartsocket.plugins"));
|
||||||
|
// used in case no other server is supplied
|
||||||
|
const http = __importStar(require("http"));
|
||||||
|
const smartsocket_logging_1 = require("./smartsocket.logging");
|
||||||
|
/**
|
||||||
|
* class socketServer
|
||||||
|
* handles the attachment of socketIo to whatever server is in play
|
||||||
|
*/
|
||||||
|
class SocketServer {
|
||||||
|
constructor(smartSocketInstance) {
|
||||||
|
// wether httpServer is standalone
|
||||||
|
this.standaloneServer = false;
|
||||||
|
this.smartsocket = smartSocketInstance;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* starts the server with another server
|
||||||
|
* also works with an express style server
|
||||||
|
*/
|
||||||
|
async setExternalServer(serverType, serverArg) {
|
||||||
|
await serverArg.startedPromise;
|
||||||
|
this.httpServer = serverArg.httpServer;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* gets the server for socket.io
|
||||||
|
*/
|
||||||
|
getServerForSocketIo() {
|
||||||
|
if (this.httpServer) {
|
||||||
|
return this.httpServer;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.httpServer = new http.Server();
|
||||||
|
this.standaloneServer = true;
|
||||||
|
return this.httpServer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* starts listening to incoming sockets:
|
||||||
|
*/
|
||||||
|
async start() {
|
||||||
|
const done = plugins.smartpromise.defer();
|
||||||
|
// handle http servers
|
||||||
|
// in case an external server has been set "this.standaloneServer" should be false
|
||||||
|
if (this.httpServer && this.standaloneServer) {
|
||||||
|
if (!this.smartsocket.options.port) {
|
||||||
|
smartsocket_logging_1.logger.log('error', 'there should be a port specifed for smartsocket!');
|
||||||
|
throw new Error('there should be a port specified for smartsocket');
|
||||||
|
}
|
||||||
|
this.httpServer.listen(this.smartsocket.options.port, () => {
|
||||||
|
smartsocket_logging_1.logger.log('success', `Server started in standalone mode on ${this.smartsocket.options.port}`);
|
||||||
|
done.resolve();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
done.resolve();
|
||||||
|
}
|
||||||
|
// nothing else to do if express server is set
|
||||||
|
await done.promise;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* closes the server
|
||||||
|
*/
|
||||||
|
async stop() { }
|
||||||
|
}
|
||||||
|
exports.SocketServer = SocketServer;
|
||||||
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRzb2NrZXQuY2xhc3Nlcy5zb2NrZXRzZXJ2ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydHNvY2tldC5jbGFzc2VzLnNvY2tldHNlcnZlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsK0RBQWlEO0FBRWpELDJDQUEyQztBQUMzQywyQ0FBNkI7QUFHN0IsK0RBQStDO0FBRS9DOzs7R0FHRztBQUNILE1BQWEsWUFBWTtJQU92QixZQUFZLG1CQUFnQztRQUo1QyxrQ0FBa0M7UUFDMUIscUJBQWdCLEdBQUcsS0FBSyxDQUFDO1FBSS9CLElBQUksQ0FBQyxXQUFXLEdBQUcsbUJBQW1CLENBQUM7SUFDekMsQ0FBQztJQUVEOzs7T0FHRztJQUNJLEtBQUssQ0FBQyxpQkFBaUIsQ0FDNUIsVUFBMEIsRUFDMUIsU0FBc0M7UUFFdEMsTUFBTSxTQUFTLENBQUMsY0FBYyxDQUFDO1FBQy9CLElBQUksQ0FBQyxVQUFVLEdBQUcsU0FBUyxDQUFDLFVBQVUsQ0FBQztJQUN6QyxDQUFDO0lBRUQ7O09BRUc7SUFDSSxvQkFBb0I7UUFDekIsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFO1lBQ25CLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQztTQUN4QjthQUFNO1lBQ0wsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNwQyxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDO1lBQzdCLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQztTQUN4QjtJQUNILENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxLQUFLO1FBQ2hCLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFFLENBQUM7UUFFMUMsc0JBQXNCO1FBQ3RCLGtGQUFrRjtRQUNsRixJQUFJLElBQUksQ0FBQyxVQUFVLElBQUksSUFBSSxDQUFDLGdCQUFnQixFQUFFO1lBQzVDLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUU7Z0JBQ2xDLDRCQUFNLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxrREFBa0QsQ0FBQyxDQUFDO2dCQUN4RSxNQUFNLElBQUksS0FBSyxDQUFDLGtEQUFrRCxDQUFDLENBQUM7YUFDckU7WUFDRCxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsR0FBRyxFQUFFO2dCQUN6RCw0QkFBTSxDQUFDLEdBQUcsQ0FBQyxTQUFTLEVBQUUsd0NBQXdDLElBQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7Z0JBQy9GLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNqQixDQUFDLENBQUMsQ0FBQztTQUNKO2FBQU07WUFDTCxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7U0FDaEI7UUFFRCw4Q0FBOEM7UUFDOUMsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDO1FBQ25CLE9BQU87SUFDVCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsSUFBSSxLQUFJLENBQUM7Q0FDdkI7QUFsRUQsb0NBa0VDIn0=
|
2
dist_ts/smartsocket.logging.d.ts
vendored
Normal file
2
dist_ts/smartsocket.logging.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import * as plugins from './smartsocket.plugins';
|
||||||
|
export declare const logger: plugins.smartlog.ConsoleLog;
|
25
dist_ts/smartsocket.logging.js
Normal file
25
dist_ts/smartsocket.logging.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
"use strict";
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||||
|
}) : (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
o[k2] = m[k];
|
||||||
|
}));
|
||||||
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||||
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||||
|
}) : function(o, v) {
|
||||||
|
o["default"] = v;
|
||||||
|
});
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.logger = void 0;
|
||||||
|
const plugins = __importStar(require("./smartsocket.plugins"));
|
||||||
|
exports.logger = new plugins.smartlog.ConsoleLog();
|
||||||
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRzb2NrZXQubG9nZ2luZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3NtYXJ0c29ja2V0LmxvZ2dpbmcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLCtEQUFpRDtBQUVwQyxRQUFBLE1BQU0sR0FBRyxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLENBQUMifQ==
|
15
dist_ts/smartsocket.plugins.d.ts
vendored
Normal file
15
dist_ts/smartsocket.plugins.d.ts
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import * as typedrequestInterfaces from '@apiglobal/typedrequest-interfaces';
|
||||||
|
export { typedrequestInterfaces };
|
||||||
|
import * as lik from '@pushrocks/lik';
|
||||||
|
import * as smartlog from '@pushrocks/smartlog';
|
||||||
|
import * as smarthash from '@pushrocks/smarthash';
|
||||||
|
import * as smartdelay from '@pushrocks/smartdelay';
|
||||||
|
import * as smartexpress from '@pushrocks/smartexpress';
|
||||||
|
import * as smartpromise from '@pushrocks/smartpromise';
|
||||||
|
import * as smarttime from '@pushrocks/smarttime';
|
||||||
|
import * as smartunique from '@pushrocks/smartunique';
|
||||||
|
import * as smartrx from '@pushrocks/smartrx';
|
||||||
|
export { lik, smartlog, smarthash, smartdelay, smartexpress, smartpromise, smarttime, smartunique, smartrx };
|
||||||
|
import socketIo from 'socket.io';
|
||||||
|
import socketIoClient from 'socket.io-client';
|
||||||
|
export { socketIo, socketIoClient };
|
53
dist_ts/smartsocket.plugins.js
Normal file
53
dist_ts/smartsocket.plugins.js
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
"use strict";
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||||
|
}) : (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
o[k2] = m[k];
|
||||||
|
}));
|
||||||
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||||
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||||
|
}) : function(o, v) {
|
||||||
|
o["default"] = v;
|
||||||
|
});
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.socketIoClient = exports.socketIo = exports.smartrx = exports.smartunique = exports.smarttime = exports.smartpromise = exports.smartexpress = exports.smartdelay = exports.smarthash = exports.smartlog = exports.lik = exports.typedrequestInterfaces = void 0;
|
||||||
|
// apiglobal scope
|
||||||
|
const typedrequestInterfaces = __importStar(require("@apiglobal/typedrequest-interfaces"));
|
||||||
|
exports.typedrequestInterfaces = typedrequestInterfaces;
|
||||||
|
// pushrocks scope
|
||||||
|
const lik = __importStar(require("@pushrocks/lik"));
|
||||||
|
exports.lik = lik;
|
||||||
|
const smartlog = __importStar(require("@pushrocks/smartlog"));
|
||||||
|
exports.smartlog = smartlog;
|
||||||
|
const smarthash = __importStar(require("@pushrocks/smarthash"));
|
||||||
|
exports.smarthash = smarthash;
|
||||||
|
const smartdelay = __importStar(require("@pushrocks/smartdelay"));
|
||||||
|
exports.smartdelay = smartdelay;
|
||||||
|
const smartexpress = __importStar(require("@pushrocks/smartexpress"));
|
||||||
|
exports.smartexpress = smartexpress;
|
||||||
|
const smartpromise = __importStar(require("@pushrocks/smartpromise"));
|
||||||
|
exports.smartpromise = smartpromise;
|
||||||
|
const smarttime = __importStar(require("@pushrocks/smarttime"));
|
||||||
|
exports.smarttime = smarttime;
|
||||||
|
const smartunique = __importStar(require("@pushrocks/smartunique"));
|
||||||
|
exports.smartunique = smartunique;
|
||||||
|
const smartrx = __importStar(require("@pushrocks/smartrx"));
|
||||||
|
exports.smartrx = smartrx;
|
||||||
|
// third party scope
|
||||||
|
const socket_io_1 = __importDefault(require("socket.io"));
|
||||||
|
exports.socketIo = socket_io_1.default;
|
||||||
|
const socket_io_client_1 = __importDefault(require("socket.io-client"));
|
||||||
|
exports.socketIoClient = socket_io_client_1.default;
|
||||||
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRzb2NrZXQucGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3NtYXJ0c29ja2V0LnBsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLGtCQUFrQjtBQUNsQiwyRkFBNkU7QUFFckUsd0RBQXNCO0FBRTlCLGtCQUFrQjtBQUNsQixvREFBc0M7QUFZcEMsa0JBQUc7QUFYTCw4REFBZ0Q7QUFZOUMsNEJBQVE7QUFYVixnRUFBa0Q7QUFZaEQsOEJBQVM7QUFYWCxrRUFBb0Q7QUFZbEQsZ0NBQVU7QUFYWixzRUFBd0Q7QUFZdEQsb0NBQVk7QUFYZCxzRUFBd0Q7QUFZdEQsb0NBQVk7QUFYZCxnRUFBa0Q7QUFZaEQsOEJBQVM7QUFYWCxvRUFBc0Q7QUFZcEQsa0NBQVc7QUFYYiw0REFBOEM7QUFZNUMsMEJBQU87QUFHVCxvQkFBb0I7QUFDcEIsMERBQWlDO0FBSS9CLG1CQUpLLG1CQUFRLENBSUw7QUFIVix3RUFBOEM7QUFJNUMseUJBSkssMEJBQWMsQ0FJTCJ9
|
@ -2,32 +2,17 @@
|
|||||||
"gitzone": {
|
"gitzone": {
|
||||||
"projectType": "npm",
|
"projectType": "npm",
|
||||||
"module": {
|
"module": {
|
||||||
"githost": "code.foss.global",
|
"githost": "gitlab.com",
|
||||||
"gitscope": "push.rocks",
|
"gitscope": "pushrocks",
|
||||||
"gitrepo": "smartsocket",
|
"gitrepo": "smartsocket",
|
||||||
"description": "Provides easy and secure websocket communication mechanisms, including server and client implementation, function call routing, connection management, and tagging.",
|
"shortDescription": "easy and secure websocket communication",
|
||||||
"npmPackagename": "@push.rocks/smartsocket",
|
"npmPackagename": "@pushrocks/smartsocket",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"projectDomain": "push.rocks",
|
"projectDomain": "push.rocks"
|
||||||
"keywords": [
|
|
||||||
"websocket",
|
|
||||||
"communication",
|
|
||||||
"server",
|
|
||||||
"client",
|
|
||||||
"socket.io",
|
|
||||||
"authentication",
|
|
||||||
"reconnection",
|
|
||||||
"tagging",
|
|
||||||
"function routing",
|
|
||||||
"secure"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"npmci": {
|
"npmci": {
|
||||||
"npmGlobalTools": [],
|
"npmGlobalTools": [],
|
||||||
"npmAccessLevel": "public"
|
"npmAccessLevel": "public"
|
||||||
},
|
|
||||||
"tsdoc": {
|
|
||||||
"legal": "\n## License and Legal Information\n\nThis repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository. \n\n**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.\n\n### Trademarks\n\nThis project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.\n\n### Company Information\n\nTask Venture Capital GmbH \nRegistered at District court Bremen HRB 35230 HB, Germany\n\nFor any legal inquiries or if you require further information, please contact us via email at hello@task.vc.\n\nBy using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.\n"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
11386
package-lock.json
generated
Normal file
11386
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
67
package.json
67
package.json
@ -1,49 +1,46 @@
|
|||||||
{
|
{
|
||||||
"name": "@push.rocks/smartsocket",
|
"name": "@pushrocks/smartsocket",
|
||||||
"version": "2.1.0",
|
"version": "1.1.60",
|
||||||
"description": "Provides easy and secure websocket communication mechanisms, including server and client implementation, function call routing, connection management, and tagging.",
|
"description": "easy and secure websocket communication",
|
||||||
"main": "dist_ts/index.js",
|
"main": "dist_ts/index.js",
|
||||||
"typings": "dist_ts/index.d.ts",
|
"typings": "dist_ts/index.d.ts",
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "(tstest test/)",
|
"test": "(tstest test/)",
|
||||||
"build": "(tsbuild --web --allowimplicitany && tsbundle --from ./ts/index.ts --to dist_bundle/bundle.js)",
|
"build": "(tsbuild --web)"
|
||||||
"buildDocs": "tsdoc"
|
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://code.foss.global/push.rocks/smartsocket.git"
|
"url": "git+ssh://git@gitlab.com/pushrocks/smartsocket.git"
|
||||||
},
|
},
|
||||||
"author": "Lossless GmbH",
|
"author": "Lossless GmbH",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://gitlab.com/pushrocks/smartsocket/issues"
|
"url": "https://gitlab.com/pushrocks/smartsocket/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://code.foss.global/push.rocks/smartsocket",
|
"homepage": "https://gitlab.com/pushrocks/smartsocket#README",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@api.global/typedrequest-interfaces": "^3.0.18",
|
"@apiglobal/typedrequest-interfaces": "^1.0.15",
|
||||||
"@api.global/typedserver": "^3.0.27",
|
"@pushrocks/lik": "^4.0.17",
|
||||||
"@push.rocks/isohash": "^2.0.0",
|
"@pushrocks/smartdelay": "^2.0.10",
|
||||||
"@push.rocks/isounique": "^1.0.5",
|
"@pushrocks/smartexpress": "^3.0.76",
|
||||||
"@push.rocks/lik": "^6.0.14",
|
"@pushrocks/smarthash": "^2.1.6",
|
||||||
"@push.rocks/smartdelay": "^3.0.5",
|
"@pushrocks/smartlog": "^2.0.39",
|
||||||
"@push.rocks/smartenv": "^5.0.12",
|
"@pushrocks/smartpromise": "^3.0.6",
|
||||||
"@push.rocks/smartjson": "^5.0.19",
|
"@pushrocks/smartrx": "^2.0.19",
|
||||||
"@push.rocks/smartlog": "^3.0.3",
|
"@pushrocks/smartunique": "^3.0.3",
|
||||||
"@push.rocks/smartpromise": "^4.0.3",
|
"@types/socket.io": "^2.1.11",
|
||||||
"@push.rocks/smartrx": "^3.0.7",
|
"@types/socket.io-client": "^1.4.33",
|
||||||
"@push.rocks/smarttime": "^4.0.6",
|
"socket.io": "^2.3.0",
|
||||||
"engine.io": "6.6.4",
|
"socket.io-client": "^2.3.0"
|
||||||
"socket.io": "4.8.1",
|
|
||||||
"socket.io-client": "4.8.1"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@git.zone/tsbuild": "^2.1.66",
|
"@gitzone/tsbuild": "^2.1.25",
|
||||||
"@git.zone/tsbundle": "^2.0.8",
|
"@gitzone/tsrun": "^1.2.12",
|
||||||
"@git.zone/tsrun": "^1.2.44",
|
"@gitzone/tstest": "^1.0.44",
|
||||||
"@git.zone/tstest": "^1.0.77",
|
"@pushrocks/tapbundle": "^3.2.9",
|
||||||
"@push.rocks/tapbundle": "^5.0.23",
|
"@types/node": "^14.11.2",
|
||||||
"@types/node": "^22.13.10"
|
"tslint": "^6.1.3",
|
||||||
|
"tslint-config-prettier": "^1.18.0"
|
||||||
},
|
},
|
||||||
"private": false,
|
"private": false,
|
||||||
"files": [
|
"files": [
|
||||||
@ -60,17 +57,5 @@
|
|||||||
],
|
],
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"last 1 chrome versions"
|
"last 1 chrome versions"
|
||||||
],
|
|
||||||
"keywords": [
|
|
||||||
"websocket",
|
|
||||||
"communication",
|
|
||||||
"server",
|
|
||||||
"client",
|
|
||||||
"socket.io",
|
|
||||||
"authentication",
|
|
||||||
"reconnection",
|
|
||||||
"tagging",
|
|
||||||
"function routing",
|
|
||||||
"secure"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
10031
pnpm-lock.yaml
generated
10031
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -1 +0,0 @@
|
|||||||
|
|
149
readme.md
149
readme.md
@ -1,149 +0,0 @@
|
|||||||
# @push.rocks/smartsocket
|
|
||||||
easy and secure websocket communication
|
|
||||||
|
|
||||||
## Install
|
|
||||||
|
|
||||||
To install @push.rocks/smartsocket, you can use npm or yarn as follows:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
npm install @push.rocks/smartsocket --save
|
|
||||||
```
|
|
||||||
or
|
|
||||||
```shell
|
|
||||||
yarn add @push.rocks/smartsocket
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
@push.rocks/smartsocket offers a robust solution for easy and secure WebSocket communication, utilizing Typescript for clean and maintainable code. Below are comprehensive examples covering various scenarios and features provided by the module.
|
|
||||||
|
|
||||||
### Getting Started
|
|
||||||
|
|
||||||
First, ensure you've installed the module as shown in the "Install" section. Once installed, you can start using @push.rocks/smartsocket in your project.
|
|
||||||
|
|
||||||
### Setting Up a WebSocket Server
|
|
||||||
|
|
||||||
To create a WebSocket server that clients can connect to:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { Smartsocket } from '@push.rocks/smartsocket';
|
|
||||||
|
|
||||||
// Create a new instance of Smartsocket for the server.
|
|
||||||
const server = new Smartsocket({ alias: 'myServer' });
|
|
||||||
|
|
||||||
// Define a SocketFunction that clients can call
|
|
||||||
server.addSocketFunction({
|
|
||||||
funcName: 'greet',
|
|
||||||
funcDef: async (data) => {
|
|
||||||
console.log(`Server received: ${data.message}`);
|
|
||||||
return { reply: `Hello, ${data.name}!` };
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Start the Smartsocket server
|
|
||||||
server.start().then(() => {
|
|
||||||
console.log('WebSocket server is running...');
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### Creating a WebSocket Client
|
|
||||||
|
|
||||||
Create a client that connects to the WebSocket server and interacts with it:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { SmartsocketClient } from '@push.rocks/smartsocket';
|
|
||||||
|
|
||||||
// Create a SmartsocketClient instance and connect to the server
|
|
||||||
const client = new SmartsocketClient({
|
|
||||||
url: 'ws://localhost',
|
|
||||||
port: 3000,
|
|
||||||
alias: 'myClient'
|
|
||||||
});
|
|
||||||
|
|
||||||
client.connect().then(() => {
|
|
||||||
console.log('Connected to WebSocket server');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Define a function to call the server's 'greet' function
|
|
||||||
async function greetServer(name) {
|
|
||||||
const response = await client.serverCall('greet', { name: name, message: 'Hello!' });
|
|
||||||
console.log(`Server replied: ${response.reply}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use the function
|
|
||||||
greetServer('Alice');
|
|
||||||
```
|
|
||||||
|
|
||||||
### Handling Disconnections and Reconnections
|
|
||||||
|
|
||||||
@push.rocks/smartsocket provides mechanisms to handle client disconnections and attempt reconnections:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
client.on('disconnect', () => {
|
|
||||||
console.log('Disconnected from server. Attempting to reconnect...');
|
|
||||||
client.connect();
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### Sending Binary Data
|
|
||||||
|
|
||||||
The library supports the transmission of binary data efficiently:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import fs from 'fs';
|
|
||||||
|
|
||||||
// Function to send a binary file to the server
|
|
||||||
async function sendBinaryData(filePath) {
|
|
||||||
const fileBuffer = fs.readFileSync(filePath);
|
|
||||||
await client.serverCall('sendFile', { file: fileBuffer });
|
|
||||||
}
|
|
||||||
|
|
||||||
sendBinaryData('./path/to/your/file.png');
|
|
||||||
```
|
|
||||||
|
|
||||||
### Securing Your WebSocket Communication
|
|
||||||
|
|
||||||
@push.rocks/smartsocket leverages secure WebSocket (WSS) connections to ensure that data transferred between the client and server is encrypted. When setting up your Smartsocket server or client, use `wss://` in your URL to enable secure communication.
|
|
||||||
|
|
||||||
### Advanced Usage
|
|
||||||
|
|
||||||
#### Mesh Networking
|
|
||||||
|
|
||||||
@push.rocks/smartsocket allows for the creation of complex mesh network configurations, enabling servers to communicate with other servers, forming a robust network with multiple nodes.
|
|
||||||
|
|
||||||
#### Scaling with @push.rocks/smartsocket
|
|
||||||
|
|
||||||
To scale your WebSocket services, you can utilize load balancers and ensure your @push.rocks/smartsocket instances are stateless to allow for horizontal scaling.
|
|
||||||
|
|
||||||
### Conclusion
|
|
||||||
|
|
||||||
This guide has covered how to set up basic WebSocket communication with @push.rocks/smartsocket, handle disconnections/reconnections, secure your communication, send binary data, and briefly touched on advanced concepts like mesh networking and scaling.
|
|
||||||
|
|
||||||
For more detailed documentation, visit [the official @push.rocks/smartsocket GitLab repository](https://gitlab.com/pushrocks/smartsocket).
|
|
||||||
|
|
||||||
Remember, WebSocket communication with @push.rocks/smartsocket is not only about sending and receiving messages. It's about creating a fast, reliable, and secure communication channel for your real-time applications.
|
|
||||||
|
|
||||||
Happy coding!
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Please note, the documentation above is a starting point. Depending on the complexity and requirements of your application, you may need to explore more features and configurations provided by @push.rocks/smartsocket. Always refer to the official documentation for the most current information and best practices.
|
|
||||||
|
|
||||||
## License and Legal Information
|
|
||||||
|
|
||||||
This repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository.
|
|
||||||
|
|
||||||
**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
### Trademarks
|
|
||||||
|
|
||||||
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.
|
|
||||||
|
|
||||||
### Company Information
|
|
||||||
|
|
||||||
Task Venture Capital GmbH
|
|
||||||
Registered at District court Bremen HRB 35230 HB, Germany
|
|
||||||
|
|
||||||
For any legal inquiries or if you require further information, please contact us via email at hello@task.vc.
|
|
||||||
|
|
||||||
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
|
|
1
test/common/test.ts
Normal file
1
test/common/test.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
console.log('TODO');
|
@ -1,15 +1,18 @@
|
|||||||
// tslint:disable-next-line:no-implicit-dependencies
|
// tslint:disable-next-line:no-implicit-dependencies
|
||||||
import { expect, expectAsync, tap } from '@push.rocks/tapbundle';
|
import { expect, tap } from '@pushrocks/tapbundle';
|
||||||
|
|
||||||
import * as isohash from '@push.rocks/isohash';
|
import * as smarthash from '@pushrocks/smarthash';
|
||||||
import * as smartexpress from '@api.global/typedserver';
|
import * as smartpromise from '@pushrocks/smartpromise';
|
||||||
|
import * as smartexpress from '@pushrocks/smartexpress';
|
||||||
|
|
||||||
import * as smartsocket from '../ts/index.js';
|
import socketIoClient = require('socket.io-client');
|
||||||
|
import smartsocket = require('../ts/index');
|
||||||
|
|
||||||
let testSmartsocket: smartsocket.Smartsocket;
|
let testSmartsocket: smartsocket.Smartsocket;
|
||||||
let testSmartsocketClient: smartsocket.SmartsocketClient;
|
let testSmartsocketClient: smartsocket.SmartsocketClient;
|
||||||
|
let testSocketRole1: smartsocket.SocketRole;
|
||||||
let testSocketFunction1: smartsocket.SocketFunction<any>;
|
let testSocketFunction1: smartsocket.SocketFunction<any>;
|
||||||
let myseServer: smartexpress.servertools.Server;
|
let myseServer: smartexpress.Server;
|
||||||
|
|
||||||
const testConfig = {
|
const testConfig = {
|
||||||
port: 3000,
|
port: 3000,
|
||||||
@ -17,12 +20,12 @@ const testConfig = {
|
|||||||
|
|
||||||
// class smartsocket
|
// class smartsocket
|
||||||
tap.test('should create a new smartsocket', async () => {
|
tap.test('should create a new smartsocket', async () => {
|
||||||
testSmartsocket = new smartsocket.Smartsocket({ alias: 'testserver', port: testConfig.port });
|
testSmartsocket = new smartsocket.Smartsocket({ port: testConfig.port });
|
||||||
expect(testSmartsocket).toBeInstanceOf(smartsocket.Smartsocket);
|
expect(testSmartsocket).be.instanceOf(smartsocket.Smartsocket);
|
||||||
});
|
});
|
||||||
|
|
||||||
tap.test('Should accept an smartExpressServer as server', async () => {
|
tap.test('Should accept an smartExpressServer as server', async () => {
|
||||||
myseServer = new smartexpress.servertools.Server({
|
myseServer = new smartexpress.Server({
|
||||||
cors: true,
|
cors: true,
|
||||||
forceSsl: false,
|
forceSsl: false,
|
||||||
port: testConfig.port,
|
port: testConfig.port,
|
||||||
@ -33,9 +36,19 @@ tap.test('Should accept an smartExpressServer as server', async () => {
|
|||||||
await myseServer.start();
|
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
|
// class SocketFunction
|
||||||
tap.test('should register a new Function', async () => {
|
tap.test('should register a new Function', async () => {
|
||||||
testSocketFunction1 = new smartsocket.SocketFunction({
|
testSocketFunction1 = new smartsocket.SocketFunction({
|
||||||
|
allowedRoles: [testSocketRole1],
|
||||||
funcDef: async (dataArg, socketConnectionArg) => {
|
funcDef: async (dataArg, socketConnectionArg) => {
|
||||||
return dataArg;
|
return dataArg;
|
||||||
},
|
},
|
||||||
@ -54,9 +67,12 @@ tap.test('should react to a new websocket connection from client', async () => {
|
|||||||
testSmartsocketClient = new smartsocket.SmartsocketClient({
|
testSmartsocketClient = new smartsocket.SmartsocketClient({
|
||||||
port: testConfig.port,
|
port: testConfig.port,
|
||||||
url: 'http://localhost',
|
url: 'http://localhost',
|
||||||
|
password: 'testPassword',
|
||||||
alias: 'testClient1',
|
alias: 'testClient1',
|
||||||
|
role: 'testRole1',
|
||||||
});
|
});
|
||||||
testSmartsocketClient.addSocketFunction(testSocketFunction1);
|
testSmartsocketClient.addSocketFunction(testSocketFunction1);
|
||||||
|
console.log(testSmartsocketClient.socketFunctions);
|
||||||
await testSmartsocketClient.connect();
|
await testSmartsocketClient.connect();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -71,25 +87,10 @@ tap.test('2 clients should connect in parallel', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
tap.test('should be able to make a functionCall from client to server', async () => {
|
tap.test('should be able to make a functionCall from client to server', async () => {
|
||||||
const totalCycles = 20000;
|
const response = await testSmartsocketClient.serverCall('testFunction1', {
|
||||||
let counter = 0;
|
value1: 'hello',
|
||||||
let startTime = Date.now();
|
});
|
||||||
while (counter < totalCycles) {
|
console.log(response);
|
||||||
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.`
|
|
||||||
);
|
|
||||||
startTime = Date.now();
|
|
||||||
}
|
|
||||||
counter++;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
tap.test('should be able to make a functionCall from server to client', async () => {});
|
tap.test('should be able to make a functionCall from server to client', async () => {});
|
||||||
|
@ -1,152 +0,0 @@
|
|||||||
// 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,10 +1,16 @@
|
|||||||
// tslint:disable-next-line:no-implicit-dependencies
|
// tslint:disable-next-line:no-implicit-dependencies
|
||||||
import { expect, tap } from '@push.rocks/tapbundle';
|
import { expect, tap } from '@pushrocks/tapbundle';
|
||||||
|
|
||||||
import * as smartsocket from '../ts/index.js';
|
import * as smarthash from '@pushrocks/smarthash';
|
||||||
|
import * as smartpromise from '@pushrocks/smartpromise';
|
||||||
|
|
||||||
|
import socketIoClient = require('socket.io-client');
|
||||||
|
import smartsocket = require('../ts/index');
|
||||||
|
|
||||||
let testSmartsocket: smartsocket.Smartsocket;
|
let testSmartsocket: smartsocket.Smartsocket;
|
||||||
let testSmartsocketClient: smartsocket.SmartsocketClient;
|
let testSmartsocketClient: smartsocket.SmartsocketClient;
|
||||||
|
let testSocketConnection: smartsocket.SocketConnection;
|
||||||
|
let testSocketRole1: smartsocket.SocketRole;
|
||||||
let testSocketFunctionForServer: smartsocket.SocketFunction<any>;
|
let testSocketFunctionForServer: smartsocket.SocketFunction<any>;
|
||||||
let testSocketFunctionClient: smartsocket.SocketFunction<any>;
|
let testSocketFunctionClient: smartsocket.SocketFunction<any>;
|
||||||
|
|
||||||
@ -34,13 +40,23 @@ const testConfig = {
|
|||||||
|
|
||||||
// class smartsocket
|
// class smartsocket
|
||||||
tap.test('should create a new smartsocket', async () => {
|
tap.test('should create a new smartsocket', async () => {
|
||||||
testSmartsocket = new smartsocket.Smartsocket({ alias: 'testserver2', port: testConfig.port });
|
testSmartsocket = new smartsocket.Smartsocket({ port: testConfig.port });
|
||||||
expect(testSmartsocket).toBeInstanceOf(smartsocket.Smartsocket);
|
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]);
|
||||||
});
|
});
|
||||||
|
|
||||||
// class SocketFunction
|
// class SocketFunction
|
||||||
tap.test('should register a new Function', async () => {
|
tap.test('should register a new Function', async () => {
|
||||||
testSocketFunctionForServer = new smartsocket.SocketFunction({
|
testSocketFunctionForServer = new smartsocket.SocketFunction({
|
||||||
|
allowedRoles: [testSocketRole1],
|
||||||
funcDef: async (dataArg, socketConnectionArg) => {
|
funcDef: async (dataArg, socketConnectionArg) => {
|
||||||
return dataArg;
|
return dataArg;
|
||||||
},
|
},
|
||||||
@ -49,12 +65,14 @@ tap.test('should register a new Function', async () => {
|
|||||||
testSmartsocket.addSocketFunction(testSocketFunctionForServer);
|
testSmartsocket.addSocketFunction(testSocketFunctionForServer);
|
||||||
|
|
||||||
testSocketFunctionClient = new smartsocket.SocketFunction({
|
testSocketFunctionClient = new smartsocket.SocketFunction({
|
||||||
|
allowedRoles: [],
|
||||||
funcDef: async (dataArg, socketConnectionArg) => {
|
funcDef: async (dataArg, socketConnectionArg) => {
|
||||||
return dataArg;
|
return dataArg;
|
||||||
},
|
},
|
||||||
funcName: 'testFunction2',
|
funcName: 'testFunction2',
|
||||||
});
|
});
|
||||||
testSmartsocket.addSocketFunction(testSocketFunctionForServer);
|
testSmartsocket.addSocketFunction(testSocketFunctionForServer);
|
||||||
|
console.log(testSmartsocket.socketFunctions);
|
||||||
});
|
});
|
||||||
|
|
||||||
tap.test('should start listening when .started is called', async () => {
|
tap.test('should start listening when .started is called', async () => {
|
||||||
@ -66,38 +84,15 @@ tap.test('should react to a new websocket connection from client', async () => {
|
|||||||
testSmartsocketClient = new smartsocket.SmartsocketClient({
|
testSmartsocketClient = new smartsocket.SmartsocketClient({
|
||||||
port: testConfig.port,
|
port: testConfig.port,
|
||||||
url: 'http://localhost',
|
url: 'http://localhost',
|
||||||
|
password: 'testPassword',
|
||||||
alias: 'testClient1',
|
alias: 'testClient1',
|
||||||
|
role: 'testRole1',
|
||||||
});
|
});
|
||||||
testSmartsocketClient.addSocketFunction(testSocketFunctionClient);
|
testSmartsocketClient.addSocketFunction(testSocketFunctionClient);
|
||||||
|
console.log(testSmartsocketClient.socketFunctions);
|
||||||
await testSmartsocketClient.connect();
|
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 () => {
|
tap.test('2 clients should connect in parallel', async () => {
|
||||||
// TODO: implement parallel test
|
// TODO: implement parallel test
|
||||||
});
|
});
|
||||||
@ -107,7 +102,7 @@ tap.test('should be able to make a functionCall from client to server', async ()
|
|||||||
value1: 'hello',
|
value1: 'hello',
|
||||||
});
|
});
|
||||||
console.log(response);
|
console.log(response);
|
||||||
expect(response.value1).toEqual('hello');
|
expect(response.value1).to.equal('hello');
|
||||||
});
|
});
|
||||||
|
|
||||||
tap.test('should be able to make a functionCall from server to client', async () => {
|
tap.test('should be able to make a functionCall from server to client', async () => {
|
||||||
@ -116,29 +111,20 @@ tap.test('should be able to make a functionCall from server to client', async ()
|
|||||||
{
|
{
|
||||||
hi: 'hi there from server',
|
hi: 'hi there from server',
|
||||||
},
|
},
|
||||||
testSmartsocket.socketConnections.findSync((socketConnection) => {
|
testSmartsocket.socketConnections.find((socketConnection) => {
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
console.log(response);
|
console.log(response);
|
||||||
expect(response.hi).toEqual('hi there from server');
|
expect(response.hi).to.equal('hi there from server');
|
||||||
});
|
});
|
||||||
|
|
||||||
tap.test('client should disconnect and reconnect', async (tools) => {
|
tap.test('client should disconnect and reconnect', async (tools) => {
|
||||||
await testSmartsocketClient.disconnect();
|
await testSmartsocketClient.disconnect();
|
||||||
|
await tools.delayFor(100);
|
||||||
await testSmartsocketClient.connect();
|
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
|
// terminate
|
||||||
tap.test('should close the server', async () => {
|
tap.test('should close the server', async () => {
|
||||||
await testSmartsocket.stop();
|
await testSmartsocket.stop();
|
@ -1,8 +0,0 @@
|
|||||||
/**
|
|
||||||
* autocreated commitinfo by @push.rocks/commitinfo
|
|
||||||
*/
|
|
||||||
export const commitinfo = {
|
|
||||||
name: '@push.rocks/smartsocket',
|
|
||||||
version: '2.1.0',
|
|
||||||
description: 'Provides easy and secure websocket communication mechanisms, including server and client implementation, function call routing, connection management, and tagging.'
|
|
||||||
}
|
|
12
ts/index.ts
12
ts/index.ts
@ -1,10 +1,8 @@
|
|||||||
// export main classes
|
// export main classes
|
||||||
export * from './smartsocket.classes.smartsocket.js';
|
export * from './smartsocket.classes.smartsocket';
|
||||||
export * from './smartsocket.classes.smartsocketclient.js';
|
export * from './smartsocket.classes.smartsocketclient';
|
||||||
|
|
||||||
// export further classes and objects
|
// export further classes and objects
|
||||||
export * from './smartsocket.classes.socketfunction.js';
|
export * from './smartsocket.classes.socketfunction';
|
||||||
export * from './smartsocket.classes.socketconnection.js';
|
export * from './smartsocket.classes.socketrole';
|
||||||
|
export * from './smartsocket.classes.socketconnection';
|
||||||
// export types so they can be referred to
|
|
||||||
export * from './interfaces/index.js';
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
export interface IRequestAuthPayload {
|
export interface IRequestAuthPayload {
|
||||||
serverAlias: string;
|
serverShortId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TConnectionStatus =
|
export type TConnectionStatus =
|
||||||
@ -7,5 +7,4 @@ export type TConnectionStatus =
|
|||||||
| 'connecting'
|
| 'connecting'
|
||||||
| 'connected'
|
| 'connected'
|
||||||
| 'disconnecting'
|
| 'disconnecting'
|
||||||
| 'disconnected'
|
| 'disconnected';
|
||||||
| 'timedOut';
|
|
||||||
|
@ -1,2 +1 @@
|
|||||||
export * from './connection.js';
|
export * from './connection';
|
||||||
export * from './tag.js';
|
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
export interface ITag<T = any> {
|
|
||||||
id: string;
|
|
||||||
payload: T;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type TTagStore = { [key: string]: ITag };
|
|
@ -1,21 +1,21 @@
|
|||||||
import * as plugins from './smartsocket.plugins.js';
|
import * as plugins from './smartsocket.plugins';
|
||||||
import * as pluginsTyped from './smartsocket.pluginstyped.js';
|
|
||||||
import * as interfaces from './interfaces/index.js';
|
|
||||||
|
|
||||||
// classes
|
// classes
|
||||||
import { SocketConnection } from './smartsocket.classes.socketconnection.js';
|
import { SocketConnection } from './smartsocket.classes.socketconnection';
|
||||||
import {
|
import {
|
||||||
type ISocketFunctionCallDataRequest,
|
ISocketFunctionCallDataRequest,
|
||||||
SocketFunction,
|
SocketFunction,
|
||||||
type ISocketFunctionCallDataResponse,
|
ISocketFunctionCallDataResponse,
|
||||||
} from './smartsocket.classes.socketfunction.js';
|
} from './smartsocket.classes.socketfunction';
|
||||||
import { SocketRequest } from './smartsocket.classes.socketrequest.js';
|
import { SocketRequest } from './smartsocket.classes.socketrequest';
|
||||||
import { SocketServer } from './smartsocket.classes.socketserver.js';
|
import { SocketRole } from './smartsocket.classes.socketrole';
|
||||||
|
import { SocketServer } from './smartsocket.classes.socketserver';
|
||||||
|
|
||||||
import { logger } from './smartsocket.logging.js';
|
// socket.io
|
||||||
|
import * as SocketIO from 'socket.io';
|
||||||
|
import { logger } from './smartsocket.logging';
|
||||||
|
|
||||||
export interface ISmartsocketConstructorOptions {
|
export interface ISmartsocketConstructorOptions {
|
||||||
alias: string;
|
|
||||||
port?: number;
|
port?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,23 +23,21 @@ export class Smartsocket {
|
|||||||
/**
|
/**
|
||||||
* a unique id to detect server restarts
|
* a unique id to detect server restarts
|
||||||
*/
|
*/
|
||||||
public alias: string;
|
public shortId = plugins.smartunique.shortId();
|
||||||
public smartenv = new plugins.smartenv.Smartenv();
|
|
||||||
public options: ISmartsocketConstructorOptions;
|
public options: ISmartsocketConstructorOptions;
|
||||||
public io: pluginsTyped.socketIo.Server;
|
public io: SocketIO.Server;
|
||||||
public socketConnections = new plugins.lik.ObjectMap<SocketConnection>();
|
public socketConnections = new plugins.lik.ObjectMap<SocketConnection>();
|
||||||
|
public socketRoles = new plugins.lik.ObjectMap<SocketRole>();
|
||||||
public socketFunctions = new plugins.lik.ObjectMap<SocketFunction<any>>();
|
public socketFunctions = new plugins.lik.ObjectMap<SocketFunction<any>>();
|
||||||
public socketRequests = new plugins.lik.ObjectMap<SocketRequest<any>>();
|
public socketRequests = new plugins.lik.ObjectMap<SocketRequest<any>>();
|
||||||
|
|
||||||
public eventSubject = new plugins.smartrx.rxjs.Subject<interfaces.TConnectionStatus>();
|
|
||||||
|
|
||||||
private socketServer = new SocketServer(this);
|
private socketServer = new SocketServer(this);
|
||||||
|
|
||||||
constructor(optionsArg: ISmartsocketConstructorOptions) {
|
constructor(optionsArg: ISmartsocketConstructorOptions) {
|
||||||
this.options = optionsArg;
|
this.options = optionsArg;
|
||||||
this.alias = plugins.isounique.uni(this.options.alias);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tslint:disable-next-line:member-ordering
|
||||||
public async setExternalServer(serverType: 'smartexpress', serverArg: any) {
|
public async setExternalServer(serverType: 'smartexpress', serverArg: any) {
|
||||||
await this.socketServer.setExternalServer(serverType, serverArg);
|
await this.socketServer.setExternalServer(serverType, serverArg);
|
||||||
}
|
}
|
||||||
@ -48,14 +46,7 @@ export class Smartsocket {
|
|||||||
* starts smartsocket
|
* starts smartsocket
|
||||||
*/
|
*/
|
||||||
public async start() {
|
public async start() {
|
||||||
const socketIoModule = await this.smartenv.getSafeNodeModule('socket.io');
|
this.io = plugins.socketIo(this.socketServer.getServerForSocketIo());
|
||||||
this.io = new socketIoModule.Server(await this.socketServer.getServerForSocketIo(), {
|
|
||||||
cors: {
|
|
||||||
allowedHeaders: '*',
|
|
||||||
methods: '*',
|
|
||||||
origin: '*',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
await this.socketServer.start();
|
await this.socketServer.start();
|
||||||
this.io.on('connection', (socketArg) => {
|
this.io.on('connection', (socketArg) => {
|
||||||
this._handleSocketConnection(socketArg);
|
this._handleSocketConnection(socketArg);
|
||||||
@ -68,13 +59,8 @@ export class Smartsocket {
|
|||||||
public async stop() {
|
public async stop() {
|
||||||
await plugins.smartdelay.delayFor(1000);
|
await plugins.smartdelay.delayFor(1000);
|
||||||
this.socketConnections.forEach((socketObjectArg: SocketConnection) => {
|
this.socketConnections.forEach((socketObjectArg: SocketConnection) => {
|
||||||
if (socketObjectArg) {
|
logger.log('info', `disconnect socket with >>alias ${socketObjectArg.alias}`);
|
||||||
logger.log(
|
socketObjectArg.socket.disconnect();
|
||||||
'info',
|
|
||||||
`disconnecting socket with >>alias ${socketObjectArg.alias} due to server stop...`
|
|
||||||
);
|
|
||||||
socketObjectArg.disconnect();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
this.socketConnections.wipe();
|
this.socketConnections.wipe();
|
||||||
this.io.close();
|
this.io.close();
|
||||||
@ -99,7 +85,7 @@ export class Smartsocket {
|
|||||||
funcName: functionNameArg,
|
funcName: functionNameArg,
|
||||||
},
|
},
|
||||||
originSocketConnection: targetSocketConnectionArg,
|
originSocketConnection: targetSocketConnectionArg,
|
||||||
shortId: plugins.isounique.uni(),
|
shortId: plugins.smartunique.shortId(),
|
||||||
side: 'requesting',
|
side: 'requesting',
|
||||||
});
|
});
|
||||||
const response: ISocketFunctionCallDataResponse<T> = await socketRequest.dispatch();
|
const response: ISocketFunctionCallDataResponse<T> = await socketRequest.dispatch();
|
||||||
@ -107,6 +93,16 @@ export class Smartsocket {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* adds socketRoles
|
||||||
|
*/
|
||||||
|
public addSocketRoles(socketRolesArray: SocketRole[]): void {
|
||||||
|
for (const socketRole of socketRolesArray) {
|
||||||
|
this.socketRoles.add(socketRole);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
public addSocketFunction(socketFunction: SocketFunction<any>) {
|
public addSocketFunction(socketFunction: SocketFunction<any>) {
|
||||||
this.socketFunctions.add(socketFunction);
|
this.socketFunctions.add(socketFunction);
|
||||||
}
|
}
|
||||||
@ -114,24 +110,18 @@ export class Smartsocket {
|
|||||||
/**
|
/**
|
||||||
* the standard handler for new socket connections
|
* the standard handler for new socket connections
|
||||||
*/
|
*/
|
||||||
private async _handleSocketConnection(socketArg: pluginsTyped.socketIo.Socket) {
|
private async _handleSocketConnection(socketArg: plugins.socketIo.Socket) {
|
||||||
const socketConnection: SocketConnection = new SocketConnection({
|
const socketConnection: SocketConnection = new SocketConnection({
|
||||||
alias: undefined,
|
alias: undefined,
|
||||||
authenticated: false,
|
authenticated: false,
|
||||||
|
role: undefined,
|
||||||
side: 'server',
|
side: 'server',
|
||||||
smartsocketHost: this,
|
smartsocketHost: this,
|
||||||
socket: socketArg,
|
socket: socketArg,
|
||||||
});
|
});
|
||||||
logger.log('info', 'Socket connected. Trying to authenticate...');
|
logger.log('info', 'Socket connected. Trying to authenticate...');
|
||||||
this.socketConnections.add(socketConnection);
|
this.socketConnections.add(socketConnection);
|
||||||
const disconnectSubscription = socketConnection.eventSubject.subscribe((eventArg) => {
|
|
||||||
if (eventArg === 'disconnected') {
|
|
||||||
this.socketConnections.remove(socketConnection);
|
|
||||||
disconnectSubscription.unsubscribe();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
await socketConnection.authenticate();
|
await socketConnection.authenticate();
|
||||||
await socketConnection.listenToFunctionRequests();
|
await socketConnection.listenToFunctionRequests();
|
||||||
await socketConnection.socket.emit('serverFullyReactive');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import * as plugins from './smartsocket.plugins.js';
|
import * as plugins from './smartsocket.plugins';
|
||||||
import * as pluginsTyped from './smartsocket.pluginstyped.js';
|
import * as interfaces from './interfaces';
|
||||||
import * as interfaces from './interfaces/index.js';
|
|
||||||
|
|
||||||
import { SocketConnection } from './smartsocket.classes.socketconnection.js';
|
import { SocketConnection } from './smartsocket.classes.socketconnection';
|
||||||
import {
|
import {
|
||||||
type ISocketFunctionCallDataRequest,
|
ISocketFunctionCallDataRequest,
|
||||||
SocketFunction,
|
SocketFunction,
|
||||||
} from './smartsocket.classes.socketfunction.js';
|
} from './smartsocket.classes.socketfunction';
|
||||||
import { type ISocketRequestDataObject, SocketRequest } from './smartsocket.classes.socketrequest.js';
|
import { ISocketRequestDataObject, SocketRequest } from './smartsocket.classes.socketrequest';
|
||||||
import { logger } from './smartsocket.logging.js';
|
import { SocketRole } from './smartsocket.classes.socketrole';
|
||||||
|
import { logger } from './smartsocket.logging';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* interface for class SmartsocketClient
|
* interface for class SmartsocketClient
|
||||||
@ -17,29 +17,24 @@ export interface ISmartsocketClientOptions {
|
|||||||
port: number;
|
port: number;
|
||||||
url: string;
|
url: string;
|
||||||
alias: string; // an alias makes it easier to identify this client in a multo client environment
|
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;
|
autoReconnect?: boolean;
|
||||||
maxRetries?: number; // maximum number of reconnection attempts
|
|
||||||
initialBackoffDelay?: number; // initial backoff delay in ms
|
|
||||||
maxBackoffDelay?: number; // maximum backoff delay in ms
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SmartsocketClient {
|
export class SmartsocketClient {
|
||||||
// a unique id
|
// a unique id
|
||||||
public shortId = plugins.isounique.uni();
|
public shortId = plugins.smartunique.shortId();
|
||||||
|
|
||||||
// the shortId of the remote we connect to
|
// the shortId of the remote we connect to
|
||||||
public remoteShortId: string = null;
|
public remoteShortId: string = null;
|
||||||
|
|
||||||
public alias: string;
|
public alias: string;
|
||||||
|
public socketRole: SocketRole;
|
||||||
public socketConnection: SocketConnection;
|
public socketConnection: SocketConnection;
|
||||||
public serverUrl: string;
|
public serverUrl: string;
|
||||||
public serverPort: number;
|
public serverPort: number;
|
||||||
public autoReconnect: boolean;
|
public autoReconnect: boolean;
|
||||||
public maxRetries: number;
|
|
||||||
public initialBackoffDelay: number;
|
|
||||||
public maxBackoffDelay: number;
|
|
||||||
public currentRetryCount = 0;
|
|
||||||
public currentBackoffDelay: number;
|
|
||||||
|
|
||||||
// status handling
|
// status handling
|
||||||
public eventSubject = new plugins.smartrx.rxjs.Subject<interfaces.TConnectionStatus>();
|
public eventSubject = new plugins.smartrx.rxjs.Subject<interfaces.TConnectionStatus>();
|
||||||
@ -47,227 +42,124 @@ export class SmartsocketClient {
|
|||||||
|
|
||||||
public socketFunctions = new plugins.lik.ObjectMap<SocketFunction<any>>();
|
public socketFunctions = new plugins.lik.ObjectMap<SocketFunction<any>>();
|
||||||
public socketRequests = new plugins.lik.ObjectMap<SocketRequest<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) {
|
constructor(optionsArg: ISmartsocketClientOptions) {
|
||||||
this.alias = optionsArg.alias;
|
this.alias = optionsArg.alias;
|
||||||
this.serverUrl = optionsArg.url;
|
this.serverUrl = optionsArg.url;
|
||||||
this.serverPort = optionsArg.port;
|
this.serverPort = optionsArg.port;
|
||||||
|
this.socketRole = new SocketRole({
|
||||||
|
name: optionsArg.role,
|
||||||
|
passwordHash: optionsArg.password,
|
||||||
|
});
|
||||||
this.autoReconnect = optionsArg.autoReconnect;
|
this.autoReconnect = optionsArg.autoReconnect;
|
||||||
this.maxRetries = optionsArg.maxRetries ?? 100; // Default to 100 retries
|
|
||||||
this.initialBackoffDelay = optionsArg.initialBackoffDelay ?? 1000; // Default to 1 second
|
|
||||||
this.maxBackoffDelay = optionsArg.maxBackoffDelay ?? 60000; // Default to 1 minute
|
|
||||||
this.currentBackoffDelay = this.initialBackoffDelay;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public addSocketFunction(socketFunction: SocketFunction<any>) {
|
public addSocketFunction(socketFunction: SocketFunction<any>) {
|
||||||
this.socketFunctions.add(socketFunction);
|
this.socketFunctions.add(socketFunction);
|
||||||
|
this.socketRole.allowedFunctions.add(socketFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* connect the client to the server
|
* connect the client to the server
|
||||||
*/
|
*/
|
||||||
public async connect() {
|
public connect() {
|
||||||
// Reset retry counters on new connection attempt
|
|
||||||
this.currentRetryCount = 0;
|
|
||||||
this.currentBackoffDelay = this.initialBackoffDelay;
|
|
||||||
|
|
||||||
const done = plugins.smartpromise.defer();
|
const done = plugins.smartpromise.defer();
|
||||||
const smartenvInstance = new plugins.smartenv.Smartenv();
|
|
||||||
const socketIoClient: any = await smartenvInstance.getEnvAwareModule({
|
|
||||||
nodeModuleName: 'socket.io-client',
|
|
||||||
webUrlArg: 'https://cdn.jsdelivr.net/npm/socket.io-client@4/dist/socket.io.js',
|
|
||||||
getFunction: () => {
|
|
||||||
const socketIoBrowserModule = (globalThis as any).io;
|
|
||||||
// console.log('loaded socket.io for browser');
|
|
||||||
return socketIoBrowserModule;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
// console.log(socketIoClient);
|
|
||||||
logger.log('info', 'trying to connect...');
|
logger.log('info', 'trying to connect...');
|
||||||
const socketUrl = `${this.serverUrl}:${this.serverPort}`;
|
const socketUrl = `${this.serverUrl}:${this.serverPort}`;
|
||||||
this.socketConnection = new SocketConnection({
|
this.socketConnection = new SocketConnection({
|
||||||
alias: this.alias,
|
alias: this.alias,
|
||||||
authenticated: false,
|
authenticated: false,
|
||||||
|
role: this.socketRole,
|
||||||
side: 'client',
|
side: 'client',
|
||||||
smartsocketHost: this,
|
smartsocketHost: this,
|
||||||
socket: await socketIoClient
|
socket: plugins.socketIoClient(socketUrl, {
|
||||||
.connect(socketUrl, {
|
multiplex: false,
|
||||||
multiplex: true,
|
reconnectionAttempts: 5,
|
||||||
rememberUpgrade: true,
|
}),
|
||||||
autoConnect: false,
|
|
||||||
reconnectionAttempts: 0,
|
|
||||||
rejectUnauthorized: socketUrl.startsWith('https://localhost') ? false : true,
|
|
||||||
})
|
|
||||||
.open(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const timer = new plugins.smarttime.Timer(5000);
|
const timer = new plugins.smarttime.Timer(5000);
|
||||||
timer.start();
|
timer.start();
|
||||||
timer.completed.then(() => {
|
timer.completed.then(() => {
|
||||||
this.updateStatus('timedOut');
|
|
||||||
logger.log('warn', 'connection to server timed out.');
|
logger.log('warn', 'connection to server timed out.');
|
||||||
this.disconnect(true);
|
this.disconnect();
|
||||||
});
|
});
|
||||||
|
|
||||||
// authentication flow
|
// authentication flow
|
||||||
this.socketConnection.socket.on('requestAuth', (dataArg: interfaces.IRequestAuthPayload) => {
|
this.socketConnection.socket.on(
|
||||||
timer.reset();
|
'requestAuth',
|
||||||
logger.log('info', `server ${dataArg.serverAlias} requested authentication`);
|
(requestAuthPayload: interfaces.IRequestAuthPayload) => {
|
||||||
|
timer.reset();
|
||||||
|
logger.log('info', 'server requested authentication');
|
||||||
|
|
||||||
// lets register the authenticated event
|
// lets register the authenticated event
|
||||||
this.socketConnection.socket.on('authenticated', async () => {
|
this.socketConnection.socket.on('authenticated', () => {
|
||||||
this.remoteShortId = dataArg.serverAlias;
|
this.remoteShortId = requestAuthPayload.serverShortId;
|
||||||
logger.log('info', 'client is authenticated');
|
logger.log('info', 'client is authenticated');
|
||||||
this.socketConnection.authenticated = true;
|
this.socketConnection.authenticated = true;
|
||||||
await this.socketConnection.listenToFunctionRequests();
|
this.socketConnection.listenToFunctionRequests();
|
||||||
});
|
done.resolve();
|
||||||
|
});
|
||||||
|
|
||||||
this.socketConnection.socket.on('serverFullyReactive', async () => {
|
// lets register the forbidden event
|
||||||
// lets take care of retagging
|
this.socketConnection.socket.on('forbidden', async () => {
|
||||||
const oldTagStore = this.tagStore;
|
logger.log('warn', `disconnecting due to being forbidden to use the ressource`);
|
||||||
this.tagStoreSubscription?.unsubscribe();
|
await this.disconnect();
|
||||||
for (const keyArg of Object.keys(this.tagStore)) {
|
});
|
||||||
this.socketConnection.addTag(this.tagStore[keyArg]);
|
|
||||||
}
|
|
||||||
this.tagStoreSubscription = this.socketConnection.tagStoreObservable.subscribe(
|
|
||||||
(tagStoreArg) => {
|
|
||||||
this.tagStore = tagStoreArg;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
for (const tag of Object.keys(oldTagStore)) {
|
// lets provide the actual auth data
|
||||||
await this.addTag(oldTagStore[tag]);
|
this.socketConnection.socket.emit('dataAuth', {
|
||||||
}
|
role: this.socketRole.name,
|
||||||
this.updateStatus('connected');
|
password: this.socketRole.passwordHash,
|
||||||
done.resolve();
|
alias: this.alias,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
// 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
|
// handle connection
|
||||||
this.socketConnection.socket.on('connect', async () => {});
|
this.socketConnection.socket.on('connect', async () => {
|
||||||
|
this.updateStatus('connected');
|
||||||
|
});
|
||||||
|
|
||||||
// handle disconnection and errors
|
// handle disconnection and errors
|
||||||
this.socketConnection.socket.on('disconnect', async () => {
|
this.socketConnection.socket.on('disconnect', async () => {
|
||||||
await this.disconnect(true);
|
await this.disconnect();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.socketConnection.socket.on('reconnect_failed', async () => {
|
this.socketConnection.socket.on('reconnect_failed', async () => {
|
||||||
await this.disconnect(true);
|
await this.disconnect();
|
||||||
});
|
});
|
||||||
this.socketConnection.socket.on('connect_error', async () => {
|
this.socketConnection.socket.on('connect_error', async () => {
|
||||||
await this.disconnect(true);
|
await this.disconnect();
|
||||||
});
|
});
|
||||||
return done.promise;
|
return done.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
private disconnectRunning = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* disconnect from the server
|
* disconnect from the server
|
||||||
*/
|
*/
|
||||||
public async disconnect(useAutoReconnectSetting = false) {
|
public async disconnect() {
|
||||||
if (this.disconnectRunning) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.disconnectRunning = true;
|
|
||||||
this.updateStatus('disconnecting');
|
|
||||||
this.tagStoreSubscription?.unsubscribe();
|
|
||||||
if (this.socketConnection) {
|
if (this.socketConnection) {
|
||||||
await this.socketConnection.disconnect();
|
await this.socketConnection.disconnect();
|
||||||
this.socketConnection = undefined;
|
this.socketConnection = undefined;
|
||||||
logger.log('ok', 'disconnected socket!');
|
logger.log('ok', 'disconnected!');
|
||||||
} else {
|
|
||||||
this.disconnectRunning = false;
|
|
||||||
logger.log('warn', 'tried to disconnect, without a SocketConnection');
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.log('warn', `disconnected from server ${this.remoteShortId}`);
|
logger.log('warn', `disconnected from server ${this.remoteShortId}`);
|
||||||
this.remoteShortId = null;
|
this.remoteShortId = null;
|
||||||
|
this.updateStatus('disconnected');
|
||||||
|
|
||||||
if (this.autoReconnect && useAutoReconnectSetting && this.eventStatus !== 'connecting') {
|
if (this.autoReconnect) {
|
||||||
this.updateStatus('connecting');
|
this.tryDebouncedReconnect();
|
||||||
|
|
||||||
// Check if we've exceeded the maximum number of retries
|
|
||||||
if (this.currentRetryCount >= this.maxRetries) {
|
|
||||||
logger.log('warn', `Maximum reconnection attempts (${this.maxRetries}) reached. Giving up.`);
|
|
||||||
this.disconnectRunning = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Increment retry counter
|
|
||||||
this.currentRetryCount++;
|
|
||||||
|
|
||||||
// Calculate backoff with jitter (±20% randomness)
|
|
||||||
const jitter = this.currentBackoffDelay * 0.2 * (Math.random() * 2 - 1);
|
|
||||||
const delay = Math.min(this.currentBackoffDelay + jitter, this.maxBackoffDelay);
|
|
||||||
|
|
||||||
logger.log('info', `Reconnect attempt ${this.currentRetryCount}/${this.maxRetries} in ${Math.round(delay)}ms`);
|
|
||||||
|
|
||||||
// Apply exponential backoff for next time (doubling with each attempt)
|
|
||||||
this.currentBackoffDelay = Math.min(this.currentBackoffDelay * 2, this.maxBackoffDelay);
|
|
||||||
|
|
||||||
await plugins.smartdelay.delayFor(delay);
|
|
||||||
this.disconnectRunning = false;
|
|
||||||
await this.connect();
|
|
||||||
} else {
|
|
||||||
this.disconnectRunning = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* stops the client completely
|
* try a reconnection
|
||||||
*/
|
*/
|
||||||
public async stop() {
|
public async tryDebouncedReconnect() {
|
||||||
this.autoReconnect = false;
|
await plugins.smartdelay.delayForRandom(10000, 60000);
|
||||||
this.currentRetryCount = 0;
|
await this.connect();
|
||||||
this.currentBackoffDelay = this.initialBackoffDelay;
|
|
||||||
await this.disconnect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -283,7 +175,7 @@ export class SmartsocketClient {
|
|||||||
const socketRequest = new SocketRequest<T>(this, {
|
const socketRequest = new SocketRequest<T>(this, {
|
||||||
side: 'requesting',
|
side: 'requesting',
|
||||||
originSocketConnection: this.socketConnection,
|
originSocketConnection: this.socketConnection,
|
||||||
shortId: plugins.isounique.uni(),
|
shortId: plugins.smartunique.shortId(),
|
||||||
funcCallData: {
|
funcCallData: {
|
||||||
funcName: functionNameArg,
|
funcName: functionNameArg,
|
||||||
funcDataArg: dataArg,
|
funcDataArg: dataArg,
|
||||||
@ -299,19 +191,5 @@ export class SmartsocketClient {
|
|||||||
this.eventSubject.next(statusArg);
|
this.eventSubject.next(statusArg);
|
||||||
}
|
}
|
||||||
this.eventStatus = statusArg;
|
this.eventStatus = statusArg;
|
||||||
|
|
||||||
// Reset reconnection state when connection is successful
|
|
||||||
if (statusArg === 'connected') {
|
|
||||||
this.currentRetryCount = 0;
|
|
||||||
this.currentBackoffDelay = this.initialBackoffDelay;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resets the reconnection state
|
|
||||||
*/
|
|
||||||
public resetReconnectionState() {
|
|
||||||
this.currentRetryCount = 0;
|
|
||||||
this.currentBackoffDelay = this.initialBackoffDelay;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
import * as plugins from './smartsocket.plugins.js';
|
import * as plugins from './smartsocket.plugins';
|
||||||
import * as pluginsTyped from './smartsocket.pluginstyped.js';
|
import * as interfaces from './interfaces';
|
||||||
import * as interfaces from './interfaces/index.js';
|
|
||||||
|
|
||||||
// import classes
|
// import classes
|
||||||
import { Smartsocket } from './smartsocket.classes.smartsocket.js';
|
import { Smartsocket } from './smartsocket.classes.smartsocket';
|
||||||
import { SocketFunction } from './smartsocket.classes.socketfunction.js';
|
import { SocketFunction } from './smartsocket.classes.socketfunction';
|
||||||
import { SocketRequest, type ISocketRequestDataObject } from './smartsocket.classes.socketrequest.js';
|
import { SocketRequest, ISocketRequestDataObject } from './smartsocket.classes.socketrequest';
|
||||||
|
import { SocketRole } from './smartsocket.classes.socketrole';
|
||||||
|
|
||||||
// socket.io
|
// socket.io
|
||||||
import { SmartsocketClient } from './smartsocket.classes.smartsocketclient.js';
|
import * as SocketIO from 'socket.io';
|
||||||
import { logger } from './smartsocket.logging.js';
|
import { SmartsocketClient } from './smartsocket.classes.smartsocketclient';
|
||||||
|
import { logger } from './smartsocket.logging';
|
||||||
|
|
||||||
// export interfaces
|
// export interfaces
|
||||||
|
|
||||||
@ -24,16 +25,19 @@ export type TSocketConnectionSide = 'server' | 'client';
|
|||||||
export interface ISocketConnectionConstructorOptions {
|
export interface ISocketConnectionConstructorOptions {
|
||||||
alias: string;
|
alias: string;
|
||||||
authenticated: boolean;
|
authenticated: boolean;
|
||||||
|
role: SocketRole;
|
||||||
side: TSocketConnectionSide;
|
side: TSocketConnectionSide;
|
||||||
smartsocketHost: Smartsocket | SmartsocketClient;
|
smartsocketHost: Smartsocket | SmartsocketClient;
|
||||||
socket: pluginsTyped.socketIo.Socket | pluginsTyped.socketIoClient.Socket;
|
socket: SocketIO.Socket | SocketIOClient.Socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* interface for authentication data
|
* interface for authentication data
|
||||||
*/
|
*/
|
||||||
export interface ISocketConnectionAuthenticationObject {
|
export interface ISocketConnectionAuthenticationObject {
|
||||||
alias: string;
|
role: 'coreflowContainer';
|
||||||
|
password: 'somePassword';
|
||||||
|
alias: 'coreflow1';
|
||||||
}
|
}
|
||||||
|
|
||||||
// export classes
|
// export classes
|
||||||
@ -46,19 +50,17 @@ export class SocketConnection {
|
|||||||
public alias: string;
|
public alias: string;
|
||||||
public side: TSocketConnectionSide;
|
public side: TSocketConnectionSide;
|
||||||
public authenticated: boolean = false;
|
public authenticated: boolean = false;
|
||||||
|
public role: SocketRole;
|
||||||
public smartsocketRef: Smartsocket | SmartsocketClient;
|
public smartsocketRef: Smartsocket | SmartsocketClient;
|
||||||
public socket: pluginsTyped.socketIo.Socket | pluginsTyped.socketIoClient.Socket;
|
public socket: SocketIO.Socket | SocketIOClient.Socket;
|
||||||
|
|
||||||
public eventSubject = new plugins.smartrx.rxjs.Subject<interfaces.TConnectionStatus>();
|
public eventSubject = new plugins.smartrx.rxjs.Subject<interfaces.TConnectionStatus>();
|
||||||
public eventStatus: interfaces.TConnectionStatus = 'new';
|
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) {
|
constructor(optionsArg: ISocketConnectionConstructorOptions) {
|
||||||
this.alias = optionsArg.alias;
|
this.alias = optionsArg.alias;
|
||||||
this.authenticated = optionsArg.authenticated;
|
this.authenticated = optionsArg.authenticated;
|
||||||
|
this.role = optionsArg.role;
|
||||||
this.side = optionsArg.side;
|
this.side = optionsArg.side;
|
||||||
this.smartsocketRef = optionsArg.smartsocketHost;
|
this.smartsocketRef = optionsArg.smartsocketHost;
|
||||||
this.socket = optionsArg.socket;
|
this.socket = optionsArg.socket;
|
||||||
@ -77,49 +79,9 @@ export class SocketConnection {
|
|||||||
);
|
);
|
||||||
await this.disconnect();
|
await this.disconnect();
|
||||||
allSocketConnections.remove(this);
|
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 --------------------------
|
// authenticating --------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -128,23 +90,24 @@ export class SocketConnection {
|
|||||||
public authenticate() {
|
public authenticate() {
|
||||||
const done = plugins.smartpromise.defer();
|
const done = plugins.smartpromise.defer();
|
||||||
this.socket.on('dataAuth', async (dataArg: ISocketConnectionAuthenticationObject) => {
|
this.socket.on('dataAuth', async (dataArg: ISocketConnectionAuthenticationObject) => {
|
||||||
logger.log('info', 'received authentication data...');
|
logger.log('info', 'received authentication data. now hashing and comparing...');
|
||||||
this.socket.removeAllListeners('dataAuth');
|
this.socket.removeListener('dataAuth', () => {});
|
||||||
if (dataArg.alias) {
|
if (SocketRole.checkPasswordForRole(dataArg, this.smartsocketRef)) {
|
||||||
// TODO: authenticate password
|
// TODO: authenticate password
|
||||||
this.alias = dataArg.alias;
|
this.alias = dataArg.alias;
|
||||||
this.authenticated = true;
|
this.authenticated = true;
|
||||||
|
this.role = SocketRole.getSocketRoleByName(this.smartsocketRef, dataArg.role);
|
||||||
this.socket.emit('authenticated');
|
this.socket.emit('authenticated');
|
||||||
logger.log('ok', `socket with >>alias ${this.alias} is authenticated!`);
|
logger.log('ok', `socket with >>alias ${this.alias} >>role ${this.role} is authenticated!`);
|
||||||
done.resolve(this);
|
done.resolve(this);
|
||||||
} else {
|
} else {
|
||||||
this.authenticated = false;
|
this.authenticated = false;
|
||||||
await this.disconnect();
|
await this.disconnect();
|
||||||
done.reject('a socket tried to connect, but could not authenticated.');
|
done.reject('not authenticated');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const requestAuthPayload: interfaces.IRequestAuthPayload = {
|
const requestAuthPayload: interfaces.IRequestAuthPayload = {
|
||||||
serverAlias: this.smartsocketRef.alias,
|
serverShortId: this.smartsocketRef.shortId,
|
||||||
};
|
};
|
||||||
this.socket.emit('requestAuth', requestAuthPayload);
|
this.socket.emit('requestAuth', requestAuthPayload);
|
||||||
return done.promise;
|
return done.promise;
|
||||||
@ -160,13 +123,14 @@ export class SocketConnection {
|
|||||||
if (this.authenticated) {
|
if (this.authenticated) {
|
||||||
this.socket.on('function', (dataArg: ISocketRequestDataObject<any>) => {
|
this.socket.on('function', (dataArg: ISocketRequestDataObject<any>) => {
|
||||||
// check if requested function is available to the socket's scope
|
// check if requested function is available to the socket's scope
|
||||||
// logger.log('info', 'function request received');
|
logger.log('info', 'function request received');
|
||||||
const referencedFunction: SocketFunction<any> =
|
const referencedFunction: SocketFunction<any> = this.role.allowedFunctions.find(
|
||||||
this.smartsocketRef.socketFunctions.findSync((socketFunctionArg) => {
|
(socketFunctionArg) => {
|
||||||
return socketFunctionArg.name === dataArg.funcCallData.funcName;
|
return socketFunctionArg.name === dataArg.funcCallData.funcName;
|
||||||
});
|
}
|
||||||
|
);
|
||||||
if (referencedFunction) {
|
if (referencedFunction) {
|
||||||
// logger.log('ok', 'function in access scope');
|
logger.log('ok', 'function in access scope');
|
||||||
const localSocketRequest = new SocketRequest(this.smartsocketRef, {
|
const localSocketRequest = new SocketRequest(this.smartsocketRef, {
|
||||||
side: 'responding',
|
side: 'responding',
|
||||||
originSocketConnection: this,
|
originSocketConnection: this,
|
||||||
@ -179,27 +143,14 @@ export class SocketConnection {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.socket.on('functionResponse', (dataArg: ISocketRequestDataObject<any>) => {
|
this.socket.on('functionResponse', (dataArg: ISocketRequestDataObject<any>) => {
|
||||||
// logger.log('info', `received response for request with id ${dataArg.shortId}`);
|
logger.log('info', `received response for request with id ${dataArg.shortId}`);
|
||||||
const targetSocketRequest = SocketRequest.getSocketRequestById(
|
const targetSocketRequest = SocketRequest.getSocketRequestById(
|
||||||
this.smartsocketRef,
|
this.smartsocketRef,
|
||||||
dataArg.shortId
|
dataArg.shortId
|
||||||
);
|
);
|
||||||
targetSocketRequest.handleResponse(dataArg);
|
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);
|
done.resolve(this);
|
||||||
} else {
|
} else {
|
||||||
const errMessage = 'socket needs to be authenticated first';
|
const errMessage = 'socket needs to be authenticated first';
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import * as plugins from './smartsocket.plugins.js';
|
import * as plugins from './smartsocket.plugins';
|
||||||
|
|
||||||
// import classes
|
// import classes
|
||||||
import { SocketConnection } from './smartsocket.classes.socketconnection.js';
|
import { SocketRole } from './smartsocket.classes.socketrole';
|
||||||
import { Smartsocket } from './smartsocket.classes.smartsocket.js';
|
import { SocketConnection } from './smartsocket.classes.socketconnection';
|
||||||
import { SmartsocketClient } from './smartsocket.classes.smartsocketclient.js';
|
import { Smartsocket } from './smartsocket.classes.smartsocket';
|
||||||
|
import { SmartsocketClient } from './smartsocket.classes.smartsocketclient';
|
||||||
|
|
||||||
// export interfaces
|
// export interfaces
|
||||||
|
|
||||||
@ -15,6 +16,7 @@ export interface ISocketFunctionConstructorOptions<
|
|||||||
> {
|
> {
|
||||||
funcName: T['method'];
|
funcName: T['method'];
|
||||||
funcDef: TFuncDef<T>;
|
funcDef: TFuncDef<T>;
|
||||||
|
allowedRoles: SocketRole[]; // all roles that are allowed to execute a SocketFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,7 +58,7 @@ export class SocketFunction<T extends plugins.typedrequestInterfaces.ITypedReque
|
|||||||
smartsocketRefArg: Smartsocket | SmartsocketClient,
|
smartsocketRefArg: Smartsocket | SmartsocketClient,
|
||||||
functionNameArg: string
|
functionNameArg: string
|
||||||
): SocketFunction<Q> {
|
): SocketFunction<Q> {
|
||||||
return smartsocketRefArg.socketFunctions.findSync((socketFunctionArg) => {
|
return smartsocketRefArg.socketFunctions.find((socketFunctionArg) => {
|
||||||
return socketFunctionArg.name === functionNameArg;
|
return socketFunctionArg.name === functionNameArg;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -64,6 +66,7 @@ export class SocketFunction<T extends plugins.typedrequestInterfaces.ITypedReque
|
|||||||
// INSTANCE
|
// INSTANCE
|
||||||
public name: string;
|
public name: string;
|
||||||
public funcDef: TFuncDef<T>;
|
public funcDef: TFuncDef<T>;
|
||||||
|
public roles: SocketRole[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the constructor for SocketFunction
|
* the constructor for SocketFunction
|
||||||
@ -71,6 +74,10 @@ export class SocketFunction<T extends plugins.typedrequestInterfaces.ITypedReque
|
|||||||
constructor(optionsArg: ISocketFunctionConstructorOptions<T>) {
|
constructor(optionsArg: ISocketFunctionConstructorOptions<T>) {
|
||||||
this.name = optionsArg.funcName;
|
this.name = optionsArg.funcName;
|
||||||
this.funcDef = optionsArg.funcDef;
|
this.funcDef = optionsArg.funcDef;
|
||||||
|
this.roles = optionsArg.allowedRoles;
|
||||||
|
for (const socketRoleArg of this.roles) {
|
||||||
|
this._notifyRole(socketRoleArg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -90,4 +97,11 @@ export class SocketFunction<T extends plugins.typedrequestInterfaces.ITypedReque
|
|||||||
throw new Error("SocketFunction.name does not match the data argument's .name!");
|
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.js';
|
import * as plugins from './smartsocket.plugins';
|
||||||
|
|
||||||
// import interfaces
|
// import interfaces
|
||||||
import {
|
import {
|
||||||
SocketFunction,
|
SocketFunction,
|
||||||
type ISocketFunctionCallDataRequest,
|
ISocketFunctionCallDataRequest,
|
||||||
type ISocketFunctionCallDataResponse,
|
ISocketFunctionCallDataResponse,
|
||||||
} from './smartsocket.classes.socketfunction.js';
|
} from './smartsocket.classes.socketfunction';
|
||||||
|
|
||||||
// import classes
|
// import classes
|
||||||
import { SocketConnection } from './smartsocket.classes.socketconnection.js';
|
import { SocketConnection } from './smartsocket.classes.socketconnection';
|
||||||
import { logger } from './smartsocket.logging.js';
|
import { logger } from './smartsocket.logging';
|
||||||
import { Smartsocket } from './smartsocket.classes.smartsocket.js';
|
import { Smartsocket } from './smartsocket.classes.smartsocket';
|
||||||
import { SmartsocketClient } from './smartsocket.classes.smartsocketclient.js';
|
import { SmartsocketClient } from './smartsocket.classes.smartsocketclient';
|
||||||
|
|
||||||
// export interfaces
|
// export interfaces
|
||||||
export type TSocketRequestStatus = 'new' | 'pending' | 'finished';
|
export type TSocketRequestStatus = 'new' | 'pending' | 'finished';
|
||||||
@ -45,7 +45,7 @@ export class SocketRequest<T extends plugins.typedrequestInterfaces.ITypedReques
|
|||||||
smartsocketRef: Smartsocket | SmartsocketClient,
|
smartsocketRef: Smartsocket | SmartsocketClient,
|
||||||
shortIdArg: string
|
shortIdArg: string
|
||||||
): SocketRequest<any> {
|
): SocketRequest<any> {
|
||||||
return smartsocketRef.socketRequests.findSync((socketRequestArg) => {
|
return smartsocketRef.socketRequests.find((socketRequestArg) => {
|
||||||
return socketRequestArg.shortid === shortIdArg;
|
return socketRequestArg.shortid === shortIdArg;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -90,7 +90,7 @@ export class SocketRequest<T extends plugins.typedrequestInterfaces.ITypedReques
|
|||||||
* handles the response that is received by the requesting side
|
* handles the response that is received by the requesting side
|
||||||
*/
|
*/
|
||||||
public async handleResponse(responseDataArg: ISocketRequestDataObject<T>) {
|
public async handleResponse(responseDataArg: ISocketRequestDataObject<T>) {
|
||||||
// logger.log('info', 'handling response!');
|
logger.log('info', 'handling response!');
|
||||||
this.done.resolve(responseDataArg.funcCallData);
|
this.done.resolve(responseDataArg.funcCallData);
|
||||||
this.smartsocketRef.socketRequests.remove(this);
|
this.smartsocketRef.socketRequests.remove(this);
|
||||||
}
|
}
|
||||||
@ -107,14 +107,15 @@ export class SocketRequest<T extends plugins.typedrequestInterfaces.ITypedReques
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!targetSocketFunction) {
|
if (!targetSocketFunction) {
|
||||||
logger.log('error', `There is no SocketFunction defined for ${this.funcCallData.funcName}`);
|
logger.log('warn', `There is no SocketFunction defined for ${this.funcCallData.funcName}`);
|
||||||
|
logger.log('warn', `So now response is being sent.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// logger.log('info', `invoking ${targetSocketFunction.name}`);
|
logger.log('info', `invoking ${targetSocketFunction.name}`);
|
||||||
targetSocketFunction
|
targetSocketFunction
|
||||||
.invoke(this.funcCallData, this.originSocketConnection)
|
.invoke(this.funcCallData, this.originSocketConnection)
|
||||||
.then((resultData) => {
|
.then((resultData) => {
|
||||||
// logger.log('info', 'got resultData. Sending it to requesting party.');
|
logger.log('info', 'got resultData. Sending it to requesting party.');
|
||||||
const responseData: ISocketRequestDataObject<T> = {
|
const responseData: ISocketRequestDataObject<T> = {
|
||||||
funcCallData: resultData,
|
funcCallData: resultData,
|
||||||
shortId: this.shortid,
|
shortId: this.shortid,
|
||||||
|
57
ts/smartsocket.classes.socketrole.ts
Normal file
57
ts/smartsocket.classes.socketrole.ts
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
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 checkPasswordForRole(
|
||||||
|
dataArg: ISocketConnectionAuthenticationObject,
|
||||||
|
referenceSmartsocket: Smartsocket | SmartsocketClient
|
||||||
|
): boolean {
|
||||||
|
const targetPasswordHash = SocketRole.getSocketRoleByName(referenceSmartsocket, dataArg.role)
|
||||||
|
.passwordHash;
|
||||||
|
const computedCompareHash = plugins.smarthash.sha256FromStringSync(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,10 @@
|
|||||||
import * as plugins from './smartsocket.plugins.js';
|
import * as plugins from './smartsocket.plugins';
|
||||||
import * as pluginsTyped from './smartsocket.pluginstyped.js';
|
|
||||||
|
|
||||||
// used in case no other server is supplied
|
// used in case no other server is supplied
|
||||||
import { Smartsocket } from './smartsocket.classes.smartsocket.js';
|
import * as http from 'http';
|
||||||
import { logger } from './smartsocket.logging.js';
|
import * as https from 'https';
|
||||||
|
import { Smartsocket } from './smartsocket.classes.smartsocket';
|
||||||
|
import { logger } from './smartsocket.logging';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* class socketServer
|
* class socketServer
|
||||||
@ -11,13 +12,10 @@ import { logger } from './smartsocket.logging.js';
|
|||||||
*/
|
*/
|
||||||
export class SocketServer {
|
export class SocketServer {
|
||||||
private smartsocket: Smartsocket;
|
private smartsocket: Smartsocket;
|
||||||
private httpServerDeferred: plugins.smartpromise.Deferred<any>;
|
private httpServer: http.Server | https.Server;
|
||||||
private httpServer: pluginsTyped.http.Server | pluginsTyped.https.Server;
|
// wether httpServer is standalone
|
||||||
|
|
||||||
/**
|
|
||||||
* wether httpServer is standalone
|
|
||||||
*/
|
|
||||||
private standaloneServer = false;
|
private standaloneServer = false;
|
||||||
|
private expressServer: any;
|
||||||
|
|
||||||
constructor(smartSocketInstance: Smartsocket) {
|
constructor(smartSocketInstance: Smartsocket) {
|
||||||
this.smartsocket = smartSocketInstance;
|
this.smartsocket = smartSocketInstance;
|
||||||
@ -29,26 +27,20 @@ export class SocketServer {
|
|||||||
*/
|
*/
|
||||||
public async setExternalServer(
|
public async setExternalServer(
|
||||||
serverType: 'smartexpress',
|
serverType: 'smartexpress',
|
||||||
serverArg: pluginsTyped.typedserver.servertools.Server
|
serverArg: plugins.smartexpress.Server
|
||||||
) {
|
) {
|
||||||
this.httpServerDeferred = plugins.smartpromise.defer();
|
|
||||||
await serverArg.startedPromise;
|
await serverArg.startedPromise;
|
||||||
this.httpServer = serverArg.httpServer;
|
this.httpServer = serverArg.httpServer;
|
||||||
this.httpServerDeferred.resolve();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gets the server for socket.io
|
* gets the server for socket.io
|
||||||
*/
|
*/
|
||||||
public async getServerForSocketIo() {
|
public getServerForSocketIo() {
|
||||||
if (this.httpServerDeferred) {
|
|
||||||
await this.httpServerDeferred.promise;
|
|
||||||
}
|
|
||||||
if (this.httpServer) {
|
if (this.httpServer) {
|
||||||
return this.httpServer;
|
return this.httpServer;
|
||||||
} else {
|
} else {
|
||||||
const httpModule = await this.smartsocket.smartenv.getSafeNodeModule('http');
|
this.httpServer = new http.Server();
|
||||||
this.httpServer = new httpModule.Server();
|
|
||||||
this.standaloneServer = true;
|
this.standaloneServer = true;
|
||||||
return this.httpServer;
|
return this.httpServer;
|
||||||
}
|
}
|
||||||
@ -86,9 +78,5 @@ export class SocketServer {
|
|||||||
/**
|
/**
|
||||||
* closes the server
|
* closes the server
|
||||||
*/
|
*/
|
||||||
public async stop() {
|
public async stop() {}
|
||||||
if (this.httpServer) {
|
|
||||||
this.httpServer.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
import * as plugins from './smartsocket.plugins.js';
|
import * as plugins from './smartsocket.plugins';
|
||||||
|
|
||||||
export const logger = new plugins.smartlog.ConsoleLog();
|
export const logger = new plugins.smartlog.ConsoleLog();
|
||||||
|
@ -1,29 +1,33 @@
|
|||||||
// apiglobal scope
|
// apiglobal scope
|
||||||
import * as typedrequestInterfaces from '@api.global/typedrequest-interfaces';
|
import * as typedrequestInterfaces from '@apiglobal/typedrequest-interfaces';
|
||||||
|
|
||||||
export { typedrequestInterfaces };
|
export { typedrequestInterfaces };
|
||||||
|
|
||||||
// pushrocks scope
|
// pushrocks scope
|
||||||
import * as isohash from '@push.rocks/isohash';
|
import * as lik from '@pushrocks/lik';
|
||||||
import * as isounique from '@push.rocks/isounique';
|
import * as smartlog from '@pushrocks/smartlog';
|
||||||
import * as lik from '@push.rocks/lik';
|
import * as smarthash from '@pushrocks/smarthash';
|
||||||
import * as smartenv from '@push.rocks/smartenv';
|
import * as smartdelay from '@pushrocks/smartdelay';
|
||||||
import * as smartjson from '@push.rocks/smartjson';
|
import * as smartexpress from '@pushrocks/smartexpress';
|
||||||
import * as smartlog from '@push.rocks/smartlog';
|
import * as smartpromise from '@pushrocks/smartpromise';
|
||||||
import * as smartdelay from '@push.rocks/smartdelay';
|
import * as smarttime from '@pushrocks/smarttime';
|
||||||
import * as smartpromise from '@push.rocks/smartpromise';
|
import * as smartunique from '@pushrocks/smartunique';
|
||||||
import * as smarttime from '@push.rocks/smarttime';
|
import * as smartrx from '@pushrocks/smartrx';
|
||||||
import * as smartrx from '@push.rocks/smartrx';
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
isohash,
|
|
||||||
isounique,
|
|
||||||
lik,
|
lik,
|
||||||
smartenv,
|
|
||||||
smartjson,
|
|
||||||
smartlog,
|
smartlog,
|
||||||
|
smarthash,
|
||||||
smartdelay,
|
smartdelay,
|
||||||
|
smartexpress,
|
||||||
smartpromise,
|
smartpromise,
|
||||||
smarttime,
|
smarttime,
|
||||||
|
smartunique,
|
||||||
smartrx,
|
smartrx,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// third party scope
|
||||||
|
import socketIo from 'socket.io';
|
||||||
|
import socketIoClient from 'socket.io-client';
|
||||||
|
|
||||||
|
export { socketIo, socketIoClient };
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
// node native
|
|
||||||
import type * as http from 'http';
|
|
||||||
import type * as https from 'https';
|
|
||||||
|
|
||||||
export type { http, https };
|
|
||||||
|
|
||||||
// pushrocks scope
|
|
||||||
import type * as typedserver from '@api.global/typedserver';
|
|
||||||
|
|
||||||
export type { typedserver };
|
|
||||||
|
|
||||||
// third party scope
|
|
||||||
import type { Socket as ServerSocket, Server as ServerServer } from 'socket.io';
|
|
||||||
import type { Socket as ClientSocket, connect as ClientIo } from 'socket.io-client';
|
|
||||||
|
|
||||||
export namespace socketIo {
|
|
||||||
export type Socket = ServerSocket;
|
|
||||||
export type Server = ServerServer;
|
|
||||||
}
|
|
||||||
export namespace socketIoClient {
|
|
||||||
export type Socket = ClientSocket;
|
|
||||||
export type connect = typeof ClientIo;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"experimentalDecorators": true,
|
|
||||||
"useDefineForClassFields": false,
|
|
||||||
"target": "ES2022",
|
|
||||||
"module": "NodeNext",
|
|
||||||
"moduleResolution": "NodeNext",
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"verbatimModuleSyntax": true
|
|
||||||
},
|
|
||||||
"exclude": [
|
|
||||||
"dist_*/**/*.d.ts"
|
|
||||||
]
|
|
||||||
}
|
|
17
tslint.json
Normal file
17
tslint.json
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user