@creator.co/wapi 1.5.3-alpha1 → 1.5.4

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 (65) hide show
  1. package/dist/index.d.ts +3 -2
  2. package/dist/index.js +5 -3
  3. package/dist/index.js.map +1 -1
  4. package/dist/package.json +1 -1
  5. package/dist/src/API/Request.js +1 -1
  6. package/dist/src/API/Request.js.map +1 -1
  7. package/dist/src/API/Response.js.map +1 -1
  8. package/dist/src/BaseEvent/EventProcessor.js.map +1 -1
  9. package/dist/src/Cache/Redis.d.ts +6 -13
  10. package/dist/src/Cache/Redis.js +32 -53
  11. package/dist/src/Cache/Redis.js.map +1 -1
  12. package/dist/src/Config/Configuration.js.map +1 -1
  13. package/dist/src/Config/EnvironmentVar.js.map +1 -1
  14. package/dist/src/Crypto/JWT.js.map +1 -1
  15. package/dist/src/Database/DatabaseManager.js +2 -1
  16. package/dist/src/Database/DatabaseManager.js.map +1 -1
  17. package/dist/src/Database/DatabaseTransaction.js.map +1 -1
  18. package/dist/src/Database/integrations/knex/KnexDatabase.js +2 -1
  19. package/dist/src/Database/integrations/knex/KnexDatabase.js.map +1 -1
  20. package/dist/src/Database/integrations/knex/KnexTransaction.js.map +1 -1
  21. package/dist/src/Database/integrations/kysely/KyselyDatabase.js +2 -1
  22. package/dist/src/Database/integrations/kysely/KyselyDatabase.js.map +1 -1
  23. package/dist/src/Database/integrations/kysely/KyselyTransaction.js.map +1 -1
  24. package/dist/src/Database/integrations/pgsql/PostgresDatabase.js +2 -1
  25. package/dist/src/Database/integrations/pgsql/PostgresDatabase.js.map +1 -1
  26. package/dist/src/Database/integrations/pgsql/PostgresTransaction.js.map +1 -1
  27. package/dist/src/Globals.js +1 -1
  28. package/dist/src/Globals.js.map +1 -1
  29. package/dist/src/Logger/Logger.js +1 -1
  30. package/dist/src/Logger/Logger.js.map +1 -1
  31. package/dist/src/Publisher/Publisher.js.map +1 -1
  32. package/dist/src/Server/RouteResolver.js.map +1 -1
  33. package/dist/src/Server/Router.js +1 -1
  34. package/dist/src/Server/Router.js.map +1 -1
  35. package/dist/src/Server/lib/ContainerServer.js.map +1 -1
  36. package/dist/src/Server/lib/Server.js.map +1 -1
  37. package/dist/src/Server/lib/container/GenericHandler.js +1 -1
  38. package/dist/src/Server/lib/container/GenericHandler.js.map +1 -1
  39. package/dist/src/Server/lib/container/GenericHandlerEvent.js +1 -1
  40. package/dist/src/Server/lib/container/GenericHandlerEvent.js.map +1 -1
  41. package/dist/src/Server/lib/container/Proxy.js +1 -1
  42. package/dist/src/Server/lib/container/Proxy.js.map +1 -1
  43. package/dist/src/Server/lib/container/Utils.js.map +1 -1
  44. package/dist/src/Util/AsyncSingleton.d.ts +31 -0
  45. package/dist/src/Util/AsyncSingleton.js +207 -0
  46. package/dist/src/Util/AsyncSingleton.js.map +1 -0
  47. package/dist/src/Util/Utils.js.map +1 -0
  48. package/dist/src/Validation/Validator.js.map +1 -1
  49. package/index.ts +3 -1
  50. package/package.json +1 -1
  51. package/src/API/Request.ts +1 -1
  52. package/src/Cache/Redis.ts +31 -42
  53. package/src/Globals.ts +1 -1
  54. package/src/Logger/Logger.ts +1 -1
  55. package/src/Server/Router.ts +1 -1
  56. package/src/Server/lib/container/GenericHandler.ts +1 -1
  57. package/src/Server/lib/container/Proxy.ts +1 -1
  58. package/src/Util/AsyncSingleton.ts +86 -0
  59. package/tests/API/Utils.test.ts +1 -1
  60. package/tests/Cache/{Redis.test.ts → Redis-client.test.ts} +15 -43
  61. package/tests/Cache/Redis-cluster.test.ts +98 -0
  62. package/dist/src/API/Utils.js.map +0 -1
  63. /package/dist/src/{API → Util}/Utils.d.ts +0 -0
  64. /package/dist/src/{API → Util}/Utils.js +0 -0
  65. /package/src/{API → Util}/Utils.ts +0 -0
@@ -7,8 +7,8 @@ import Server from './../Server'
7
7
  import GenericHandler from './GenericHandler'
8
8
  import HealthHandler from './HealthHandler'
9
9
  import { version as appVersion } from '../../../../package.json'
10
- import Utils from '../../../API/Utils'
11
10
  import Globals from '../../../Globals'
11
+ import Utils from '../../../Util/Utils'
12
12
  import { RouterConfig } from '../../Router'
13
13
 
14
14
  /**
@@ -0,0 +1,86 @@
1
+ type ResolveReject = [(value: void | PromiseLike<void>) => void, (reason?: any) => void]
2
+
3
+ /**
4
+ * Represents a class that can be used to create a singleton instance of a class that is created asynchronously.
5
+ */
6
+ export default class AsyncSingleton<T, R> {
7
+ private readonly factory: (r: R) => Promise<T>
8
+ private readonly checker: (value: T) => Promise<boolean>
9
+
10
+ private queue: ResolveReject[] = []
11
+ private instantiating: boolean = false
12
+
13
+ private value?: T
14
+
15
+ /**
16
+ * Creates a new instance of the AsyncSingleton class.
17
+ * @param factory The factory function that creates the instance.
18
+ * @param checker The function that checks if the instance is valid.
19
+ */
20
+ public constructor(
21
+ factory: (r: R) => Promise<T>,
22
+ checker: (value: T) => Promise<boolean> = async () => true
23
+ ) {
24
+ this.factory = factory
25
+ this.checker = checker
26
+ }
27
+
28
+ /**
29
+ * Gets the instance of the class.
30
+ * @param r The configuration object for creating the instance.
31
+ */
32
+ public async instance(r: R): Promise<T> {
33
+ if (this.value && (await this.checker(this.value))) return this.value
34
+
35
+ if (this.instantiating) {
36
+ return await this.awaitOtherInit()
37
+ }
38
+
39
+ return await this.initHere(r)
40
+ }
41
+
42
+ /**
43
+ * Gets the current value, may be undefined or invalid.
44
+ */
45
+ public getValue(): T | undefined {
46
+ return this.value
47
+ }
48
+
49
+ /**
50
+ * Clears the current value and rejects all pending promises.
51
+ */
52
+ public clear() {
53
+ this.value = undefined
54
+ for (const [, rej] of this.queue) {
55
+ rej()
56
+ }
57
+ this.queue = []
58
+ }
59
+
60
+ private async initHere(r: R): Promise<T> {
61
+ try {
62
+ this.instantiating = true
63
+ this.value = await this.factory(r)
64
+
65
+ for (const [res] of this.queue) {
66
+ res()
67
+ }
68
+
69
+ this.queue = []
70
+
71
+ return this.value
72
+ } finally {
73
+ for (const [, rej] of this.queue) {
74
+ rej()
75
+ }
76
+ this.instantiating = false
77
+ }
78
+ }
79
+
80
+ private async awaitOtherInit(): Promise<T> {
81
+ await new Promise<void>((res, rej) => {
82
+ this.queue.push([res, rej])
83
+ })
84
+ return this.value!
85
+ }
86
+ }
@@ -1,6 +1,6 @@
1
1
  import { expect } from 'chai'
2
2
 
3
- import Utils from '../../src/API/Utils'
3
+ import Utils from '../../src/Util/Utils'
4
4
 
5
5
  describe('isHybridlessContainer', () => {
6
6
  test('Simple isHybridlessContainer test', () => {
@@ -1,6 +1,7 @@
1
1
  import Redis from '../../src/Cache/Redis'
2
2
 
3
3
  let _connectionId = 1
4
+
4
5
  async function simpleRedisTest(config: any, concurrent?: boolean) {
5
6
  const RedisMock = jest.fn(() => {
6
7
  let opened = false
@@ -20,18 +21,11 @@ async function simpleRedisTest(config: any, concurrent?: boolean) {
20
21
  } as any
21
22
  })
22
23
  Redis['ClientFactory'] = RedisMock
23
- // Cleanup previous connection
24
- if (Redis['_connection']) (await Redis.connection({} as any))?.['close']()
25
24
  // Double call is intentional
26
- let provider, provider2
27
- if (concurrent) {
28
- const ps = await Promise.all([Redis.connection(config as any), Redis.connection(config as any)])
29
- provider = ps[0]
30
- provider2 = ps[1]
31
- } else {
32
- provider = await Redis.connection(config as any)
33
- provider2 = await Redis.connection(config as any)
34
- }
25
+ const [provider, provider2] = concurrent
26
+ ? await Promise.all([Redis.connection(config), Redis.connection(config)])
27
+ : [await Redis.connection(config), await Redis.connection(config)]
28
+
35
29
  // client checks
36
30
  expect(RedisMock).toHaveBeenNthCalledWith(1, {
37
31
  username: config.username,
@@ -44,46 +38,26 @@ async function simpleRedisTest(config: any, concurrent?: boolean) {
44
38
  },
45
39
  })
46
40
  // Does not have double connection
47
- expect(provider.connectionId).toEqual(provider2.connectionId)
41
+ expect(provider['connectionId']).toEqual(provider2['connectionId'])
48
42
  expect(provider.connect).toHaveBeenCalledTimes(1)
49
43
  expect(provider2.connect).toHaveBeenCalledTimes(1)
50
44
  }
51
45
 
52
- describe('Redis', () => {
46
+ describe('Redis (client)', () => {
53
47
  beforeEach(async () => {
54
48
  // hack to close singleton connection
55
- // if (Redis['_connection']) (await Redis.connection({} as any))?.['close']()
49
+ if (Redis['singleton'].getValue()) Redis['singleton'].clear()
56
50
  })
57
51
  test('Simple redis - do not connect twice', async () => {
58
- try {
59
- const c = await Redis.connection({
60
- // fetch from SSM -> /shared/redis-primary-endpoint for dev/prod
61
- // note: prefix needs to be set through code
62
- hostname: 'localhost',
63
- username: 'writer',
64
- password: 'writer', // passwordless but redis clie needs this
65
- enableTLS: true,
66
- type: 'redis',
67
- })
68
- await c.set('abc', 123)
69
- const a = await c.get('abc')
70
- await c.flushAll()
71
- console.log(a)
72
- console.log('de')
73
- } catch (e) {
74
- console.error(e)
75
- }
76
- // Redis['_connection'] = null as any
77
- // await simpleRedisTest({
78
- // hostname: 'redis://localhost',
79
- // username: 'gabe',
80
- // password: 'mypassword',
81
- // enableTLS: true,
82
- // type: 'redis',
83
- // })
52
+ await simpleRedisTest({
53
+ hostname: 'redis://localhost',
54
+ username: 'gabe',
55
+ password: 'mypassword',
56
+ enableTLS: true,
57
+ type: 'redis',
58
+ })
84
59
  })
85
60
  test('Simple redis (no SSL) - do not connect twice', async () => {
86
- Redis['_connection'] = null as any
87
61
  await simpleRedisTest({
88
62
  hostname: 'redis://localhost',
89
63
  username: 'gabe',
@@ -93,7 +67,6 @@ describe('Redis', () => {
93
67
  })
94
68
  })
95
69
  test('Simple redis (passwordless) - do not connect twice', async () => {
96
- Redis['_connection'] = null as any
97
70
  await simpleRedisTest({
98
71
  hostname: 'redis://localhost',
99
72
  username: 'gabe',
@@ -102,7 +75,6 @@ describe('Redis', () => {
102
75
  })
103
76
  })
104
77
  test('Concurrent redis - do not connect twice', async () => {
105
- Redis['_connection'] = null as any
106
78
  await simpleRedisTest(
107
79
  {
108
80
  hostname: 'redis://localhost',
@@ -0,0 +1,98 @@
1
+ import Redis from '../../src/Cache/Redis'
2
+
3
+ let _connectionId = 1
4
+
5
+ async function simpleRedisTest(config: any, concurrent?: boolean) {
6
+ const RedisMock = jest.fn(() => {
7
+ let opened = false
8
+ const connectionId = _connectionId++
9
+ return {
10
+ connectionId,
11
+ isOpen: () => opened,
12
+ close: () => (opened = false),
13
+ connect: jest.fn(() => {
14
+ opened = true
15
+ return {
16
+ mget: jest.fn(() => {
17
+ return true
18
+ }),
19
+ }
20
+ }),
21
+ } as any
22
+ })
23
+ Redis['ClusterFactory'] = RedisMock
24
+ // Double call is intentional
25
+ const [provider, provider2] = concurrent
26
+ ? await Promise.all([Redis.connection(config), Redis.connection(config)])
27
+ : [await Redis.connection(config), await Redis.connection(config)]
28
+
29
+ // client checks
30
+ expect(RedisMock).toHaveBeenNthCalledWith(1, {
31
+ defaults: {
32
+ username: config.username,
33
+ ...(config.password ? { password: config.password } : {}),
34
+ socket: {
35
+ ...(config.enableTLS ? { tls: true } : {}),
36
+ connectTimeout: 10000,
37
+ },
38
+ },
39
+ rootNodes: [
40
+ {
41
+ url: `redis://${config.username}:${config.username}@${config.hostname}:6379`,
42
+ disableOfflineQueue: true,
43
+ },
44
+ ],
45
+ })
46
+ // Does not have double connection
47
+ expect(provider['connectionId']).toEqual(provider2['connectionId'])
48
+ expect(provider.connect).toHaveBeenCalledTimes(1)
49
+ expect(provider2.connect).toHaveBeenCalledTimes(1)
50
+ }
51
+
52
+ describe('Redis (cluster)', () => {
53
+ beforeEach(async () => {
54
+ // hack to close singleton connection
55
+ if (Redis['singleton'].getValue()) Redis['singleton'].clear()
56
+ })
57
+ test('Simple redis - do not connect twice', async () => {
58
+ await simpleRedisTest({
59
+ hostname: 'redis://localhost',
60
+ username: 'gabe',
61
+ password: 'mypassword',
62
+ enableTLS: true,
63
+ clusterMode: true,
64
+ type: 'redis',
65
+ })
66
+ })
67
+ test('Simple redis (no SSL) - do not connect twice', async () => {
68
+ await simpleRedisTest({
69
+ hostname: 'redis://localhost',
70
+ username: 'gabe',
71
+ password: 'mypassword',
72
+ enableTLS: false,
73
+ clusterMode: true,
74
+ type: 'redis',
75
+ })
76
+ })
77
+ test('Simple redis (passwordless) - do not connect twice', async () => {
78
+ await simpleRedisTest({
79
+ hostname: 'redis://localhost',
80
+ username: 'gabe',
81
+ enableTLS: false,
82
+ clusterMode: true,
83
+ type: 'redis',
84
+ })
85
+ })
86
+ test('Concurrent redis - do not connect twice', async () => {
87
+ await simpleRedisTest(
88
+ {
89
+ hostname: 'redis://localhost',
90
+ username: 'gabe',
91
+ enableTLS: false,
92
+ clusterMode: true,
93
+ type: 'redis',
94
+ },
95
+ true
96
+ )
97
+ })
98
+ })
@@ -1 +0,0 @@
1
- {"version":3,"file":"Utils.js","sourceRoot":"","sources":["../../../src/API/Utils.ts"],"names":[],"mappings":";;AAAA;;GAEG;AACH;IAAA;IAwEA,CAAC;IAvEC;;;OAGG;IACW,2BAAqB,GAAnC;QACE,OAAO,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,MAAM,CAAA;IACjD,CAAC;IAED;;;;OAIG;IACW,mBAAa,GAA3B,UAA4B,MAAc;QACxC,OAAO,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,MAAM,IAAG,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IACrD,CAAC;IAED;;;;OAIG;IACW,uBAAiB,GAA/B,UAAgC,GAAY;QAC1C,IAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,IAAI,EAAE,CAAC,CAAA;QAC7B,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;IAC5B,CAAC;IAED;;;;;OAKG;IACW,4BAAsB,GAApC,UAAqC,MAA0B;QAC7D,IAAI,CAAC,GAAG,IAAI,CAAA;QACZ,IAAI;YACF,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;YACtC,IAAI,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC;gBAAE,CAAC,GAAG,IAAI,CAAA;SAC9C;QAAC,OAAO,CAAC,EAAE;YACV,WAAW;SACZ;QACD,OAAO,CAAC,CAAA;IACV,CAAC;IAED;;;;OAIG;IACW,mBAAa,GAA3B,UAA4B,MAAc;QACxC,IAAI,SAAS,GAAG,GAAG,CAAA;QACnB,IAAI;YACF,SAAS,GAAG,QAAQ,CAAC,MAAM,GAAG,EAAE,CAAC,CAAA;SAClC;QAAC,OAAO,CAAC,EAAE;YACV,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,CAAC,CAAC,CAAA;SAClD;QACD,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IACpD,CAAC;IAED;;;;;OAKG;IACW,iCAA2B,GAAzC,UAA0C,GAAQ,EAAE,GAAW;QAC7D,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAA;QACrB,IAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,UAAA,CAAC,IAAI,OAAA,CAAC,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,WAAW,EAAE,EAArC,CAAqC,CAAC,CAAA;QACxF,IAAI,cAAc,IAAI,cAAc,IAAI,EAAE;YAAE,OAAO,GAAG,CAAC,cAAc,CAAC,CAAA;QACtE,OAAO,IAAI,CAAA;IACb,CAAC;IACH,YAAC;AAAD,CAAC,AAxED,IAwEC"}
File without changes
File without changes
File without changes