@futdevpro/nts-dynamo 1.15.151 → 1.15.153
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.c8rc.json +26 -26
- package/.copilot/patterns.json +7 -7
- package/.cursor/rules/__assistant_guide.mdc +30 -30
- package/.cursor/rules/__main.mdc +64 -64
- package/.cursor/rules/_ag_backend-structure.mdc +85 -85
- package/.cursor/rules/_ag_backend.mdc +16 -16
- package/.cursor/rules/_ag_debug.mdc +7 -7
- package/.cursor/rules/_ag_documentation_writing_rules.mdc +372 -372
- package/.cursor/rules/_ag_file-refactoring.mdc +113 -113
- package/.cursor/rules/_ag_fixes_rules.mdc +5 -5
- package/.cursor/rules/_ag_frontend-structure.mdc +86 -86
- package/.cursor/rules/_ag_frontend.mdc +39 -39
- package/.cursor/rules/_ag_import-rules.mdc +44 -44
- package/.cursor/rules/_ag_naming.mdc +115 -115
- package/.cursor/rules/_ag_running_commands.mdc +4 -4
- package/.cursor/rules/_ag_server-controller.mdc +5 -5
- package/.cursor/rules/_ag_should-be.mdc +6 -6
- package/.cursor/rules/_ag_swearing.mdc +47 -47
- package/.cursor/rules/ai_development_guide.md +60 -60
- package/.cursor/rules/ai_directives.md +114 -114
- package/.cursor/rules/cursor-rules.md +160 -160
- package/.cursor/rules/default-command.mdc +464 -464
- package/.cursor/rules/error_code_pattern.md +39 -39
- package/.cursor/rules/saved rule mcp server use.md +15 -15
- package/.dynamo/pipeline.cicd.config.json +190 -190
- package/.dynamo/version-bump.config.json +5 -5
- package/.github/workflows/main.yml +438 -438
- package/.husky/pre-commit +3 -3
- package/.vscode/settings.json +10 -10
- package/HOWTO.md +15 -15
- package/LICENSE +21 -21
- package/README.md +780 -754
- package/__documentations/2026-04-28-logs-module.md +49 -49
- package/__documentations/2026-05-17-oai-compatible-providers.md +229 -229
- package/__documentations/2026-05-17-static-client-serving-howto.md +144 -144
- package/__documentations/2026-06-01-fr041-cors-middleware.md +96 -96
- package/__documentations/2026-06-01-fr047-p2p3-function-calling.md +81 -81
- package/__documentations/2026-06-15-fr193-memory-guard.md +73 -73
- package/__documentations/2026-08-08-fr292-app-version-header.md +38 -38
- package/__documentations/2026-08-14-field-encryption-mongoose-document-spread.md +124 -124
- package/__documentations/2026-08-18-artifact-compiler.md +46 -46
- package/__documentations/2026-08-18-mongo-transaction-control-service.md +82 -82
- package/__documentations/2026-08-18-standalone-account-security-and-privacy-bedrock.md +132 -132
- package/__documentations/2026-08-21-distributed-rate-limit-bfr-ctm-010.md +59 -59
- package/__documentations/2026-08-22-npm-token-state-classifier.md +92 -92
- package/__documentations/nts-integration-tests-2026-03-17.md +26 -26
- package/__documentations/plans/BEDROCK-HYPERPLAN.md +95 -95
- package/_specifications/BACKLOG.md +92 -92
- package/_specifications/TODO.md +15 -15
- package/_specifications/agent.md +138 -138
- package/build/_modules/server/index.d.ts +4 -0
- package/build/_modules/server/index.d.ts.map +1 -1
- package/build/_modules/server/index.js +4 -0
- package/build/_modules/server/index.js.map +1 -1
- package/build/_modules/server/server-status/db-readiness-probe-code.type-enum.d.ts +14 -0
- package/build/_modules/server/server-status/db-readiness-probe-code.type-enum.d.ts.map +1 -0
- package/build/_modules/server/server-status/db-readiness-probe-code.type-enum.js +18 -0
- package/build/_modules/server/server-status/db-readiness-probe-code.type-enum.js.map +1 -0
- package/build/_modules/server/server-status/db-readiness-probe-stage.type-enum.d.ts +8 -0
- package/build/_modules/server/server-status/db-readiness-probe-stage.type-enum.d.ts.map +1 -0
- package/build/_modules/server/server-status/db-readiness-probe-stage.type-enum.js +12 -0
- package/build/_modules/server/server-status/db-readiness-probe-stage.type-enum.js.map +1 -0
- package/build/_modules/server/server-status/db-readiness-probe.control-service.d.ts +14 -0
- package/build/_modules/server/server-status/db-readiness-probe.control-service.d.ts.map +1 -0
- package/build/_modules/server/server-status/db-readiness-probe.control-service.js +126 -0
- package/build/_modules/server/server-status/db-readiness-probe.control-service.js.map +1 -0
- package/build/_modules/server/server-status/db-readiness-probe.interface.d.ts +18 -0
- package/build/_modules/server/server-status/db-readiness-probe.interface.d.ts.map +1 -0
- package/build/_modules/server/server-status/db-readiness-probe.interface.js +3 -0
- package/build/_modules/server/server-status/db-readiness-probe.interface.js.map +1 -0
- package/eslint.config.js +3 -3
- package/nodemon.json +24 -24
- package/package.json +1 -1
- package/pnpm-workspace.yaml +6 -6
- package/scripts/_seed-out/aim-seed.fixtures.ts +161 -161
- package/scripts/_seed-out/llm-expand-raw.json +59 -59
- package/scripts/_seed-out/seed-raw.json +152 -152
- package/scripts/ai-fixture-seed.js +126 -126
- package/scripts/run-coverage-tests.js +28 -28
- package/spec/support/helpers/spec-reporter-loader.js +359 -359
- package/spec/support/helpers/ts-node-helper.js +93 -93
- package/spec/support/jasmine.coverage.json +24 -24
- package/spec/support/jasmine.json +24 -24
- package/src/_collections/app-version-header.util.spec.ts +108 -108
- package/src/_collections/app-version-header.util.ts +74 -74
- package/src/_collections/archive-service-registry.const.ts +21 -21
- package/src/_collections/archive.util.spec.ts +57 -57
- package/src/_collections/archive.util.ts +18 -18
- package/src/_collections/atlas-default-db-options.const.ts +9 -9
- package/src/_collections/client-safe-error.util.spec.ts +151 -151
- package/src/_collections/client-safe-error.util.ts +107 -107
- package/src/_collections/default-fallback-cache-max-age.const.spec.ts +11 -11
- package/src/_collections/default-fallback-cache-max-age.const.ts +2 -2
- package/src/_collections/default-not-found-page.const.spec.ts +19 -19
- package/src/_collections/default-not-found-page.const.ts +22 -22
- package/src/_collections/default-socket-path.const.spec.ts +12 -12
- package/src/_collections/default-socket-path.const.ts +2 -2
- package/src/_collections/field-encryption.util.spec.ts +195 -195
- package/src/_collections/field-encryption.util.ts +222 -222
- package/src/_collections/get-environment-settings.util.spec.ts +210 -210
- package/src/_collections/get-environment-settings.util.ts +48 -48
- package/src/_collections/global-settings.const.ts +126 -126
- package/src/_collections/load-shed.util.spec.ts +62 -62
- package/src/_collections/load-shed.util.ts +51 -51
- package/src/_collections/mongo-reconnect-guard.util.spec.ts +52 -52
- package/src/_collections/mongo-reconnect-guard.util.ts +172 -172
- package/src/_collections/npm-token-check.util.spec.ts +218 -218
- package/src/_collections/npm-token-check.util.ts +327 -327
- package/src/_collections/sample.env +21 -21
- package/src/_collections/security-headers.util.spec.ts +98 -98
- package/src/_collections/security-headers.util.ts +96 -96
- package/src/_collections/signed-url.util.spec.ts +198 -198
- package/src/_collections/signed-url.util.ts +170 -170
- package/src/_collections/star.controller.spec.ts +224 -224
- package/src/_collections/star.controller.ts +129 -129
- package/src/_collections/static-cache-control.util.spec.ts +47 -47
- package/src/_collections/static-cache-control.util.ts +25 -25
- package/src/_enums/data-model-type.enum.ts +14 -14
- package/src/_enums/data-service-function.enum.ts +24 -24
- package/src/_enums/predefined-data-types.enum.ts +16 -16
- package/src/_enums/route-security.enum.ts +12 -12
- package/src/_models/control-models/api-call-params.control-model.spec.ts +152 -152
- package/src/_models/control-models/api-call-params.control-model.ts +142 -142
- package/src/_models/control-models/app-ext-system-controls.control-model.spec.ts +52 -52
- package/src/_models/control-models/app-ext-system-controls.control-model.ts +9 -9
- package/src/_models/control-models/app-params.control-model.spec.ts +225 -225
- package/src/_models/control-models/app-params.control-model.ts +136 -136
- package/src/_models/control-models/app-system-controls.control-model.spec.ts +31 -31
- package/src/_models/control-models/app-system-controls.control-model.ts +9 -9
- package/src/_models/control-models/endpoint-params.control-model.spec.ts +669 -669
- package/src/_models/control-models/endpoint-params.control-model.ts +664 -664
- package/src/_models/control-models/http-settings.control-model.spec.ts +77 -77
- package/src/_models/control-models/http-settings.control-model.ts +37 -37
- package/src/_models/control-models/system-control.control-model.spec.ts +27 -27
- package/src/_models/control-models/system-control.control-model.ts +12 -12
- package/src/_models/data-models/schema-migration.data-model.ts +50 -50
- package/src/_models/interfaces/app-version-header-settings.interface.ts +17 -17
- package/src/_models/interfaces/certification-settings.interface.ts +7 -7
- package/src/_models/interfaces/compare-data-options.interface.ts +27 -27
- package/src/_models/interfaces/compare-data-result.interface.ts +12 -12
- package/src/_models/interfaces/cors-settings.interface.spec.ts +52 -52
- package/src/_models/interfaces/cors-settings.interface.ts +56 -56
- package/src/_models/interfaces/db-query-options.interface.ts +33 -33
- package/src/_models/interfaces/environment-settings.interface.ts +59 -59
- package/src/_models/interfaces/global-log-settings.interface.ts +171 -171
- package/src/_models/interfaces/global-service-settings.interface.ts +47 -47
- package/src/_models/interfaces/global-settings.interface.ts +294 -294
- package/src/_models/interfaces/migration-entry.interface.ts +19 -19
- package/src/_models/interfaces/mongo-transaction-settings.interface.ts +9 -9
- package/src/_models/interfaces/routing-module-settings.interface.ts +21 -21
- package/src/_models/interfaces/security-headers-settings.interface.ts +50 -50
- package/src/_models/interfaces/signed-url-verify-result.interface.ts +13 -13
- package/src/_models/interfaces/static-client-settings.interface.spec.ts +29 -29
- package/src/_models/interfaces/static-client-settings.interface.ts +36 -36
- package/src/_models/types/db-update.type.ts +100 -100
- package/src/_modules/account-security/_enums/account-challenge-purpose.type-enum.ts +5 -5
- package/src/_modules/account-security/_enums/account-refresh-token-state.type-enum.ts +6 -6
- package/src/_modules/account-security/_enums/account-session-state.type-enum.ts +6 -6
- package/src/_modules/account-security/_models/account-challenge-adapter.interface.ts +17 -17
- package/src/_modules/account-security/_models/account-challenge-issued.interface.ts +6 -6
- package/src/_modules/account-security/_models/account-challenge-record.interface.ts +13 -13
- package/src/_modules/account-security/_models/account-challenge-result.interface.ts +8 -8
- package/src/_modules/account-security/_models/account-challenge-settings.interface.ts +9 -9
- package/src/_modules/account-security/_models/account-password-policy.interface.ts +11 -11
- package/src/_modules/account-security/_models/account-password-verification.interface.ts +5 -5
- package/src/_modules/account-security/_models/account-refresh-token-record.interface.ts +13 -13
- package/src/_modules/account-security/_models/account-session-adapter.interface.ts +19 -19
- package/src/_modules/account-security/_models/account-session-claims.interface.ts +7 -7
- package/src/_modules/account-security/_models/account-session-context.interface.ts +6 -6
- package/src/_modules/account-security/_models/account-session-create.interface.ts +8 -8
- package/src/_modules/account-security/_models/account-session-record.interface.ts +21 -21
- package/src/_modules/account-security/_models/account-session-rotate.interface.ts +11 -11
- package/src/_modules/account-security/_models/account-session-settings.interface.ts +11 -11
- package/src/_modules/account-security/_models/account-session-token-pair.interface.ts +8 -8
- package/src/_modules/account-security/_models/account-session-view.interface.ts +13 -13
- package/src/_modules/account-security/account-challenge.control-service.spec.ts +195 -195
- package/src/_modules/account-security/account-challenge.control-service.ts +164 -164
- package/src/_modules/account-security/account-password.control-service.spec.ts +96 -96
- package/src/_modules/account-security/account-password.control-service.ts +288 -288
- package/src/_modules/account-security/account-session.control-service.spec.ts +294 -294
- package/src/_modules/account-security/account-session.control-service.ts +376 -376
- package/src/_modules/account-security/index.ts +31 -31
- package/src/_modules/admin-auth/_models/admin-api-key-config.interface.ts +33 -33
- package/src/_modules/admin-auth/admin-api-key.auth-service.spec.ts +200 -200
- package/src/_modules/admin-auth/admin-api-key.auth-service.ts +220 -220
- package/src/_modules/admin-auth/index.ts +2 -2
- package/src/_modules/ai/_collections/ai-model-config-validator.util.spec.ts +150 -150
- package/src/_modules/ai/_collections/ai-model-config-validator.util.ts +131 -131
- package/src/_modules/ai/_collections/ai-provider-error.util.ts +144 -144
- package/src/_modules/ai/_models/ai-input-interfaces.ts +117 -117
- package/src/_modules/ai/_models/ai-test-generation-result.interface.ts +16 -16
- package/src/_modules/ai/_models/interfaces/dynts-ai-cost-event-callback.interface.ts +14 -14
- package/src/_modules/ai/_models/interfaces/dynts-ai-cost-event.interface.ts +56 -56
- package/src/_modules/ai/_models/interfaces/dynts-ai-provider-error.interface.ts +16 -16
- package/src/_modules/ai/_modules/ai-mock/_collections/aim-default-collection.util.spec.ts +72 -72
- package/src/_modules/ai/_modules/ai-mock/_collections/aim-default-collection.util.ts +71 -71
- package/src/_modules/ai/_modules/ai-mock/_collections/aim-fixture-match.util.spec.ts +57 -57
- package/src/_modules/ai/_modules/ai-mock/_collections/aim-fixture-match.util.ts +60 -60
- package/src/_modules/ai/_modules/ai-mock/_collections/aim-fixture-serializer.util.spec.ts +56 -56
- package/src/_modules/ai/_modules/ai-mock/_collections/aim-fixture-serializer.util.ts +117 -117
- package/src/_modules/ai/_modules/ai-mock/_enums/aim-modality.enum.ts +28 -28
- package/src/_modules/ai/_modules/ai-mock/_models/interfaces/aim-call-input.interface.ts +14 -14
- package/src/_modules/ai/_modules/ai-mock/_models/interfaces/aim-error.interface.ts +11 -11
- package/src/_modules/ai/_modules/ai-mock/_models/interfaces/aim-fixture.interface.ts +30 -30
- package/src/_modules/ai/_modules/ai-mock/_models/interfaces/aim-request.interface.ts +19 -19
- package/src/_modules/ai/_modules/ai-mock/_models/interfaces/aim-service-collection.interface.ts +20 -20
- package/src/_modules/ai/_modules/ai-mock/_services/ai-embedding-mock.service.spec.ts +115 -115
- package/src/_modules/ai/_modules/ai-mock/_services/ai-embedding-mock.service.ts +233 -233
- package/src/_modules/ai/_modules/ai-mock/_services/aim-fixture-harness.service.spec.ts +134 -134
- package/src/_modules/ai/_modules/ai-mock/_services/aim-fixture-harness.service.ts +127 -127
- package/src/_modules/ai/_modules/ai-mock/_services/aim-fixture-pipeline.spec.ts +105 -105
- package/src/_modules/ai/_modules/ai-mock/_services/aim-fixture-store.service.spec.ts +50 -50
- package/src/_modules/ai/_modules/ai-mock/_services/aim-fixture-store.service.ts +65 -65
- package/src/_modules/ai/_modules/ai-mock/_services/aim-integration-proof.spec.ts +92 -92
- package/src/_modules/ai/_modules/ai-mock/_services/aim-mock.service.spec.ts +112 -112
- package/src/_modules/ai/_modules/ai-mock/_services/aim-mock.service.ts +155 -155
- package/src/_modules/ai/_modules/ai-mock/fixtures/aim-text.fixtures.ts +649 -649
- package/src/_modules/ai/_modules/ai-mock/index.ts +47 -47
- package/src/_modules/ai/_modules/anthropic/_services/aai-user-key.control-service.ts +138 -138
- package/src/_modules/ai/_modules/anthropic/index.ts +5 -5
- package/src/_modules/ai/_modules/document-ai/_collections/dai-chunking.util.spec.ts +242 -242
- package/src/_modules/ai/_modules/document-ai/_collections/dai-chunking.util.ts +639 -639
- package/src/_modules/ai/_modules/document-ai/_collections/dai-code-chunking.util.spec.ts +295 -295
- package/src/_modules/ai/_modules/document-ai/_collections/dai-code-chunking.util.ts +552 -552
- package/src/_modules/ai/_modules/document-ai/_collections/dai-document.util.spec.ts +209 -209
- package/src/_modules/ai/_modules/document-ai/_collections/dai-document.util.ts +85 -85
- package/src/_modules/ai/_modules/document-ai/_enums/dai-compare-result-type.enum.ts +7 -7
- package/src/_modules/ai/_modules/document-ai/_models/data-models/dai-doc-chunk.data-model.ts +146 -146
- package/src/_modules/ai/_modules/document-ai/_models/data-models/dai-doc-page.data-model.ts +162 -162
- package/src/_modules/ai/_modules/document-ai/_models/data-models/dai-document.data-model.ts +99 -99
- package/src/_modules/ai/_modules/document-ai/_models/interfaces/dai-code-chunk.interface.ts +68 -68
- package/src/_modules/ai/_modules/document-ai/_models/interfaces/dai-doc-chunk-compare-result.interface.ts +18 -18
- package/src/_modules/ai/_modules/document-ai/_models/interfaces/dai-doc-page-compare-result.interface.ts +19 -19
- package/src/_modules/ai/_modules/document-ai/_models/interfaces/dai-document-compare-result.interface.ts +25 -25
- package/src/_modules/ai/_modules/document-ai/index.ts +30 -30
- package/src/_modules/ai/_modules/fdp-ai/_services/fdpai-user-key.control-service.ts +189 -189
- package/src/_modules/ai/_modules/fdp-ai/index.ts +5 -5
- package/src/_modules/ai/_modules/open-ai/_collections/oai-global-settings.const.ts +9 -9
- package/src/_modules/ai/_modules/open-ai/_collections/oai-llm-predefined-requests-hu.conts.ts +82 -82
- package/src/_modules/ai/_modules/open-ai/_collections/oai-llm-predefined-requests.conts.ts +75 -75
- package/src/_modules/ai/_modules/open-ai/_enums/oai-gpt-message-role.enum.ts +45 -45
- package/src/_modules/ai/_modules/open-ai/_models/interfaces/oai-global-settings.interface.ts +7 -7
- package/src/_modules/ai/_modules/open-ai/_models/interfaces/oai-gpt-message.interface.ts +7 -7
- package/src/_modules/ai/_modules/open-ai/_models/interfaces/oai-llm-predefined-requests.interface.ts +57 -57
- package/src/_modules/ai/_modules/open-ai/_services/data-services/oai-doc-chunk-data.service.ts +292 -292
- package/src/_modules/ai/_modules/open-ai/_services/data-services/oai-doc-page.data-service.ts +572 -572
- package/src/_modules/ai/_modules/open-ai/_services/data-services/oai-document.data-service.spec.ts +342 -342
- package/src/_modules/ai/_modules/open-ai/_services/data-services/oai-document.data-service.ts +435 -435
- package/src/_modules/ai/_modules/open-ai/_services/data-services/oai-vector-data.service.spec.ts +550 -550
- package/src/_modules/ai/_modules/open-ai/_services/data-services/oai-vector-data.service.ts +630 -630
- package/src/_modules/ai/_modules/open-ai/_services/oai-embedding.control-service.spec.ts +332 -332
- package/src/_modules/ai/_modules/open-ai/_services/oai-embedding.control-service.ts +132 -132
- package/src/_modules/ai/_modules/open-ai/_services/oai-llm-chat.service-base.spec.ts +462 -462
- package/src/_modules/ai/_modules/open-ai/_services/oai-llm-chat.service-base.ts +634 -634
- package/src/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.spec.ts +489 -489
- package/src/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.tools.spec.ts +173 -173
- package/src/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.ts +1085 -1085
- package/src/_modules/ai/_modules/open-ai/_services/oai-user-key.control-service.ts +157 -157
- package/src/_modules/ai/_modules/open-ai/index.ts +74 -74
- package/src/_modules/ai/_services/ai-embedding-provider.registry.spec.ts +110 -110
- package/src/_modules/ai/_services/ai-embedding-provider.registry.ts +114 -114
- package/src/_modules/ai/_services/ai-embedding.service-base.spec.ts +98 -98
- package/src/_modules/ai/_services/ai-embedding.service-base.ts +48 -48
- package/src/_modules/ai/_services/ai-llm-chat.service-base.spec.ts +229 -229
- package/src/_modules/ai/_services/ai-llm-chat.service-base.ts +68 -68
- package/src/_modules/ai/_services/ai-llm.service-base.reconciler.spec.ts +133 -133
- package/src/_modules/ai/_services/ai-llm.service-base.spec.ts +250 -250
- package/src/_modules/ai/_services/ai-llm.service-base.ts +599 -599
- package/src/_modules/ai/_services/ai-provider.service-base.spec.ts +158 -158
- package/src/_modules/ai/_services/ai-provider.service-base.ts +67 -67
- package/src/_modules/ai/_services/ai-user-key.service-base.ts +59 -59
- package/src/_modules/ai/_services/lmstudio-embedding.control-service.spec.ts +197 -197
- package/src/_modules/ai/_services/lmstudio-embedding.control-service.ts +399 -399
- package/src/_modules/ai/index.ts +33 -33
- package/src/_modules/artifact-compiler/_enums/artifact-compile-outcome.type-enum.ts +5 -5
- package/src/_modules/artifact-compiler/_enums/artifact-compile-stage.type-enum.ts +8 -8
- package/src/_modules/artifact-compiler/_enums/artifact-retry-class.type-enum.ts +6 -6
- package/src/_modules/artifact-compiler/_models/artifact-compile.interface.ts +35 -35
- package/src/_modules/artifact-compiler/artifact-compiler.control-service.spec.ts +151 -151
- package/src/_modules/artifact-compiler/artifact-compiler.control-service.ts +356 -356
- package/src/_modules/artifact-compiler/index.ts +9 -9
- package/src/_modules/assistant/_collections/ass-global-settings.const.ts +13 -13
- package/src/_modules/assistant/_collections/ass.util.spec.ts +176 -176
- package/src/_modules/assistant/_collections/ass.util.ts +50 -50
- package/src/_modules/assistant/_models/ass-global-settings.interface.ts +15 -15
- package/src/_modules/assistant/_services/ass-io.control-service.spec.ts +140 -140
- package/src/_modules/assistant/_services/ass-io.control-service.ts +74 -74
- package/src/_modules/assistant/_services/ass-main.control-service.spec.ts +192 -192
- package/src/_modules/assistant/_services/ass-main.control-service.ts +107 -107
- package/src/_modules/assistant/index.ts +19 -19
- package/src/_modules/bot/_collections/bot-default-commands.const.ts +12 -12
- package/src/_modules/bot/_collections/bot-global-settings.const.ts +39 -39
- package/src/_modules/bot/_models/bot-channel-wrapper.interface.ts +62 -62
- package/src/_modules/bot/_models/bot-command.interface.ts +8 -8
- package/src/_modules/bot/_models/bot-global-settings.interface.ts +96 -96
- package/src/_modules/bot/_models/bot-last-mention-date.interface.ts +6 -6
- package/src/_modules/bot/_models/bot-last-message-date.interface.ts +5 -5
- package/src/_modules/bot/_models/bot-message-wrapper.interface.ts +90 -90
- package/src/_modules/bot/_models/bot-user-wrapper.interface.ts +41 -41
- package/src/_modules/bot/_modules/discord-bot/_models/dib-platform.types.ts +9 -9
- package/src/_modules/bot/_modules/discord-bot/_services/dib-messaging-provider.control-service.spec.ts +431 -431
- package/src/_modules/bot/_modules/discord-bot/_services/dib-messaging-provider.control-service.ts +641 -641
- package/src/_modules/bot/_modules/discord-bot/index.ts +12 -12
- package/src/_modules/bot/_modules/dynamo-bot/_collections/dyb-operations.util.spec.ts +160 -160
- package/src/_modules/bot/_modules/dynamo-bot/_collections/dyb-operations.util.ts +55 -55
- package/src/_modules/bot/_modules/dynamo-bot/_models/dyb-platform.types.ts +15 -15
- package/src/_modules/bot/_modules/dynamo-bot/_services/dyb-messaging-provider.control-service.spec.ts +374 -374
- package/src/_modules/bot/_modules/dynamo-bot/_services/dyb-messaging-provider.control-service.ts +447 -447
- package/src/_modules/bot/_modules/dynamo-bot/index.ts +15 -15
- package/src/_modules/bot/_modules/slack-bot/_models/slb-platform.types.ts +9 -9
- package/src/_modules/bot/_modules/slack-bot/_services/slb-messaging-provider.control-service.spec.ts +344 -344
- package/src/_modules/bot/_modules/slack-bot/_services/slb-messaging-provider.control-service.ts +197 -197
- package/src/_modules/bot/_modules/slack-bot/index.ts +12 -12
- package/src/_modules/bot/_modules/teams-bot/_models/teb-platform.types.ts +9 -9
- package/src/_modules/bot/_modules/teams-bot/_services/teb-messaging-provider.control-service.spec.ts +345 -345
- package/src/_modules/bot/_modules/teams-bot/_services/teb-messaging-provider.control-service.ts +197 -197
- package/src/_modules/bot/_modules/teams-bot/index.ts +11 -11
- package/src/_modules/bot/_services/bot-commands.control-service.spec.ts +116 -116
- package/src/_modules/bot/_services/bot-commands.control-service.ts +158 -158
- package/src/_modules/bot/_services/bot-io.control-service.spec.ts +285 -285
- package/src/_modules/bot/_services/bot-io.control-service.ts +329 -329
- package/src/_modules/bot/_services/bot-main.control-service.spec.ts +208 -208
- package/src/_modules/bot/_services/bot-main.control-service.ts +489 -489
- package/src/_modules/bot/_services/bot-messaging-provider.service-base.spec.ts +349 -349
- package/src/_modules/bot/_services/bot-messaging-provider.service-base.ts +158 -158
- package/src/_modules/bot/_services/bot-routines.control-service.spec.ts +111 -111
- package/src/_modules/bot/_services/bot-routines.control-service.ts +78 -78
- package/src/_modules/bot/index.ts +37 -37
- package/src/_modules/custom-data/custom-data.controller.spec.ts +49 -49
- package/src/_modules/custom-data/custom-data.controller.ts +67 -67
- package/src/_modules/custom-data/custom-data.data-service.spec.ts +54 -54
- package/src/_modules/custom-data/custom-data.data-service.ts +21 -21
- package/src/_modules/custom-data/get-custom-data-routing-module.util.spec.ts +28 -28
- package/src/_modules/custom-data/get-custom-data-routing-module.util.ts +24 -24
- package/src/_modules/custom-data/index.ts +9 -9
- package/src/_modules/data-readers/_collections/dynts-sqlite-reader.util.spec.ts +176 -176
- package/src/_modules/data-readers/_collections/dynts-sqlite-reader.util.ts +203 -203
- package/src/_modules/data-readers/_models/interfaces/dynts-sqlite-reader.interface.ts +33 -33
- package/src/_modules/data-readers/index.ts +11 -11
- package/src/_modules/defaults/_collections/default-endpoints.util.ts +487 -487
- package/src/_modules/defaults/_models/default-user.data-model.ts +72 -72
- package/src/_modules/defaults/_services/default-auth.service.spec.ts +269 -269
- package/src/_modules/defaults/_services/default-auth.service.ts +177 -177
- package/src/_modules/defaults/_services/default-socket-events.service.spec.ts +42 -42
- package/src/_modules/defaults/_services/default-socket-events.service.ts +61 -61
- package/src/_modules/defaults/_services/default-user.data-service.spec.ts +187 -187
- package/src/_modules/defaults/_services/default-user.data-service.ts +98 -98
- package/src/_modules/defaults/index.ts +17 -17
- package/src/_modules/discord-assistant/_collections/dias-global-settings.const.ts +19 -19
- package/src/_modules/discord-assistant/_collections/dias.util.spec.ts +366 -366
- package/src/_modules/discord-assistant/_collections/dias.util.ts +132 -132
- package/src/_modules/discord-assistant/_models/dias-global-settings.interface.ts +19 -19
- package/src/_modules/discord-assistant/_models/dias-knowledge.data-model.ts +52 -52
- package/src/_modules/discord-assistant/_services/dias-chunk.data-service.ts +177 -177
- package/src/_modules/discord-assistant/_services/dias-io.control-service.spec.ts +108 -108
- package/src/_modules/discord-assistant/_services/dias-io.control-service.ts +69 -69
- package/src/_modules/discord-assistant/_services/dias-main.control-service.spec.ts +22 -22
- package/src/_modules/discord-assistant/_services/dias-main.control-service.ts +27 -27
- package/src/_modules/discord-assistant/_services/dias.service-base.spec.ts +195 -195
- package/src/_modules/discord-assistant/_services/dias.service-base.ts +76 -76
- package/src/_modules/discord-assistant/index.ts +38 -38
- package/src/_modules/discord-assistant-voiced/_services/dias-discord-bot.control-service.spec.ts +34 -34
- package/src/_modules/discord-assistant-voiced/_services/dias-discord-bot.control-service.ts +11 -11
- package/src/_modules/discord-assistant-voiced/index.ts +36 -36
- package/src/_modules/discord-bot/_collections/dibo-default-commands.const.ts +16 -16
- package/src/_modules/discord-bot/_collections/dibo-global-settings.conts.ts +55 -55
- package/src/_modules/discord-bot/_collections/dibo-operations.util.spec.ts +214 -214
- package/src/_modules/discord-bot/_collections/dibo-operations.util.ts +387 -387
- package/src/_modules/discord-bot/_models/dibo-command.interface.ts +12 -12
- package/src/_modules/discord-bot/_models/dibo-global-settings.interface.ts +98 -98
- package/src/_modules/discord-bot/_models/dibo-last-mention-date.inteface.ts +7 -7
- package/src/_modules/discord-bot/_models/dibo-last-message-date.interface.ts +6 -6
- package/src/_modules/discord-bot/_services/dibo-commands.control-service.spec.ts +154 -154
- package/src/_modules/discord-bot/_services/dibo-commands.control-service.ts +153 -153
- package/src/_modules/discord-bot/_services/dibo-io.control-service.spec.ts +264 -264
- package/src/_modules/discord-bot/_services/dibo-io.control-service.ts +306 -306
- package/src/_modules/discord-bot/_services/dibo-main.control-service.spec.ts +408 -408
- package/src/_modules/discord-bot/_services/dibo-main.control-service.ts +487 -487
- package/src/_modules/discord-bot/_services/dibo-routines.control-service.spec.ts +105 -105
- package/src/_modules/discord-bot/_services/dibo-routines.control-service.ts +97 -97
- package/src/_modules/discord-bot/index.ts +36 -36
- package/src/_modules/local-vector-search/_enums/lvs-search-mode.enum.ts +35 -35
- package/src/_modules/local-vector-search/_models/data-models/lvs-vector-persist.data-model.ts +60 -60
- package/src/_modules/local-vector-search/_models/lvs-search-result.interface.ts +17 -17
- package/src/_modules/local-vector-search/_services/lvs-bm25.util.spec.ts +159 -159
- package/src/_modules/local-vector-search/_services/lvs-bm25.util.ts +206 -206
- package/src/_modules/local-vector-search/_services/lvs-doc-chunk-data.service.spec.ts +418 -418
- package/src/_modules/local-vector-search/_services/lvs-doc-chunk-data.service.ts +276 -276
- package/src/_modules/local-vector-search/_services/lvs-local-vector-search.data-service.spec.ts +480 -480
- package/src/_modules/local-vector-search/_services/lvs-local-vector-search.data-service.ts +416 -416
- package/src/_modules/local-vector-search/_services/lvs-persistent-vector-pool.control-service.spec.ts +214 -214
- package/src/_modules/local-vector-search/_services/lvs-persistent-vector-pool.control-service.ts +186 -186
- package/src/_modules/local-vector-search/_services/lvs-vector-persist.data-service.spec.ts +167 -167
- package/src/_modules/local-vector-search/_services/lvs-vector-persist.data-service.ts +130 -130
- package/src/_modules/local-vector-search/_services/lvs-vector-pool.control-service.spec.ts +509 -509
- package/src/_modules/local-vector-search/_services/lvs-vector-pool.control-service.ts +323 -323
- package/src/_modules/local-vector-search/index.ts +16 -16
- package/src/_modules/logs/_models/file-log-entry.interface.ts +13 -13
- package/src/_modules/logs/_models/file-log-read-result.interface.ts +37 -37
- package/src/_modules/logs/file-log.service.spec.ts +341 -341
- package/src/_modules/logs/file-log.service.ts +466 -466
- package/src/_modules/logs/file-logs.controller.spec.ts +245 -245
- package/src/_modules/logs/file-logs.controller.ts +165 -165
- package/src/_modules/logs/get-file-logs-routing-module.util.ts +51 -51
- package/src/_modules/logs/get-logs-routing-module.util.ts +36 -36
- package/src/_modules/logs/index.ts +11 -11
- package/src/_modules/logs/log-buffer.service.ts +101 -101
- package/src/_modules/logs/logs.controller.ts +109 -109
- package/src/_modules/logs/logs.service.ts +100 -100
- package/src/_modules/mcp/_models/interfaces/dynts-mcp.interface.ts +111 -111
- package/src/_modules/mcp/_services/dynts-mcp-server.service-base.spec.ts +151 -151
- package/src/_modules/mcp/_services/dynts-mcp-server.service-base.ts +125 -125
- package/src/_modules/mcp/_services/dynts-mcp.adapter.ts +168 -168
- package/src/_modules/mcp/index.ts +13 -13
- package/src/_modules/messaging/README.md +354 -354
- package/src/_modules/messaging/_collections/get-messaging-routing-module.util.ts +26 -26
- package/src/_modules/messaging/_collections/msg-global-settings.const.ts +22 -22
- package/src/_modules/messaging/_collections/msg.util.spec.ts +226 -226
- package/src/_modules/messaging/_collections/msg.util.ts +83 -83
- package/src/_modules/messaging/_models/msg-global-settings.interface.ts +37 -37
- package/src/_modules/messaging/_services/msg-conversation.data-service.ts +146 -146
- package/src/_modules/messaging/_services/msg-events.service.spec.ts +219 -219
- package/src/_modules/messaging/_services/msg-events.service.ts +267 -267
- package/src/_modules/messaging/_services/msg-integration.control-service.ts +179 -179
- package/src/_modules/messaging/_services/msg-main.control-service.spec.ts +147 -147
- package/src/_modules/messaging/_services/msg-main.control-service.ts +571 -571
- package/src/_modules/messaging/_services/msg-message.data-service.ts +129 -129
- package/src/_modules/messaging/_services/msg.controller.spec.ts +201 -201
- package/src/_modules/messaging/_services/msg.controller.ts +370 -370
- package/src/_modules/messaging/index.ts +30 -30
- package/src/_modules/mock/app-extended-server.mock.ts +201 -201
- package/src/_modules/mock/app-integration-test.mock.ts +51 -51
- package/src/_modules/mock/app-params.mock.spec.ts +21 -21
- package/src/_modules/mock/app-params.mock.ts +9 -9
- package/src/_modules/mock/app-server.mock.ts +188 -188
- package/src/_modules/mock/auth-service.mock.spec.ts +47 -47
- package/src/_modules/mock/auth-service.mock.ts +28 -28
- package/src/_modules/mock/controller.mock.spec.ts +26 -26
- package/src/_modules/mock/controller.mock.ts +16 -16
- package/src/_modules/mock/data-model.mock.spec.ts +111 -111
- package/src/_modules/mock/data-model.mock.ts +82 -82
- package/src/_modules/mock/email-service-collection.mock.spec.ts +24 -24
- package/src/_modules/mock/email-service-collection.mock.ts +15 -15
- package/src/_modules/mock/email-service.mock.spec.ts +17 -17
- package/src/_modules/mock/email-service.mock.ts +20 -20
- package/src/_modules/mock/email-template.mock.html +14 -14
- package/src/_modules/mock/endpoint.mock.ts +91 -91
- package/src/_modules/mock/socket-client.mock.spec.ts +40 -40
- package/src/_modules/mock/socket-client.mock.ts +45 -45
- package/src/_modules/mock/socket-server.mock.spec.ts +44 -44
- package/src/_modules/mock/socket-server.mock.ts +46 -46
- package/src/_modules/oauth2/_routes/oauth2.controller.spec.ts +107 -107
- package/src/_modules/oauth2/_routes/oauth2.controller.ts +98 -98
- package/src/_modules/oauth2/_services/oauth2.auth-service.spec.ts +254 -254
- package/src/_modules/oauth2/_services/oauth2.auth-service.ts +232 -232
- package/src/_modules/oauth2/_services/oauth2.control-service.spec.ts +585 -585
- package/src/_modules/oauth2/_services/oauth2.control-service.ts +653 -653
- package/src/_modules/oauth2/index.ts +17 -17
- package/src/_modules/privacy-lifecycle/_enums/privacy-consent-decision.type-enum.ts +5 -5
- package/src/_modules/privacy-lifecycle/_enums/privacy-contributor-action.type-enum.ts +10 -10
- package/src/_modules/privacy-lifecycle/_enums/privacy-contributor-outcome.type-enum.ts +7 -7
- package/src/_modules/privacy-lifecycle/_enums/privacy-request-state.type-enum.ts +15 -15
- package/src/_modules/privacy-lifecycle/_enums/privacy-request.type-enum.ts +9 -9
- package/src/_modules/privacy-lifecycle/_models/privacy-consent-input.interface.ts +12 -12
- package/src/_modules/privacy-lifecycle/_models/privacy-consent-persistence-result.interface.ts +7 -7
- package/src/_modules/privacy-lifecycle/_models/privacy-consent-record.interface.ts +15 -15
- package/src/_modules/privacy-lifecycle/_models/privacy-consent-result.interface.ts +7 -7
- package/src/_modules/privacy-lifecycle/_models/privacy-consent-view.interface.ts +13 -13
- package/src/_modules/privacy-lifecycle/_models/privacy-contributor-context.interface.ts +9 -9
- package/src/_modules/privacy-lifecycle/_models/privacy-contributor-outcome.interface.ts +14 -14
- package/src/_modules/privacy-lifecycle/_models/privacy-contributor-plan.interface.ts +8 -8
- package/src/_modules/privacy-lifecycle/_models/privacy-contributor.interface.ts +17 -17
- package/src/_modules/privacy-lifecycle/_models/privacy-ledger-adapter.interface.ts +21 -21
- package/src/_modules/privacy-lifecycle/_models/privacy-ledger-result.interface.ts +9 -9
- package/src/_modules/privacy-lifecycle/_models/privacy-ledger-settings.interface.ts +7 -7
- package/src/_modules/privacy-lifecycle/_models/privacy-legal-acceptance-input.interface.ts +10 -10
- package/src/_modules/privacy-lifecycle/_models/privacy-legal-acceptance-persistence-result.interface.ts +7 -7
- package/src/_modules/privacy-lifecycle/_models/privacy-legal-acceptance-result.interface.ts +7 -7
- package/src/_modules/privacy-lifecycle/_models/privacy-legal-acceptance-view.interface.ts +11 -11
- package/src/_modules/privacy-lifecycle/_models/privacy-legal-acceptance.interface.ts +13 -13
- package/src/_modules/privacy-lifecycle/_models/privacy-lifecycle-adapter.interface.ts +19 -19
- package/src/_modules/privacy-lifecycle/_models/privacy-lifecycle-settings.interface.ts +9 -9
- package/src/_modules/privacy-lifecycle/_models/privacy-request-create-result.interface.ts +7 -7
- package/src/_modules/privacy-lifecycle/_models/privacy-request-open.interface.ts +10 -10
- package/src/_modules/privacy-lifecycle/_models/privacy-request-persistence-create-result.interface.ts +7 -7
- package/src/_modules/privacy-lifecycle/_models/privacy-request-record.interface.ts +21 -21
- package/src/_modules/privacy-lifecycle/_models/privacy-request-result.interface.ts +8 -8
- package/src/_modules/privacy-lifecycle/_models/privacy-request-view.interface.ts +20 -20
- package/src/_modules/privacy-lifecycle/index.ts +40 -40
- package/src/_modules/privacy-lifecycle/privacy-ledger.control-service.spec.ts +206 -206
- package/src/_modules/privacy-lifecycle/privacy-ledger.control-service.ts +253 -253
- package/src/_modules/privacy-lifecycle/privacy-lifecycle.control-service.spec.ts +353 -353
- package/src/_modules/privacy-lifecycle/privacy-lifecycle.control-service.ts +586 -586
- package/src/_modules/rate-limit/_enums/rate-limit-store-kind.type-enum.ts +5 -5
- package/src/_modules/rate-limit/_models/rate-limit-config.interface.ts +82 -82
- package/src/_modules/rate-limit/_models/rate-limit-consume-request.interface.ts +9 -9
- package/src/_modules/rate-limit/_models/rate-limit-consume-result.interface.ts +6 -6
- package/src/_modules/rate-limit/_models/rate-limit-policy.interface.ts +16 -16
- package/src/_modules/rate-limit/_models/rate-limit-store.interface.ts +9 -9
- package/src/_modules/rate-limit/index.ts +8 -8
- package/src/_modules/rate-limit/rate-limit-in-memory.store.ts +91 -91
- package/src/_modules/rate-limit/rate-limit.middleware.spec.ts +488 -488
- package/src/_modules/rate-limit/rate-limit.middleware.ts +504 -504
- package/src/_modules/scheduler/_models/scheduler-job.interface.ts +35 -35
- package/src/_modules/scheduler/get-scheduler-routing-module.util.ts +33 -33
- package/src/_modules/scheduler/index.ts +8 -8
- package/src/_modules/scheduler/scheduler.controller.spec.ts +42 -42
- package/src/_modules/scheduler/scheduler.controller.ts +69 -69
- package/src/_modules/scheduler/scheduler.service.spec.ts +141 -141
- package/src/_modules/scheduler/scheduler.service.ts +176 -176
- package/src/_modules/scoped-config/_enums/dynts-scoped-config-level.enum.ts +22 -22
- package/src/_modules/scoped-config/_models/data-models/dynts-scoped-config.data-model.ts +82 -82
- package/src/_modules/scoped-config/_models/interfaces/dynts-scoped-config.interface.ts +107 -107
- package/src/_modules/scoped-config/_services/dynts-scoped-config.control-service.spec.ts +312 -312
- package/src/_modules/scoped-config/_services/dynts-scoped-config.control-service.ts +311 -311
- package/src/_modules/scoped-config/_services/dynts-scoped-config.data-service.spec.ts +123 -123
- package/src/_modules/scoped-config/_services/dynts-scoped-config.data-service.ts +108 -108
- package/src/_modules/scoped-config/index.ts +17 -17
- package/src/_modules/server/errors/errors.control-service.spec.ts +246 -246
- package/src/_modules/server/errors/errors.control-service.ts +100 -100
- package/src/_modules/server/errors/errors.controller.spec.ts +340 -340
- package/src/_modules/server/errors/errors.controller.ts +559 -559
- package/src/_modules/server/errors/errors.data-service.spec.ts +480 -480
- package/src/_modules/server/errors/errors.data-service.ts +867 -867
- package/src/_modules/server/index.ts +34 -30
- package/src/_modules/server/server-status/db-readiness-probe-code.type-enum.ts +13 -0
- package/src/_modules/server/server-status/db-readiness-probe-stage.type-enum.ts +7 -0
- package/src/_modules/server/server-status/db-readiness-probe.control-service.spec.ts +235 -0
- package/src/_modules/server/server-status/db-readiness-probe.control-service.ts +158 -0
- package/src/_modules/server/server-status/db-readiness-probe.interface.ts +20 -0
- package/src/_modules/server/server-status/server-status-snapshot.control-service.spec.ts +70 -70
- package/src/_modules/server/server-status/server-status-snapshot.control-service.ts +17 -17
- package/src/_modules/server/server-status/server-status-snapshot.data-service.spec.ts +77 -77
- package/src/_modules/server/server-status/server-status-snapshot.data-service.ts +37 -37
- package/src/_modules/server/server-status/server-status.control-service.spec.ts +672 -672
- package/src/_modules/server/server-status/server-status.control-service.ts +490 -490
- package/src/_modules/server/server-status/server-status.controller.spec.ts +276 -276
- package/src/_modules/server/server-status/server-status.controller.ts +336 -336
- package/src/_modules/socket/_enums/socket-security.enum.ts +11 -11
- package/src/_modules/socket/_models/socket-client-service-params.control-model.spec.ts +32 -32
- package/src/_modules/socket/_models/socket-client-service-params.control-model.ts +22 -22
- package/src/_modules/socket/_models/socket-presence.control-model.spec.ts +165 -165
- package/src/_modules/socket/_models/socket-presence.control-model.ts +211 -211
- package/src/_modules/socket/_models/socket-server-service-params.control-model.spec.ts +69 -69
- package/src/_modules/socket/_models/socket-server-service-params.control-model.ts +33 -33
- package/src/_modules/socket/_services/socket-client.service.spec.ts +15 -15
- package/src/_modules/socket/_services/socket-client.service.ts +260 -260
- package/src/_modules/socket/_services/socket-server.service.spec.ts +272 -272
- package/src/_modules/socket/_services/socket-server.service.ts +1037 -1037
- package/src/_modules/socket/app-extended.integration.spec.ts +85 -85
- package/src/_modules/socket/app-extended.server.ts +648 -648
- package/src/_modules/socket/index.ts +42 -42
- package/src/_modules/test/get-test-routing-module.util.spec.ts +28 -28
- package/src/_modules/test/get-test-routing-module.util.ts +23 -23
- package/src/_modules/test/index.ts +11 -11
- package/src/_modules/test/test.controller.spec.ts +72 -72
- package/src/_modules/test/test.controller.ts +115 -115
- package/src/_modules/test-email-sink/_collections/test-email-pattern.const.ts +10 -10
- package/src/_modules/test-email-sink/_models/data-models/dynts-sent-test-mail.data-model.ts +41 -41
- package/src/_modules/test-email-sink/_services/dynts-test-email-sink.service.spec.ts +112 -112
- package/src/_modules/test-email-sink/_services/dynts-test-email-sink.service.ts +141 -141
- package/src/_modules/test-email-sink/get-sent-mail-routing-module.util.ts +29 -29
- package/src/_modules/test-email-sink/index.ts +11 -11
- package/src/_modules/test-email-sink/test-email-sink.controller.ts +83 -83
- package/src/_modules/usage/get-usage-routing-module.util.ts +22 -22
- package/src/_modules/usage/index.ts +15 -15
- package/src/_modules/usage/usage.controller.spec.ts +106 -106
- package/src/_modules/usage/usage.controller.ts +140 -140
- package/src/_modules/usage/usage.data-service.spec.ts +332 -332
- package/src/_modules/usage/usage.data-service.ts +185 -185
- package/src/_services/base/api.service-base.spec.ts +125 -125
- package/src/_services/base/api.service-base.ts +74 -74
- package/src/_services/base/archive-data.service.spec.ts +209 -209
- package/src/_services/base/archive-data.service.ts +228 -228
- package/src/_services/base/data.service.spec.ts +784 -784
- package/src/_services/base/data.service.ts +2792 -2792
- package/src/_services/base/db.service.encryption.spec.ts +76 -76
- package/src/_services/base/db.service.spec.ts +160 -160
- package/src/_services/base/db.service.ts +1698 -1698
- package/src/_services/base/singleton.service-base.spec.ts +28 -28
- package/src/_services/base/singleton.service-base.ts +24 -24
- package/src/_services/base/singleton.service.spec.ts +114 -114
- package/src/_services/base/singleton.service.ts +38 -38
- package/src/_services/core/api.service.spec.ts +187 -187
- package/src/_services/core/api.service.ts +627 -627
- package/src/_services/core/auth.service.spec.ts +159 -159
- package/src/_services/core/auth.service.ts +174 -174
- package/src/_services/core/collection-growth-monitor.service.spec.ts +119 -119
- package/src/_services/core/collection-growth-monitor.service.ts +234 -234
- package/src/_services/core/db-stats.service.ts +104 -104
- package/src/_services/core/diagnostics.service.spec.ts +44 -44
- package/src/_services/core/diagnostics.service.ts +158 -158
- package/src/_services/core/email.service.spec.ts +85 -85
- package/src/_services/core/email.service.ts +757 -757
- package/src/_services/core/event-loop-diag.service.spec.ts +22 -22
- package/src/_services/core/event-loop-diag.service.ts +144 -144
- package/src/_services/core/global.service.spec.ts +292 -292
- package/src/_services/core/global.service.ts +487 -487
- package/src/_services/core/memory-guard.service.spec.ts +245 -245
- package/src/_services/core/memory-guard.service.ts +481 -481
- package/src/_services/core/migration-runner.service.spec.ts +91 -91
- package/src/_services/core/migration-runner.service.ts +106 -106
- package/src/_services/core/mongo-transaction.control-service.spec.ts +165 -165
- package/src/_services/core/mongo-transaction.control-service.ts +148 -148
- package/src/_services/core/request-hunter.service.spec.ts +124 -124
- package/src/_services/core/request-hunter.service.ts +157 -157
- package/src/_services/core/service-collection.service.spec.ts +46 -46
- package/src/_services/core/service-collection.service.ts +6 -6
- package/src/_services/route/controller.service.spec.ts +53 -53
- package/src/_services/route/controller.service.ts +148 -148
- package/src/_services/route/routing-module.service.spec.ts +98 -98
- package/src/_services/route/routing-module.service.ts +330 -330
- package/src/_services/server/app.server-retention.spec.ts +106 -106
- package/src/_services/server/app.server.ts +2012 -2012
- package/src/_services/shared.static-service.spec.ts +99 -99
- package/src/_services/shared.static-service.ts +78 -78
- package/src/index.ts +117 -117
- package/tsconfig.app.json +12 -12
- package/tsconfig.json +42 -42
- package/.dynamo/logs/cicd-pipeline/output.log +0 -2883
- package/.dynamo/logs/cicd-pipeline/status.json +0 -74
|
@@ -1,1037 +1,1037 @@
|
|
|
1
|
-
|
|
2
|
-
import * as SocketIO from 'socket.io';
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
DyFM_AnyError, DyFM_Array, DyFM_Error, DyFM_Error_Settings, DyFM_errorFlag, DyFM_Log
|
|
6
|
-
} from '@futdevpro/fsm-dynamo';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
import {
|
|
10
|
-
DyFM_SocketEvent,
|
|
11
|
-
DyFM_SocketEvent_Key, DyFM_SocketEventPreprocessTask, DyFM_SocketEventTask
|
|
12
|
-
} from '@futdevpro/fsm-dynamo/socket';
|
|
13
|
-
|
|
14
|
-
import { DyNTS_global_settings } from '../../../_collections/global-settings.const';
|
|
15
|
-
import { DyNTS_SingletonService } from '../../../_services/base/singleton.service';
|
|
16
|
-
import { DyNTS_SocketSecurity } from '../_enums/socket-security.enum';
|
|
17
|
-
import {
|
|
18
|
-
DyNTS_SocketPresence
|
|
19
|
-
} from '../_models/socket-presence.control-model';
|
|
20
|
-
import {
|
|
21
|
-
DyNTS_SocketServerService_Params
|
|
22
|
-
} from '../_models/socket-server-service-params.control-model';
|
|
23
|
-
|
|
24
|
-
/** Opciók a setupSocketServer híváshoz: attacholt HTTP szerver esetén ne hívjuk a listen()-t. */
|
|
25
|
-
export interface DyNTS_SocketServerSetupOptions {
|
|
26
|
-
/** Ha true, a Socket.IO egy már listenelő HTTP/HTTPS szerverre van attacholva – ne hívjuk a listen()-t. */
|
|
27
|
-
attachedToExistingServer?: boolean;
|
|
28
|
-
/** A tényleges port (pl. defaultolt httpPort/httpsPort) – logokban használjuk. */
|
|
29
|
-
effectivePort?: number;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* You need to define the following functions:
|
|
34
|
-
* ```ts
|
|
35
|
-
* getServiceParams(): DyNTS_SocketServerServiceParams;
|
|
36
|
-
*
|
|
37
|
-
* getIncomingEvents(): DyFM_SocketEvent<any>[];
|
|
38
|
-
*
|
|
39
|
-
* getPresenceFromSubscriptionEventContent(
|
|
40
|
-
* socketSubscription: T_SubscriptionContent,
|
|
41
|
-
* socket: SocketIO.Socket
|
|
42
|
-
* ): Promise<T_Presence>;
|
|
43
|
-
* ```
|
|
44
|
-
*/
|
|
45
|
-
export abstract class DyNTS_SocketServerService<
|
|
46
|
-
T_Presence extends DyNTS_SocketPresence = DyNTS_SocketPresence,
|
|
47
|
-
T_SubscriptionContent = any,
|
|
48
|
-
T_ErrorContent = any
|
|
49
|
-
> extends DyNTS_SingletonService {
|
|
50
|
-
|
|
51
|
-
protected params: DyNTS_SocketServerService_Params;
|
|
52
|
-
get name(): string { return this.params.name; }
|
|
53
|
-
get port(): number | undefined { return this.params.port; }
|
|
54
|
-
/** BFR-MASTERPROMPTER-025: explicit dedikált-listener opt-in (default false = shared). */
|
|
55
|
-
get dedicatedPort(): boolean { return this.params.dedicatedPort ?? false; }
|
|
56
|
-
get security(): DyNTS_SocketSecurity { return this.params.security; }
|
|
57
|
-
get activeSubscriptionsCount(): number { return this.presences.length; }
|
|
58
|
-
|
|
59
|
-
protected openSocketServer: SocketIO.Server;
|
|
60
|
-
protected secureSocketServer: SocketIO.Server;
|
|
61
|
-
|
|
62
|
-
/* private connectEvent: DyFM_SocketEvent<SocketIO.Socket>; */
|
|
63
|
-
protected incomingEvents: DyFM_SocketEvent<any>[];
|
|
64
|
-
|
|
65
|
-
/* private subscriptionEvent: DyFM_SocketEvent<any>; */
|
|
66
|
-
/* private unsubscribeEvent: DyFM_SocketEvent<any>; */
|
|
67
|
-
|
|
68
|
-
protected presences: T_Presence[] = [];
|
|
69
|
-
private readonly disconnectedSockets: WeakSet<SocketIO.Socket> = new WeakSet();
|
|
70
|
-
|
|
71
|
-
get logSetup(): boolean { return DyNTS_global_settings.log_settings.setup; }
|
|
72
|
-
get highDetailedLogs(): boolean { return DyNTS_global_settings.log_settings.highDetailedLogs; }
|
|
73
|
-
|
|
74
|
-
override readonly defaultErrorUserMsg =
|
|
75
|
-
`We encountered an unhandled Socket Server Error, ` +
|
|
76
|
-
`\nplease contact the responsible development team.`;
|
|
77
|
-
|
|
78
|
-
/* readonly thisLocationStack: string; */
|
|
79
|
-
|
|
80
|
-
protected constructor(){
|
|
81
|
-
super();
|
|
82
|
-
|
|
83
|
-
/* this.thisLocationStack = DyNTS_getStackLocation(); */
|
|
84
|
-
|
|
85
|
-
this.asyncConstructor().catch((error: any) => {
|
|
86
|
-
DyFM_Log.error(
|
|
87
|
-
`Socket Server Service setup failed: "${this.params?.name}" (${this.params?.port})`,
|
|
88
|
-
error
|
|
89
|
-
);
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* You need to setup a function that converts subscription event content to presence.
|
|
95
|
-
* You should do authentication and authorization here.
|
|
96
|
-
*/
|
|
97
|
-
protected abstract getPresenceFromSubscriptionEventContent(
|
|
98
|
-
socketSubscription: T_SubscriptionContent,
|
|
99
|
-
socket: SocketIO.Socket
|
|
100
|
-
): Promise<T_Presence>;
|
|
101
|
-
|
|
102
|
-
private async asyncConstructor(): Promise<void> {
|
|
103
|
-
try {
|
|
104
|
-
this.params = this.getServiceParams();
|
|
105
|
-
this.incomingEvents = this.getIncomingEvents() ?? [];
|
|
106
|
-
|
|
107
|
-
await this.prepareEvents();
|
|
108
|
-
|
|
109
|
-
if (this.logSetup) console.log(
|
|
110
|
-
`Socket Server Service setup done: "${this.params.name}" (${this.params.port}) ` +
|
|
111
|
-
`security: ${this.params.security}\n`
|
|
112
|
-
);
|
|
113
|
-
} catch (error) {
|
|
114
|
-
DyFM_Log.error(
|
|
115
|
-
`Socket Server Service setup failed: "${this.params?.name}" (${this.params?.port})`,
|
|
116
|
-
error
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
throw new DyFM_Error({
|
|
120
|
-
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-GPFSRC0`,
|
|
121
|
-
error: error,
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* You must setup events and required services for this function
|
|
128
|
-
*/
|
|
129
|
-
private async prepareEvents(): Promise<void> {
|
|
130
|
-
try {
|
|
131
|
-
/** Setup connect event */
|
|
132
|
-
/* const connectEventIndex = this.incomingEvents.findIndex(
|
|
133
|
-
(event: DyFM_SocketEvent<any>) =>
|
|
134
|
-
event.eventKey === DyFM_SocketEvent_Key.connection
|
|
135
|
-
);
|
|
136
|
-
|
|
137
|
-
if (0 <= connectEventIndex) {
|
|
138
|
-
this.connectEvent = this.incomingEvents.splice(connectEventIndex)[0];
|
|
139
|
-
} else {
|
|
140
|
-
this.connectEvent = new DyFM_SocketEvent({
|
|
141
|
-
eventKey: DyFM_SocketEvent_Key.connection,
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
this.connectEvent.serviceName = this.params.name; */
|
|
145
|
-
|
|
146
|
-
if (!this.getPresenceFromSubscriptionEventContent) {
|
|
147
|
-
throw new DyFM_Error({
|
|
148
|
-
error: new Error('getPresenceFromSubscriptionEventContent must be set'),
|
|
149
|
-
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-PPE1`,
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
if (!this.getSubscriptionTasks) {
|
|
154
|
-
DyFM_Log.warn(
|
|
155
|
-
`You should not set the subscription event, ` +
|
|
156
|
-
`in case you need additional steps for your subscriptions.`,
|
|
157
|
-
`${this.params.name} (${this.params.port})`
|
|
158
|
-
);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
if (this.incomingEvents.find(
|
|
162
|
-
(event: DyFM_SocketEvent<any>) =>
|
|
163
|
-
event.eventKey === DyFM_SocketEvent_Key.subscribe
|
|
164
|
-
)) {
|
|
165
|
-
DyFM_Log.warn(
|
|
166
|
-
`You need to use getSubscriptionTasks() ` +
|
|
167
|
-
`instead of setting the subscribe event in getIncomingEvents().`,
|
|
168
|
-
`${this.params.name} (${this.params.port})`
|
|
169
|
-
);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
if (!this.incomingEvents.find(
|
|
173
|
-
(event: DyFM_SocketEvent<any>) =>
|
|
174
|
-
event.eventKey === DyFM_SocketEvent_Key.unsubscribe
|
|
175
|
-
)) {
|
|
176
|
-
DyFM_Log.warn(
|
|
177
|
-
`You should not set the unsubscribe event, ` +
|
|
178
|
-
`in case you need additional steps for your unsubscribe.`,
|
|
179
|
-
`${this.params.name} (${this.params.port})`
|
|
180
|
-
);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
if (this.incomingEvents.find(
|
|
184
|
-
(event: DyFM_SocketEvent<any>) => !event.eventKey
|
|
185
|
-
)) {
|
|
186
|
-
throw new DyFM_Error({
|
|
187
|
-
error: new Error('eventKey must be set'),
|
|
188
|
-
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-PPE2`,
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
this.incomingEvents.push(
|
|
193
|
-
new DyFM_SocketEvent({
|
|
194
|
-
eventKey: DyFM_SocketEvent_Key.disconnect,
|
|
195
|
-
})
|
|
196
|
-
);
|
|
197
|
-
|
|
198
|
-
if (this.errorHandling) {
|
|
199
|
-
this.incomingEvents.push(new DyFM_SocketEvent<T_ErrorContent>({
|
|
200
|
-
serviceName: this.params.name,
|
|
201
|
-
eventKey: DyFM_SocketEvent_Key.error,
|
|
202
|
-
tasks: [
|
|
203
|
-
async (content: any) => this.errorHandling(content),
|
|
204
|
-
],
|
|
205
|
-
}));
|
|
206
|
-
} else {
|
|
207
|
-
DyFM_Log.warn(
|
|
208
|
-
`You should not set the error event, ` +
|
|
209
|
-
`in case you need additional steps for your error.`,
|
|
210
|
-
`${this.params.name} (${this.params.port})`
|
|
211
|
-
);
|
|
212
|
-
|
|
213
|
-
this.incomingEvents.push(new DyFM_SocketEvent<T_ErrorContent>({
|
|
214
|
-
serviceName: this.params.name,
|
|
215
|
-
eventKey: DyFM_SocketEvent_Key.error,
|
|
216
|
-
tasks: [
|
|
217
|
-
async (content: any) => {
|
|
218
|
-
if (content instanceof DyFM_Error) {
|
|
219
|
-
content.logSimple(`=--> socket-client (${this.params.name}) ERROR`);
|
|
220
|
-
} else {
|
|
221
|
-
DyFM_Log.error(`=--> socket-client (${this.params.name}) ERROR:`, content);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
],
|
|
225
|
-
}));
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// Merge incoming events of the same eventKey
|
|
229
|
-
const eventKeys = this.incomingEvents.map(
|
|
230
|
-
(event: DyFM_SocketEvent<any>) => event.eventKey
|
|
231
|
-
).filter(
|
|
232
|
-
(eventKey: string, index: number, self: string[]) =>
|
|
233
|
-
self.indexOf(eventKey) === index
|
|
234
|
-
);
|
|
235
|
-
const mergedEvents: DyFM_SocketEvent<any>[] = [];
|
|
236
|
-
eventKeys.forEach((eventKey: string) => {
|
|
237
|
-
const events = this.incomingEvents.filter(
|
|
238
|
-
(event: DyFM_SocketEvent<any>) => event.eventKey === eventKey
|
|
239
|
-
);
|
|
240
|
-
|
|
241
|
-
mergedEvents.push(new DyFM_SocketEvent({
|
|
242
|
-
eventKey: eventKey,
|
|
243
|
-
preProcesses: events.map((event: DyFM_SocketEvent<any>) => event.preProcesses).flat(),
|
|
244
|
-
tasks: events.map((event: DyFM_SocketEvent<any>) => event.tasks).flat(),
|
|
245
|
-
}));
|
|
246
|
-
});
|
|
247
|
-
this.incomingEvents = mergedEvents;
|
|
248
|
-
|
|
249
|
-
if (DyNTS_global_settings.log_settings.setup) {
|
|
250
|
-
DyFM_Log.log(
|
|
251
|
-
`Socket Server Service - Event Preparation setup done: ` +
|
|
252
|
-
`"${this.params?.name}" (${this.params?.port})` +
|
|
253
|
-
`\nincomingEvents:`, this.incomingEvents.map(
|
|
254
|
-
(event: DyFM_SocketEvent<any>) =>
|
|
255
|
-
`\n\t"${event.eventKey}": preProcesses: ${event.preProcesses?.length} ` +
|
|
256
|
-
`tasks: ${event.tasks?.length}`
|
|
257
|
-
)
|
|
258
|
-
);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// Set incoming events serviceName
|
|
262
|
-
this.incomingEvents.forEach((event: DyFM_SocketEvent<any>) => {
|
|
263
|
-
event.serviceName = this.params.name;
|
|
264
|
-
});
|
|
265
|
-
} catch (error) {
|
|
266
|
-
DyFM_Log.error(
|
|
267
|
-
`Socket Server Service - Event Preparation setup failed: ` +
|
|
268
|
-
`"${this.params?.name}" (${this.params?.port})`,
|
|
269
|
-
error
|
|
270
|
-
);
|
|
271
|
-
|
|
272
|
-
throw error;
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
// eslint-disable-next-line max-lines-per-function
|
|
277
|
-
async setupSocketServer(
|
|
278
|
-
newSocketServer: SocketIO.Server,
|
|
279
|
-
security: DyNTS_SocketSecurity.open | DyNTS_SocketSecurity.secure,
|
|
280
|
-
successCallback: () => void,
|
|
281
|
-
options?: DyNTS_SocketServerSetupOptions
|
|
282
|
-
): Promise<SocketIO.Server> {
|
|
283
|
-
try {
|
|
284
|
-
if (this.highDetailedLogs) console.log('\nfn:. setupSocketServer');
|
|
285
|
-
|
|
286
|
-
const effectivePort: number | undefined = options?.effectivePort ?? this.params.port;
|
|
287
|
-
|
|
288
|
-
newSocketServer.on(DyFM_SocketEvent_Key.incomingNewConnection, async (socket: SocketIO.Socket) => {
|
|
289
|
-
try {
|
|
290
|
-
let issuer: string = `${this.params.name} anonymous socket`;
|
|
291
|
-
|
|
292
|
-
/* await this.connectEvent.executeEventTasks(socket); */
|
|
293
|
-
|
|
294
|
-
await DyFM_Array.asyncForEach(
|
|
295
|
-
this.incomingEvents.filter(
|
|
296
|
-
(event: DyFM_SocketEvent<any>) =>
|
|
297
|
-
event.eventKey === DyFM_SocketEvent_Key.incomingNewConnection
|
|
298
|
-
),
|
|
299
|
-
async (event: DyFM_SocketEvent<any>) => {
|
|
300
|
-
await event.executeEventTasks(socket);
|
|
301
|
-
}
|
|
302
|
-
);
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
if (this.getPresenceFromSubscriptionEventContent) {
|
|
306
|
-
socket.on(
|
|
307
|
-
DyFM_SocketEvent_Key.subscribe,
|
|
308
|
-
async (content: any) => {
|
|
309
|
-
let presence: T_Presence;
|
|
310
|
-
|
|
311
|
-
try {
|
|
312
|
-
/**
|
|
313
|
-
* usually socket logs are in event.executeEventTasks(),
|
|
314
|
-
* but subscribe event is an exception from this,
|
|
315
|
-
* to be able to check content before getPresenceFromSubscriptionEventContent
|
|
316
|
-
*/
|
|
317
|
-
if (DyNTS_global_settings.log_settings.socket_eventContent) {
|
|
318
|
-
DyFM_Log.log(
|
|
319
|
-
`--=> incoming socket (${this.params.name}) ` +
|
|
320
|
-
`event: "${DyFM_SocketEvent_Key.subscribe}";` +
|
|
321
|
-
`\ncontent:`, content
|
|
322
|
-
);
|
|
323
|
-
} else {
|
|
324
|
-
DyFM_Log.log(
|
|
325
|
-
`--=> incoming socket (${this.params.name}) ` +
|
|
326
|
-
`event: "${DyFM_SocketEvent_Key.subscribe}"`
|
|
327
|
-
);
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
presence = await this.getPresenceFromSubscriptionEventContent(
|
|
331
|
-
content, socket
|
|
332
|
-
);
|
|
333
|
-
|
|
334
|
-
presence.serviceName = this.params.name;
|
|
335
|
-
issuer = presence.issuerLocalId;
|
|
336
|
-
|
|
337
|
-
await this.addSocketToPresence(presence);
|
|
338
|
-
/* await this.subscriptionEvent.executeEventTasks(content, issuer); */
|
|
339
|
-
|
|
340
|
-
if (this.getSubscriptionTasks) {
|
|
341
|
-
await DyFM_Array.asyncForEach(
|
|
342
|
-
this.getSubscriptionTasks(),
|
|
343
|
-
async (task: DyFM_SocketEventTask<T_SubscriptionContent>) => {
|
|
344
|
-
await task(content, issuer);
|
|
345
|
-
}
|
|
346
|
-
);
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
socket.emit(
|
|
350
|
-
DyFM_SocketEvent_Key.subscriptionSuccessful,
|
|
351
|
-
'subscribe was successful',
|
|
352
|
-
error => {
|
|
353
|
-
DyFM_Log.error(
|
|
354
|
-
`Emitting subscriptionSuccessful event failed!` +
|
|
355
|
-
`\nerror:`, error
|
|
356
|
-
);
|
|
357
|
-
}
|
|
358
|
-
);
|
|
359
|
-
|
|
360
|
-
DyFM_Log.success(
|
|
361
|
-
`<-==> socket(${this.params.name}) subscription successful (${issuer})`
|
|
362
|
-
);
|
|
363
|
-
} catch (error) {
|
|
364
|
-
if (error instanceof DyFM_Error) {
|
|
365
|
-
error.logShort(
|
|
366
|
-
`Socket Subscription failed: "${this.params.name}" ` +
|
|
367
|
-
`(${this.params.port}) will disconnect now...`
|
|
368
|
-
)
|
|
369
|
-
} else if (DyNTS_global_settings.log_settings.socket_eventContent) {
|
|
370
|
-
DyFM_Log.error(
|
|
371
|
-
`Socket Subscription failed: "${this.params.name}" ` +
|
|
372
|
-
`(${this.params.port}) will disconnect now...`,
|
|
373
|
-
/* `${this.thisLocationStack}`, */
|
|
374
|
-
error
|
|
375
|
-
);
|
|
376
|
-
} else {
|
|
377
|
-
DyFM_Log.error(
|
|
378
|
-
`Socket Subscription failed: "${this.params.name}" ` ,
|
|
379
|
-
`(${this.params.port}) will disconnect now...`,
|
|
380
|
-
/* `${this.thisLocationStack}` */
|
|
381
|
-
);
|
|
382
|
-
}
|
|
383
|
-
await this.closeSocket(socket, issuer, error);
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
);
|
|
387
|
-
|
|
388
|
-
socket.on(
|
|
389
|
-
DyFM_SocketEvent_Key.unsubscribe,
|
|
390
|
-
async (issuer: string) => {
|
|
391
|
-
try {
|
|
392
|
-
/**
|
|
393
|
-
* usually socket logs are in event.executeEventTasks(),
|
|
394
|
-
* but unsubscribe event is an exception from this,
|
|
395
|
-
* to be able to check content before getPresenceFromSubscriptionEventContent
|
|
396
|
-
*/
|
|
397
|
-
if (DyNTS_global_settings.log_settings.socket_eventContent) {
|
|
398
|
-
DyFM_Log.log(
|
|
399
|
-
`--=> incoming socket (${this.params.name}) ` +
|
|
400
|
-
`event: ${DyFM_SocketEvent_Key.unsubscribe};` +
|
|
401
|
-
`\ncontent:`, issuer
|
|
402
|
-
);
|
|
403
|
-
} else {
|
|
404
|
-
DyFM_Log.log(
|
|
405
|
-
`--=> incoming socket (${this.params.name}) ` +
|
|
406
|
-
`event: ${DyFM_SocketEvent_Key.unsubscribe}`
|
|
407
|
-
);
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
/* await this.unsubscribeEvent.executeEventTasks(null, issuer); */
|
|
411
|
-
await DyFM_Array.asyncForEach(
|
|
412
|
-
this.incomingEvents.filter(
|
|
413
|
-
(event: DyFM_SocketEvent<any>) =>
|
|
414
|
-
event.eventKey === DyFM_SocketEvent_Key.unsubscribe
|
|
415
|
-
),
|
|
416
|
-
async (event: DyFM_SocketEvent<any>) => {
|
|
417
|
-
await event.executeEventTasks(null, issuer);
|
|
418
|
-
}
|
|
419
|
-
);
|
|
420
|
-
|
|
421
|
-
await this.removeSubscription(socket, issuer);
|
|
422
|
-
|
|
423
|
-
DyFM_Log.success(
|
|
424
|
-
`< x > socket(${this.params.name}) unsubscribe successful (${issuer})`
|
|
425
|
-
);
|
|
426
|
-
} catch (error) {
|
|
427
|
-
if (error instanceof DyFM_Error) {
|
|
428
|
-
error.logSimple(
|
|
429
|
-
`Socket Unsubscription failed: "${this.params.name}" ` +
|
|
430
|
-
`(${this.params.port}) will disconnect now...`
|
|
431
|
-
)
|
|
432
|
-
} else if (DyNTS_global_settings.log_settings.socket_eventContent) {
|
|
433
|
-
DyFM_Log.error(
|
|
434
|
-
`Socket unsubscribe failed: "${this.params.name}" ` ,
|
|
435
|
-
`(${this.params.port}) will disconnect now...`,
|
|
436
|
-
error
|
|
437
|
-
);
|
|
438
|
-
} else {
|
|
439
|
-
DyFM_Log.error(
|
|
440
|
-
`Socket unsubscribe failed: "${this.params.name}" ` ,
|
|
441
|
-
`(${this.params.port}) will disconnect now...`
|
|
442
|
-
);
|
|
443
|
-
}
|
|
444
|
-
socket.emit(DyFM_SocketEvent_Key.error, error);
|
|
445
|
-
await this.removeSubscription(socket, issuer);
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
);
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
this.incomingEvents.filter(
|
|
452
|
-
(event: DyFM_SocketEvent<any>) =>
|
|
453
|
-
event.eventKey !== DyFM_SocketEvent_Key.incomingNewConnection &&
|
|
454
|
-
event.eventKey !== DyFM_SocketEvent_Key.subscribe &&
|
|
455
|
-
event.eventKey !== DyFM_SocketEvent_Key.unsubscribe
|
|
456
|
-
).forEach((event: DyFM_SocketEvent<any>) => {
|
|
457
|
-
socket.on(
|
|
458
|
-
event.eventKey,
|
|
459
|
-
async (content: any) => {
|
|
460
|
-
try {
|
|
461
|
-
if (event.eventKey === DyFM_SocketEvent_Key.disconnect) {
|
|
462
|
-
await this.executeDisconnectTasks(socket, issuer);
|
|
463
|
-
} else {
|
|
464
|
-
await event.executeEventTasks(content, issuer, socket);
|
|
465
|
-
}
|
|
466
|
-
} catch (error) {
|
|
467
|
-
if (error instanceof DyFM_Error) {
|
|
468
|
-
error.logSimple(
|
|
469
|
-
`Socket Event failed: "${this.params.name}" (${this.params.port})`
|
|
470
|
-
)
|
|
471
|
-
} else {
|
|
472
|
-
DyFM_Log.error(
|
|
473
|
-
`Socket Event failed: "${this.params.name}" (${this.params.port})`,
|
|
474
|
-
error
|
|
475
|
-
);
|
|
476
|
-
}
|
|
477
|
-
socket.emit(DyFM_SocketEvent_Key.error, error);
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
);
|
|
481
|
-
});
|
|
482
|
-
|
|
483
|
-
if (DyNTS_global_settings.log_settings.socket_mainEvents) {
|
|
484
|
-
DyFM_Log.success(`< > socket(${this.params.name}): new CONNECTION established`);
|
|
485
|
-
}
|
|
486
|
-
} catch (error) {
|
|
487
|
-
if (error instanceof DyFM_Error) {
|
|
488
|
-
error.logSimple(
|
|
489
|
-
`Socket Connection failed: "${this.params.name}" ` +
|
|
490
|
-
`(${this.params.port}) will disconnect now...`
|
|
491
|
-
)
|
|
492
|
-
} else {
|
|
493
|
-
DyFM_Log.error(
|
|
494
|
-
`Socket Connection failed: "${this.params.name}" ` +
|
|
495
|
-
`(${this.params.port}) will disconnect now...`,
|
|
496
|
-
error
|
|
497
|
-
);
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
await this.closeSocket(socket, `${this.params.name} on connection error`, error);
|
|
501
|
-
}
|
|
502
|
-
});
|
|
503
|
-
|
|
504
|
-
const isAttach: boolean =
|
|
505
|
-
options?.attachedToExistingServer === true ||
|
|
506
|
-
(this.params.port === undefined && options?.effectivePort !== undefined);
|
|
507
|
-
|
|
508
|
-
if (isAttach) {
|
|
509
|
-
DyFM_Log.success(
|
|
510
|
-
`\nsocket server setup finished: "${this.params.name}"` +
|
|
511
|
-
(effectivePort !== undefined ? ` (attached to server on port: ${effectivePort})` : ' (attached to existing server)')
|
|
512
|
-
);
|
|
513
|
-
successCallback();
|
|
514
|
-
} else {
|
|
515
|
-
try {
|
|
516
|
-
const portToListen: number | undefined = this.params.port ?? options?.effectivePort;
|
|
517
|
-
if (portToListen === undefined) {
|
|
518
|
-
throw new Error(
|
|
519
|
-
`PORT NOT SET: "${this.params.name}". ` +
|
|
520
|
-
`Either set port in getServiceParams() or pass effectivePort in setupSocketServer options.`
|
|
521
|
-
);
|
|
522
|
-
}
|
|
523
|
-
newSocketServer.listen(portToListen);
|
|
524
|
-
|
|
525
|
-
DyFM_Log.success(
|
|
526
|
-
`\nsocket server setup finished: "${this.params.name}"` +
|
|
527
|
-
`\nsocket server listening on port: "${portToListen}"`
|
|
528
|
-
);
|
|
529
|
-
} catch (listenError) {
|
|
530
|
-
const portForMsg: number | undefined = this.params.port ?? options?.effectivePort;
|
|
531
|
-
const errorMessage = `Failed to bind socket server "${this.params.name}" to port ${portForMsg}. ` +
|
|
532
|
-
`This could be due to port already in use or insufficient permissions. ` +
|
|
533
|
-
`Please ensure the port is available and try again.`;
|
|
534
|
-
|
|
535
|
-
DyFM_Log.error(errorMessage, listenError);
|
|
536
|
-
throw new Error(errorMessage);
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
successCallback();
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
if (security === DyNTS_SocketSecurity.open) {
|
|
543
|
-
this.openSocketServer = newSocketServer;
|
|
544
|
-
|
|
545
|
-
return this.openSocketServer;
|
|
546
|
-
} else {
|
|
547
|
-
this.secureSocketServer = newSocketServer;
|
|
548
|
-
|
|
549
|
-
return this.secureSocketServer;
|
|
550
|
-
}
|
|
551
|
-
} catch (error) {
|
|
552
|
-
if (error instanceof DyFM_Error) {
|
|
553
|
-
error.logSimple(
|
|
554
|
-
`Socket Server Service - Deep Setup failed: "${this.params?.name}" ` +
|
|
555
|
-
`(${this.params?.port})`
|
|
556
|
-
)
|
|
557
|
-
} else {
|
|
558
|
-
DyFM_Log.error(
|
|
559
|
-
`Socket Server Service - Deep Setup failed: "${this.params?.name}" ` +
|
|
560
|
-
`(${this.params?.port})`,
|
|
561
|
-
error
|
|
562
|
-
);
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
throw error;
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
protected async addSocketToPresence(newPresence: T_Presence): Promise<void> {
|
|
570
|
-
try {
|
|
571
|
-
const activePresence: T_Presence = this.presences.find(
|
|
572
|
-
(pres: T_Presence) => pres.issuerLocalId === newPresence.issuerLocalId
|
|
573
|
-
);
|
|
574
|
-
|
|
575
|
-
if (activePresence) {
|
|
576
|
-
activePresence.sockets.push(...newPresence.sockets);
|
|
577
|
-
} else {
|
|
578
|
-
this.presences.push(newPresence);
|
|
579
|
-
}
|
|
580
|
-
} catch (error) {
|
|
581
|
-
if (error instanceof DyFM_Error) {
|
|
582
|
-
error.logShort(
|
|
583
|
-
`Socket Subscription failed: "${this.params?.name}" (${this.params?.port})`
|
|
584
|
-
)
|
|
585
|
-
} else if (DyNTS_global_settings.log_settings.socket_eventContent) {
|
|
586
|
-
DyFM_Log.error(
|
|
587
|
-
`Socket Subscription failed: "${this.params?.name}" (${this.params?.port})`,
|
|
588
|
-
/* `${this.thisLocationStack}`, */
|
|
589
|
-
error
|
|
590
|
-
);
|
|
591
|
-
} else {
|
|
592
|
-
DyFM_Log.error(
|
|
593
|
-
`Socket Subscription failed: "${this.params?.name}" (${this.params?.port})`,
|
|
594
|
-
/* `${this.thisLocationStack}` */
|
|
595
|
-
);
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
throw error;
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
protected async closeSocket(socket: SocketIO.Socket, issuer: string, withError?: DyFM_AnyError): Promise<void> {
|
|
603
|
-
try {
|
|
604
|
-
if (withError) {
|
|
605
|
-
socket.emit(DyFM_SocketEvent_Key.error, withError);
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
await this.executeDisconnectTasks(socket, issuer);
|
|
609
|
-
|
|
610
|
-
/* if (this.getSubscriptionCloseTasks) {
|
|
611
|
-
await DyFM_Array.asyncForEach(
|
|
612
|
-
this.getSubscriptionCloseTasks(),
|
|
613
|
-
async (task: DyFM_SocketEventTask<null>) => {
|
|
614
|
-
await task(null, issuer);
|
|
615
|
-
}
|
|
616
|
-
);
|
|
617
|
-
} */
|
|
618
|
-
|
|
619
|
-
socket.disconnect();
|
|
620
|
-
} catch (error) {
|
|
621
|
-
throw new DyFM_Error({
|
|
622
|
-
...this._getDefaultErrorSettings('closeSocket', error),
|
|
623
|
-
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-CS0`,
|
|
624
|
-
});
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
/** Disconnect taskokat socketenkent pontosan egyszer, magaval a sockettel futtatja. */
|
|
629
|
-
protected async executeDisconnectTasks(
|
|
630
|
-
socket: SocketIO.Socket,
|
|
631
|
-
issuer: string
|
|
632
|
-
): Promise<void> {
|
|
633
|
-
if (this.disconnectedSockets.has(socket)) {
|
|
634
|
-
return;
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
this.disconnectedSockets.add(socket);
|
|
638
|
-
try {
|
|
639
|
-
await DyFM_Array.asyncForEach(
|
|
640
|
-
this.incomingEvents.filter(
|
|
641
|
-
(event: DyFM_SocketEvent<unknown>): boolean =>
|
|
642
|
-
event.eventKey === DyFM_SocketEvent_Key.disconnect
|
|
643
|
-
),
|
|
644
|
-
async (event: DyFM_SocketEvent<unknown>): Promise<void> => {
|
|
645
|
-
await event.executeEventTasks(socket, issuer);
|
|
646
|
-
}
|
|
647
|
-
);
|
|
648
|
-
await this.removeSocketFromPresence(socket);
|
|
649
|
-
DyFM_Log.info(`< x > socket(${this.params.name}) disconnected (${issuer})`);
|
|
650
|
-
} catch (error) {
|
|
651
|
-
this.disconnectedSockets.delete(socket);
|
|
652
|
-
throw error;
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
protected async removeSocketFromPresence(socket: SocketIO.Socket): Promise<void> {
|
|
657
|
-
try {
|
|
658
|
-
const presence: T_Presence = this.presences.find(
|
|
659
|
-
(pres: T_Presence) => pres.sockets.includes(socket)
|
|
660
|
-
);
|
|
661
|
-
|
|
662
|
-
if (presence) {
|
|
663
|
-
const socketIndex: number = presence.sockets.indexOf(socket);
|
|
664
|
-
|
|
665
|
-
if (socketIndex !== -1) {
|
|
666
|
-
presence.sockets.splice(socketIndex, 1);
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
if (presence.sockets.length === 0) {
|
|
670
|
-
const presenceIndex: number = this.presences.indexOf(presence);
|
|
671
|
-
|
|
672
|
-
if (presenceIndex !== -1) {
|
|
673
|
-
this.presences.splice(presenceIndex, 1);
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
} catch (error) {
|
|
678
|
-
throw new DyFM_Error({
|
|
679
|
-
...this._getDefaultErrorSettings('removeSocketFromPresence', error),
|
|
680
|
-
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-RSO0`,
|
|
681
|
-
});
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
private async removeSubscription(socket: SocketIO.Socket, issuer?: string): Promise<void> {
|
|
686
|
-
try {
|
|
687
|
-
if (!this.presences.length) {
|
|
688
|
-
throw new DyFM_Error({
|
|
689
|
-
...this._getDefaultErrorSettings(
|
|
690
|
-
'removeSubscription',
|
|
691
|
-
new Error(`No presences found (${this.params.name})`),
|
|
692
|
-
issuer ?? 'unknown issuer'
|
|
693
|
-
),
|
|
694
|
-
|
|
695
|
-
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-RS1`,
|
|
696
|
-
});
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
const activePresenceIndex: number = this.presences.findIndex(
|
|
700
|
-
(pres: DyNTS_SocketPresence) => pres.sockets.includes(socket)
|
|
701
|
-
);
|
|
702
|
-
|
|
703
|
-
if (activePresenceIndex === -1) {
|
|
704
|
-
throw new DyFM_Error({
|
|
705
|
-
...this._getDefaultErrorSettings(
|
|
706
|
-
'sendEventForId',
|
|
707
|
-
new Error(
|
|
708
|
-
`closing socket (${this.params.name}) does not match any in the activePresences`
|
|
709
|
-
),
|
|
710
|
-
issuer ?? 'unknown issuer'
|
|
711
|
-
),
|
|
712
|
-
|
|
713
|
-
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-RS2`,
|
|
714
|
-
});
|
|
715
|
-
}
|
|
716
|
-
|
|
717
|
-
const activePresence: DyNTS_SocketPresence = this.presences[activePresenceIndex];
|
|
718
|
-
|
|
719
|
-
if (issuer && activePresence.issuerLocalId !== issuer) {
|
|
720
|
-
throw new DyFM_Error({
|
|
721
|
-
...this._getDefaultErrorSettings(
|
|
722
|
-
'sendEventForId',
|
|
723
|
-
new Error(
|
|
724
|
-
`socket unsubscription for "${issuer}" and ` +
|
|
725
|
-
`"${activePresence.issuerLocalId}" does not match.`
|
|
726
|
-
),
|
|
727
|
-
issuer
|
|
728
|
-
),
|
|
729
|
-
|
|
730
|
-
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-RS3`,
|
|
731
|
-
});
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
const socketIndex = activePresence.sockets.findIndex((s: SocketIO.Socket) => s === socket);
|
|
735
|
-
|
|
736
|
-
if (socketIndex === -1) {
|
|
737
|
-
throw new DyFM_Error({
|
|
738
|
-
...this._getDefaultErrorSettings(
|
|
739
|
-
'sendEventForId',
|
|
740
|
-
new Error(
|
|
741
|
-
`closing socket (${this.params.name}) does not match any in the activePresences`
|
|
742
|
-
),
|
|
743
|
-
activePresence.issuerLocalId
|
|
744
|
-
),
|
|
745
|
-
|
|
746
|
-
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-RS4`,
|
|
747
|
-
});
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
activePresence.sockets.splice(socketIndex, 1);
|
|
751
|
-
|
|
752
|
-
await DyFM_Array.asyncForEach(
|
|
753
|
-
this.incomingEvents.filter(
|
|
754
|
-
(event: DyFM_SocketEvent<any>) =>
|
|
755
|
-
event.eventKey === DyFM_SocketEvent_Key.unsubscribeSuccessful
|
|
756
|
-
),
|
|
757
|
-
async (event: DyFM_SocketEvent<any>) => {
|
|
758
|
-
await event.executeEventTasks(null, issuer);
|
|
759
|
-
}
|
|
760
|
-
);
|
|
761
|
-
|
|
762
|
-
/* if (this.getSubscriptionCloseTasks) {
|
|
763
|
-
await DyFM_Array.asyncForEach(
|
|
764
|
-
this.getSubscriptionCloseTasks(),
|
|
765
|
-
async (task: DyFM_SocketEventTask<null>) => {
|
|
766
|
-
await task(null, issuer);
|
|
767
|
-
}
|
|
768
|
-
);
|
|
769
|
-
} */
|
|
770
|
-
|
|
771
|
-
if (activePresence.sockets.length === 0) {
|
|
772
|
-
this.presences.splice(activePresenceIndex, 1);
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
socket.emit(DyFM_SocketEvent_Key.unsubscribeSuccessful, 'unsubscribe was successful');
|
|
776
|
-
socket.disconnect();
|
|
777
|
-
DyFM_Log.info(`<x==> socket (${this.params.name}) unsubscription successful (${issuer})`);
|
|
778
|
-
} catch (error) {
|
|
779
|
-
throw new DyFM_Error({
|
|
780
|
-
...this._getDefaultErrorSettings(
|
|
781
|
-
'sendEventForId',
|
|
782
|
-
error,
|
|
783
|
-
issuer ?? 'unknown issuer'
|
|
784
|
-
),
|
|
785
|
-
|
|
786
|
-
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-RS0`,
|
|
787
|
-
message: `socket (${this.params.name}) Subscription Removal failed: "${this.params?.name}"`,
|
|
788
|
-
});
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
/* emitServerEvent(event: string, content: any): void {
|
|
793
|
-
try {
|
|
794
|
-
DyFM_Log.log(` <=-- emitting server socket(${this.params.name}) event: ${event}`);
|
|
795
|
-
|
|
796
|
-
this.openSocketServer.emit(event, content, error => {
|
|
797
|
-
DyFM_Log.error(`Emitting server event '${event}' failed!\nerror:`, error);
|
|
798
|
-
});
|
|
799
|
-
} catch (error) {
|
|
800
|
-
throw new DyFM_Error({
|
|
801
|
-
...this._getDefaultErrorSettings(
|
|
802
|
-
'emitEvent',
|
|
803
|
-
error
|
|
804
|
-
),
|
|
805
|
-
|
|
806
|
-
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-500',
|
|
807
|
-
message: `socket(${this.params.name}) Event Emit (${event}) failed: ${this.params?.name}`,
|
|
808
|
-
});
|
|
809
|
-
}
|
|
810
|
-
} */
|
|
811
|
-
|
|
812
|
-
idIsSubscribed(id: string): boolean {
|
|
813
|
-
try {
|
|
814
|
-
return !!this.presences.find(
|
|
815
|
-
(presence: DyNTS_SocketPresence) => presence.issuerLocalId === id
|
|
816
|
-
);
|
|
817
|
-
} catch (error) {
|
|
818
|
-
throw new DyFM_Error({
|
|
819
|
-
...this._getDefaultErrorSettings(
|
|
820
|
-
'idIsSubscribed',
|
|
821
|
-
error
|
|
822
|
-
),
|
|
823
|
-
|
|
824
|
-
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-IIS0`,
|
|
825
|
-
message: `socket (${this.params.name}) ID Subscription Check (${id}) failed`,
|
|
826
|
-
});
|
|
827
|
-
}
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
async emitError(presenceIssuerId: string, error: any, issuer: string): Promise<void> {
|
|
831
|
-
try {
|
|
832
|
-
await this.sendEventForId(presenceIssuerId, DyFM_SocketEvent_Key.error, error, issuer);
|
|
833
|
-
} catch (error) {
|
|
834
|
-
throw new DyFM_Error({
|
|
835
|
-
...this._getDefaultErrorSettings(
|
|
836
|
-
'emitError',
|
|
837
|
-
error,
|
|
838
|
-
presenceIssuerId
|
|
839
|
-
),
|
|
840
|
-
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-EE0`,
|
|
841
|
-
message: `socket (${this.params.name}) Error Emit (id: ${presenceIssuerId}) failed`,
|
|
842
|
-
});
|
|
843
|
-
}
|
|
844
|
-
}
|
|
845
|
-
|
|
846
|
-
async sendEventForId(id: string, event: string, content: any, issuer: string): Promise<void> {
|
|
847
|
-
try {
|
|
848
|
-
if (!event) {
|
|
849
|
-
throw new DyFM_Error({
|
|
850
|
-
...this._getDefaultErrorSettings(
|
|
851
|
-
'sendEventForId',
|
|
852
|
-
new Error('No event was provided'),
|
|
853
|
-
content?.source
|
|
854
|
-
),
|
|
855
|
-
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-SEFI1`,
|
|
856
|
-
});
|
|
857
|
-
}
|
|
858
|
-
|
|
859
|
-
if (!id) {
|
|
860
|
-
throw new DyFM_Error({
|
|
861
|
-
...this._getDefaultErrorSettings(
|
|
862
|
-
'sendEventForId',
|
|
863
|
-
new Error('No ID was provided'),
|
|
864
|
-
content?.source
|
|
865
|
-
),
|
|
866
|
-
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-SEFI2`,
|
|
867
|
-
});
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
const presence: DyNTS_SocketPresence = this.presences.find(
|
|
871
|
-
(pres: DyNTS_SocketPresence) => pres.issuerLocalId === id
|
|
872
|
-
);
|
|
873
|
-
|
|
874
|
-
if (!presence) {
|
|
875
|
-
throw new DyFM_Error({
|
|
876
|
-
...this._getDefaultErrorSettings(
|
|
877
|
-
'sendEventForId',
|
|
878
|
-
new Error(`No active socket with this specific ID: "${id}"`),
|
|
879
|
-
content?.source
|
|
880
|
-
),
|
|
881
|
-
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-SEFI3`,
|
|
882
|
-
});
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
presence.emitEvent(event, content, issuer);
|
|
886
|
-
|
|
887
|
-
if (DyNTS_global_settings.log_settings.socket_eventContent) {
|
|
888
|
-
DyFM_Log.success(
|
|
889
|
-
` <--= emitted socket (${this.params.name}) event: "${event}", ` +
|
|
890
|
-
`\n presenceId: "${id}", sockets: ${presence.sockets.length}` +
|
|
891
|
-
`\n content:`, content
|
|
892
|
-
);
|
|
893
|
-
} else {
|
|
894
|
-
DyFM_Log.success(
|
|
895
|
-
` <--= emitted socket (${this.params.name}) event: "${event}", ` +
|
|
896
|
-
`\n presenceId: ${id}, sockets: ${presence.sockets.length}`
|
|
897
|
-
);
|
|
898
|
-
}
|
|
899
|
-
} catch (error) {
|
|
900
|
-
try {
|
|
901
|
-
if (error?.flag?.includes(DyFM_errorFlag) && error?.additionalInfo?.inactiveSockets) {
|
|
902
|
-
const sockets: SocketIO.Socket[] = error.additionalInfo.inactiveSockets;
|
|
903
|
-
|
|
904
|
-
await DyFM_Array.asyncForEach(sockets, async (socket: SocketIO.Socket) => {
|
|
905
|
-
await this.removeSubscription(socket);
|
|
906
|
-
});
|
|
907
|
-
|
|
908
|
-
const presence: DyNTS_SocketPresence = this.presences.find(
|
|
909
|
-
(pres: DyNTS_SocketPresence) => pres.issuerLocalId === id
|
|
910
|
-
);
|
|
911
|
-
|
|
912
|
-
if (!presence) {
|
|
913
|
-
throw new DyFM_Error({
|
|
914
|
-
...this._getDefaultErrorSettings(
|
|
915
|
-
'sendEventForId',
|
|
916
|
-
new Error(`No active socket (${this.params.name}) with this specific ID: "${id}"`),
|
|
917
|
-
content?.source
|
|
918
|
-
),
|
|
919
|
-
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-SEFI4`,
|
|
920
|
-
});
|
|
921
|
-
}
|
|
922
|
-
}
|
|
923
|
-
} catch (error) {
|
|
924
|
-
throw new DyFM_Error({
|
|
925
|
-
...this._getDefaultErrorSettings('sendEventForId', error, content?.source),
|
|
926
|
-
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-SEFI5`,
|
|
927
|
-
message:
|
|
928
|
-
`Error handling of inactive sockets (${this.params.name}) failed!` +
|
|
929
|
-
`\n(Socket Event Emit for id (${id}, ${event}) failed)`,
|
|
930
|
-
});
|
|
931
|
-
}
|
|
932
|
-
|
|
933
|
-
throw new DyFM_Error({
|
|
934
|
-
...this._getDefaultErrorSettings('sendEventForId', error, content?.source),
|
|
935
|
-
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-SEFI0`,
|
|
936
|
-
message: `socket (${this.params.name}) Event Emit for id (${id}, ${event}) failed`,
|
|
937
|
-
});
|
|
938
|
-
}
|
|
939
|
-
}
|
|
940
|
-
|
|
941
|
-
async broadcastEvent(event: string, content: any, issuer: string): Promise<void> {
|
|
942
|
-
try {
|
|
943
|
-
DyFM_Log.log(`<=-== broadcasting socket (${this.params.name}) event: "${event}"`);
|
|
944
|
-
|
|
945
|
-
this.presences.forEach((presence: DyNTS_SocketPresence) => {
|
|
946
|
-
presence.emitEvent(event, content, issuer);
|
|
947
|
-
});
|
|
948
|
-
} catch (error) {
|
|
949
|
-
if (DyNTS_global_settings.log_settings.detailedErrors) {
|
|
950
|
-
if (error instanceof DyFM_Error) {
|
|
951
|
-
error.logSimple(`socket (${this.params.name}) Event Broadcast (${event}) failed`);
|
|
952
|
-
} else {
|
|
953
|
-
DyFM_Log.error(`socket (${this.params.name}) Event Broadcast (${event}) failed`, error);
|
|
954
|
-
}
|
|
955
|
-
}
|
|
956
|
-
|
|
957
|
-
throw new DyFM_Error({
|
|
958
|
-
...this._getDefaultErrorSettings('broadcastEvent', error),
|
|
959
|
-
|
|
960
|
-
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-BE0`,
|
|
961
|
-
message: `socket (${this.params.name}) Event Broadcast (${event}) failed`,
|
|
962
|
-
});
|
|
963
|
-
}
|
|
964
|
-
}
|
|
965
|
-
|
|
966
|
-
async sendError(error: DyFM_AnyError, issuer: string): Promise<void> {
|
|
967
|
-
try {
|
|
968
|
-
await this.sendEventForId(issuer, DyFM_SocketEvent_Key.error, error, issuer);
|
|
969
|
-
} catch (error) {
|
|
970
|
-
throw new DyFM_Error({
|
|
971
|
-
...this._getDefaultErrorSettings('sendError', error, issuer),
|
|
972
|
-
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-SE0`,
|
|
973
|
-
message: `socket (${this.params.name}) Error Send (${issuer}) failed`,
|
|
974
|
-
});
|
|
975
|
-
}
|
|
976
|
-
}
|
|
977
|
-
|
|
978
|
-
private _getDefaultErrorSettings(
|
|
979
|
-
fnName: string,
|
|
980
|
-
error: DyFM_AnyError,
|
|
981
|
-
issuer?: string
|
|
982
|
-
): DyFM_Error_Settings {
|
|
983
|
-
return {
|
|
984
|
-
status: (error as DyFM_Error)?.___status ?? 500,
|
|
985
|
-
message: (error as Error)?.message ??
|
|
986
|
-
(error as DyFM_Error)?._message ??
|
|
987
|
-
`${fnName} was UNSUCCESSFUL (NTS)`,
|
|
988
|
-
addECToUserMsg: !(error as DyFM_Error)?.__userMessage,
|
|
989
|
-
userMessage: (error as DyFM_Error)?.__userMessage ?? this.defaultErrorUserMsg,
|
|
990
|
-
issuer: issuer,
|
|
991
|
-
issuerService: this.constructor?.name,
|
|
992
|
-
error: error,
|
|
993
|
-
};
|
|
994
|
-
}
|
|
995
|
-
|
|
996
|
-
/**
|
|
997
|
-
* You must setup params for the service in this function
|
|
998
|
-
*/
|
|
999
|
-
protected abstract getServiceParams(): DyNTS_SocketServerService_Params;
|
|
1000
|
-
|
|
1001
|
-
/**
|
|
1002
|
-
* You must setup events and required services in this function
|
|
1003
|
-
*/
|
|
1004
|
-
protected abstract getIncomingEvents(): DyFM_SocketEvent<any>[];
|
|
1005
|
-
|
|
1006
|
-
/**
|
|
1007
|
-
* You can setup tasks for the subscription event in this function
|
|
1008
|
-
*/
|
|
1009
|
-
/* protected getSubscriptionCloseTasks?(): DyFM_SocketEventTask<null>[]; */
|
|
1010
|
-
|
|
1011
|
-
/**
|
|
1012
|
-
* You can setup preprocesses for the subscription event in this function
|
|
1013
|
-
*/
|
|
1014
|
-
/* protected getSubscriptionPreProcesses?(): DyFM_SocketEventPreprocessTask[]; */
|
|
1015
|
-
|
|
1016
|
-
/**
|
|
1017
|
-
* You can setup tasks for the subscription event in this function
|
|
1018
|
-
* This will happen after the presence is created
|
|
1019
|
-
* If this throws an error, the socket will be closed
|
|
1020
|
-
*/
|
|
1021
|
-
protected getSubscriptionTasks?(): DyFM_SocketEventTask<T_SubscriptionContent>[];
|
|
1022
|
-
|
|
1023
|
-
/**
|
|
1024
|
-
* You can setup tasks for the unsubscribe event in this function
|
|
1025
|
-
*/
|
|
1026
|
-
/* protected getUnsubscribeTasks?(): DyFM_SocketEventTask<T_SubscriptionContent>[]; */
|
|
1027
|
-
|
|
1028
|
-
/**
|
|
1029
|
-
* You can setup preprocesses for the unsubscribe event in this function
|
|
1030
|
-
*/
|
|
1031
|
-
/* protected getUnsubscribePreProcesses?(): DyFM_SocketEventPreprocessTask[]; */
|
|
1032
|
-
|
|
1033
|
-
/**
|
|
1034
|
-
* You can setup tasks for the error event in this function
|
|
1035
|
-
*/
|
|
1036
|
-
protected errorHandling?: DyFM_SocketEventTask<T_ErrorContent>;
|
|
1037
|
-
}
|
|
1
|
+
|
|
2
|
+
import * as SocketIO from 'socket.io';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
DyFM_AnyError, DyFM_Array, DyFM_Error, DyFM_Error_Settings, DyFM_errorFlag, DyFM_Log
|
|
6
|
+
} from '@futdevpro/fsm-dynamo';
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
DyFM_SocketEvent,
|
|
11
|
+
DyFM_SocketEvent_Key, DyFM_SocketEventPreprocessTask, DyFM_SocketEventTask
|
|
12
|
+
} from '@futdevpro/fsm-dynamo/socket';
|
|
13
|
+
|
|
14
|
+
import { DyNTS_global_settings } from '../../../_collections/global-settings.const';
|
|
15
|
+
import { DyNTS_SingletonService } from '../../../_services/base/singleton.service';
|
|
16
|
+
import { DyNTS_SocketSecurity } from '../_enums/socket-security.enum';
|
|
17
|
+
import {
|
|
18
|
+
DyNTS_SocketPresence
|
|
19
|
+
} from '../_models/socket-presence.control-model';
|
|
20
|
+
import {
|
|
21
|
+
DyNTS_SocketServerService_Params
|
|
22
|
+
} from '../_models/socket-server-service-params.control-model';
|
|
23
|
+
|
|
24
|
+
/** Opciók a setupSocketServer híváshoz: attacholt HTTP szerver esetén ne hívjuk a listen()-t. */
|
|
25
|
+
export interface DyNTS_SocketServerSetupOptions {
|
|
26
|
+
/** Ha true, a Socket.IO egy már listenelő HTTP/HTTPS szerverre van attacholva – ne hívjuk a listen()-t. */
|
|
27
|
+
attachedToExistingServer?: boolean;
|
|
28
|
+
/** A tényleges port (pl. defaultolt httpPort/httpsPort) – logokban használjuk. */
|
|
29
|
+
effectivePort?: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* You need to define the following functions:
|
|
34
|
+
* ```ts
|
|
35
|
+
* getServiceParams(): DyNTS_SocketServerServiceParams;
|
|
36
|
+
*
|
|
37
|
+
* getIncomingEvents(): DyFM_SocketEvent<any>[];
|
|
38
|
+
*
|
|
39
|
+
* getPresenceFromSubscriptionEventContent(
|
|
40
|
+
* socketSubscription: T_SubscriptionContent,
|
|
41
|
+
* socket: SocketIO.Socket
|
|
42
|
+
* ): Promise<T_Presence>;
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export abstract class DyNTS_SocketServerService<
|
|
46
|
+
T_Presence extends DyNTS_SocketPresence = DyNTS_SocketPresence,
|
|
47
|
+
T_SubscriptionContent = any,
|
|
48
|
+
T_ErrorContent = any
|
|
49
|
+
> extends DyNTS_SingletonService {
|
|
50
|
+
|
|
51
|
+
protected params: DyNTS_SocketServerService_Params;
|
|
52
|
+
get name(): string { return this.params.name; }
|
|
53
|
+
get port(): number | undefined { return this.params.port; }
|
|
54
|
+
/** BFR-MASTERPROMPTER-025: explicit dedikált-listener opt-in (default false = shared). */
|
|
55
|
+
get dedicatedPort(): boolean { return this.params.dedicatedPort ?? false; }
|
|
56
|
+
get security(): DyNTS_SocketSecurity { return this.params.security; }
|
|
57
|
+
get activeSubscriptionsCount(): number { return this.presences.length; }
|
|
58
|
+
|
|
59
|
+
protected openSocketServer: SocketIO.Server;
|
|
60
|
+
protected secureSocketServer: SocketIO.Server;
|
|
61
|
+
|
|
62
|
+
/* private connectEvent: DyFM_SocketEvent<SocketIO.Socket>; */
|
|
63
|
+
protected incomingEvents: DyFM_SocketEvent<any>[];
|
|
64
|
+
|
|
65
|
+
/* private subscriptionEvent: DyFM_SocketEvent<any>; */
|
|
66
|
+
/* private unsubscribeEvent: DyFM_SocketEvent<any>; */
|
|
67
|
+
|
|
68
|
+
protected presences: T_Presence[] = [];
|
|
69
|
+
private readonly disconnectedSockets: WeakSet<SocketIO.Socket> = new WeakSet();
|
|
70
|
+
|
|
71
|
+
get logSetup(): boolean { return DyNTS_global_settings.log_settings.setup; }
|
|
72
|
+
get highDetailedLogs(): boolean { return DyNTS_global_settings.log_settings.highDetailedLogs; }
|
|
73
|
+
|
|
74
|
+
override readonly defaultErrorUserMsg =
|
|
75
|
+
`We encountered an unhandled Socket Server Error, ` +
|
|
76
|
+
`\nplease contact the responsible development team.`;
|
|
77
|
+
|
|
78
|
+
/* readonly thisLocationStack: string; */
|
|
79
|
+
|
|
80
|
+
protected constructor(){
|
|
81
|
+
super();
|
|
82
|
+
|
|
83
|
+
/* this.thisLocationStack = DyNTS_getStackLocation(); */
|
|
84
|
+
|
|
85
|
+
this.asyncConstructor().catch((error: any) => {
|
|
86
|
+
DyFM_Log.error(
|
|
87
|
+
`Socket Server Service setup failed: "${this.params?.name}" (${this.params?.port})`,
|
|
88
|
+
error
|
|
89
|
+
);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* You need to setup a function that converts subscription event content to presence.
|
|
95
|
+
* You should do authentication and authorization here.
|
|
96
|
+
*/
|
|
97
|
+
protected abstract getPresenceFromSubscriptionEventContent(
|
|
98
|
+
socketSubscription: T_SubscriptionContent,
|
|
99
|
+
socket: SocketIO.Socket
|
|
100
|
+
): Promise<T_Presence>;
|
|
101
|
+
|
|
102
|
+
private async asyncConstructor(): Promise<void> {
|
|
103
|
+
try {
|
|
104
|
+
this.params = this.getServiceParams();
|
|
105
|
+
this.incomingEvents = this.getIncomingEvents() ?? [];
|
|
106
|
+
|
|
107
|
+
await this.prepareEvents();
|
|
108
|
+
|
|
109
|
+
if (this.logSetup) console.log(
|
|
110
|
+
`Socket Server Service setup done: "${this.params.name}" (${this.params.port}) ` +
|
|
111
|
+
`security: ${this.params.security}\n`
|
|
112
|
+
);
|
|
113
|
+
} catch (error) {
|
|
114
|
+
DyFM_Log.error(
|
|
115
|
+
`Socket Server Service setup failed: "${this.params?.name}" (${this.params?.port})`,
|
|
116
|
+
error
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
throw new DyFM_Error({
|
|
120
|
+
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-GPFSRC0`,
|
|
121
|
+
error: error,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* You must setup events and required services for this function
|
|
128
|
+
*/
|
|
129
|
+
private async prepareEvents(): Promise<void> {
|
|
130
|
+
try {
|
|
131
|
+
/** Setup connect event */
|
|
132
|
+
/* const connectEventIndex = this.incomingEvents.findIndex(
|
|
133
|
+
(event: DyFM_SocketEvent<any>) =>
|
|
134
|
+
event.eventKey === DyFM_SocketEvent_Key.connection
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
if (0 <= connectEventIndex) {
|
|
138
|
+
this.connectEvent = this.incomingEvents.splice(connectEventIndex)[0];
|
|
139
|
+
} else {
|
|
140
|
+
this.connectEvent = new DyFM_SocketEvent({
|
|
141
|
+
eventKey: DyFM_SocketEvent_Key.connection,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
this.connectEvent.serviceName = this.params.name; */
|
|
145
|
+
|
|
146
|
+
if (!this.getPresenceFromSubscriptionEventContent) {
|
|
147
|
+
throw new DyFM_Error({
|
|
148
|
+
error: new Error('getPresenceFromSubscriptionEventContent must be set'),
|
|
149
|
+
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-PPE1`,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (!this.getSubscriptionTasks) {
|
|
154
|
+
DyFM_Log.warn(
|
|
155
|
+
`You should not set the subscription event, ` +
|
|
156
|
+
`in case you need additional steps for your subscriptions.`,
|
|
157
|
+
`${this.params.name} (${this.params.port})`
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (this.incomingEvents.find(
|
|
162
|
+
(event: DyFM_SocketEvent<any>) =>
|
|
163
|
+
event.eventKey === DyFM_SocketEvent_Key.subscribe
|
|
164
|
+
)) {
|
|
165
|
+
DyFM_Log.warn(
|
|
166
|
+
`You need to use getSubscriptionTasks() ` +
|
|
167
|
+
`instead of setting the subscribe event in getIncomingEvents().`,
|
|
168
|
+
`${this.params.name} (${this.params.port})`
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (!this.incomingEvents.find(
|
|
173
|
+
(event: DyFM_SocketEvent<any>) =>
|
|
174
|
+
event.eventKey === DyFM_SocketEvent_Key.unsubscribe
|
|
175
|
+
)) {
|
|
176
|
+
DyFM_Log.warn(
|
|
177
|
+
`You should not set the unsubscribe event, ` +
|
|
178
|
+
`in case you need additional steps for your unsubscribe.`,
|
|
179
|
+
`${this.params.name} (${this.params.port})`
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (this.incomingEvents.find(
|
|
184
|
+
(event: DyFM_SocketEvent<any>) => !event.eventKey
|
|
185
|
+
)) {
|
|
186
|
+
throw new DyFM_Error({
|
|
187
|
+
error: new Error('eventKey must be set'),
|
|
188
|
+
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-PPE2`,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
this.incomingEvents.push(
|
|
193
|
+
new DyFM_SocketEvent({
|
|
194
|
+
eventKey: DyFM_SocketEvent_Key.disconnect,
|
|
195
|
+
})
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
if (this.errorHandling) {
|
|
199
|
+
this.incomingEvents.push(new DyFM_SocketEvent<T_ErrorContent>({
|
|
200
|
+
serviceName: this.params.name,
|
|
201
|
+
eventKey: DyFM_SocketEvent_Key.error,
|
|
202
|
+
tasks: [
|
|
203
|
+
async (content: any) => this.errorHandling(content),
|
|
204
|
+
],
|
|
205
|
+
}));
|
|
206
|
+
} else {
|
|
207
|
+
DyFM_Log.warn(
|
|
208
|
+
`You should not set the error event, ` +
|
|
209
|
+
`in case you need additional steps for your error.`,
|
|
210
|
+
`${this.params.name} (${this.params.port})`
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
this.incomingEvents.push(new DyFM_SocketEvent<T_ErrorContent>({
|
|
214
|
+
serviceName: this.params.name,
|
|
215
|
+
eventKey: DyFM_SocketEvent_Key.error,
|
|
216
|
+
tasks: [
|
|
217
|
+
async (content: any) => {
|
|
218
|
+
if (content instanceof DyFM_Error) {
|
|
219
|
+
content.logSimple(`=--> socket-client (${this.params.name}) ERROR`);
|
|
220
|
+
} else {
|
|
221
|
+
DyFM_Log.error(`=--> socket-client (${this.params.name}) ERROR:`, content);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
],
|
|
225
|
+
}));
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Merge incoming events of the same eventKey
|
|
229
|
+
const eventKeys = this.incomingEvents.map(
|
|
230
|
+
(event: DyFM_SocketEvent<any>) => event.eventKey
|
|
231
|
+
).filter(
|
|
232
|
+
(eventKey: string, index: number, self: string[]) =>
|
|
233
|
+
self.indexOf(eventKey) === index
|
|
234
|
+
);
|
|
235
|
+
const mergedEvents: DyFM_SocketEvent<any>[] = [];
|
|
236
|
+
eventKeys.forEach((eventKey: string) => {
|
|
237
|
+
const events = this.incomingEvents.filter(
|
|
238
|
+
(event: DyFM_SocketEvent<any>) => event.eventKey === eventKey
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
mergedEvents.push(new DyFM_SocketEvent({
|
|
242
|
+
eventKey: eventKey,
|
|
243
|
+
preProcesses: events.map((event: DyFM_SocketEvent<any>) => event.preProcesses).flat(),
|
|
244
|
+
tasks: events.map((event: DyFM_SocketEvent<any>) => event.tasks).flat(),
|
|
245
|
+
}));
|
|
246
|
+
});
|
|
247
|
+
this.incomingEvents = mergedEvents;
|
|
248
|
+
|
|
249
|
+
if (DyNTS_global_settings.log_settings.setup) {
|
|
250
|
+
DyFM_Log.log(
|
|
251
|
+
`Socket Server Service - Event Preparation setup done: ` +
|
|
252
|
+
`"${this.params?.name}" (${this.params?.port})` +
|
|
253
|
+
`\nincomingEvents:`, this.incomingEvents.map(
|
|
254
|
+
(event: DyFM_SocketEvent<any>) =>
|
|
255
|
+
`\n\t"${event.eventKey}": preProcesses: ${event.preProcesses?.length} ` +
|
|
256
|
+
`tasks: ${event.tasks?.length}`
|
|
257
|
+
)
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Set incoming events serviceName
|
|
262
|
+
this.incomingEvents.forEach((event: DyFM_SocketEvent<any>) => {
|
|
263
|
+
event.serviceName = this.params.name;
|
|
264
|
+
});
|
|
265
|
+
} catch (error) {
|
|
266
|
+
DyFM_Log.error(
|
|
267
|
+
`Socket Server Service - Event Preparation setup failed: ` +
|
|
268
|
+
`"${this.params?.name}" (${this.params?.port})`,
|
|
269
|
+
error
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
throw error;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// eslint-disable-next-line max-lines-per-function
|
|
277
|
+
async setupSocketServer(
|
|
278
|
+
newSocketServer: SocketIO.Server,
|
|
279
|
+
security: DyNTS_SocketSecurity.open | DyNTS_SocketSecurity.secure,
|
|
280
|
+
successCallback: () => void,
|
|
281
|
+
options?: DyNTS_SocketServerSetupOptions
|
|
282
|
+
): Promise<SocketIO.Server> {
|
|
283
|
+
try {
|
|
284
|
+
if (this.highDetailedLogs) console.log('\nfn:. setupSocketServer');
|
|
285
|
+
|
|
286
|
+
const effectivePort: number | undefined = options?.effectivePort ?? this.params.port;
|
|
287
|
+
|
|
288
|
+
newSocketServer.on(DyFM_SocketEvent_Key.incomingNewConnection, async (socket: SocketIO.Socket) => {
|
|
289
|
+
try {
|
|
290
|
+
let issuer: string = `${this.params.name} anonymous socket`;
|
|
291
|
+
|
|
292
|
+
/* await this.connectEvent.executeEventTasks(socket); */
|
|
293
|
+
|
|
294
|
+
await DyFM_Array.asyncForEach(
|
|
295
|
+
this.incomingEvents.filter(
|
|
296
|
+
(event: DyFM_SocketEvent<any>) =>
|
|
297
|
+
event.eventKey === DyFM_SocketEvent_Key.incomingNewConnection
|
|
298
|
+
),
|
|
299
|
+
async (event: DyFM_SocketEvent<any>) => {
|
|
300
|
+
await event.executeEventTasks(socket);
|
|
301
|
+
}
|
|
302
|
+
);
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
if (this.getPresenceFromSubscriptionEventContent) {
|
|
306
|
+
socket.on(
|
|
307
|
+
DyFM_SocketEvent_Key.subscribe,
|
|
308
|
+
async (content: any) => {
|
|
309
|
+
let presence: T_Presence;
|
|
310
|
+
|
|
311
|
+
try {
|
|
312
|
+
/**
|
|
313
|
+
* usually socket logs are in event.executeEventTasks(),
|
|
314
|
+
* but subscribe event is an exception from this,
|
|
315
|
+
* to be able to check content before getPresenceFromSubscriptionEventContent
|
|
316
|
+
*/
|
|
317
|
+
if (DyNTS_global_settings.log_settings.socket_eventContent) {
|
|
318
|
+
DyFM_Log.log(
|
|
319
|
+
`--=> incoming socket (${this.params.name}) ` +
|
|
320
|
+
`event: "${DyFM_SocketEvent_Key.subscribe}";` +
|
|
321
|
+
`\ncontent:`, content
|
|
322
|
+
);
|
|
323
|
+
} else {
|
|
324
|
+
DyFM_Log.log(
|
|
325
|
+
`--=> incoming socket (${this.params.name}) ` +
|
|
326
|
+
`event: "${DyFM_SocketEvent_Key.subscribe}"`
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
presence = await this.getPresenceFromSubscriptionEventContent(
|
|
331
|
+
content, socket
|
|
332
|
+
);
|
|
333
|
+
|
|
334
|
+
presence.serviceName = this.params.name;
|
|
335
|
+
issuer = presence.issuerLocalId;
|
|
336
|
+
|
|
337
|
+
await this.addSocketToPresence(presence);
|
|
338
|
+
/* await this.subscriptionEvent.executeEventTasks(content, issuer); */
|
|
339
|
+
|
|
340
|
+
if (this.getSubscriptionTasks) {
|
|
341
|
+
await DyFM_Array.asyncForEach(
|
|
342
|
+
this.getSubscriptionTasks(),
|
|
343
|
+
async (task: DyFM_SocketEventTask<T_SubscriptionContent>) => {
|
|
344
|
+
await task(content, issuer);
|
|
345
|
+
}
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
socket.emit(
|
|
350
|
+
DyFM_SocketEvent_Key.subscriptionSuccessful,
|
|
351
|
+
'subscribe was successful',
|
|
352
|
+
error => {
|
|
353
|
+
DyFM_Log.error(
|
|
354
|
+
`Emitting subscriptionSuccessful event failed!` +
|
|
355
|
+
`\nerror:`, error
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
);
|
|
359
|
+
|
|
360
|
+
DyFM_Log.success(
|
|
361
|
+
`<-==> socket(${this.params.name}) subscription successful (${issuer})`
|
|
362
|
+
);
|
|
363
|
+
} catch (error) {
|
|
364
|
+
if (error instanceof DyFM_Error) {
|
|
365
|
+
error.logShort(
|
|
366
|
+
`Socket Subscription failed: "${this.params.name}" ` +
|
|
367
|
+
`(${this.params.port}) will disconnect now...`
|
|
368
|
+
)
|
|
369
|
+
} else if (DyNTS_global_settings.log_settings.socket_eventContent) {
|
|
370
|
+
DyFM_Log.error(
|
|
371
|
+
`Socket Subscription failed: "${this.params.name}" ` +
|
|
372
|
+
`(${this.params.port}) will disconnect now...`,
|
|
373
|
+
/* `${this.thisLocationStack}`, */
|
|
374
|
+
error
|
|
375
|
+
);
|
|
376
|
+
} else {
|
|
377
|
+
DyFM_Log.error(
|
|
378
|
+
`Socket Subscription failed: "${this.params.name}" ` ,
|
|
379
|
+
`(${this.params.port}) will disconnect now...`,
|
|
380
|
+
/* `${this.thisLocationStack}` */
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
await this.closeSocket(socket, issuer, error);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
);
|
|
387
|
+
|
|
388
|
+
socket.on(
|
|
389
|
+
DyFM_SocketEvent_Key.unsubscribe,
|
|
390
|
+
async (issuer: string) => {
|
|
391
|
+
try {
|
|
392
|
+
/**
|
|
393
|
+
* usually socket logs are in event.executeEventTasks(),
|
|
394
|
+
* but unsubscribe event is an exception from this,
|
|
395
|
+
* to be able to check content before getPresenceFromSubscriptionEventContent
|
|
396
|
+
*/
|
|
397
|
+
if (DyNTS_global_settings.log_settings.socket_eventContent) {
|
|
398
|
+
DyFM_Log.log(
|
|
399
|
+
`--=> incoming socket (${this.params.name}) ` +
|
|
400
|
+
`event: ${DyFM_SocketEvent_Key.unsubscribe};` +
|
|
401
|
+
`\ncontent:`, issuer
|
|
402
|
+
);
|
|
403
|
+
} else {
|
|
404
|
+
DyFM_Log.log(
|
|
405
|
+
`--=> incoming socket (${this.params.name}) ` +
|
|
406
|
+
`event: ${DyFM_SocketEvent_Key.unsubscribe}`
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/* await this.unsubscribeEvent.executeEventTasks(null, issuer); */
|
|
411
|
+
await DyFM_Array.asyncForEach(
|
|
412
|
+
this.incomingEvents.filter(
|
|
413
|
+
(event: DyFM_SocketEvent<any>) =>
|
|
414
|
+
event.eventKey === DyFM_SocketEvent_Key.unsubscribe
|
|
415
|
+
),
|
|
416
|
+
async (event: DyFM_SocketEvent<any>) => {
|
|
417
|
+
await event.executeEventTasks(null, issuer);
|
|
418
|
+
}
|
|
419
|
+
);
|
|
420
|
+
|
|
421
|
+
await this.removeSubscription(socket, issuer);
|
|
422
|
+
|
|
423
|
+
DyFM_Log.success(
|
|
424
|
+
`< x > socket(${this.params.name}) unsubscribe successful (${issuer})`
|
|
425
|
+
);
|
|
426
|
+
} catch (error) {
|
|
427
|
+
if (error instanceof DyFM_Error) {
|
|
428
|
+
error.logSimple(
|
|
429
|
+
`Socket Unsubscription failed: "${this.params.name}" ` +
|
|
430
|
+
`(${this.params.port}) will disconnect now...`
|
|
431
|
+
)
|
|
432
|
+
} else if (DyNTS_global_settings.log_settings.socket_eventContent) {
|
|
433
|
+
DyFM_Log.error(
|
|
434
|
+
`Socket unsubscribe failed: "${this.params.name}" ` ,
|
|
435
|
+
`(${this.params.port}) will disconnect now...`,
|
|
436
|
+
error
|
|
437
|
+
);
|
|
438
|
+
} else {
|
|
439
|
+
DyFM_Log.error(
|
|
440
|
+
`Socket unsubscribe failed: "${this.params.name}" ` ,
|
|
441
|
+
`(${this.params.port}) will disconnect now...`
|
|
442
|
+
);
|
|
443
|
+
}
|
|
444
|
+
socket.emit(DyFM_SocketEvent_Key.error, error);
|
|
445
|
+
await this.removeSubscription(socket, issuer);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
this.incomingEvents.filter(
|
|
452
|
+
(event: DyFM_SocketEvent<any>) =>
|
|
453
|
+
event.eventKey !== DyFM_SocketEvent_Key.incomingNewConnection &&
|
|
454
|
+
event.eventKey !== DyFM_SocketEvent_Key.subscribe &&
|
|
455
|
+
event.eventKey !== DyFM_SocketEvent_Key.unsubscribe
|
|
456
|
+
).forEach((event: DyFM_SocketEvent<any>) => {
|
|
457
|
+
socket.on(
|
|
458
|
+
event.eventKey,
|
|
459
|
+
async (content: any) => {
|
|
460
|
+
try {
|
|
461
|
+
if (event.eventKey === DyFM_SocketEvent_Key.disconnect) {
|
|
462
|
+
await this.executeDisconnectTasks(socket, issuer);
|
|
463
|
+
} else {
|
|
464
|
+
await event.executeEventTasks(content, issuer, socket);
|
|
465
|
+
}
|
|
466
|
+
} catch (error) {
|
|
467
|
+
if (error instanceof DyFM_Error) {
|
|
468
|
+
error.logSimple(
|
|
469
|
+
`Socket Event failed: "${this.params.name}" (${this.params.port})`
|
|
470
|
+
)
|
|
471
|
+
} else {
|
|
472
|
+
DyFM_Log.error(
|
|
473
|
+
`Socket Event failed: "${this.params.name}" (${this.params.port})`,
|
|
474
|
+
error
|
|
475
|
+
);
|
|
476
|
+
}
|
|
477
|
+
socket.emit(DyFM_SocketEvent_Key.error, error);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
);
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
if (DyNTS_global_settings.log_settings.socket_mainEvents) {
|
|
484
|
+
DyFM_Log.success(`< > socket(${this.params.name}): new CONNECTION established`);
|
|
485
|
+
}
|
|
486
|
+
} catch (error) {
|
|
487
|
+
if (error instanceof DyFM_Error) {
|
|
488
|
+
error.logSimple(
|
|
489
|
+
`Socket Connection failed: "${this.params.name}" ` +
|
|
490
|
+
`(${this.params.port}) will disconnect now...`
|
|
491
|
+
)
|
|
492
|
+
} else {
|
|
493
|
+
DyFM_Log.error(
|
|
494
|
+
`Socket Connection failed: "${this.params.name}" ` +
|
|
495
|
+
`(${this.params.port}) will disconnect now...`,
|
|
496
|
+
error
|
|
497
|
+
);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
await this.closeSocket(socket, `${this.params.name} on connection error`, error);
|
|
501
|
+
}
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
const isAttach: boolean =
|
|
505
|
+
options?.attachedToExistingServer === true ||
|
|
506
|
+
(this.params.port === undefined && options?.effectivePort !== undefined);
|
|
507
|
+
|
|
508
|
+
if (isAttach) {
|
|
509
|
+
DyFM_Log.success(
|
|
510
|
+
`\nsocket server setup finished: "${this.params.name}"` +
|
|
511
|
+
(effectivePort !== undefined ? ` (attached to server on port: ${effectivePort})` : ' (attached to existing server)')
|
|
512
|
+
);
|
|
513
|
+
successCallback();
|
|
514
|
+
} else {
|
|
515
|
+
try {
|
|
516
|
+
const portToListen: number | undefined = this.params.port ?? options?.effectivePort;
|
|
517
|
+
if (portToListen === undefined) {
|
|
518
|
+
throw new Error(
|
|
519
|
+
`PORT NOT SET: "${this.params.name}". ` +
|
|
520
|
+
`Either set port in getServiceParams() or pass effectivePort in setupSocketServer options.`
|
|
521
|
+
);
|
|
522
|
+
}
|
|
523
|
+
newSocketServer.listen(portToListen);
|
|
524
|
+
|
|
525
|
+
DyFM_Log.success(
|
|
526
|
+
`\nsocket server setup finished: "${this.params.name}"` +
|
|
527
|
+
`\nsocket server listening on port: "${portToListen}"`
|
|
528
|
+
);
|
|
529
|
+
} catch (listenError) {
|
|
530
|
+
const portForMsg: number | undefined = this.params.port ?? options?.effectivePort;
|
|
531
|
+
const errorMessage = `Failed to bind socket server "${this.params.name}" to port ${portForMsg}. ` +
|
|
532
|
+
`This could be due to port already in use or insufficient permissions. ` +
|
|
533
|
+
`Please ensure the port is available and try again.`;
|
|
534
|
+
|
|
535
|
+
DyFM_Log.error(errorMessage, listenError);
|
|
536
|
+
throw new Error(errorMessage);
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
successCallback();
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
if (security === DyNTS_SocketSecurity.open) {
|
|
543
|
+
this.openSocketServer = newSocketServer;
|
|
544
|
+
|
|
545
|
+
return this.openSocketServer;
|
|
546
|
+
} else {
|
|
547
|
+
this.secureSocketServer = newSocketServer;
|
|
548
|
+
|
|
549
|
+
return this.secureSocketServer;
|
|
550
|
+
}
|
|
551
|
+
} catch (error) {
|
|
552
|
+
if (error instanceof DyFM_Error) {
|
|
553
|
+
error.logSimple(
|
|
554
|
+
`Socket Server Service - Deep Setup failed: "${this.params?.name}" ` +
|
|
555
|
+
`(${this.params?.port})`
|
|
556
|
+
)
|
|
557
|
+
} else {
|
|
558
|
+
DyFM_Log.error(
|
|
559
|
+
`Socket Server Service - Deep Setup failed: "${this.params?.name}" ` +
|
|
560
|
+
`(${this.params?.port})`,
|
|
561
|
+
error
|
|
562
|
+
);
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
throw error;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
protected async addSocketToPresence(newPresence: T_Presence): Promise<void> {
|
|
570
|
+
try {
|
|
571
|
+
const activePresence: T_Presence = this.presences.find(
|
|
572
|
+
(pres: T_Presence) => pres.issuerLocalId === newPresence.issuerLocalId
|
|
573
|
+
);
|
|
574
|
+
|
|
575
|
+
if (activePresence) {
|
|
576
|
+
activePresence.sockets.push(...newPresence.sockets);
|
|
577
|
+
} else {
|
|
578
|
+
this.presences.push(newPresence);
|
|
579
|
+
}
|
|
580
|
+
} catch (error) {
|
|
581
|
+
if (error instanceof DyFM_Error) {
|
|
582
|
+
error.logShort(
|
|
583
|
+
`Socket Subscription failed: "${this.params?.name}" (${this.params?.port})`
|
|
584
|
+
)
|
|
585
|
+
} else if (DyNTS_global_settings.log_settings.socket_eventContent) {
|
|
586
|
+
DyFM_Log.error(
|
|
587
|
+
`Socket Subscription failed: "${this.params?.name}" (${this.params?.port})`,
|
|
588
|
+
/* `${this.thisLocationStack}`, */
|
|
589
|
+
error
|
|
590
|
+
);
|
|
591
|
+
} else {
|
|
592
|
+
DyFM_Log.error(
|
|
593
|
+
`Socket Subscription failed: "${this.params?.name}" (${this.params?.port})`,
|
|
594
|
+
/* `${this.thisLocationStack}` */
|
|
595
|
+
);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
throw error;
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
protected async closeSocket(socket: SocketIO.Socket, issuer: string, withError?: DyFM_AnyError): Promise<void> {
|
|
603
|
+
try {
|
|
604
|
+
if (withError) {
|
|
605
|
+
socket.emit(DyFM_SocketEvent_Key.error, withError);
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
await this.executeDisconnectTasks(socket, issuer);
|
|
609
|
+
|
|
610
|
+
/* if (this.getSubscriptionCloseTasks) {
|
|
611
|
+
await DyFM_Array.asyncForEach(
|
|
612
|
+
this.getSubscriptionCloseTasks(),
|
|
613
|
+
async (task: DyFM_SocketEventTask<null>) => {
|
|
614
|
+
await task(null, issuer);
|
|
615
|
+
}
|
|
616
|
+
);
|
|
617
|
+
} */
|
|
618
|
+
|
|
619
|
+
socket.disconnect();
|
|
620
|
+
} catch (error) {
|
|
621
|
+
throw new DyFM_Error({
|
|
622
|
+
...this._getDefaultErrorSettings('closeSocket', error),
|
|
623
|
+
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-CS0`,
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
/** Disconnect taskokat socketenkent pontosan egyszer, magaval a sockettel futtatja. */
|
|
629
|
+
protected async executeDisconnectTasks(
|
|
630
|
+
socket: SocketIO.Socket,
|
|
631
|
+
issuer: string
|
|
632
|
+
): Promise<void> {
|
|
633
|
+
if (this.disconnectedSockets.has(socket)) {
|
|
634
|
+
return;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
this.disconnectedSockets.add(socket);
|
|
638
|
+
try {
|
|
639
|
+
await DyFM_Array.asyncForEach(
|
|
640
|
+
this.incomingEvents.filter(
|
|
641
|
+
(event: DyFM_SocketEvent<unknown>): boolean =>
|
|
642
|
+
event.eventKey === DyFM_SocketEvent_Key.disconnect
|
|
643
|
+
),
|
|
644
|
+
async (event: DyFM_SocketEvent<unknown>): Promise<void> => {
|
|
645
|
+
await event.executeEventTasks(socket, issuer);
|
|
646
|
+
}
|
|
647
|
+
);
|
|
648
|
+
await this.removeSocketFromPresence(socket);
|
|
649
|
+
DyFM_Log.info(`< x > socket(${this.params.name}) disconnected (${issuer})`);
|
|
650
|
+
} catch (error) {
|
|
651
|
+
this.disconnectedSockets.delete(socket);
|
|
652
|
+
throw error;
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
protected async removeSocketFromPresence(socket: SocketIO.Socket): Promise<void> {
|
|
657
|
+
try {
|
|
658
|
+
const presence: T_Presence = this.presences.find(
|
|
659
|
+
(pres: T_Presence) => pres.sockets.includes(socket)
|
|
660
|
+
);
|
|
661
|
+
|
|
662
|
+
if (presence) {
|
|
663
|
+
const socketIndex: number = presence.sockets.indexOf(socket);
|
|
664
|
+
|
|
665
|
+
if (socketIndex !== -1) {
|
|
666
|
+
presence.sockets.splice(socketIndex, 1);
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
if (presence.sockets.length === 0) {
|
|
670
|
+
const presenceIndex: number = this.presences.indexOf(presence);
|
|
671
|
+
|
|
672
|
+
if (presenceIndex !== -1) {
|
|
673
|
+
this.presences.splice(presenceIndex, 1);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
} catch (error) {
|
|
678
|
+
throw new DyFM_Error({
|
|
679
|
+
...this._getDefaultErrorSettings('removeSocketFromPresence', error),
|
|
680
|
+
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-RSO0`,
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
private async removeSubscription(socket: SocketIO.Socket, issuer?: string): Promise<void> {
|
|
686
|
+
try {
|
|
687
|
+
if (!this.presences.length) {
|
|
688
|
+
throw new DyFM_Error({
|
|
689
|
+
...this._getDefaultErrorSettings(
|
|
690
|
+
'removeSubscription',
|
|
691
|
+
new Error(`No presences found (${this.params.name})`),
|
|
692
|
+
issuer ?? 'unknown issuer'
|
|
693
|
+
),
|
|
694
|
+
|
|
695
|
+
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-RS1`,
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
const activePresenceIndex: number = this.presences.findIndex(
|
|
700
|
+
(pres: DyNTS_SocketPresence) => pres.sockets.includes(socket)
|
|
701
|
+
);
|
|
702
|
+
|
|
703
|
+
if (activePresenceIndex === -1) {
|
|
704
|
+
throw new DyFM_Error({
|
|
705
|
+
...this._getDefaultErrorSettings(
|
|
706
|
+
'sendEventForId',
|
|
707
|
+
new Error(
|
|
708
|
+
`closing socket (${this.params.name}) does not match any in the activePresences`
|
|
709
|
+
),
|
|
710
|
+
issuer ?? 'unknown issuer'
|
|
711
|
+
),
|
|
712
|
+
|
|
713
|
+
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-RS2`,
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
const activePresence: DyNTS_SocketPresence = this.presences[activePresenceIndex];
|
|
718
|
+
|
|
719
|
+
if (issuer && activePresence.issuerLocalId !== issuer) {
|
|
720
|
+
throw new DyFM_Error({
|
|
721
|
+
...this._getDefaultErrorSettings(
|
|
722
|
+
'sendEventForId',
|
|
723
|
+
new Error(
|
|
724
|
+
`socket unsubscription for "${issuer}" and ` +
|
|
725
|
+
`"${activePresence.issuerLocalId}" does not match.`
|
|
726
|
+
),
|
|
727
|
+
issuer
|
|
728
|
+
),
|
|
729
|
+
|
|
730
|
+
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-RS3`,
|
|
731
|
+
});
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
const socketIndex = activePresence.sockets.findIndex((s: SocketIO.Socket) => s === socket);
|
|
735
|
+
|
|
736
|
+
if (socketIndex === -1) {
|
|
737
|
+
throw new DyFM_Error({
|
|
738
|
+
...this._getDefaultErrorSettings(
|
|
739
|
+
'sendEventForId',
|
|
740
|
+
new Error(
|
|
741
|
+
`closing socket (${this.params.name}) does not match any in the activePresences`
|
|
742
|
+
),
|
|
743
|
+
activePresence.issuerLocalId
|
|
744
|
+
),
|
|
745
|
+
|
|
746
|
+
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-RS4`,
|
|
747
|
+
});
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
activePresence.sockets.splice(socketIndex, 1);
|
|
751
|
+
|
|
752
|
+
await DyFM_Array.asyncForEach(
|
|
753
|
+
this.incomingEvents.filter(
|
|
754
|
+
(event: DyFM_SocketEvent<any>) =>
|
|
755
|
+
event.eventKey === DyFM_SocketEvent_Key.unsubscribeSuccessful
|
|
756
|
+
),
|
|
757
|
+
async (event: DyFM_SocketEvent<any>) => {
|
|
758
|
+
await event.executeEventTasks(null, issuer);
|
|
759
|
+
}
|
|
760
|
+
);
|
|
761
|
+
|
|
762
|
+
/* if (this.getSubscriptionCloseTasks) {
|
|
763
|
+
await DyFM_Array.asyncForEach(
|
|
764
|
+
this.getSubscriptionCloseTasks(),
|
|
765
|
+
async (task: DyFM_SocketEventTask<null>) => {
|
|
766
|
+
await task(null, issuer);
|
|
767
|
+
}
|
|
768
|
+
);
|
|
769
|
+
} */
|
|
770
|
+
|
|
771
|
+
if (activePresence.sockets.length === 0) {
|
|
772
|
+
this.presences.splice(activePresenceIndex, 1);
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
socket.emit(DyFM_SocketEvent_Key.unsubscribeSuccessful, 'unsubscribe was successful');
|
|
776
|
+
socket.disconnect();
|
|
777
|
+
DyFM_Log.info(`<x==> socket (${this.params.name}) unsubscription successful (${issuer})`);
|
|
778
|
+
} catch (error) {
|
|
779
|
+
throw new DyFM_Error({
|
|
780
|
+
...this._getDefaultErrorSettings(
|
|
781
|
+
'sendEventForId',
|
|
782
|
+
error,
|
|
783
|
+
issuer ?? 'unknown issuer'
|
|
784
|
+
),
|
|
785
|
+
|
|
786
|
+
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-RS0`,
|
|
787
|
+
message: `socket (${this.params.name}) Subscription Removal failed: "${this.params?.name}"`,
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
/* emitServerEvent(event: string, content: any): void {
|
|
793
|
+
try {
|
|
794
|
+
DyFM_Log.log(` <=-- emitting server socket(${this.params.name}) event: ${event}`);
|
|
795
|
+
|
|
796
|
+
this.openSocketServer.emit(event, content, error => {
|
|
797
|
+
DyFM_Log.error(`Emitting server event '${event}' failed!\nerror:`, error);
|
|
798
|
+
});
|
|
799
|
+
} catch (error) {
|
|
800
|
+
throw new DyFM_Error({
|
|
801
|
+
...this._getDefaultErrorSettings(
|
|
802
|
+
'emitEvent',
|
|
803
|
+
error
|
|
804
|
+
),
|
|
805
|
+
|
|
806
|
+
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-500',
|
|
807
|
+
message: `socket(${this.params.name}) Event Emit (${event}) failed: ${this.params?.name}`,
|
|
808
|
+
});
|
|
809
|
+
}
|
|
810
|
+
} */
|
|
811
|
+
|
|
812
|
+
idIsSubscribed(id: string): boolean {
|
|
813
|
+
try {
|
|
814
|
+
return !!this.presences.find(
|
|
815
|
+
(presence: DyNTS_SocketPresence) => presence.issuerLocalId === id
|
|
816
|
+
);
|
|
817
|
+
} catch (error) {
|
|
818
|
+
throw new DyFM_Error({
|
|
819
|
+
...this._getDefaultErrorSettings(
|
|
820
|
+
'idIsSubscribed',
|
|
821
|
+
error
|
|
822
|
+
),
|
|
823
|
+
|
|
824
|
+
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-IIS0`,
|
|
825
|
+
message: `socket (${this.params.name}) ID Subscription Check (${id}) failed`,
|
|
826
|
+
});
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
async emitError(presenceIssuerId: string, error: any, issuer: string): Promise<void> {
|
|
831
|
+
try {
|
|
832
|
+
await this.sendEventForId(presenceIssuerId, DyFM_SocketEvent_Key.error, error, issuer);
|
|
833
|
+
} catch (error) {
|
|
834
|
+
throw new DyFM_Error({
|
|
835
|
+
...this._getDefaultErrorSettings(
|
|
836
|
+
'emitError',
|
|
837
|
+
error,
|
|
838
|
+
presenceIssuerId
|
|
839
|
+
),
|
|
840
|
+
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-EE0`,
|
|
841
|
+
message: `socket (${this.params.name}) Error Emit (id: ${presenceIssuerId}) failed`,
|
|
842
|
+
});
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
async sendEventForId(id: string, event: string, content: any, issuer: string): Promise<void> {
|
|
847
|
+
try {
|
|
848
|
+
if (!event) {
|
|
849
|
+
throw new DyFM_Error({
|
|
850
|
+
...this._getDefaultErrorSettings(
|
|
851
|
+
'sendEventForId',
|
|
852
|
+
new Error('No event was provided'),
|
|
853
|
+
content?.source
|
|
854
|
+
),
|
|
855
|
+
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-SEFI1`,
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
if (!id) {
|
|
860
|
+
throw new DyFM_Error({
|
|
861
|
+
...this._getDefaultErrorSettings(
|
|
862
|
+
'sendEventForId',
|
|
863
|
+
new Error('No ID was provided'),
|
|
864
|
+
content?.source
|
|
865
|
+
),
|
|
866
|
+
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-SEFI2`,
|
|
867
|
+
});
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
const presence: DyNTS_SocketPresence = this.presences.find(
|
|
871
|
+
(pres: DyNTS_SocketPresence) => pres.issuerLocalId === id
|
|
872
|
+
);
|
|
873
|
+
|
|
874
|
+
if (!presence) {
|
|
875
|
+
throw new DyFM_Error({
|
|
876
|
+
...this._getDefaultErrorSettings(
|
|
877
|
+
'sendEventForId',
|
|
878
|
+
new Error(`No active socket with this specific ID: "${id}"`),
|
|
879
|
+
content?.source
|
|
880
|
+
),
|
|
881
|
+
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-SEFI3`,
|
|
882
|
+
});
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
presence.emitEvent(event, content, issuer);
|
|
886
|
+
|
|
887
|
+
if (DyNTS_global_settings.log_settings.socket_eventContent) {
|
|
888
|
+
DyFM_Log.success(
|
|
889
|
+
` <--= emitted socket (${this.params.name}) event: "${event}", ` +
|
|
890
|
+
`\n presenceId: "${id}", sockets: ${presence.sockets.length}` +
|
|
891
|
+
`\n content:`, content
|
|
892
|
+
);
|
|
893
|
+
} else {
|
|
894
|
+
DyFM_Log.success(
|
|
895
|
+
` <--= emitted socket (${this.params.name}) event: "${event}", ` +
|
|
896
|
+
`\n presenceId: ${id}, sockets: ${presence.sockets.length}`
|
|
897
|
+
);
|
|
898
|
+
}
|
|
899
|
+
} catch (error) {
|
|
900
|
+
try {
|
|
901
|
+
if (error?.flag?.includes(DyFM_errorFlag) && error?.additionalInfo?.inactiveSockets) {
|
|
902
|
+
const sockets: SocketIO.Socket[] = error.additionalInfo.inactiveSockets;
|
|
903
|
+
|
|
904
|
+
await DyFM_Array.asyncForEach(sockets, async (socket: SocketIO.Socket) => {
|
|
905
|
+
await this.removeSubscription(socket);
|
|
906
|
+
});
|
|
907
|
+
|
|
908
|
+
const presence: DyNTS_SocketPresence = this.presences.find(
|
|
909
|
+
(pres: DyNTS_SocketPresence) => pres.issuerLocalId === id
|
|
910
|
+
);
|
|
911
|
+
|
|
912
|
+
if (!presence) {
|
|
913
|
+
throw new DyFM_Error({
|
|
914
|
+
...this._getDefaultErrorSettings(
|
|
915
|
+
'sendEventForId',
|
|
916
|
+
new Error(`No active socket (${this.params.name}) with this specific ID: "${id}"`),
|
|
917
|
+
content?.source
|
|
918
|
+
),
|
|
919
|
+
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-SEFI4`,
|
|
920
|
+
});
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
} catch (error) {
|
|
924
|
+
throw new DyFM_Error({
|
|
925
|
+
...this._getDefaultErrorSettings('sendEventForId', error, content?.source),
|
|
926
|
+
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-SEFI5`,
|
|
927
|
+
message:
|
|
928
|
+
`Error handling of inactive sockets (${this.params.name}) failed!` +
|
|
929
|
+
`\n(Socket Event Emit for id (${id}, ${event}) failed)`,
|
|
930
|
+
});
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
throw new DyFM_Error({
|
|
934
|
+
...this._getDefaultErrorSettings('sendEventForId', error, content?.source),
|
|
935
|
+
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-SEFI0`,
|
|
936
|
+
message: `socket (${this.params.name}) Event Emit for id (${id}, ${event}) failed`,
|
|
937
|
+
});
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
async broadcastEvent(event: string, content: any, issuer: string): Promise<void> {
|
|
942
|
+
try {
|
|
943
|
+
DyFM_Log.log(`<=-== broadcasting socket (${this.params.name}) event: "${event}"`);
|
|
944
|
+
|
|
945
|
+
this.presences.forEach((presence: DyNTS_SocketPresence) => {
|
|
946
|
+
presence.emitEvent(event, content, issuer);
|
|
947
|
+
});
|
|
948
|
+
} catch (error) {
|
|
949
|
+
if (DyNTS_global_settings.log_settings.detailedErrors) {
|
|
950
|
+
if (error instanceof DyFM_Error) {
|
|
951
|
+
error.logSimple(`socket (${this.params.name}) Event Broadcast (${event}) failed`);
|
|
952
|
+
} else {
|
|
953
|
+
DyFM_Log.error(`socket (${this.params.name}) Event Broadcast (${event}) failed`, error);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
throw new DyFM_Error({
|
|
958
|
+
...this._getDefaultErrorSettings('broadcastEvent', error),
|
|
959
|
+
|
|
960
|
+
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-BE0`,
|
|
961
|
+
message: `socket (${this.params.name}) Event Broadcast (${event}) failed`,
|
|
962
|
+
});
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
async sendError(error: DyFM_AnyError, issuer: string): Promise<void> {
|
|
967
|
+
try {
|
|
968
|
+
await this.sendEventForId(issuer, DyFM_SocketEvent_Key.error, error, issuer);
|
|
969
|
+
} catch (error) {
|
|
970
|
+
throw new DyFM_Error({
|
|
971
|
+
...this._getDefaultErrorSettings('sendError', error, issuer),
|
|
972
|
+
errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SSS-SE0`,
|
|
973
|
+
message: `socket (${this.params.name}) Error Send (${issuer}) failed`,
|
|
974
|
+
});
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
private _getDefaultErrorSettings(
|
|
979
|
+
fnName: string,
|
|
980
|
+
error: DyFM_AnyError,
|
|
981
|
+
issuer?: string
|
|
982
|
+
): DyFM_Error_Settings {
|
|
983
|
+
return {
|
|
984
|
+
status: (error as DyFM_Error)?.___status ?? 500,
|
|
985
|
+
message: (error as Error)?.message ??
|
|
986
|
+
(error as DyFM_Error)?._message ??
|
|
987
|
+
`${fnName} was UNSUCCESSFUL (NTS)`,
|
|
988
|
+
addECToUserMsg: !(error as DyFM_Error)?.__userMessage,
|
|
989
|
+
userMessage: (error as DyFM_Error)?.__userMessage ?? this.defaultErrorUserMsg,
|
|
990
|
+
issuer: issuer,
|
|
991
|
+
issuerService: this.constructor?.name,
|
|
992
|
+
error: error,
|
|
993
|
+
};
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
/**
|
|
997
|
+
* You must setup params for the service in this function
|
|
998
|
+
*/
|
|
999
|
+
protected abstract getServiceParams(): DyNTS_SocketServerService_Params;
|
|
1000
|
+
|
|
1001
|
+
/**
|
|
1002
|
+
* You must setup events and required services in this function
|
|
1003
|
+
*/
|
|
1004
|
+
protected abstract getIncomingEvents(): DyFM_SocketEvent<any>[];
|
|
1005
|
+
|
|
1006
|
+
/**
|
|
1007
|
+
* You can setup tasks for the subscription event in this function
|
|
1008
|
+
*/
|
|
1009
|
+
/* protected getSubscriptionCloseTasks?(): DyFM_SocketEventTask<null>[]; */
|
|
1010
|
+
|
|
1011
|
+
/**
|
|
1012
|
+
* You can setup preprocesses for the subscription event in this function
|
|
1013
|
+
*/
|
|
1014
|
+
/* protected getSubscriptionPreProcesses?(): DyFM_SocketEventPreprocessTask[]; */
|
|
1015
|
+
|
|
1016
|
+
/**
|
|
1017
|
+
* You can setup tasks for the subscription event in this function
|
|
1018
|
+
* This will happen after the presence is created
|
|
1019
|
+
* If this throws an error, the socket will be closed
|
|
1020
|
+
*/
|
|
1021
|
+
protected getSubscriptionTasks?(): DyFM_SocketEventTask<T_SubscriptionContent>[];
|
|
1022
|
+
|
|
1023
|
+
/**
|
|
1024
|
+
* You can setup tasks for the unsubscribe event in this function
|
|
1025
|
+
*/
|
|
1026
|
+
/* protected getUnsubscribeTasks?(): DyFM_SocketEventTask<T_SubscriptionContent>[]; */
|
|
1027
|
+
|
|
1028
|
+
/**
|
|
1029
|
+
* You can setup preprocesses for the unsubscribe event in this function
|
|
1030
|
+
*/
|
|
1031
|
+
/* protected getUnsubscribePreProcesses?(): DyFM_SocketEventPreprocessTask[]; */
|
|
1032
|
+
|
|
1033
|
+
/**
|
|
1034
|
+
* You can setup tasks for the error event in this function
|
|
1035
|
+
*/
|
|
1036
|
+
protected errorHandling?: DyFM_SocketEventTask<T_ErrorContent>;
|
|
1037
|
+
}
|