@futdevpro/nts-dynamo 1.15.2 → 1.15.3

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.
Files changed (121) hide show
  1. package/.cursor/rules/__assistant_guide.mdc +30 -0
  2. package/.cursor/rules/__main.mdc +62 -0
  3. package/.cursor/rules/_ag_backend-structure.mdc +86 -0
  4. package/.cursor/rules/_ag_backend.mdc +16 -0
  5. package/.cursor/rules/_ag_debug.mdc +8 -0
  6. package/.cursor/rules/_ag_documentation_writing_rules.mdc +372 -0
  7. package/.cursor/rules/_ag_file-refactoring.mdc +113 -0
  8. package/.cursor/rules/_ag_fixes_rules.mdc +6 -0
  9. package/.cursor/rules/_ag_frontend-structure.mdc +87 -0
  10. package/.cursor/rules/_ag_frontend.mdc +40 -0
  11. package/.cursor/rules/_ag_import-rules.mdc +45 -0
  12. package/.cursor/rules/_ag_naming.mdc +116 -0
  13. package/.cursor/rules/_ag_running_commands.mdc +5 -0
  14. package/.cursor/rules/_ag_server-controller.mdc +6 -0
  15. package/.cursor/rules/_ag_should-be.mdc +7 -0
  16. package/.cursor/rules/_ag_swearing.mdc +47 -0
  17. package/.cursor/rules/ai_development_guide.md +61 -0
  18. package/.cursor/rules/ai_directives.md +114 -0
  19. package/.cursor/rules/cursor-rules.md +160 -0
  20. package/.cursor/rules/default-command.mdc +229 -0
  21. package/.cursor/rules/error_code_pattern.md +40 -0
  22. package/.cursor/rules/saved rule mcp server use.md +16 -0
  23. package/build/_modules/custom-data/custom-data.controller.d.ts.map +1 -1
  24. package/build/_modules/custom-data/custom-data.controller.js +1 -2
  25. package/build/_modules/custom-data/custom-data.controller.js.map +1 -1
  26. package/build/_services/core/api.service.d.ts.map +1 -1
  27. package/build/_services/core/api.service.js +1 -0
  28. package/build/_services/core/api.service.js.map +1 -1
  29. package/package.json +5 -4
  30. package/scripts/run-coverage-tests.js +5 -1
  31. package/spec/support/helpers/spec-reporter-loader.js +359 -0
  32. package/spec/support/helpers/ts-node-helper.js +84 -0
  33. package/spec/support/jasmine.coverage.json +2 -1
  34. package/spec/support/jasmine.json +3 -3
  35. package/src/_collections/archive.util.spec.ts +36 -0
  36. package/src/_collections/get-environment-settings.util.spec.ts +210 -0
  37. package/src/_collections/star.controller.spec.ts +224 -0
  38. package/src/_models/control-models/api-call-params.control-model.spec.ts +62 -3
  39. package/src/_models/control-models/app-ext-system-controls.control-model.spec.ts +52 -0
  40. package/src/_models/control-models/app-params.control-model.spec.ts +158 -2
  41. package/src/_models/control-models/endpoint-params.control-model.spec.ts +578 -0
  42. package/src/_modules/ai/_modules/document-ai/_collections/dai-chunking.util.spec.ts +242 -0
  43. package/src/_modules/ai/_modules/document-ai/_collections/dai-document.util.spec.ts +209 -0
  44. package/src/_modules/ai/_modules/open-ai/_services/data-services/oai-document.data-service.spec.ts +342 -0
  45. package/src/_modules/ai/_modules/open-ai/_services/data-services/oai-vector-data.service.spec.ts +550 -0
  46. package/src/_modules/ai/_modules/open-ai/_services/oai-embedding.control-service.spec.ts +240 -0
  47. package/src/_modules/ai/_modules/open-ai/_services/oai-llm-chat.service-base.spec.ts +462 -0
  48. package/src/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.spec.ts +437 -0
  49. package/src/_modules/ai/_services/ai-embedding.service-base.spec.ts +98 -0
  50. package/src/_modules/ai/_services/ai-llm-chat.service-base.spec.ts +229 -0
  51. package/src/_modules/ai/_services/ai-llm.service-base.spec.ts +250 -0
  52. package/src/_modules/ai/_services/ai-provider.service-base.spec.ts +79 -0
  53. package/src/_modules/assistant/_collections/ass.util.spec.ts +176 -0
  54. package/src/_modules/assistant/_services/ass-io.control-service.spec.ts +140 -0
  55. package/src/_modules/assistant/_services/ass-main.control-service.spec.ts +192 -0
  56. package/src/_modules/bot/_modules/discord-bot/_services/dib-messaging-provider.control-service.spec.ts +431 -0
  57. package/src/_modules/bot/_modules/dynamo-bot/_collections/dyb-operations.util.spec.ts +160 -0
  58. package/src/_modules/bot/_modules/dynamo-bot/_services/dyb-messaging-provider.control-service.spec.ts +374 -0
  59. package/src/_modules/bot/_modules/slack-bot/_services/slb-messaging-provider.control-service.spec.ts +344 -0
  60. package/src/_modules/bot/_modules/teams-bot/_services/teb-messaging-provider.control-service.spec.ts +345 -0
  61. package/src/_modules/bot/_services/bot-commands.control-service.spec.ts +116 -0
  62. package/src/_modules/bot/_services/bot-io.control-service.spec.ts +285 -0
  63. package/src/_modules/bot/_services/bot-main.control-service.spec.ts +208 -0
  64. package/src/_modules/bot/_services/bot-messaging-provider.service-base.spec.ts +349 -0
  65. package/src/_modules/bot/_services/bot-routines.control-service.spec.ts +111 -0
  66. package/src/_modules/custom-data/custom-data.controller.spec.ts +49 -0
  67. package/src/_modules/custom-data/custom-data.controller.ts +1 -3
  68. package/src/_modules/custom-data/custom-data.data-service.spec.ts +54 -0
  69. package/src/_modules/custom-data/get-custom-data-routing-module.util.spec.ts +28 -0
  70. package/src/_modules/defaults/_services/default-auth.service.spec.ts +269 -0
  71. package/src/_modules/defaults/_services/default-socket-events.service.spec.ts +42 -0
  72. package/src/_modules/defaults/_services/default-user.data-service.spec.ts +187 -0
  73. package/src/_modules/discord-assistant/_collections/dias.util.spec.ts +366 -0
  74. package/src/_modules/discord-assistant/_services/dias-io.control-service.spec.ts +108 -0
  75. package/src/_modules/discord-assistant/_services/dias-main.control-service.spec.ts +22 -0
  76. package/src/_modules/discord-assistant/_services/dias.service-base.spec.ts +195 -0
  77. package/src/_modules/discord-assistant-voiced/_services/dias-discord-bot.control-service.spec.ts +34 -0
  78. package/src/_modules/discord-bot/_collections/dibo-operations.util.spec.ts +214 -0
  79. package/src/_modules/discord-bot/_services/dibo-commands.control-service.spec.ts +154 -0
  80. package/src/_modules/discord-bot/_services/dibo-io.control-service.spec.ts +264 -0
  81. package/src/_modules/discord-bot/_services/dibo-main.control-service.spec.ts +408 -0
  82. package/src/_modules/discord-bot/_services/dibo-routines.control-service.spec.ts +105 -0
  83. package/src/_modules/local-vector-search/_services/lvs-doc-chunk-data.service.spec.ts +418 -0
  84. package/src/_modules/local-vector-search/_services/lvs-local-vector-search.data-service.spec.ts +345 -0
  85. package/src/_modules/messaging/_collections/msg.util.spec.ts +226 -0
  86. package/src/_modules/messaging/_services/msg-events.service.spec.ts +219 -0
  87. package/src/_modules/messaging/_services/msg-main.control-service.spec.ts +147 -0
  88. package/src/_modules/messaging/_services/msg.controller.spec.ts +201 -0
  89. package/src/_modules/mock/data-model.mock.spec.ts +27 -24
  90. package/src/_modules/oauth2/_routes/oauth2.controller.spec.ts +107 -0
  91. package/src/_modules/oauth2/_services/oauth2.auth-service.spec.ts +254 -0
  92. package/src/_modules/oauth2/_services/oauth2.control-service.spec.ts +585 -0
  93. package/src/_modules/server/errors/errors.control-service.spec.ts +230 -0
  94. package/src/_modules/server/errors/errors.controller.spec.ts +165 -0
  95. package/src/_modules/server/errors/errors.data-service.spec.ts +355 -0
  96. package/src/_modules/server/server-status/server-status-snapshot.control-service.spec.ts +70 -0
  97. package/src/_modules/server/server-status/server-status-snapshot.data-service.spec.ts +77 -0
  98. package/src/_modules/server/server-status/server-status.control-service.spec.ts +516 -0
  99. package/src/_modules/server/server-status/server-status.controller.spec.ts +156 -0
  100. package/src/_modules/socket/_models/socket-client-service-params.control-model.spec.ts +6 -3
  101. package/src/_modules/socket/_models/socket-presence.control-model.spec.ts +164 -0
  102. package/src/_modules/socket/_services/socket-client.service.spec.ts +15 -0
  103. package/src/_modules/test/get-test-routing-module.util.spec.ts +28 -0
  104. package/src/_modules/test/test.controller.spec.ts +72 -0
  105. package/src/_modules/usage/usage.controller.spec.ts +81 -0
  106. package/src/_modules/usage/usage.data-service.spec.ts +332 -0
  107. package/src/_services/base/api.service-base.spec.ts +125 -0
  108. package/src/_services/base/archive-data.service.spec.ts +196 -0
  109. package/src/_services/base/data.service.spec.ts +493 -0
  110. package/src/_services/base/db.service.spec.ts +59 -18
  111. package/src/_services/base/singleton.service-base.spec.ts +28 -0
  112. package/src/_services/base/singleton.service.spec.ts +114 -0
  113. package/src/_services/core/api.service.ts +1 -0
  114. package/src/_services/core/auth.service.spec.ts +159 -0
  115. package/src/_services/core/email.service.spec.ts +14 -22
  116. package/src/_services/core/global.service.spec.ts +275 -0
  117. package/src/_services/core/service-collection.service.spec.ts +46 -0
  118. package/src/_services/route/routing-module.service.spec.ts +8 -6
  119. package/src/_services/shared.static-service.spec.ts +89 -0
  120. package/src/_modules/socket/app-extended.server.spec.ts +0 -227
  121. package/src/_services/server/app.server.spec.ts +0 -138
@@ -0,0 +1,114 @@
1
+
2
+ import { DyNTS_SingletonService } from './singleton.service';
3
+ import { DyFM_Error, DyFM_Error_Settings } from '@futdevpro/fsm-dynamo';
4
+ import { DyNTS_global_settings } from '../../_collections/global-settings.const';
5
+
6
+ class TestSingletonService extends DyNTS_SingletonService {
7
+ static getInstance(): TestSingletonService {
8
+ return TestSingletonService.getSingletonInstance();
9
+ }
10
+ }
11
+
12
+ describe('| DyNTS_SingletonService', () => {
13
+ let service: TestSingletonService;
14
+
15
+ beforeEach(() => {
16
+ service = TestSingletonService.getInstance();
17
+ });
18
+
19
+ it('| should be a singleton instance', () => {
20
+ const instance1 = TestSingletonService.getInstance();
21
+ const instance2 = TestSingletonService.getInstance();
22
+
23
+ expect(instance1).toBe(instance2);
24
+ expect(instance1).toBeInstanceOf(TestSingletonService);
25
+ });
26
+
27
+ it('| should have default error user message', () => {
28
+ expect(service.defaultErrorUserMsg).toBeDefined();
29
+ expect(service.defaultErrorUserMsg).toContain('Control Service Error');
30
+ });
31
+
32
+ describe('| getDefaultErrorSettings', () => {
33
+ it('| should return error settings with default values', () => {
34
+ const error = new Error('Test error');
35
+ const issuer = 'issuer-123';
36
+
37
+ const result = (service as any).getDefaultErrorSettings('testFunction', error, issuer);
38
+
39
+ expect(result).toBeDefined();
40
+ expect(result.message).toBe('Test error');
41
+ // useMessageAsUserMessage defaults to true, so userMessage will be error.message
42
+ expect(result.userMessage).toBe('Test error');
43
+ expect(result.issuer).toBe(issuer);
44
+ expect(result.issuerService).toBe('TestSingletonService');
45
+ expect(result.systemVersion).toBe(DyNTS_global_settings.systemVersion);
46
+ expect(result.error).toBe(error);
47
+ });
48
+
49
+ it('| should use DyFM_Error status when available', () => {
50
+ const error = new DyFM_Error({
51
+ status: 404,
52
+ message: 'Not found',
53
+ });
54
+ const issuer = 'issuer-123';
55
+
56
+ const result = (service as any).getDefaultErrorSettings('testFunction', error, issuer);
57
+
58
+ expect(result.status).toBe(404);
59
+ });
60
+
61
+ it('| should use default status when error is not DyFM_Error', () => {
62
+ const error = new Error('Test error');
63
+ const issuer = 'issuer-123';
64
+
65
+ const result = (service as any).getDefaultErrorSettings('testFunction', error, issuer);
66
+
67
+ expect(result.status).toBe(500);
68
+ });
69
+
70
+ it('| should use error message when available', () => {
71
+ const error = new Error('Test error message');
72
+ const issuer = 'issuer-123';
73
+
74
+ const result = (service as any).getDefaultErrorSettings('testFunction', error, issuer);
75
+
76
+ expect(result.message).toBe('Test error message');
77
+ });
78
+
79
+ it('| should use default message when error message is not available', () => {
80
+ const error = {} as Error;
81
+ const issuer = 'issuer-123';
82
+
83
+ const result = (service as any).getDefaultErrorSettings('testFunction', error, issuer);
84
+
85
+ expect(result.message).toContain('testFunction was UNSUCCESSFUL');
86
+ });
87
+
88
+ it('| should use DyFM_Error user message when available', () => {
89
+ const error = new DyFM_Error({
90
+ message: 'Test error',
91
+ userMessage: 'Custom user message',
92
+ });
93
+ const issuer = 'issuer-123';
94
+
95
+ const result = (service as any).getDefaultErrorSettings('testFunction', error, issuer);
96
+
97
+ expect(result.userMessage).toBe('Custom user message');
98
+ expect(result.addECToUserMsg).toBe(false);
99
+ });
100
+
101
+ it('| should use default user message when DyFM_Error user message is not available', () => {
102
+ const error = new DyFM_Error({
103
+ message: 'Test error',
104
+ });
105
+ const issuer = 'issuer-123';
106
+
107
+ const result = (service as any).getDefaultErrorSettings('testFunction', error, issuer, false);
108
+
109
+ expect(result.userMessage).toBe(service.defaultErrorUserMsg);
110
+ expect(result.addECToUserMsg).toBe(true);
111
+ });
112
+ });
113
+ });
114
+
@@ -266,6 +266,7 @@ export class DyNTS_ApiService {
266
266
  errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-API-HE1`,
267
267
  message:
268
268
  `API call "${callParams.name}" failed on the other end!`+
269
+ `\nurl: ${url}` +
269
270
  `\nerror response found: ${errorMsg}`,
270
271
  error: dyfmErrorInAxiosResponse,
271
272
  additionalContent: {
@@ -0,0 +1,159 @@
1
+
2
+ import { DyNTS_AuthService } from './auth.service';
3
+ import { Request } from 'express';
4
+ import { DyFM_Error } from '@futdevpro/fsm-dynamo';
5
+ import { DyNTS_global_settings } from '../../_collections/global-settings.const';
6
+
7
+ class TestAuthService extends DyNTS_AuthService {
8
+ static getInstance(): TestAuthService {
9
+ return TestAuthService.getSingletonInstance();
10
+ }
11
+
12
+ authenticate_token = async (req: Request, res: any): Promise<void> => {
13
+ // Mock implementation
14
+ };
15
+
16
+ authenticate_tokenSelf = async (req: Request, res: any): Promise<void> => {
17
+ // Mock implementation
18
+ };
19
+
20
+ authenticate_tokenPerm_accUsageData = async (req: Request, res: any): Promise<void> => {
21
+ // Mock implementation
22
+ };
23
+
24
+ getIssuerFromRequest(req: Request): string {
25
+ return 'test-issuer';
26
+ }
27
+
28
+ getUsernameFromRequest(req: Request): string {
29
+ return 'test-user';
30
+ }
31
+ }
32
+
33
+ describe('| DyNTS_AuthService', () => {
34
+ let service: TestAuthService;
35
+
36
+ beforeEach(() => {
37
+ service = TestAuthService.getInstance();
38
+ });
39
+
40
+ it('| should be a singleton instance', () => {
41
+ const instance1 = TestAuthService.getInstance();
42
+ const instance2 = TestAuthService.getInstance();
43
+
44
+ expect(instance1).toBe(instance2);
45
+ expect(instance1).toBeInstanceOf(TestAuthService);
46
+ });
47
+
48
+ it('| should have default service name', () => {
49
+ expect(service.serviceName).toBe('AuthService');
50
+ });
51
+
52
+ it('| should have default error user message', () => {
53
+ expect(service.defaultErrorUserMsg).toBeDefined();
54
+ expect(service.defaultErrorUserMsg).toContain('Auth Error');
55
+ });
56
+
57
+ describe('| getTokenFromRequest', () => {
58
+ it('| should extract token from authorization header', () => {
59
+ const req = {
60
+ headers: {
61
+ authorization: 'Bearer test-token-123',
62
+ },
63
+ } as any as Request;
64
+
65
+ const result = service.getTokenFromRequest(req);
66
+
67
+ expect(result).toBe('test-token-123');
68
+ });
69
+
70
+ it('| should throw error when authorization header is missing', () => {
71
+ const req = {
72
+ headers: {},
73
+ } as any as Request;
74
+
75
+ expect(() => {
76
+ service.getTokenFromRequest(req);
77
+ }).toThrow();
78
+ });
79
+
80
+ it('| should throw error when authorization header is null', () => {
81
+ const req = {
82
+ headers: {
83
+ authorization: null,
84
+ },
85
+ } as any as Request;
86
+
87
+ expect(() => {
88
+ service.getTokenFromRequest(req);
89
+ }).toThrow();
90
+ });
91
+
92
+ it('| should throw error when token is missing from header', () => {
93
+ const req = {
94
+ headers: {
95
+ authorization: 'Bearer ',
96
+ },
97
+ } as any as Request;
98
+
99
+ expect(() => {
100
+ service.getTokenFromRequest(req);
101
+ }).toThrow();
102
+ });
103
+
104
+ it('| should throw error when authorization header does not contain Bearer', () => {
105
+ const req = {
106
+ headers: {
107
+ authorization: 'InvalidFormat token',
108
+ },
109
+ } as any as Request;
110
+
111
+ const result = service.getTokenFromRequest(req);
112
+
113
+ expect(result).toBe('token');
114
+ });
115
+
116
+ it('| should handle token with spaces correctly', () => {
117
+ const req = {
118
+ headers: {
119
+ authorization: 'Bearer token-with-spaces',
120
+ },
121
+ } as any as Request;
122
+
123
+ const result = service.getTokenFromRequest(req);
124
+
125
+ expect(result).toBe('token-with-spaces');
126
+ });
127
+
128
+ it('| should include error code in thrown error', () => {
129
+ const req = {
130
+ headers: {},
131
+ } as any as Request;
132
+
133
+ try {
134
+ service.getTokenFromRequest(req);
135
+ fail('Should have thrown an error');
136
+ } catch (error) {
137
+ expect(error).toBeInstanceOf(DyFM_Error);
138
+ expect((error as DyFM_Error)._errorCode).toContain('DyNTS-AS0-GT0');
139
+ }
140
+ });
141
+
142
+ it('| should include confidential content in error when header missing', () => {
143
+ const req = {
144
+ headers: {
145
+ 'x-custom-header': 'value',
146
+ },
147
+ } as any as Request;
148
+
149
+ try {
150
+ service.getTokenFromRequest(req);
151
+ fail('Should have thrown an error');
152
+ } catch (error) {
153
+ expect(error).toBeInstanceOf(DyFM_Error);
154
+ expect((error as DyFM_Error).confidentialContent).toBeDefined();
155
+ }
156
+ });
157
+ });
158
+ });
159
+
@@ -1,6 +1,7 @@
1
1
 
2
- import { DyFM_Error } from '@futdevpro/fsm-dynamo';
2
+ import { DyFM_Error, DyFM_EnvironmentFlag } from '@futdevpro/fsm-dynamo';
3
3
  import { DyNTS_EmailService, DyNTS_EmailService_Settings, DyNTS_EmailTemplateComponent, DyNTS_SendEmail_Settings } from './email.service';
4
+ import { DyNTS_global_settings } from '../../_collections/global-settings.const';
4
5
 
5
6
  describe('| DyNTS_EmailService', () => {
6
7
  let emailService: DyNTS_EmailService;
@@ -21,7 +22,19 @@ describe('| DyNTS_EmailService', () => {
21
22
  ],
22
23
  };
23
24
 
25
+ beforeAll(() => {
26
+ if (!DyNTS_global_settings.systemShortCodeName) (DyNTS_global_settings as { systemShortCodeName?: string }).systemShortCodeName = 'TEST';
27
+ if (!DyNTS_global_settings.env_settings) (DyNTS_global_settings as { env_settings?: unknown }).env_settings = { environment: DyFM_EnvironmentFlag.local };
28
+ });
29
+
24
30
  beforeEach(() => {
31
+ (DyNTS_global_settings as { env_settings: unknown }).env_settings = {
32
+ environment: DyFM_EnvironmentFlag.local,
33
+ mongoUri: 'mongodb://localhost:27017/test',
34
+ discord: undefined,
35
+ openAi: undefined,
36
+ };
37
+
25
38
  emailService = new DyNTS_EmailService(settings);
26
39
  });
27
40
 
@@ -37,17 +50,6 @@ describe('| DyNTS_EmailService', () => {
37
50
  expect(emailService['componentsBySelector']['test-selector']).toBeDefined();
38
51
  });
39
52
 
40
- xit('should send email with direct content', async () => {
41
- const sendEmailSettings: DyNTS_SendEmail_Settings = {
42
- to: 'recipient@example.com',
43
- subject: 'Test Subject',
44
- content: '<p>Test Content</p>',
45
- };
46
-
47
- await emailService.sendEmail(sendEmailSettings, 'testIssuer');
48
- // No error should be thrown
49
- });
50
-
51
53
  it('| should throw error if no template component name is provided', async () => {
52
54
  const sendEmailSettings: DyNTS_SendEmail_Settings = {
53
55
  to: 'recipient@example.com',
@@ -69,16 +71,6 @@ describe('| DyNTS_EmailService', () => {
69
71
  .toBeRejectedWith(jasmine.any(DyFM_Error));
70
72
  });
71
73
 
72
- xit('should compile template component correctly', async () => {
73
- const compiledTemplate = await emailService['compileTemplateComponent'](
74
- 'testComponent',
75
- { property: 'value' },
76
- 'testIssuer'
77
- );
78
-
79
- expect(compiledTemplate).toContain('<div>value</div>');
80
- });
81
-
82
74
  it('| should throw error if template property is missing', async () => {
83
75
  const component = new DyNTS_EmailTemplateComponent({
84
76
  name: 'testComponent',
@@ -0,0 +1,275 @@
1
+
2
+ import { DyNTS_GlobalService } from './global.service';
3
+ import { DyNTS_AuthService } from './auth.service';
4
+ import { DyNTS_EmailService } from './email.service';
5
+ import { DyNTS_DBService } from '../base/db.service';
6
+ import { DyNTS_Service_Collection } from './service-collection.service';
7
+ import { DyNTS_App_Params } from '../../_models/control-models/app-params.control-model';
8
+ import { DyFM_DataModel_Params, DyFM_Error, DyFM_Metadata, DyFM_EnvironmentFlag } from '@futdevpro/fsm-dynamo';
9
+ import { DyNTS_GlobalService_Settings } from '../../_models/interfaces/global-service-settings.interface';
10
+ import { DyNTS_global_settings } from '../../_collections/global-settings.const';
11
+
12
+ class TestMetadata extends DyFM_Metadata {
13
+ name: string;
14
+ }
15
+
16
+ class TestAuthService extends DyNTS_AuthService {
17
+ static getInstance(): TestAuthService {
18
+ return TestAuthService.getSingletonInstance();
19
+ }
20
+
21
+ authenticate_token = async (req: any, res: any): Promise<void> => {};
22
+ authenticate_tokenSelf = async (req: any, res: any): Promise<void> => {};
23
+ authenticate_tokenPerm_accUsageData = async (req: any, res: any): Promise<void> => {};
24
+ getIssuerFromRequest(req: any): string { return 'test'; }
25
+ getUsernameFromRequest(req: any): string { return 'test'; }
26
+ }
27
+
28
+ describe('| DyNTS_GlobalService', () => {
29
+ // Ensure env_settings exists before tests
30
+ beforeAll(() => {
31
+ if (!DyNTS_global_settings.env_settings) {
32
+ (DyNTS_global_settings as any).env_settings = {
33
+ environment: DyFM_EnvironmentFlag.local,
34
+ discord: {},
35
+ mongoUri: undefined,
36
+ openAi: {},
37
+ };
38
+ } else if (!DyNTS_global_settings.env_settings.environment) {
39
+ DyNTS_global_settings.env_settings.environment = DyFM_EnvironmentFlag.local;
40
+ }
41
+ });
42
+
43
+ beforeEach(() => {
44
+ // Reset singleton instance
45
+ (DyNTS_GlobalService as any).instance = undefined;
46
+ });
47
+
48
+ it('| should be a singleton instance', () => {
49
+ const instance1 = DyNTS_GlobalService.getInstance();
50
+ const instance2 = DyNTS_GlobalService.getInstance();
51
+
52
+ expect(instance1).toBe(instance2);
53
+ expect(instance1).toBeInstanceOf(DyNTS_GlobalService);
54
+ });
55
+
56
+ describe('| params', () => {
57
+ it('| should return undefined when not set', () => {
58
+ // Reset params before test
59
+ (DyNTS_GlobalService as any)._params = undefined;
60
+ expect(DyNTS_GlobalService.params).toBeUndefined();
61
+ });
62
+
63
+ it('| should return set params', () => {
64
+ const params = new DyNTS_App_Params({
65
+ name: 'Test App',
66
+ version: '1.0.0',
67
+ dbName: 'test_db',
68
+ });
69
+
70
+ DyNTS_GlobalService.setParams(params);
71
+
72
+ expect(DyNTS_GlobalService.params).toBe(params);
73
+ expect(DyNTS_GlobalService.params.name).toBe('Test App');
74
+ });
75
+ });
76
+
77
+ describe('| upSince', () => {
78
+ it('| should return a Date object', () => {
79
+ expect(DyNTS_GlobalService.upSince).toBeInstanceOf(Date);
80
+ });
81
+
82
+ it('| should return the same date on multiple calls', () => {
83
+ const date1 = DyNTS_GlobalService.upSince;
84
+ const date2 = DyNTS_GlobalService.upSince;
85
+
86
+ expect(date1).toBe(date2);
87
+ });
88
+ });
89
+
90
+ describe('| upTime', () => {
91
+ it('| should return a number', () => {
92
+ expect(typeof DyNTS_GlobalService.upTime).toBe('number');
93
+ });
94
+
95
+ it('| should return positive value', () => {
96
+ expect(DyNTS_GlobalService.upTime).toBeGreaterThanOrEqual(0);
97
+ });
98
+ });
99
+
100
+ describe('| setParams', () => {
101
+ it('| should set params', () => {
102
+ const params = new DyNTS_App_Params({
103
+ name: 'Test App',
104
+ version: '1.0.0',
105
+ dbName: 'test_db',
106
+ });
107
+
108
+ DyNTS_GlobalService.setParams(params);
109
+
110
+ expect(DyNTS_GlobalService.params).toBe(params);
111
+ });
112
+ });
113
+
114
+ describe('| getAuthService', () => {
115
+ it('| should throw error when auth service not set', () => {
116
+ expect(() => {
117
+ DyNTS_GlobalService.getAuthService();
118
+ }).toThrow();
119
+ });
120
+
121
+ it('| should return auth service when set', async () => {
122
+ const authService = TestAuthService.getInstance();
123
+ await DyNTS_GlobalService.setServices({
124
+ authService: authService,
125
+ });
126
+
127
+ const result = DyNTS_GlobalService.getAuthService();
128
+
129
+ expect(result).toBe(authService);
130
+ });
131
+ });
132
+
133
+ describe('| getDBServiceCollection', () => {
134
+ it('| should throw error when db service collection not set', () => {
135
+ expect(() => {
136
+ DyNTS_GlobalService.getDBServiceCollection();
137
+ }).toThrow();
138
+ });
139
+
140
+ it('| should return db service collection when set', async () => {
141
+ const dbModel = new DyFM_DataModel_Params<TestMetadata>({
142
+ dataName: 'test_data',
143
+ properties: { name: { key: 'name', type: 'string' } },
144
+ });
145
+
146
+ await DyNTS_GlobalService.setServices({
147
+ dbModels: [dbModel],
148
+ });
149
+
150
+ const result = DyNTS_GlobalService.getDBServiceCollection();
151
+
152
+ expect(result).toBeDefined();
153
+ expect(result['test_data']).toBeDefined();
154
+ });
155
+ });
156
+
157
+ describe('| getDBService', () => {
158
+ it('| should return db service by data params', async () => {
159
+ const dbModel = new DyFM_DataModel_Params<TestMetadata>({
160
+ dataName: 'test_data',
161
+ properties: { name: { key: 'name', type: 'string' } },
162
+ });
163
+
164
+ await DyNTS_GlobalService.setServices({
165
+ dbModels: [dbModel],
166
+ });
167
+
168
+ const result = DyNTS_GlobalService.getDBService(dbModel);
169
+
170
+ expect(result).toBeDefined();
171
+ expect(result).toBeInstanceOf(DyNTS_DBService);
172
+ });
173
+
174
+ it('| should throw error when db service not found', async () => {
175
+ const dbModel = new DyFM_DataModel_Params<TestMetadata>({
176
+ dataName: 'non_existent',
177
+ properties: { name: { key: 'name', type: 'string' } },
178
+ });
179
+
180
+ await DyNTS_GlobalService.setServices({
181
+ dbModels: [],
182
+ });
183
+
184
+ expect(() => {
185
+ DyNTS_GlobalService.getDBService(dbModel);
186
+ }).toThrow();
187
+ });
188
+ });
189
+
190
+ describe('| getDBServiceByKey', () => {
191
+ it('| should return db service by key', async () => {
192
+ const dbModel = new DyFM_DataModel_Params<TestMetadata>({
193
+ dataName: 'test_data',
194
+ properties: { name: { key: 'name', type: 'string' } },
195
+ });
196
+
197
+ await DyNTS_GlobalService.setServices({
198
+ dbModels: [dbModel],
199
+ });
200
+
201
+ const result = DyNTS_GlobalService.getDBServiceByKey<TestMetadata>('test_data');
202
+
203
+ expect(result).toBeDefined();
204
+ expect(result).toBeInstanceOf(DyNTS_DBService);
205
+ });
206
+
207
+ it('| should throw error when key not found', async () => {
208
+ await DyNTS_GlobalService.setServices({
209
+ dbModels: [],
210
+ });
211
+
212
+ expect(() => {
213
+ DyNTS_GlobalService.getDBServiceByKey('non_existent');
214
+ }).toThrow();
215
+ });
216
+ });
217
+
218
+ describe('| getEmailServiceCollection', () => {
219
+ it('| should throw error when email service collection not set', () => {
220
+ expect(() => {
221
+ DyNTS_GlobalService.getEmailServiceCollection();
222
+ }).toThrow();
223
+ });
224
+
225
+ it('| should return email service collection when set', async () => {
226
+ const emailServiceCollection = {} as DyNTS_Service_Collection<DyNTS_EmailService>;
227
+
228
+ await DyNTS_GlobalService.setServices({
229
+ emailServiceCollection: emailServiceCollection,
230
+ });
231
+
232
+ const result = DyNTS_GlobalService.getEmailServiceCollection();
233
+
234
+ expect(result).toBe(emailServiceCollection);
235
+ });
236
+ });
237
+
238
+ describe('| setServices', () => {
239
+ it('| should setup all services', async () => {
240
+ const authService = TestAuthService.getInstance();
241
+ const dbModel = new DyFM_DataModel_Params<TestMetadata>({
242
+ dataName: 'test_data',
243
+ properties: { name: { key: 'name', type: 'string' } },
244
+ });
245
+ const emailServiceCollection = {} as DyNTS_Service_Collection<DyNTS_EmailService>;
246
+
247
+ await DyNTS_GlobalService.setServices({
248
+ authService: authService,
249
+ dbModels: [dbModel],
250
+ emailServiceCollection: emailServiceCollection,
251
+ });
252
+
253
+ expect(DyNTS_GlobalService.getAuthService()).toBe(authService);
254
+ expect(DyNTS_GlobalService.getDBServiceCollection()).toBeDefined();
255
+ expect(DyNTS_GlobalService.getEmailServiceCollection()).toBe(emailServiceCollection);
256
+ });
257
+
258
+ it('| should handle empty settings', async () => {
259
+ await expectAsync(
260
+ DyNTS_GlobalService.setServices({})
261
+ ).toBeResolved();
262
+ });
263
+
264
+ it('| should throw error on setup failure', async () => {
265
+ const invalidDbModel = null as any;
266
+
267
+ await expectAsync(
268
+ DyNTS_GlobalService.setServices({
269
+ dbModels: [invalidDbModel],
270
+ })
271
+ ).toBeRejected();
272
+ });
273
+ });
274
+ });
275
+
@@ -0,0 +1,46 @@
1
+
2
+ import { DyNTS_Service_Collection } from './service-collection.service';
3
+
4
+ class TestService {
5
+ name: string;
6
+ constructor(name: string) {
7
+ this.name = name;
8
+ }
9
+ }
10
+
11
+ describe('| DyNTS_Service_Collection', () => {
12
+ it('| should be a singleton instance', () => {
13
+ class TestCollection extends DyNTS_Service_Collection<TestService> {
14
+ static getInstance(): TestCollection {
15
+ return TestCollection.getSingletonInstance();
16
+ }
17
+ }
18
+
19
+ const instance1 = TestCollection.getInstance();
20
+ const instance2 = TestCollection.getInstance();
21
+
22
+ expect(instance1).toBe(instance2);
23
+ expect(instance1).toBeInstanceOf(TestCollection);
24
+ });
25
+
26
+ it('| should allow dynamic property assignment', () => {
27
+ class TestCollection extends DyNTS_Service_Collection<TestService> {
28
+ static getInstance(): TestCollection {
29
+ return TestCollection.getSingletonInstance();
30
+ }
31
+ }
32
+
33
+ const collection = TestCollection.getInstance();
34
+ const service1 = new TestService('service1');
35
+ const service2 = new TestService('service2');
36
+
37
+ collection['service1'] = service1;
38
+ collection['service2'] = service2;
39
+
40
+ expect(collection['service1']).toBe(service1);
41
+ expect(collection['service2']).toBe(service2);
42
+ expect(collection['service1'].name).toBe('service1');
43
+ expect(collection['service2'].name).toBe('service2');
44
+ });
45
+ });
46
+