@nsshunt/stsappframework 3.1.136 → 3.1.138

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 (54) hide show
  1. package/dist/fhir/STSFhirTypes.js +3 -0
  2. package/dist/fhir/STSFhirTypes.js.map +1 -0
  3. package/dist/fhir/dalFhirManagerPGRes.js +87 -0
  4. package/dist/fhir/dalFhirManagerPGRes.js.map +1 -0
  5. package/dist/fhir/dalFhirManagerPGRes.test.js +31 -0
  6. package/dist/fhir/dalFhirManagerPGRes.test.js.map +1 -0
  7. package/dist/fhir/dalFhirManagerPGResEntity.js +116 -0
  8. package/dist/fhir/dalFhirManagerPGResEntity.js.map +1 -0
  9. package/dist/fhir/dalFhirManagerPGResEntity.test.js +32 -0
  10. package/dist/fhir/dalFhirManagerPGResEntity.test.js.map +1 -0
  11. package/dist/fhir/dalFhirManagerRedisJson.js +87 -0
  12. package/dist/fhir/dalFhirManagerRedisJson.js.map +1 -0
  13. package/dist/fhir/dalFhirManagerRedisJson.test.js +33 -0
  14. package/dist/fhir/dalFhirManagerRedisJson.test.js.map +1 -0
  15. package/dist/fhir/dalFhirTestHelpers.js +130 -0
  16. package/dist/fhir/dalFhirTestHelpers.js.map +1 -0
  17. package/dist/index.js +2 -0
  18. package/dist/index.js.map +1 -1
  19. package/dist/redisMessageHandler.js +23 -0
  20. package/dist/redisMessageHandler.js.map +1 -1
  21. package/dist/testing/app.js +9 -0
  22. package/dist/testing/app.js.map +1 -1
  23. package/package.json +1 -1
  24. package/src/fhir/STSFhirTypes.ts +501 -0
  25. package/src/fhir/dalFhirManagerPGRes.test.ts +42 -0
  26. package/src/fhir/dalFhirManagerPGRes.ts +92 -0
  27. package/src/fhir/dalFhirManagerPGResEntity.test.ts +43 -0
  28. package/src/fhir/dalFhirManagerPGResEntity.ts +123 -0
  29. package/src/fhir/dalFhirManagerRedisJson.test.ts +44 -0
  30. package/src/fhir/dalFhirManagerRedisJson.ts +92 -0
  31. package/src/fhir/dalFhirTestHelpers.ts +163 -0
  32. package/src/index.ts +2 -0
  33. package/src/redisMessageHandler.ts +23 -0
  34. package/src/testing/app.ts +10 -0
  35. package/types/fhir/STSFhirTypes.d.ts +318 -0
  36. package/types/fhir/STSFhirTypes.d.ts.map +1 -0
  37. package/types/fhir/dalFhirManagerPGRes.d.ts +16 -0
  38. package/types/fhir/dalFhirManagerPGRes.d.ts.map +1 -0
  39. package/types/fhir/dalFhirManagerPGRes.test.d.ts +2 -0
  40. package/types/fhir/dalFhirManagerPGRes.test.d.ts.map +1 -0
  41. package/types/fhir/dalFhirManagerPGResEntity.d.ts +15 -0
  42. package/types/fhir/dalFhirManagerPGResEntity.d.ts.map +1 -0
  43. package/types/fhir/dalFhirManagerPGResEntity.test.d.ts +2 -0
  44. package/types/fhir/dalFhirManagerPGResEntity.test.d.ts.map +1 -0
  45. package/types/fhir/dalFhirManagerRedisJson.d.ts +17 -0
  46. package/types/fhir/dalFhirManagerRedisJson.d.ts.map +1 -0
  47. package/types/fhir/dalFhirManagerRedisJson.test.d.ts +2 -0
  48. package/types/fhir/dalFhirManagerRedisJson.test.d.ts.map +1 -0
  49. package/types/fhir/dalFhirTestHelpers.d.ts +14 -0
  50. package/types/fhir/dalFhirTestHelpers.d.ts.map +1 -0
  51. package/types/index.d.ts +2 -0
  52. package/types/index.d.ts.map +1 -1
  53. package/types/redisMessageHandler.d.ts +1 -0
  54. package/types/redisMessageHandler.d.ts.map +1 -1
@@ -0,0 +1,42 @@
1
+ /* eslint @typescript-eslint/no-explicit-any: 0 */ // --> OFF
2
+ import { beforeAll, afterAll, test, describe, expect } from 'vitest';
3
+
4
+ import { accessLayerType, IPGAccessLayerOptions, SYSTEM_USER_ID } from '@nsshunt/stsdatamanagement'
5
+
6
+ import { DALFhirManagerPGRes } from './dalFhirManagerPGRes'
7
+
8
+ import { IPerson } from './STSFhirTypes'
9
+
10
+ import { TestHelpers } from './dalFhirTestHelpers'
11
+
12
+ describe("Test hl7 fhir resource data access layer - PGRes", () =>
13
+ {
14
+ let testHelpers: TestHelpers;
15
+
16
+ beforeAll(async () =>
17
+ {
18
+ testHelpers = new TestHelpers();
19
+ await testHelpers.StartDatabase();
20
+ }, 30000);
21
+
22
+ test('Testing Person', async () => {
23
+ expect.assertions(6);
24
+
25
+ const personManager = new DALFhirManagerPGRes<IPerson>({
26
+ accessLayerType: accessLayerType.postgresql,
27
+ accessLayerOptions: {
28
+ logger: testHelpers.logger,
29
+ usedefaultdb: false
30
+ } as IPGAccessLayerOptions,
31
+ resourceName: 'STSFhirPerson',
32
+ dbactionuser: SYSTEM_USER_ID
33
+ });
34
+
35
+ await testHelpers.TestFhirPerson(personManager);
36
+ }, 30000);
37
+
38
+ afterAll(async () =>
39
+ {
40
+ await testHelpers.StopDatabase();
41
+ }, 5000);
42
+ });
@@ -0,0 +1,92 @@
1
+ import { DBAccessLayerManager, IDBAccessLayer, IDBAccessLayerManagerOptions, IDBResource } from '@nsshunt/stsdatamanagement'
2
+
3
+ import { IDomainResource, IDALFhirDataAccessManager } from './STSFhirTypes'
4
+
5
+ export interface IFhirManagerPGResOptions extends IDBAccessLayerManagerOptions {
6
+ resourceName: string
7
+ dbactionuser: string
8
+ }
9
+
10
+ export class DALFhirManagerPGRes<T> implements IDALFhirDataAccessManager<T> {
11
+ #options: IFhirManagerPGResOptions;
12
+ #accessLayer: IDBAccessLayer;
13
+
14
+ constructor(options: IFhirManagerPGResOptions) {
15
+ this.#options = options;
16
+ this.#accessLayer = new DBAccessLayerManager().CreateAccessLayer({
17
+ accessLayerType: options.accessLayerType,
18
+ accessLayerOptions: options.accessLayerOptions
19
+ });
20
+ }
21
+
22
+ GetResourceType(fhir: Partial<T>): string {
23
+ return `${this.#options.resourceName}_${(fhir as Partial<IDomainResource>).id}`;
24
+ }
25
+
26
+ async GetFhirResource(fhir: Partial<T>, ecb?: (error: Error) => void): Promise<T | null> {
27
+ const retVal = await this.#accessLayer.GetResource<T>({
28
+ filters: {
29
+ resname: this.GetResourceType(fhir)
30
+ }
31
+ });
32
+ if (retVal.error) {
33
+ if (ecb) {
34
+ ecb(retVal.error.error);
35
+ }
36
+ return null;
37
+ } else {
38
+ return (retVal.detail as IDBResource<T>).resdesc;
39
+ }
40
+ }
41
+
42
+ async CreateFhirResource(fhir: T, ecb?: (error: Error) => void): Promise<T | null> {
43
+ const retVal = await this.#accessLayer.CreateResource<T>({
44
+ filters: {
45
+ dbactionuser: this.#options.dbactionuser,
46
+ resname: this.GetResourceType(fhir)
47
+ }
48
+ }, fhir);
49
+ if (retVal.error) {
50
+ if (ecb) {
51
+ ecb(retVal.error.error);
52
+ }
53
+ return null;
54
+ } else {
55
+ return (retVal.detail as IDBResource<T>).resdesc;
56
+ }
57
+ }
58
+
59
+ async UpdateFhirResource(fhir: T, ecb?: (error: Error) => void): Promise<T | null> {
60
+ const retVal = await this.#accessLayer.UpdateResource<T>({
61
+ filters: {
62
+ dbactionuser: this.#options.dbactionuser,
63
+ resname: this.GetResourceType(fhir)
64
+ }
65
+ }, fhir);
66
+ if (retVal.error) {
67
+ if (ecb) {
68
+ ecb(retVal.error.error);
69
+ }
70
+ return null;
71
+ } else {
72
+ return (retVal.detail as IDBResource<T>).resdesc;
73
+ }
74
+ }
75
+
76
+ async DeleteFhirResource(fhir: Partial<T>, ecb?: (error: Error) => void): Promise<T | null> {
77
+ const retVal = await this.#accessLayer.DeleteResource<T>({
78
+ filters: {
79
+ dbactionuser: this.#options.dbactionuser,
80
+ resname: this.GetResourceType(fhir)
81
+ }
82
+ });
83
+ if (retVal.error) {
84
+ if (ecb) {
85
+ ecb(retVal.error.error);
86
+ }
87
+ return null;
88
+ } else {
89
+ return (retVal.detail as IDBResource<T>).resdesc;
90
+ }
91
+ }
92
+ }
@@ -0,0 +1,43 @@
1
+ /* eslint @typescript-eslint/no-explicit-any: 0 */ // --> OFF
2
+ import { beforeAll, afterAll, test, describe, expect } from 'vitest';
3
+
4
+ import { accessLayerType, IPGAccessLayerOptions, SYSTEM_USER_ID } from '@nsshunt/stsdatamanagement'
5
+
6
+ import { DALFhirManagerPGResEntity } from './dalFhirManagerPGResEntity'
7
+
8
+ import { IPerson } from './STSFhirTypes'
9
+
10
+ import { TestHelpers } from './dalFhirTestHelpers'
11
+
12
+ describe("Test hl7 fhir resource data access layer - PGResEntity", () =>
13
+ {
14
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
+ let testHelpers: TestHelpers;
16
+
17
+ beforeAll(async () =>
18
+ {
19
+ testHelpers = new TestHelpers();
20
+ await testHelpers.StartDatabase();
21
+ }, 30000);
22
+
23
+ test('Testing Person', async () => {
24
+ expect.assertions(6);
25
+
26
+ const personManager = new DALFhirManagerPGResEntity<IPerson>({
27
+ accessLayerType: accessLayerType.postgresql,
28
+ accessLayerOptions: {
29
+ logger: testHelpers.logger,
30
+ usedefaultdb: false
31
+ } as IPGAccessLayerOptions,
32
+ resourceName: 'STSFhirPerson',
33
+ dbactionuser: SYSTEM_USER_ID
34
+ });
35
+
36
+ await testHelpers.TestFhirPerson(personManager);
37
+ }, 30000);
38
+
39
+ afterAll(async () =>
40
+ {
41
+ await testHelpers.StopDatabase();
42
+ }, 5000);
43
+ });
@@ -0,0 +1,123 @@
1
+ import { DBAccessLayerManager, IDBAccessLayer, IDBAccessLayerManagerOptions, IDBResource, IDBEntity } from '@nsshunt/stsdatamanagement'
2
+
3
+ import { IDomainResource, IFHIRResource, IDALFhirDataAccessManager } from './STSFhirTypes'
4
+
5
+ export interface IFhirManagerPGResEntityOptions extends IDBAccessLayerManagerOptions {
6
+ resourceName: string
7
+ dbactionuser: string
8
+ }
9
+
10
+ export class DALFhirManagerPGResEntity<T> implements IDALFhirDataAccessManager<T> {
11
+ #options: IFhirManagerPGResEntityOptions;
12
+ #accessLayer: IDBAccessLayer;
13
+ #fhirResource: IDBResource<IFHIRResource> | undefined;
14
+
15
+ constructor(options: IFhirManagerPGResEntityOptions) {
16
+ this.#options = options;
17
+ this.#accessLayer = new DBAccessLayerManager().CreateAccessLayer({
18
+ accessLayerType: options.accessLayerType,
19
+ accessLayerOptions: options.accessLayerOptions
20
+ });
21
+ }
22
+
23
+ #GetSTSFhirBaseResource = async (): Promise<IDBResource<IFHIRResource>> => {
24
+ if (!this.#fhirResource) {
25
+ this.#fhirResource = ((await this.#accessLayer.GetResource<IFHIRResource>({
26
+ filters: {
27
+ resname: this.#options.resourceName
28
+ }
29
+ })).detail as IDBResource<IFHIRResource>);
30
+
31
+ if (!this.#fhirResource) {
32
+ const fhirResourceType: IFHIRResource = {
33
+ name: this.#options.resourceName,
34
+ description: `${this.#options.resourceName} description`,
35
+ notes: `${this.#options.resourceName} notes`,
36
+ }
37
+ this.#fhirResource = ((await this.#accessLayer.CreateResource<IFHIRResource>({
38
+ filters: {
39
+ dbactionuser: this.#options.dbactionuser,
40
+ resname: this.#options.resourceName
41
+ }
42
+ }, fhirResourceType)).detail as IDBResource<IFHIRResource>);
43
+ }
44
+ }
45
+
46
+ return this.#fhirResource;
47
+ }
48
+
49
+ async GetFhirResource(fhir: Partial<T>, ecb?: (error: Error) => void): Promise<T | null> {
50
+ const fhirResource = await this.#GetSTSFhirBaseResource();
51
+ const retVal = await this.#accessLayer.GetEntity<T>({
52
+ filters: {
53
+ resname: fhirResource.resname,
54
+ entname: (fhir as Partial<IDomainResource>).id
55
+ }
56
+ });
57
+ if (retVal.error) {
58
+ if (ecb) {
59
+ ecb(retVal.error.error);
60
+ }
61
+ return null;
62
+ } else {
63
+ return (retVal.detail as IDBEntity<T>).entvalue;
64
+ }
65
+ }
66
+
67
+ async CreateFhirResource(fhir: T, ecb?: (error: Error) => void): Promise<T | null> {
68
+ const fhirResource = await this.#GetSTSFhirBaseResource();
69
+ const retVal = await this.#accessLayer.CreateEntity<T>({
70
+ filters: {
71
+ dbactionuser: this.#options.dbactionuser,
72
+ resname: fhirResource.resname,
73
+ entname: (fhir as Partial<IDomainResource>).id
74
+ }
75
+ }, fhir);
76
+ if (retVal.error) {
77
+ if (ecb) {
78
+ ecb(retVal.error.error);
79
+ }
80
+ return null;
81
+ } else {
82
+ return (retVal.detail as IDBEntity<T>).entvalue;
83
+ }
84
+ }
85
+
86
+ async UpdateFhirResource(fhir: T, ecb?: (error: Error) => void): Promise<T | null> {
87
+ const fhirResource = await this.#GetSTSFhirBaseResource();
88
+ const retVal = await this.#accessLayer.UpdateEntity<T>({
89
+ filters: {
90
+ dbactionuser: this.#options.dbactionuser,
91
+ resname: fhirResource.resname,
92
+ entname: (fhir as Partial<IDomainResource>).id
93
+ }
94
+ }, fhir);
95
+ if (retVal.error) {
96
+ if (ecb) {
97
+ ecb(retVal.error.error);
98
+ }
99
+ return null;
100
+ } else {
101
+ return (retVal.detail as IDBEntity<T>).entvalue;
102
+ }
103
+ }
104
+
105
+ async DeleteFhirResource(fhir: Partial<T>, ecb?: (error: Error) => void): Promise<T | null> {
106
+ const fhirResource = await this.#GetSTSFhirBaseResource();
107
+ const retVal = await this.#accessLayer.DeleteEntity<T>({
108
+ filters: {
109
+ dbactionuser: this.#options.dbactionuser,
110
+ resname: fhirResource.resname,
111
+ entname: (fhir as Partial<IDomainResource>).id
112
+ }
113
+ });
114
+ if (retVal.error) {
115
+ if (ecb) {
116
+ ecb(retVal.error.error);
117
+ }
118
+ return null;
119
+ } else {
120
+ return (retVal.detail as IDBEntity<T>).entvalue;
121
+ }
122
+ }
123
+ }
@@ -0,0 +1,44 @@
1
+ /* eslint @typescript-eslint/no-explicit-any: 0 */ // --> OFF
2
+ import { beforeAll, afterAll, test, describe, expect } from 'vitest';
3
+
4
+ import { DALFhirManagerRedisJson } from './dalFhirManagerRedisJson'
5
+
6
+ import { IPerson } from './STSFhirTypes'
7
+
8
+ import { TestHelpers } from './dalFhirTestHelpers'
9
+
10
+ import { JestSleep } from '@nsshunt/stsutils'
11
+
12
+ describe.skip("Test hl7 fhir resource data access layer - RedisJson", () =>
13
+ {
14
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
+ let personManager: DALFhirManagerRedisJson<IPerson>;
16
+ let testHelpers: TestHelpers;
17
+
18
+ beforeAll(async () =>
19
+ {
20
+ testHelpers = new TestHelpers();
21
+ await testHelpers.StartRedis();
22
+
23
+ personManager = new DALFhirManagerRedisJson<IPerson>({
24
+ //const personManager = new DALFhirManagerPGRes<IPerson>({
25
+ //const personManager = new DALFhirManagerPGResEntity<IPerson>({
26
+ resourceName: 'STSFhirPerson',
27
+ redisUrl: testHelpers.ioRedisMessageProcessorUrl
28
+ });
29
+ personManager.Start();
30
+ }, 30000);
31
+
32
+ test('Testing Person', async () => {
33
+ expect.assertions(6);
34
+
35
+ await testHelpers.TestFhirPerson(personManager);
36
+ }, 30000);
37
+
38
+ afterAll(async () =>
39
+ {
40
+ personManager.Stop();
41
+ await JestSleep();
42
+ await testHelpers.StopRedis();
43
+ }, 5000);
44
+ });
@@ -0,0 +1,92 @@
1
+ import { IDomainResource, IDALFhirDataAccessManager } from './STSFhirTypes'
2
+
3
+ import { Redis, RedisOptions } from "ioredis";
4
+
5
+ export interface IFhirManagerRedisJsonOptions {
6
+ redisUrl: string
7
+ resourceName: string
8
+ }
9
+
10
+ export class DALFhirManagerRedisJson<T> implements IDALFhirDataAccessManager<T> {
11
+ #options: IFhirManagerRedisJsonOptions;
12
+ #redisSubscriber: Redis | null = null;
13
+
14
+ constructor(options: IFhirManagerRedisJsonOptions) {
15
+ this.#options = options;
16
+ }
17
+
18
+ Start() {
19
+ const redisOptions: RedisOptions = {
20
+ showFriendlyErrorStack: true,
21
+ maxRetriesPerRequest: 20
22
+ }
23
+
24
+ this.#redisSubscriber = new Redis(this.#options.redisUrl, redisOptions);
25
+ }
26
+
27
+ Stop() {
28
+ if (this.#redisSubscriber) {
29
+ this.#redisSubscriber.quit();
30
+ this.#redisSubscriber.disconnect();
31
+ }
32
+ }
33
+
34
+ GetResourceType(fhir: Partial<T>): string {
35
+ return `${this.#options.resourceName}_${(fhir as Partial<IDomainResource>).id}`;
36
+ }
37
+
38
+ async GetFhirResource(fhir: Partial<T>, ecb?: (error: Error) => void): Promise<T | null> {
39
+ if (this.#redisSubscriber) {
40
+ const retValRaw = await this.#redisSubscriber?.get(this.GetResourceType(fhir))
41
+ if (retValRaw) {
42
+ try {
43
+ return JSON.parse(retValRaw) as T;
44
+ } catch (error: unknown) {
45
+ if (ecb) {
46
+ ecb(error as Error);
47
+ }
48
+ return null;
49
+ }
50
+ } else {
51
+ return null;
52
+ }
53
+ } else {
54
+ return null;
55
+ }
56
+ }
57
+
58
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
59
+ async CreateFhirResource(fhir: T, ecb?: (error: Error) => void): Promise<T | null> {
60
+ const retVal = await this.#redisSubscriber?.set(this.GetResourceType(fhir), JSON.stringify(fhir));
61
+ if (retVal) {
62
+ return fhir;
63
+ } else {
64
+ return null;
65
+ }
66
+ }
67
+
68
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
69
+ async UpdateFhirResource(fhir: T, ecb?: (error: Error) => void): Promise<T | null> {
70
+ const retVal = await this.#redisSubscriber?.set(this.GetResourceType(fhir), JSON.stringify(fhir));
71
+ if (retVal) {
72
+ return fhir;
73
+ } else {
74
+ return null;
75
+ }
76
+ }
77
+
78
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
79
+ async DeleteFhirResource(fhir: Partial<T>, ecb?: (error: Error) => void): Promise<T | null> {
80
+ const deleteResource = await this.GetFhirResource(fhir);
81
+ if (deleteResource) {
82
+ const retVal = await this.#redisSubscriber?.del(this.GetResourceType(fhir));
83
+ if (retVal) {
84
+ return deleteResource;
85
+ } else {
86
+ return null;
87
+ }
88
+ } else {
89
+ return null;
90
+ }
91
+ }
92
+ }
@@ -0,0 +1,163 @@
1
+ import { expect } from 'vitest';
2
+ import { IDALFhirDataAccessManager, INarrative, IPerson } from './STSFhirTypes'
3
+ import { v4 as uuidv4 } from 'uuid';
4
+
5
+ import chalk from 'chalk';
6
+
7
+ import { goptions, $ResetOptions } from '@nsshunt/stsconfig'
8
+
9
+ import { JestSleep, defaultLogger, Sleep } from '@nsshunt/stsutils'
10
+
11
+ import { DatabaseUtils, DBAccessLayerManager, IDBAccessLayer, accessLayerType, IPGAccessLayerOptions } from '@nsshunt/stsdatamanagement'
12
+
13
+ import { GenericContainer } from "testcontainers";
14
+
15
+ import winston from 'winston'
16
+
17
+ export class TestHelpers {
18
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
+ #postgresContainer: any;
20
+ #accessLayer: IDBAccessLayer | null = null;
21
+ #logger: winston.Logger;
22
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
23
+ #ioRedisContainer: any;
24
+ #ioRedisMessageProcessorUrl = '';
25
+
26
+ constructor() {
27
+ winston.format.combine(
28
+ winston.format.colorize(),
29
+ winston.format.simple()
30
+ );
31
+
32
+ this.#logger = winston.createLogger({
33
+ level: 'silly',
34
+ format: winston.format.combine(
35
+ winston.format.colorize(),
36
+ winston.format.simple()
37
+ ),
38
+ transports: [
39
+ new winston.transports.Console(),
40
+ ]});
41
+ }
42
+
43
+ get logger(): winston.Logger {
44
+ return this.#logger;
45
+ }
46
+
47
+ TestFhirPerson = async (personManager: IDALFhirDataAccessManager<IPerson>) => {
48
+ expect.assertions(6);
49
+
50
+ const id = uuidv4();
51
+
52
+ const personRecord: IPerson = {
53
+ id,
54
+ _resourceType: 'Person',
55
+ name: [
56
+ {
57
+ family: 'family',
58
+ given: [ 'given' ],
59
+ use: 'usual'
60
+ }
61
+ ],
62
+ text: {
63
+ div: 'New Record',
64
+ status: 'generated'
65
+ }
66
+ };
67
+
68
+ const newPerson01 = await personManager.CreateFhirResource(personRecord);
69
+ expect(newPerson01).toMatchObject(personRecord);
70
+
71
+ (personRecord.text as INarrative).div = 'user01 updated at ' + new Date().toString();
72
+ const updatedPerson01 = await personManager.UpdateFhirResource(personRecord);
73
+ expect(updatedPerson01).toMatchObject(personRecord);
74
+
75
+ const getPerson01 = await personManager.GetFhirResource({id})
76
+ expect(getPerson01).toMatchObject(personRecord);
77
+
78
+ const getPerson02 = await personManager.GetFhirResource({id:'willnotfind'})
79
+ expect(getPerson02).toBeNull();
80
+
81
+ const deletePerson01 = await personManager.DeleteFhirResource({id})
82
+ expect(deletePerson01).toMatchObject(personRecord);
83
+
84
+ const getPerson01AfterDelete = await personManager.GetFhirResource({id})
85
+ expect(getPerson01AfterDelete).toBeNull();
86
+ }
87
+
88
+ StartDatabase = async() => {
89
+ this.#postgresContainer = await new GenericContainer("postgres")
90
+ .withExposedPorts(5432)
91
+ .withEnvironment({
92
+ POSTGRES_PASSWORD: "postgres",
93
+ //UV_THREADPOOL_SIZE: "64"
94
+ })
95
+ .withCommand(['-c', 'max_connections=20'])
96
+ .start();
97
+
98
+ await Sleep(1000);
99
+
100
+ const postgresHttpPort = this.#postgresContainer.getMappedPort(5432);
101
+ const postgresHost = this.#postgresContainer.getHost();
102
+
103
+ process.env.DB_HOST = `${postgresHost}:${postgresHttpPort}`;
104
+ process.env.POOL_SIZE = '10';
105
+
106
+ $ResetOptions();
107
+
108
+ this.logger.info(chalk.green(`httpPort: [${postgresHttpPort}]`));
109
+ this.logger.info(chalk.green(`host: [${postgresHost}]`));
110
+ this.logger.info(chalk.yellow(`connectionString: [${goptions.connectionString}]`));
111
+ this.logger.info(chalk.yellow(`defaultDatabaseConnectionString: [${goptions.defaultDatabaseConnectionString }]`));
112
+
113
+ const dbOptions = {
114
+ start: 0,
115
+ iterations: 10000,
116
+ minextradata: 0,
117
+ maxextradata: 1000,
118
+ workerScriptFolder: './dist', //@@
119
+ useMultiBar: false
120
+ }
121
+
122
+ const dbUtils = new DatabaseUtils({
123
+ logger: this.logger
124
+ });
125
+ await dbUtils.CreateDatabase(dbOptions);
126
+
127
+ await Sleep(1000);
128
+
129
+ this.logger.info(chalk.green(`Starting accessLayer`));
130
+
131
+ this.#accessLayer = new DBAccessLayerManager().CreateAccessLayer({
132
+ accessLayerType: accessLayerType.postgresql,
133
+ accessLayerOptions: {
134
+ logger: defaultLogger,
135
+ usedefaultdb: false
136
+ } as IPGAccessLayerOptions
137
+ })
138
+
139
+ this.logger.info(chalk.green(`accessLayer:startdatabase()`));
140
+ await this.#accessLayer.StartDatabase();
141
+ }
142
+
143
+ StopDatabase = async () => {
144
+ await this.#accessLayer?.EndDatabase();
145
+ await JestSleep();
146
+ await this.#postgresContainer.stop();
147
+ }
148
+
149
+ StartRedis = async () => {
150
+ this.#ioRedisContainer = await new GenericContainer("redis")
151
+ .withExposedPorts(6379)
152
+ .start();
153
+ this.#ioRedisMessageProcessorUrl = `redis://${this.#ioRedisContainer.getHost()}:${this.#ioRedisContainer.getMappedPort(6379)}`;
154
+ }
155
+
156
+ get ioRedisMessageProcessorUrl() {
157
+ return this.#ioRedisMessageProcessorUrl;
158
+ }
159
+
160
+ StopRedis = async () => {
161
+ await this.#ioRedisContainer.stop();
162
+ }
163
+ }
package/src/index.ts CHANGED
@@ -26,3 +26,5 @@ export * from './ipcMessageProcessorPrimary'
26
26
  export * from './ipcMessageProcessorWorker'
27
27
  export * from './ipcMessageManager'
28
28
  export * from './redisMessageHandler'
29
+ export * from './fhir/STSFhirTypes'
30
+ export * from './fhir/dalFhirManagerPGResEntity'
@@ -341,6 +341,29 @@ export class RedisMessageHandler extends TinyEmitter {
341
341
  return this;
342
342
  }
343
343
 
344
+ emitWithError(event: string, args: JSONObject, responseCb: (response: JSONObject | undefined) => void, errorCb: (error: any) => void): this {
345
+ (async () => {
346
+ try {
347
+ const retVal = await this.#ipcMessageManager?.SendMessage({
348
+ __eventName: event,
349
+ args: [ args ]
350
+ } as IEventPayload);
351
+ // Invoke the response callback
352
+ responseCb(retVal);
353
+ } catch (error) {
354
+ if (this.#options.ignoreEvents) {
355
+ //console.log(chalk.red(`RedisMessageHandler:emit(): ignoreEvents: [${this.#options.ignoreEvents}]`))
356
+ if (this.#options.ignoreEvents.indexOf((error as any).__eventName) !== -1) {
357
+ return;
358
+ }
359
+ }
360
+ //this.#options.logger.error(chalk.red(`RedisMessageHandler:emit(): Error: [${JSON.stringify(error)}]`));
361
+ errorCb(error);
362
+ }
363
+ })();
364
+ return this;
365
+ }
366
+
344
367
  emitex = async(event: string, ...args: any[]): Promise<JSONObject> => {
345
368
  return (this.#ipcMessageManager as IPCMessageManager).SendMessage({
346
369
  __eventName: event,
@@ -526,8 +526,18 @@ if (cluster.isPrimary) {
526
526
  worker.redisMessageHandler.emit('GetSystemInformation', {
527
527
  group: 'primary'
528
528
  }, (response: any) => {
529
+ console.log(`------------------------------------------------------------------------`);
529
530
  console.log(response);
530
531
  });
531
532
 
533
+ worker.redisMessageHandler.emitWithError('GetSystemInformation', {
534
+ group: 'primary'
535
+ }, (response: any) => {
536
+ console.log(`************************************************************************`);
537
+ console.log(response);
538
+ }, (error: any) => {
539
+ console.log(chalk.red(`GetSystemInformation Error: [${error}]`));
540
+ });
541
+
532
542
  }, 2000);
533
543
  }