backend-test-tools 1.0.0

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 (187) hide show
  1. package/.env.example +51 -0
  2. package/.mocharc.js +9 -0
  3. package/.prettierrc +7 -0
  4. package/README.md +271 -0
  5. package/babel.config.json +33 -0
  6. package/dist/factory/factory.d.ts +11 -0
  7. package/dist/factory/factory.js +39 -0
  8. package/dist/factory/factory.js.map +1 -0
  9. package/dist/factory/factory.types.d.ts +38 -0
  10. package/dist/factory/factory.types.js +2 -0
  11. package/dist/factory/factory.types.js.map +1 -0
  12. package/dist/factory/index.d.ts +2 -0
  13. package/dist/factory/index.js +28 -0
  14. package/dist/factory/index.js.map +1 -0
  15. package/dist/factory/workers/connection.d.ts +3 -0
  16. package/dist/factory/workers/connection.js +25 -0
  17. package/dist/factory/workers/connection.js.map +1 -0
  18. package/dist/factory/workers/connection.types.d.ts +28 -0
  19. package/dist/factory/workers/connection.types.js +2 -0
  20. package/dist/factory/workers/connection.types.js.map +1 -0
  21. package/dist/factory/workers/index.d.ts +6 -0
  22. package/dist/factory/workers/index.js +72 -0
  23. package/dist/factory/workers/index.js.map +1 -0
  24. package/dist/factory/workers/organization.d.ts +3 -0
  25. package/dist/factory/workers/organization.js +36 -0
  26. package/dist/factory/workers/organization.js.map +1 -0
  27. package/dist/factory/workers/organization.types.d.ts +51 -0
  28. package/dist/factory/workers/organization.types.js +2 -0
  29. package/dist/factory/workers/organization.types.js.map +1 -0
  30. package/dist/factory/workers/user.d.ts +5 -0
  31. package/dist/factory/workers/user.js +60 -0
  32. package/dist/factory/workers/user.js.map +1 -0
  33. package/dist/factory/workers/user.types.d.ts +76 -0
  34. package/dist/factory/workers/user.types.js +2 -0
  35. package/dist/factory/workers/user.types.js.map +1 -0
  36. package/dist/generators/generateAccessToken.d.ts +3 -0
  37. package/dist/generators/generateAccessToken.js +27 -0
  38. package/dist/generators/generateAccessToken.js.map +1 -0
  39. package/dist/generators/generateChatId.d.ts +2 -0
  40. package/dist/generators/generateChatId.js +13 -0
  41. package/dist/generators/generateChatId.js.map +1 -0
  42. package/dist/generators/generateEcdsaKeyPair.d.ts +2 -0
  43. package/dist/generators/generateEcdsaKeyPair.js +31 -0
  44. package/dist/generators/generateEcdsaKeyPair.js.map +1 -0
  45. package/dist/generators/generateImageBuffer.d.ts +3 -0
  46. package/dist/generators/generateImageBuffer.js +23 -0
  47. package/dist/generators/generateImageBuffer.js.map +1 -0
  48. package/dist/generators/generateImageBuffer.types.d.ts +7 -0
  49. package/dist/generators/generateImageBuffer.types.js +2 -0
  50. package/dist/generators/generateImageBuffer.types.js.map +1 -0
  51. package/dist/generators/generateKeyPair.d.ts +6 -0
  52. package/dist/generators/generateKeyPair.js +36 -0
  53. package/dist/generators/generateKeyPair.js.map +1 -0
  54. package/dist/generators/generateKeyPair.types.d.ts +9 -0
  55. package/dist/generators/generateKeyPair.types.js +2 -0
  56. package/dist/generators/generateKeyPair.types.js.map +1 -0
  57. package/dist/generators/generateLocale.d.ts +5 -0
  58. package/dist/generators/generateLocale.js +16 -0
  59. package/dist/generators/generateLocale.js.map +1 -0
  60. package/dist/generators/generateRegId.d.ts +4 -0
  61. package/dist/generators/generateRegId.js +14 -0
  62. package/dist/generators/generateRegId.js.map +1 -0
  63. package/dist/generators/generateRsaKeyPair.d.ts +2 -0
  64. package/dist/generators/generateRsaKeyPair.js +22 -0
  65. package/dist/generators/generateRsaKeyPair.js.map +1 -0
  66. package/dist/generators/generateUserCrypto.d.ts +15 -0
  67. package/dist/generators/generateUserCrypto.js +33 -0
  68. package/dist/generators/generateUserCrypto.js.map +1 -0
  69. package/dist/generators/index.d.ts +9 -0
  70. package/dist/generators/index.js +105 -0
  71. package/dist/generators/index.js.map +1 -0
  72. package/dist/index.d.ts +4 -0
  73. package/dist/index.js +50 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/stubs/index.d.ts +1 -0
  76. package/dist/stubs/index.js +17 -0
  77. package/dist/stubs/index.js.map +1 -0
  78. package/dist/stubs/server-engine/Leader.types.d.ts +8 -0
  79. package/dist/stubs/server-engine/Leader.types.js +2 -0
  80. package/dist/stubs/server-engine/Leader.types.js.map +1 -0
  81. package/dist/stubs/server-engine/Localizator.d.ts +3 -0
  82. package/dist/stubs/server-engine/Localizator.js +34 -0
  83. package/dist/stubs/server-engine/Localizator.js.map +1 -0
  84. package/dist/stubs/server-engine/Localizator.types.d.ts +22 -0
  85. package/dist/stubs/server-engine/Localizator.types.js +2 -0
  86. package/dist/stubs/server-engine/Localizator.types.js.map +1 -0
  87. package/dist/stubs/server-engine/PubSub.d.ts +3 -0
  88. package/dist/stubs/server-engine/PubSub.js +24 -0
  89. package/dist/stubs/server-engine/PubSub.js.map +1 -0
  90. package/dist/stubs/server-engine/PubSub.types.d.ts +14 -0
  91. package/dist/stubs/server-engine/PubSub.types.js +2 -0
  92. package/dist/stubs/server-engine/PubSub.types.js.map +1 -0
  93. package/dist/stubs/server-engine/PushNotification.d.ts +3 -0
  94. package/dist/stubs/server-engine/PushNotification.js +18 -0
  95. package/dist/stubs/server-engine/PushNotification.js.map +1 -0
  96. package/dist/stubs/server-engine/PushNotification.types.d.ts +8 -0
  97. package/dist/stubs/server-engine/PushNotification.types.js +2 -0
  98. package/dist/stubs/server-engine/PushNotification.types.js.map +1 -0
  99. package/dist/stubs/server-engine/index.d.ts +4 -0
  100. package/dist/stubs/server-engine/index.js +50 -0
  101. package/dist/stubs/server-engine/index.js.map +1 -0
  102. package/dist/stubs/server-engine/sendPush.d.ts +3 -0
  103. package/dist/stubs/server-engine/sendPush.js +15 -0
  104. package/dist/stubs/server-engine/sendPush.js.map +1 -0
  105. package/dist/utils/generateCerts/generateCerts.const.d.ts +5 -0
  106. package/dist/utils/generateCerts/generateCerts.const.js +35 -0
  107. package/dist/utils/generateCerts/generateCerts.const.js.map +1 -0
  108. package/dist/utils/generateCerts/generateCerts.d.ts +9 -0
  109. package/dist/utils/generateCerts/generateCerts.js +108 -0
  110. package/dist/utils/generateCerts/generateCerts.js.map +1 -0
  111. package/dist/utils/generateCerts/generateCerts.types.d.ts +19 -0
  112. package/dist/utils/generateCerts/generateCerts.types.js +2 -0
  113. package/dist/utils/generateCerts/generateCerts.types.js.map +1 -0
  114. package/dist/utils/generateCerts/index.d.ts +1 -0
  115. package/dist/utils/generateCerts/index.js +17 -0
  116. package/dist/utils/generateCerts/index.js.map +1 -0
  117. package/dist/utils/getAdminApiBearer.d.ts +2 -0
  118. package/dist/utils/getAdminApiBearer.js +19 -0
  119. package/dist/utils/getAdminApiBearer.js.map +1 -0
  120. package/dist/utils/getBearer.d.ts +3 -0
  121. package/dist/utils/getBearer.js +12 -0
  122. package/dist/utils/getBearer.js.map +1 -0
  123. package/dist/utils/index.d.ts +6 -0
  124. package/dist/utils/index.js +72 -0
  125. package/dist/utils/index.js.map +1 -0
  126. package/dist/utils/jwtRequest.d.ts +9 -0
  127. package/dist/utils/jwtRequest.js +29 -0
  128. package/dist/utils/jwtRequest.js.map +1 -0
  129. package/dist/utils/staticRequest.d.ts +10 -0
  130. package/dist/utils/staticRequest.js +24 -0
  131. package/dist/utils/staticRequest.js.map +1 -0
  132. package/dist/utils/tlsRequest.d.ts +6 -0
  133. package/dist/utils/tlsRequest.js +44 -0
  134. package/dist/utils/tlsRequest.js.map +1 -0
  135. package/dist/utils/tlsRequest.types.d.ts +9 -0
  136. package/dist/utils/tlsRequest.types.js +2 -0
  137. package/dist/utils/tlsRequest.types.js.map +1 -0
  138. package/eslint.config.mjs +11 -0
  139. package/jsconfig.json +14 -0
  140. package/package.json +83 -0
  141. package/src/factory/factory.ts +51 -0
  142. package/src/factory/factory.types.ts +50 -0
  143. package/src/factory/index.ts +2 -0
  144. package/src/factory/workers/connection.ts +22 -0
  145. package/src/factory/workers/connection.types.ts +29 -0
  146. package/src/factory/workers/index.ts +6 -0
  147. package/src/factory/workers/organization.ts +35 -0
  148. package/src/factory/workers/organization.types.ts +53 -0
  149. package/src/factory/workers/user.ts +57 -0
  150. package/src/factory/workers/user.types.ts +77 -0
  151. package/src/generators/generateAccessToken.ts +24 -0
  152. package/src/generators/generateChatId.ts +6 -0
  153. package/src/generators/generateEcdsaKeyPair.ts +16 -0
  154. package/src/generators/generateImageBuffer.ts +19 -0
  155. package/src/generators/generateImageBuffer.types.ts +7 -0
  156. package/src/generators/generateKeyPair.ts +24 -0
  157. package/src/generators/generateKeyPair.types.ts +9 -0
  158. package/src/generators/generateLocale.ts +28 -0
  159. package/src/generators/generateRegId.ts +9 -0
  160. package/src/generators/generateRsaKeyPair.ts +12 -0
  161. package/src/generators/generateUserCrypto.ts +24 -0
  162. package/src/generators/index.ts +9 -0
  163. package/src/index.ts +4 -0
  164. package/src/stubs/index.ts +1 -0
  165. package/src/stubs/server-engine/Leader.types.ts +9 -0
  166. package/src/stubs/server-engine/Localizator.ts +25 -0
  167. package/src/stubs/server-engine/Localizator.types.ts +24 -0
  168. package/src/stubs/server-engine/PubSub.ts +13 -0
  169. package/src/stubs/server-engine/PubSub.types.ts +15 -0
  170. package/src/stubs/server-engine/PushNotification.ts +11 -0
  171. package/src/stubs/server-engine/PushNotification.types.ts +9 -0
  172. package/src/stubs/server-engine/index.ts +4 -0
  173. package/src/stubs/server-engine/sendPush.ts +7 -0
  174. package/src/utils/generateCerts/generateCerts.const.ts +48 -0
  175. package/src/utils/generateCerts/generateCerts.ts +108 -0
  176. package/src/utils/generateCerts/generateCerts.types.ts +21 -0
  177. package/src/utils/generateCerts/index.ts +1 -0
  178. package/src/utils/getAdminApiBearer.ts +17 -0
  179. package/src/utils/getBearer.ts +11 -0
  180. package/src/utils/index.ts +6 -0
  181. package/src/utils/jwtRequest.ts +25 -0
  182. package/src/utils/staticRequest.ts +22 -0
  183. package/src/utils/tlsRequest.ts +41 -0
  184. package/src/utils/tlsRequest.types.ts +9 -0
  185. package/test/env.ts +10 -0
  186. package/tsconfig.build.json +4 -0
  187. package/tsconfig.json +30 -0
@@ -0,0 +1,51 @@
1
+ import {randomUUID} from 'crypto';
2
+ import {
3
+ FactoryModel,
4
+ FactoryBuildOptions,
5
+ FactoryModelOverride,
6
+ FactoryReturnType,
7
+ ModelsMap,
8
+ } from './factory.types';
9
+ import {connectionFactoryWorker, organizationFactoryWorker, userFactoryWorker} from './workers';
10
+
11
+ const modelsMap: ModelsMap = {
12
+ connection: connectionFactoryWorker,
13
+ organization: organizationFactoryWorker,
14
+ user: userFactoryWorker,
15
+ };
16
+
17
+ export const factory = {
18
+ /**
19
+ * Build an object according to a defined model
20
+ */
21
+ build: function <T extends FactoryModel>(
22
+ name: T,
23
+ attributes: FactoryModelOverride<T> = {},
24
+ buildOptions: FactoryBuildOptions<T> = {},
25
+ ): FactoryReturnType<T> {
26
+ if (!Object.keys(modelsMap).includes(name)) throw new Error(`Factory: unknown model "${name}"`);
27
+ const worker = modelsMap[name];
28
+ const instance = worker(buildOptions);
29
+ return {
30
+ id: randomUUID(),
31
+ ...instance,
32
+ ...attributes,
33
+ };
34
+ },
35
+
36
+ /**
37
+ * Build multiple objects according to a defined model
38
+ */
39
+ buildMany: function <T extends FactoryModel>(
40
+ name: T,
41
+ count: number,
42
+ attributes: FactoryModelOverride<T> = {},
43
+ buildOptions: FactoryBuildOptions<T> = {},
44
+ ): Array<FactoryReturnType<T>> {
45
+ const instances: Array<FactoryReturnType<T>> = [];
46
+ for (let i = 0; i < count; i++) {
47
+ instances.push(this.build(name, attributes, buildOptions));
48
+ }
49
+ return instances;
50
+ },
51
+ };
@@ -0,0 +1,50 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import {
3
+ ConnectionModel,
4
+ ConnectionBuildOptions,
5
+ OrganizationModel,
6
+ UserModel,
7
+ UserBuildOptions,
8
+ } from './workers';
9
+
10
+ type FactoryTyping = {
11
+ /** Mapping for the connection model */
12
+ connection: {
13
+ /** Options for the connection model */
14
+ options: ConnectionBuildOptions;
15
+ /** Return type for the connection model */
16
+ return: ConnectionModel;
17
+ };
18
+ /** Mapping for the organization model */
19
+ organization: {
20
+ /** Options for the organization model */
21
+ options: any;
22
+ /** Return type for the organization model */
23
+ return: OrganizationModel;
24
+ };
25
+ /** Mapping for the user model */
26
+ user: {
27
+ /** Options for the user model */
28
+ options: UserBuildOptions;
29
+ /** Return type for the user model */
30
+ return: UserModel;
31
+ };
32
+ };
33
+
34
+ export type FactoryModel = keyof FactoryTyping;
35
+
36
+ export type FactoryModelOverride<T extends FactoryModel> = Partial<FactoryTyping[T]['return']> & {
37
+ /** Id of the model */
38
+ id?: string;
39
+ };
40
+
41
+ export type FactoryBuildOptions<T extends FactoryModel> = FactoryTyping[T]['options'];
42
+
43
+ export type FactoryReturnType<T extends FactoryModel> = FactoryTyping[T]['return'] & {
44
+ /** Id of the model */
45
+ id: string;
46
+ };
47
+
48
+ export type ModelsMap = {
49
+ [T in FactoryModel]: (buildOptions: FactoryTyping[T]['options']) => FactoryTyping[T]['return'];
50
+ };
@@ -0,0 +1,2 @@
1
+ export * from './workers';
2
+ export * from './factory';
@@ -0,0 +1,22 @@
1
+ import {randomUUID} from 'crypto';
2
+ import { faker } from '@faker-js/faker';
3
+ import {ConnectionBuildOptions, ConnectionModel} from './connection.types';
4
+
5
+ /** Create a random connection */
6
+ export function connectionFactoryWorker(
7
+ buildOptions: ConnectionBuildOptions = {},
8
+ ): ConnectionModel {
9
+ const accepted = buildOptions.accepted ?? true;
10
+ const blocked = buildOptions.blocked ?? false;
11
+ return {
12
+ ownerId: randomUUID(),
13
+ otherUserId: randomUUID(),
14
+ accepted,
15
+ acceptedAt: accepted ? faker.date.recent() : undefined,
16
+ blocked,
17
+ blockedAt: blocked ? faker.date.recent() : undefined,
18
+ initiator: true,
19
+ message: faker.lorem.sentence(),
20
+ note: faker.lorem.sentence(),
21
+ };
22
+ }
@@ -0,0 +1,29 @@
1
+ /** Connection base model */
2
+ export interface ConnectionModel {
3
+ /** Owner of the connection */
4
+ ownerId: string;
5
+ /** USer with which the owner is connected */
6
+ otherUserId: string;
7
+ /** Wether the connection is accepted or not */
8
+ accepted: boolean;
9
+ /** Date at which the connection was accepted */
10
+ acceptedAt?: Date;
11
+ /** Wether the owner did block the other user */
12
+ blocked: boolean;
13
+ /** Date at which the connection was blocked */
14
+ blockedAt?: Date;
15
+ /** Did the owner initiate the connection */
16
+ initiator: boolean;
17
+ /** Message sent to the other user with the connection */
18
+ message: string;
19
+ /** Private note the user has on the connection */
20
+ note: string;
21
+ }
22
+
23
+ /** Build options for connections */
24
+ export interface ConnectionBuildOptions {
25
+ /** Wether the connection is accepted or not */
26
+ accepted?: boolean;
27
+ /** Wether the owner did block the other user */
28
+ blocked?: boolean;
29
+ }
@@ -0,0 +1,6 @@
1
+ export * from './user';
2
+ export * from './user.types';
3
+ export * from './connection';
4
+ export * from './connection.types';
5
+ export * from './organization';
6
+ export * from './organization.types';
@@ -0,0 +1,35 @@
1
+ import { faker } from '@faker-js/faker';
2
+ import {OrganizationModel} from './organization.types';
3
+
4
+ /** Create a random organization */
5
+ export function organizationFactoryWorker(): OrganizationModel {
6
+ return {
7
+ name: faker.company.name(),
8
+ territory: faker.address.countryCode(),
9
+ description: faker.company.catchPhrase(),
10
+ contactInfo: faker.address.streetAddress(),
11
+ productsInfo: faker.company.catchPhrase(),
12
+ avatarUrl: faker.internet.url(),
13
+ coverUrl: faker.internet.url(),
14
+ membersVisible: faker.datatype.boolean(),
15
+ searchable: faker.datatype.boolean(),
16
+ activities: [
17
+ {
18
+ id: faker.string.uuid(),
19
+ translationKey: faker.lorem.word(),
20
+ },
21
+ ],
22
+ members: [
23
+ {
24
+ id: faker.string.uuid(),
25
+ organizationId: faker.string.uuid(),
26
+ userId: faker.string.uuid(),
27
+ requested: faker.datatype.boolean(),
28
+ requestedAt: faker.date.recent(),
29
+ invited: faker.datatype.boolean(),
30
+ invitedAt: faker.date.recent(),
31
+ admin: faker.datatype.boolean(),
32
+ },
33
+ ],
34
+ };
35
+ }
@@ -0,0 +1,53 @@
1
+ /** Organization base model */
2
+ export interface OrganizationModel {
3
+ /** Name of the organization */
4
+ name: string;
5
+ /** ISO Code of the territory in which the organization is located */
6
+ territory: string;
7
+ /** Description of the organization */
8
+ description: string;
9
+ /** Contact information of the organization */
10
+ contactInfo: string;
11
+ /** Product information fo the organization */
12
+ productsInfo: string;
13
+ /** URL of the organization avatar */
14
+ avatarUrl: string;
15
+ /** URL of the organization cover picture */
16
+ coverUrl: string;
17
+ /** Indicates if organization members are visible publicly */
18
+ membersVisible: boolean;
19
+ /** Indicates if organization is searchable publicly */
20
+ searchable: boolean;
21
+ /** List of activities that the organization has */
22
+ activities: Array<OrganizationActivityModel>;
23
+ /** List of organization members */
24
+ members: Array<OrganizationMemberModel>;
25
+ }
26
+
27
+ /** Organization activity template */
28
+ export interface OrganizationActivityModel {
29
+ /** ID of the activity */
30
+ id: string;
31
+ /** Translation key to display the activity name */
32
+ translationKey: string;
33
+ }
34
+
35
+ /** Organization member */
36
+ export interface OrganizationMemberModel {
37
+ /** ID of the membership */
38
+ id: string;
39
+ /** ID of the organization on which the user has membership */
40
+ organizationId: string;
41
+ /** ID of the user */
42
+ userId: string;
43
+ /** Did the user accept/request to join the organization */
44
+ requested: boolean;
45
+ /** Time at which the user accepted/requested to join the organization */
46
+ requestedAt: Date;
47
+ /** Did the user get accepted/invited by an organization admin */
48
+ invited: boolean;
49
+ /** Time at which the user got accepted/invited by an organization admin */
50
+ invitedAt: Date;
51
+ /** Is the user an admin of the organization */
52
+ admin: boolean;
53
+ }
@@ -0,0 +1,57 @@
1
+ import { randomUUID } from 'crypto';
2
+ import { faker } from '@faker-js/faker';
3
+ import { UserModel, UserBuildOptions } from './user.types';
4
+ import {
5
+ generateRegId,
6
+ generateLocale,
7
+ generateSignKeyPub,
8
+ generateSignKeyEncrypted,
9
+ generateBbEncrypted
10
+ } from 'generators';
11
+
12
+ /**
13
+ * Create a random user
14
+ */
15
+ export function userFactoryWorker(
16
+ buildOptions: UserBuildOptions = {}
17
+ ): UserModel {
18
+ const firstName = buildOptions.firstName ?? faker.person.firstName();
19
+ const lastName = buildOptions.lastName ?? faker.person.lastName();
20
+ const email = faker.internet.email({ firstName, lastName });
21
+ const userName = faker.internet.userName({ firstName, lastName });
22
+ const random = Math.random().toString(36).substring(7);
23
+ const organizationId = buildOptions.organizationId;
24
+ const organizationMember = buildOptions.member ?? false;
25
+ const organizationAdmin = buildOptions.admin ?? false;
26
+ return {
27
+ firstName,
28
+ lastName,
29
+ firstNameLastName: `${firstName}${lastName}`,
30
+ firstNameSpaceLastName: `${firstName} ${lastName}`,
31
+ lastNameFirstName: `${lastName}${firstName}`,
32
+ lastNameSpaceFirstName: `${lastName} ${firstName}`,
33
+ displayName: `${firstName} ${lastName}`,
34
+ casualName: `${firstName}`,
35
+ formalName: `${firstName}`,
36
+ email: buildOptions.moreRandom ? `${random}${email}` : email,
37
+ username: buildOptions.moreRandom ? `${random}${userName}` : userName,
38
+ regId: generateRegId(),
39
+ locale: generateLocale(),
40
+ pictureUrl: faker.image.avatar(),
41
+ organizationId,
42
+ joinedOrganizationAt: organizationId ? faker.date.recent() : null,
43
+ organizationAdmin: organizationAdmin,
44
+ requestedToJoinOrganization: organizationMember || organizationAdmin,
45
+ acceptedInOrganization: organizationMember || organizationAdmin,
46
+ linkId: randomUUID(),
47
+ bbId: randomUUID(),
48
+ bbEncrypted: generateBbEncrypted(),
49
+ signKeyEncrypted: generateSignKeyEncrypted(),
50
+ signKeyPub: generateSignKeyPub(),
51
+ autoConnect: true,
52
+ searchable: true,
53
+ enableUrlScan: true,
54
+ enableMessageTranslation: true,
55
+ emailVisibility: true
56
+ };
57
+ }
@@ -0,0 +1,77 @@
1
+ /** User model template */
2
+ export interface UserModel {
3
+ /** User's first name */
4
+ firstName: string;
5
+ /** User's last name */
6
+ lastName: string;
7
+ /** @deprecated */
8
+ firstNameLastName: string;
9
+ /** @deprecated */
10
+ firstNameSpaceLastName: string;
11
+ /** @deprecated */
12
+ lastNameFirstName: string;
13
+ /** @deprecated */
14
+ lastNameSpaceFirstName: string;
15
+ /** User's regular display name */
16
+ displayName: string;
17
+ /** User's casual display name */
18
+ casualName: string;
19
+ /** User's formal display name */
20
+ formalName: string;
21
+ /** User's email address */
22
+ email: string;
23
+ /** @deprecated User's username */
24
+ username: string;
25
+ /** User's RegId */
26
+ regId: string;
27
+ /** User's locale */
28
+ locale: string;
29
+ /** URL opf the user's avatar */
30
+ pictureUrl: string;
31
+ /** @deprecated ID of the user's organization */
32
+ organizationId?: string;
33
+ /** @deprecated Date at which the user joined the organization */
34
+ joinedOrganizationAt?: Date | null;
35
+ /** @deprecated Admin status of the user in the organization */
36
+ organizationAdmin: boolean;
37
+ /** @deprecated */
38
+ requestedToJoinOrganization: boolean;
39
+ /** @deprecated */
40
+ acceptedInOrganization: boolean;
41
+ /** User's ID for QR codes */
42
+ linkId: string;
43
+ /** User's BlackBerry ID */
44
+ bbId: string;
45
+ /** User's BlackBerry encrypted key */
46
+ bbEncrypted: string;
47
+ /** User's signature keys */
48
+ signKeyEncrypted: string;
49
+ /** User's public key */
50
+ signKeyPub: string;
51
+ /** Enables auto-acceptance of contact requests */
52
+ autoConnect: boolean;
53
+ /** Is the user searchable publicly */
54
+ searchable: boolean;
55
+ /** Is URL scanning enabled for the user */
56
+ enableUrlScan: boolean;
57
+ /** Is message translation enabled for the user */
58
+ enableMessageTranslation: boolean;
59
+ /** Is the user's email visible publicly */
60
+ emailVisibility: boolean;
61
+ }
62
+
63
+ /** User template build options */
64
+ export interface UserBuildOptions {
65
+ /** User's first name */
66
+ firstName?: string;
67
+ /** User's last name */
68
+ lastName?: string;
69
+ /** Id of the organization to which the user is affiliated */
70
+ organizationId?: string;
71
+ /** Admin status of the user in his organization */
72
+ admin?: boolean;
73
+ /** Membership status of the user in his organization */
74
+ member?: boolean;
75
+ /** Add randomness to avoid collisions when generating a large number of entities */
76
+ moreRandom?: boolean;
77
+ }
@@ -0,0 +1,24 @@
1
+ import { randomUUID } from 'crypto';
2
+ import { sign, SignOptions } from 'jsonwebtoken';
3
+
4
+ /** Returns an API access token valid in test environment */
5
+ export function generateAccessToken(
6
+ userId: string,
7
+ options: SignOptions = {},
8
+ payload: string | Buffer | object = {}
9
+ ): string {
10
+ const id = userId ?? randomUUID();
11
+ if (!process.env.JWT_SECRET) throw new Error('Missing JWT signing secret');
12
+ return sign(
13
+ typeof payload === 'object' ? { ...payload, user: { id } } : payload,
14
+ process.env.JWT_SECRET,
15
+ {
16
+ expiresIn: '1d',
17
+ audience: process.env.ACCESS_TOKEN_AUDIENCE,
18
+ issuer: process.env.ACCESS_TOKEN_ISSUER,
19
+ subject: id,
20
+ jwtid: randomUUID(),
21
+ ...options
22
+ }
23
+ );
24
+ }
@@ -0,0 +1,6 @@
1
+ import crypto from 'crypto';
2
+
3
+ /** Generate a BlackBerry Spark chatId */
4
+ export function generateChatId(): string {
5
+ return `${crypto.randomBytes(20).toString('hex')}.1`;
6
+ }
@@ -0,0 +1,16 @@
1
+ import {generateKeyPairSync} from 'crypto';
2
+ import {writeFileSync, existsSync, mkdirSync} from 'fs';
3
+ import {resolve} from 'path';
4
+
5
+ /** Generate a signature key pair for ECDSA */
6
+ export function generateEcdsaKeyPair(): void {
7
+ const DIR = resolve('certs');
8
+ if (!existsSync(DIR)) mkdirSync(DIR);
9
+ const {privateKey, publicKey} = generateKeyPairSync('ec', {
10
+ namedCurve: 'prime256v1',
11
+ privateKeyEncoding: {type: 'pkcs8', format: 'pem'},
12
+ publicKeyEncoding: {type: 'spki', format: 'pem'},
13
+ });
14
+ writeFileSync(`${DIR}/ecdsa.key`, privateKey);
15
+ writeFileSync(`${DIR}/ecdsa.key.pub`, publicKey);
16
+ }
@@ -0,0 +1,19 @@
1
+ import Jimp from 'jimp';
2
+ import {generateImageBufferOptions} from './generateImageBuffer.types';
3
+
4
+ /** Generate a binary buffer containing a PNG image */
5
+ export async function generateImageBuffer(
6
+ options: generateImageBufferOptions = {},
7
+ ): Promise<Buffer> {
8
+ const image = await generateImage(options);
9
+ return image.getBufferAsync(Jimp.MIME_PNG);
10
+ }
11
+
12
+ /** Generate the asynchronously image using Jimp */
13
+ async function generateImage(options: generateImageBufferOptions = {}): Promise<Jimp> {
14
+ return new Promise<Jimp>((resolve) => {
15
+ new Jimp(options.width ?? 150, options.height ?? 150, function (err, image) {
16
+ resolve(image);
17
+ });
18
+ });
19
+ }
@@ -0,0 +1,7 @@
1
+ /** Options to generate a fake image buffer */
2
+ export interface generateImageBufferOptions {
3
+ /** Image width */
4
+ width?: number;
5
+ /** Image height */
6
+ height?: number;
7
+ }
@@ -0,0 +1,24 @@
1
+ import {generateKeyPairSync, randomBytes} from 'crypto';
2
+ import {GeneratedKeyPair} from './generateKeyPair.types';
3
+
4
+ /**
5
+ * Generate a RSA key pair
6
+ * @param pass - passphrase used to encrypt the private key (default: generates a random passphrase)
7
+ */
8
+ export function generateKeyPair(pass: string): GeneratedKeyPair {
9
+ const passphrase = pass ?? process.env.ID_TOKEN_PASSPHRASE ?? randomBytes(32).toString('base64');
10
+ const {publicKey, privateKey} = generateKeyPairSync('rsa', {
11
+ modulusLength: 1024,
12
+ publicKeyEncoding: {
13
+ type: 'spki',
14
+ format: 'pem',
15
+ },
16
+ privateKeyEncoding: {
17
+ type: 'pkcs8',
18
+ format: 'pem',
19
+ cipher: 'aes-256-cbc',
20
+ passphrase,
21
+ },
22
+ });
23
+ return {passphrase, publicKey, privateKey};
24
+ }
@@ -0,0 +1,9 @@
1
+ /** Key pair that was generated */
2
+ export interface GeneratedKeyPair {
3
+ /** PAssphrase used to encrypt the private key */
4
+ passphrase: string;
5
+ /** Public key generated, PEM encoded */
6
+ publicKey: string;
7
+ /** Private key generated, PEM encoded */
8
+ privateKey: string;
9
+ }
@@ -0,0 +1,28 @@
1
+ export const TEST_LOCALES = [
2
+ 'ar',
3
+ 'en-US',
4
+ 'es-ES',
5
+ 'fr-FR',
6
+ 'id-ID',
7
+ 'it-IT',
8
+ 'ja-JP',
9
+ 'km-KH',
10
+ 'ko-KR',
11
+ 'ms-MY',
12
+ 'my-MM',
13
+ 'nl-NL',
14
+ 'pt-PT',
15
+ 'ry-RU',
16
+ 'th-TH',
17
+ 'uk-UA',
18
+ 'vi-VN',
19
+ 'zh-CN',
20
+ 'zh-TW',
21
+ ];
22
+
23
+ /**
24
+ * Pick up a random locale from the list of testable ones
25
+ */
26
+ export function generateLocale(): string {
27
+ return TEST_LOCALES[Math.floor(Math.random() * TEST_LOCALES.length)];
28
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Generates a regID like BBM Spark would
3
+ */
4
+ export function generateRegId(): string {
5
+ const length = 18;
6
+ return Math.floor(Math.random() * Math.pow(10, length))
7
+ .toString()
8
+ .padStart(length, '0');
9
+ }
@@ -0,0 +1,12 @@
1
+ import {writeFileSync, mkdirSync, existsSync} from 'fs';
2
+ import path from 'path';
3
+ import {generateKeyPair} from './generateKeyPair';
4
+
5
+ /** Generate a RSA key pair and store it under "{cwd}/certs/rsa.*" */
6
+ export function generateRsaKeyPair(passphrase: string): void {
7
+ const DIR = path.resolve('certs');
8
+ if (!existsSync(DIR)) mkdirSync(DIR);
9
+ const {publicKey, privateKey} = generateKeyPair(passphrase);
10
+ writeFileSync(`${DIR}/rsa.key`, privateKey);
11
+ writeFileSync(`${DIR}/rsa.pub.key`, publicKey);
12
+ }
@@ -0,0 +1,24 @@
1
+ import crypto from 'crypto';
2
+
3
+ /**
4
+ * Generates a fake base64 string that looks like a user public key
5
+ * /!\ This is not a valid crypto key
6
+ */
7
+ export function generateSignKeyPub(): string {
8
+ return crypto.randomBytes(162).toString('base64');
9
+ }
10
+ /**
11
+ * Generates a fake base64 string that looks like a user encrypted private key
12
+ * /!\ This is not a valid crypto key
13
+ */
14
+ export function generateSignKeyEncrypted(): string {
15
+ return crypto.randomBytes(640).toString('base64');
16
+ }
17
+
18
+ /**
19
+ * Generates a fake base64 string that looks like a user encrypted Blackberry Passcode
20
+ * /!\ This is not a valid crypto key
21
+ */
22
+ export function generateBbEncrypted(): string {
23
+ return crypto.randomBytes(80).toString('base64');
24
+ }
@@ -0,0 +1,9 @@
1
+ export * from './generateAccessToken';
2
+ export * from './generateImageBuffer';
3
+ export * from './generateKeyPair';
4
+ export * from './generateLocale';
5
+ export * from './generateRegId';
6
+ export * from './generateRsaKeyPair';
7
+ export * from './generateUserCrypto';
8
+ export * from './generateChatId';
9
+ export * from './generateEcdsaKeyPair';
package/src/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ export * from './generators';
2
+ export * from './utils';
3
+ export * from './factory';
4
+ export * from './stubs';
@@ -0,0 +1 @@
1
+ export * from './server-engine';
@@ -0,0 +1,9 @@
1
+ import {SinonStub} from 'sinon';
2
+
3
+ /** Stubbed properties of the Leader entity */
4
+ export interface LeaderStub {
5
+ /** Stub of the init method */
6
+ init: SinonStub;
7
+ /** Stub of the shutdown method */
8
+ shutdown: SinonStub;
9
+ }
@@ -0,0 +1,25 @@
1
+ import {Localizator} from '@gwcdata/node-server-engine/dist/entities/Localizator/Localizator';
2
+ import {stub} from 'sinon';
3
+ import {LocalizatorStub, LocalizatorStubOptions} from './Localizator.types';
4
+
5
+ const DEFAULT_LOCALE_DATA = {
6
+ enabled: true,
7
+ display: 'English',
8
+ names: {
9
+ firstNameFirst: true,
10
+ spacing: true,
11
+ },
12
+ cloudTranslationKey: 'en',
13
+ };
14
+
15
+ /** Stub the Localizator service */
16
+ export function stubLocalizator(overrides: LocalizatorStubOptions): LocalizatorStub {
17
+ const synchronize = stub(Localizator, 'synchronize').resolves();
18
+ const init = stub(Localizator, 'init').resolves();
19
+ const shutdown = stub(Localizator, 'shutdown').resolves();
20
+ const getLocaleData = stub(Localizator, 'getLocaleData').returns(
21
+ overrides?.localeData ?? DEFAULT_LOCALE_DATA,
22
+ );
23
+ const isValidLocale = stub(Localizator, 'isValidLocale').returns(overrides?.isValid ?? true);
24
+ return {synchronize, init, shutdown, getLocaleData, isValidLocale};
25
+ }
@@ -0,0 +1,24 @@
1
+ import {LocalizatorLocalizationDataElement} from '@gwcdata/node-server-engine';
2
+ import {SinonStub} from 'sinon';
3
+
4
+ /** Stubbing options for the Localizator */
5
+ export interface LocalizatorStubOptions {
6
+ /** Forces the return value of the isValidLocale functions */
7
+ isValid?: boolean;
8
+ /** Forces the return value of the getLocaleData functions */
9
+ localeData?: LocalizatorLocalizationDataElement;
10
+ }
11
+
12
+ /** Stubbed properties of the Localizator entity */
13
+ export interface LocalizatorStub {
14
+ /** Stub of the synchronize method */
15
+ synchronize: SinonStub;
16
+ /** Stub of the init method */
17
+ init: SinonStub;
18
+ /** Stub of the shutdown method */
19
+ shutdown: SinonStub;
20
+ /** Stub of the getLocaleData method */
21
+ getLocaleData: SinonStub;
22
+ /** Stub of the isValidLocale method */
23
+ isValidLocale: SinonStub;
24
+ }