@friggframework/core 0.2.31-v1-alpha-package-update.0 → 1.0.1-v1-alpha-package-update.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 (193) hide show
  1. package/assertions/CHANGELOG.md +87 -0
  2. package/assertions/LICENSE.md +9 -0
  3. package/assertions/README.md +3 -0
  4. package/assertions/bump.txt +1 -0
  5. package/assertions/get.js +139 -0
  6. package/assertions/index.js +19 -0
  7. package/assertions/is-equal.js +17 -0
  8. package/associations/LICENSE.md +9 -0
  9. package/associations/README.md +3 -0
  10. package/associations/association.js +78 -0
  11. package/associations/bump3.txt +0 -0
  12. package/associations/jest.config.js +5 -0
  13. package/associations/model.js +54 -0
  14. package/bump.txt +0 -0
  15. package/core/.eslintrc.json +3 -0
  16. package/{Delegate.js → core/Delegate.js} +1 -1
  17. package/core/LICENSE.md +9 -0
  18. package/{Worker.js → core/Worker.js} +2 -2
  19. package/core/bump3.txt +0 -0
  20. package/{create-handler.js → core/create-handler.js} +2 -2
  21. package/core/index.js +6 -0
  22. package/core/jest.config.js +5 -0
  23. package/database/.eslintrc.json +3 -0
  24. package/database/CHANGELOG.md +97 -0
  25. package/database/LICENSE.md +9 -0
  26. package/database/README.md +3 -0
  27. package/database/bump3.txt +0 -0
  28. package/database/index.js +17 -0
  29. package/database/jest.config.js +5 -0
  30. package/database/models/IndividualUser.js +76 -0
  31. package/database/models/OrganizationUser.js +29 -0
  32. package/database/models/State.js +9 -0
  33. package/database/models/Token.js +70 -0
  34. package/database/models/UserModel.js +7 -0
  35. package/database/mongo.js +45 -0
  36. package/database/mongoose.js +5 -0
  37. package/encrypt/.eslintrc.json +3 -0
  38. package/encrypt/CHANGELOG.md +65 -0
  39. package/encrypt/Cryptor.js +236 -0
  40. package/encrypt/Cryptor.test.js +32 -0
  41. package/encrypt/LICENSE.md +9 -0
  42. package/encrypt/README.md +3 -0
  43. package/encrypt/aes.js +27 -0
  44. package/encrypt/bump3.txt +0 -0
  45. package/encrypt/encrypt.js +124 -0
  46. package/encrypt/encrypt.test.js +1068 -0
  47. package/encrypt/index.js +3 -0
  48. package/encrypt/jest.config.js +5 -0
  49. package/encrypt/test-encrypt.js +107 -0
  50. package/errors/.eslintrc.json +3 -0
  51. package/errors/CHANGELOG.md +44 -0
  52. package/errors/LICENSE.md +9 -0
  53. package/errors/README.md +3 -0
  54. package/errors/base-error.js +23 -0
  55. package/errors/base-error.test.js +32 -0
  56. package/errors/bump.txt +1 -0
  57. package/errors/bump3.txt +0 -0
  58. package/errors/fetch-error.js +72 -0
  59. package/errors/fetch-error.test.js +79 -0
  60. package/errors/halt-error.js +10 -0
  61. package/errors/halt-error.test.js +11 -0
  62. package/errors/index.js +15 -0
  63. package/errors/jest.config.js +5 -0
  64. package/errors/validation-errors.js +23 -0
  65. package/errors/validation-errors.test.js +120 -0
  66. package/eslint-config/.eslintrc.json +3 -0
  67. package/eslint-config/CHANGELOG.md +17 -0
  68. package/eslint-config/LICENSE.md +9 -0
  69. package/eslint-config/README.md +3 -0
  70. package/eslint-config/bump3.txt +0 -0
  71. package/eslint-config/index.js +38 -0
  72. package/index.js +29 -5
  73. package/integrations/.eslintrc.json +3 -0
  74. package/integrations/CHANGELOG.md +244 -0
  75. package/integrations/LICENSE.md +9 -0
  76. package/integrations/README.md +3 -0
  77. package/integrations/bump3.txt +0 -0
  78. package/integrations/create-frigg-backend.js +31 -0
  79. package/integrations/index.js +19 -0
  80. package/integrations/integration-base.js +162 -0
  81. package/integrations/integration-factory.js +166 -0
  82. package/integrations/integration-mapping.js +43 -0
  83. package/integrations/integration-model.js +42 -0
  84. package/integrations/integration-router.js +367 -0
  85. package/integrations/integration-user.js +144 -0
  86. package/integrations/jest-setup.js +2 -0
  87. package/integrations/jest-teardown.js +2 -0
  88. package/integrations/jest.config.js +12 -0
  89. package/integrations/options.js +54 -0
  90. package/integrations/test/integration-base.test.js +143 -0
  91. package/lambda/README.md +3 -0
  92. package/lambda/TimeoutCatcher.js +43 -0
  93. package/lambda/TimeoutCatcher.test.js +68 -0
  94. package/lambda/bump3.txt +0 -0
  95. package/lambda/index.js +3 -0
  96. package/lambda/jest.config.js +3 -0
  97. package/logs/.eslintrc.json +3 -0
  98. package/logs/CHANGELOG.md +57 -0
  99. package/logs/LICENSE.md +9 -0
  100. package/logs/README.md +3 -0
  101. package/logs/bump3.txt +0 -0
  102. package/logs/index.js +7 -0
  103. package/logs/jest.config.js +5 -0
  104. package/logs/logger.js +69 -0
  105. package/logs/logger.test.js +76 -0
  106. package/migrations/README.md +3 -0
  107. package/migrations/bump3.txt +0 -0
  108. package/migrations/index.js +9 -0
  109. package/migrations/jest.config.js +3 -0
  110. package/migrations/manager.js +33 -0
  111. package/migrations/migrator.js +170 -0
  112. package/migrations/options.js +28 -0
  113. package/module-plugin/.eslintrc.json +3 -0
  114. package/module-plugin/CHANGELOG.md +224 -0
  115. package/module-plugin/LICENSE.md +9 -0
  116. package/module-plugin/ModuleConstants.js +10 -0
  117. package/module-plugin/README.md +3 -0
  118. package/module-plugin/auther.js +342 -0
  119. package/module-plugin/bump3.txt +0 -0
  120. package/module-plugin/credential.js +22 -0
  121. package/module-plugin/entity-manager.js +70 -0
  122. package/module-plugin/entity.js +46 -0
  123. package/module-plugin/index.js +25 -0
  124. package/module-plugin/jest-setup.js +3 -0
  125. package/module-plugin/jest-teardown.js +2 -0
  126. package/module-plugin/jest.config.js +20 -0
  127. package/module-plugin/manager.js +169 -0
  128. package/module-plugin/module-factory.js +60 -0
  129. package/module-plugin/requester/api-key.js +36 -0
  130. package/module-plugin/requester/basic.js +43 -0
  131. package/module-plugin/requester/oauth-2.js +219 -0
  132. package/module-plugin/requester/requester.js +150 -0
  133. package/module-plugin/requester/requester.test.js +28 -0
  134. package/module-plugin/test/auther.test.js +97 -0
  135. package/module-plugin/test/mock-api/api.js +29 -0
  136. package/module-plugin/test/mock-api/definition.js +48 -0
  137. package/module-plugin/test/mock-api/mocks/hubspot.js +43 -0
  138. package/package.json +37 -12
  139. package/prettier-config/.eslintrc.json +3 -0
  140. package/prettier-config/CHANGELOG.md +17 -0
  141. package/prettier-config/LICENSE.md +9 -0
  142. package/prettier-config/README.md +3 -0
  143. package/prettier-config/bump3.txt +0 -0
  144. package/prettier-config/index.js +6 -0
  145. package/syncs/README.md +3 -0
  146. package/syncs/bump3.txt +0 -0
  147. package/syncs/jest.config.js +5 -0
  148. package/syncs/manager.js +466 -0
  149. package/syncs/model.js +62 -0
  150. package/syncs/sync.js +114 -0
  151. package/test-environment/.eslintrc.json +3 -0
  152. package/test-environment/Authenticator.js +73 -0
  153. package/test-environment/CHANGELOG.md +46 -0
  154. package/test-environment/LICENSE.md +9 -0
  155. package/test-environment/README.md +3 -0
  156. package/test-environment/auther-definition-method-tester.js +45 -0
  157. package/test-environment/auther-definition-tester.js +104 -0
  158. package/test-environment/bump3.txt +0 -0
  159. package/test-environment/index.js +24 -0
  160. package/test-environment/integration-validator.js +2 -0
  161. package/test-environment/jest-global-setup.js +6 -0
  162. package/test-environment/jest-global-teardown.js +3 -0
  163. package/test-environment/jest-preset.js +14 -0
  164. package/test-environment/mock-api-readme.md +102 -0
  165. package/test-environment/mock-api.js +284 -0
  166. package/test-environment/mock-integration.js +82 -0
  167. package/test-environment/mongodb.js +22 -0
  168. package/test-environment/override-environment.js +11 -0
  169. package/types/CHANGELOG.md +49 -0
  170. package/types/README.md +24 -0
  171. package/types/assertions/index.d.ts +83 -0
  172. package/types/associations/index.d.ts +74 -0
  173. package/types/bump3.txt +0 -0
  174. package/types/core/index.d.ts +54 -0
  175. package/types/database/index.d.ts +3 -0
  176. package/types/encrypt/index.d.ts +5 -0
  177. package/types/errors/index.d.ts +66 -0
  178. package/types/eslint-config/index.d.ts +41 -0
  179. package/types/index.d.ts +14 -0
  180. package/types/integrations/index.d.ts +191 -0
  181. package/types/lambda/index.d.ts +31 -0
  182. package/types/logs/index.d.ts +5 -0
  183. package/types/module-plugin/index.d.ts +293 -0
  184. package/types/prettier-config/index.d.ts +6 -0
  185. package/types/syncs/index.d.ts +128 -0
  186. package/types/test-environment/index.d.ts +17 -0
  187. package/types/tsconfig.json +103 -0
  188. /package/{.eslintrc.json → assertions/.eslintrc.json} +0 -0
  189. /package/{bump3.txt → assertions/bump3.txt} +0 -0
  190. /package/{jest.config.js → assertions/jest.config.js} +0 -0
  191. /package/{CHANGELOG.md → core/CHANGELOG.md} +0 -0
  192. /package/{README.md → core/README.md} +0 -0
  193. /package/{load-installed-modules.js → core/load-installed-modules.js} +0 -0
@@ -0,0 +1,3 @@
1
+ const { Encrypt } = require('./encrypt');
2
+
3
+ module.exports = { Encrypt };
@@ -0,0 +1,5 @@
1
+ module.exports = async () => {
2
+ return {
3
+ preset: '@friggframework/test-environment',
4
+ };
5
+ };
@@ -0,0 +1,107 @@
1
+ const AWS = require('aws-sdk');
2
+ const { mongoose } = require('../database/mongoose');
3
+ const crypto = require('crypto');
4
+ const { Encrypt } = require('./encrypt');
5
+
6
+ const hexPattern = /^[a-f0-9]+$/i; // match hex strings of length >= 1
7
+
8
+ // Test that an encrypted secret value appears to have valid values (without actually decrypting it).
9
+ function expectValidSecret(secret) {
10
+ const parts = secret.split(':');
11
+ const keyId = Buffer.from(parts[0], 'base64').toString();
12
+ const iv = parts[1];
13
+ const encryptedText = parts[2];
14
+ const encryptedKey = Buffer.from(parts[3], 'base64').toString();
15
+
16
+ expect(iv).toHaveLength(32);
17
+ expect(iv).toMatch(hexPattern);
18
+ expect(encryptedText).toHaveLength(14);
19
+ expect(encryptedText).toMatch(hexPattern);
20
+
21
+ // Keys from AWS start with Karn and have a different format.
22
+ if (keyId.startsWith('arn:aws')) {
23
+ expect(keyId).toBe(
24
+ `arn:aws:kms:us-east-1:000000000000:key/${process.env.KMS_KEY_ARN}`
25
+ );
26
+ // The length here is a sanity check. Seems they are always within this range.
27
+ expect(encryptedKey.length).toBeGreaterThanOrEqual(85);
28
+ expect(encryptedKey.length).toBeLessThanOrEqual(140);
29
+ } else {
30
+ const { AES_KEY_ID, DEPRECATED_AES_KEY_ID } = process.env;
31
+ expect([AES_KEY_ID, DEPRECATED_AES_KEY_ID]).toContain(keyId);
32
+
33
+ const encryptedKeyParts = encryptedKey.split(':');
34
+ const iv2 = encryptedKeyParts[0];
35
+ const encryptedKeyPart = encryptedKeyParts[1];
36
+
37
+ expect(iv2).toHaveLength(32);
38
+ expect(iv2).toMatch(hexPattern);
39
+ expect(encryptedKeyPart).toHaveLength(64);
40
+ expect(encryptedKeyPart).toMatch(hexPattern);
41
+ }
42
+ }
43
+
44
+ // Load and validate a raw test document compared to a Mongoose document object.
45
+ async function expectValidRawDoc(Model, doc) {
46
+ const rawDoc = await expectValidRawDocById(Model, doc._id);
47
+
48
+ expect(rawDoc.notSecret.toString()).toBe(doc.notSecret.toString());
49
+ expect(rawDoc).not.toHaveProperty('secret', doc.secret);
50
+
51
+ return rawDoc;
52
+ }
53
+
54
+ // Load and validate a raw test document by ID.
55
+ async function expectValidRawDocById(Model, _id) {
56
+ const rawDoc = await Model.collection.findOne({ _id });
57
+
58
+ expect(rawDoc).toHaveProperty('notSecret');
59
+ expect(rawDoc).toHaveProperty('secret');
60
+ expectValidSecret(rawDoc.secret);
61
+
62
+ return rawDoc;
63
+ }
64
+
65
+ // Create a clean test model, so that the plug-in can be reinitialized.
66
+ function createModel() {
67
+ const randomHex = crypto.randomBytes(16).toString('hex');
68
+ const schema = new mongoose.Schema({
69
+ secret: { type: String, lhEncrypt: true },
70
+ notSecret: { type: mongoose.Schema.Types.ObjectId },
71
+ 'deeply.nested.secret': { type: String, lhEncrypt: true },
72
+ });
73
+
74
+ schema.plugin(Encrypt);
75
+
76
+ const Model = mongoose.model(`EncryptTest_${randomHex}`, schema);
77
+ return { schema, Model };
78
+ }
79
+
80
+ // Save and validate a test doc.
81
+ async function saveTestDocument(Model) {
82
+ const notSecret = new mongoose.Types.ObjectId();
83
+ const secret = 'abcdefg';
84
+ const doc = new Model({ notSecret, secret });
85
+
86
+ expect(doc).toHaveProperty('notSecret');
87
+ expect(doc.notSecret.toString()).toBe(notSecret.toString());
88
+ expect(doc).toHaveProperty('secret');
89
+ expect(doc.secret).toBe(secret);
90
+
91
+ await doc.save();
92
+
93
+ expect(doc).toHaveProperty('notSecret');
94
+ expect(doc.notSecret.toString()).toBe(notSecret.toString());
95
+ expect(doc).toHaveProperty('secret');
96
+ expect(doc.secret).toBe(secret);
97
+
98
+ return { doc, secret, notSecret };
99
+ }
100
+
101
+ module.exports = {
102
+ expectValidSecret,
103
+ expectValidRawDoc,
104
+ expectValidRawDocById,
105
+ createModel,
106
+ saveTestDocument,
107
+ };
@@ -0,0 +1,3 @@
1
+ {
2
+ "extends": "@friggframework/eslint-config"
3
+ }
@@ -0,0 +1,44 @@
1
+ # v1.1.6 (Wed Feb 08 2023)
2
+
3
+ #### 🐛 Bug Fix
4
+
5
+ - URLSearchParams (used in OAuth2 base) was not printing out bodies in … [#124](https://github.com/friggframework/frigg/pull/124) ([@seanspeaks](https://github.com/seanspeaks))
6
+ - URLSearchParams (used in OAuth2 base) was not printing out bodies in error logs. ([@seanspeaks](https://github.com/seanspeaks))
7
+ - Bump independent versions \[skip ci\] ([@seanspeaks](https://github.com/seanspeaks))
8
+
9
+ #### Authors: 1
10
+
11
+ - Sean Matthews ([@seanspeaks](https://github.com/seanspeaks))
12
+
13
+ ---
14
+
15
+ # v1.1.5 (Wed Jan 18 2023)
16
+
17
+ #### 🐛 Bug Fix
18
+
19
+ - Ironclad and slack updates [#96](https://github.com/friggframework/frigg/pull/96) ([@seanspeaks](https://github.com/seanspeaks))
20
+ - Fetch Error fix to also log a body if already used (and passed in) ([@seanspeaks](https://github.com/seanspeaks))
21
+
22
+ #### Authors: 1
23
+
24
+ - Sean Matthews ([@seanspeaks](https://github.com/seanspeaks))
25
+
26
+ ---
27
+
28
+ # v1.1.4 (Mon Jan 09 2023)
29
+
30
+ #### 🐛 Bug Fix
31
+
32
+ - Merge remote-tracking branch 'origin/main' into gitbook-updates [#48](https://github.com/friggframework/frigg/pull/48) ([@seanspeaks](https://github.com/seanspeaks))
33
+ - Bump independent versions \[skip ci\] ([@seanspeaks](https://github.com/seanspeaks))
34
+ - Merge remote-tracking branch 'origin/main' into simplify-mongoose-models ([@seanspeaks](https://github.com/seanspeaks))
35
+ - Add READMEs for all packages and api-modules [#20](https://github.com/friggframework/frigg/pull/20) ([@seanspeaks](https://github.com/seanspeaks))
36
+ - Add READMEs for all packages and api-modules ([@seanspeaks](https://github.com/seanspeaks))
37
+
38
+ #### ⚠️ Pushed to `main`
39
+
40
+ - Refactored for more conventional naming (at least for packages) ([@seanspeaks](https://github.com/seanspeaks))
41
+
42
+ #### Authors: 1
43
+
44
+ - Sean Matthews ([@seanspeaks](https://github.com/seanspeaks))
@@ -0,0 +1,9 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Left Hook Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,3 @@
1
+ # errors
2
+
3
+ This package exports the `errors` used in [Frigg](https://friggframework.org). You can find its documentation [on Frigg's website](https://docs.friggframework.org/packages/errors).
@@ -0,0 +1,23 @@
1
+ // See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#differentiate_between_similar_errors
2
+ class BaseError extends Error {
3
+ constructor(message, options, ...moreOptions) {
4
+ // Pass remaining arguments (including vendor specific ones) to parent constructor
5
+ super(message, options, ...moreOptions);
6
+
7
+ // In the future `cause` will be handled by V8 in Node.js. For now, add the property manually
8
+ // See: https://v8.dev/features/error-cause
9
+ if (options?.cause) {
10
+ this.cause = options.cause;
11
+ }
12
+
13
+ // Maintains proper stack trace for where our error was thrown (method only available under V8)
14
+ if (Error.captureStackTrace) {
15
+ Error.captureStackTrace(this, BaseError);
16
+ }
17
+
18
+ // Set the error name for console output
19
+ this.name = this.constructor?.name;
20
+ }
21
+ }
22
+
23
+ module.exports = { BaseError };
@@ -0,0 +1,32 @@
1
+ const { BaseError } = require('./base-error');
2
+
3
+ describe('BaseError', () => {
4
+ it('can be inherited and instantiated', () => {
5
+ class XyzError extends BaseError {}
6
+ const error = new XyzError();
7
+ expect(error).toHaveProperty('message', '');
8
+ expect(error).toHaveProperty('stack');
9
+ expect(error.stack).toContain('XyzError');
10
+ expect(error.stack).toContain('at new XyzError');
11
+ expect(error.stack).toContain('base-error.test.js:');
12
+ });
13
+
14
+ it('can set the error message', () => {
15
+ class TestError extends BaseError {}
16
+ const error = new TestError('Goblins!');
17
+ expect(error).toHaveProperty('message', 'Goblins!');
18
+ });
19
+
20
+ it('sets the error name correctly', () => {
21
+ class TestError extends BaseError {}
22
+ const error = new TestError();
23
+ expect(error).toHaveProperty('name', 'TestError');
24
+ });
25
+
26
+ it('can set the parent cause', () => {
27
+ class TestError extends BaseError {}
28
+ const rootError = new Error('Davros!');
29
+ const error = new TestError('Daleks!', { cause: rootError });
30
+ expect(error).toHaveProperty('cause', rootError);
31
+ });
32
+ });
@@ -0,0 +1 @@
1
+ 0
File without changes
@@ -0,0 +1,72 @@
1
+ const { BaseError } = require('./base-error');
2
+ const { stripIndent } = require('common-tags');
3
+
4
+ // TODO hide header values
5
+
6
+ // Parameters names here are based on fetch. See:
7
+ // https://developer.mozilla.org/en-US/docs/Web/API/fetch
8
+
9
+ class FetchError extends BaseError {
10
+ constructor(options = {}) {
11
+ const { resource, init, response, responseBody } = options;
12
+ const method = init?.method ?? 'GET';
13
+ const initText = init
14
+ ? init.body instanceof URLSearchParams
15
+ ? (() => {
16
+ init.body = init.body.toString();
17
+ return JSON.stringify({ init }, null, 2);
18
+ })()
19
+ : JSON.stringify({ init }, null, 2)
20
+ : '';
21
+
22
+ let responseBodyText = '<response body is unavailable>';
23
+ if (typeof responseBody === 'string') {
24
+ responseBodyText = responseBody;
25
+ } else if (responseBody) {
26
+ responseBodyText = JSON.stringify(responseBody, null, 2);
27
+ }
28
+
29
+ const responseHeaders = {};
30
+ if (response?.headers) {
31
+ for (const [key, value] of response.headers) {
32
+ responseHeaders[key] = value;
33
+ }
34
+ }
35
+
36
+ const responseHeaderText = response
37
+ ? JSON.stringify({ headers: responseHeaders }, null, 2)
38
+ : '';
39
+
40
+ const messageParts = [
41
+ stripIndent`
42
+ -----------------------------------------------------
43
+ An error ocurred while fetching an external resource.
44
+ -----------------------------------------------------
45
+ >>> Request Details >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
46
+ ${method} ${resource}
47
+ `,
48
+ initText,
49
+ stripIndent`
50
+ <<< Response Details <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
51
+ ${response?.status} ${response?.statusText}
52
+ `,
53
+ responseHeaderText,
54
+ responseBodyText,
55
+ stripIndent`
56
+ -----------------------------------------------------
57
+ Stack Trace:
58
+ `,
59
+ ];
60
+
61
+ super(messageParts.filter(Boolean).join('\n'));
62
+ }
63
+
64
+ static async create(options = {}) {
65
+ const { response } = options;
66
+ let responseBody = response?.bodyUsed ? null : await response?.text();
67
+ if (!responseBody && options.body) responseBody = options.body;
68
+ return new FetchError({ ...options, responseBody });
69
+ }
70
+ }
71
+
72
+ module.exports = { FetchError };
@@ -0,0 +1,79 @@
1
+ const fetch = require('node-fetch');
2
+ const { stripIndent } = require('common-tags');
3
+ const { FetchError } = require('./fetch-error');
4
+ const FormData = require('form-data');
5
+
6
+ describe('FetchError', () => {
7
+ it('can be instantiated with default arguments', () => {
8
+ const error = new FetchError();
9
+ expect(error).toHaveProperty('message');
10
+ expect(error).not.toHaveProperty('cause');
11
+ });
12
+
13
+ it('can be created asynchronously with default values', async () => {
14
+ const error = await FetchError.create();
15
+ expect(error).toHaveProperty('message');
16
+ expect(error).not.toHaveProperty('cause');
17
+ });
18
+
19
+ it('can be created asynchronously', async () => {
20
+ const resource = 'http://example.com';
21
+ const init = {};
22
+ const response = {
23
+ status: 500,
24
+ statusText: 'Space aliens!',
25
+ headers: Object.entries({ 'cache-control': '123' }), // needs to be an Iterable
26
+ text: async () => '<!doctype html>',
27
+ };
28
+
29
+ const error = await FetchError.create({
30
+ resource,
31
+ init,
32
+ response,
33
+ });
34
+
35
+ expect(error).toHaveProperty('message');
36
+ expect(error.message).toContain('GET http://example.com');
37
+ expect(error.message).toContain('500 Space aliens!');
38
+ expect(error.message).toContain('"cache-control": "123"');
39
+ expect(error.message).toContain('<!doctype html>');
40
+ });
41
+
42
+ it('can be passed an object for the body', async () => {
43
+ const error = new FetchError({ responseBody: { test: true } });
44
+ expect(error).toHaveProperty('message');
45
+ expect(error.message).toContain('"test": true');
46
+ });
47
+
48
+ it('ignores response body if already streamed', async () => {
49
+ const response = { bodyUsed: true };
50
+ const error = await FetchError.create({ response });
51
+
52
+ expect(error).toHaveProperty('message');
53
+ expect(error.message).toContain('<response body is unavailable>');
54
+ });
55
+
56
+ it.only('prints a formData body legibly', async () => {
57
+ const response = {
58
+ status: 500,
59
+ statusText: 'Space aliens!',
60
+ headers: Object.entries({ 'cache-control': '123' }), // needs to be an Iterable
61
+ text: async () => '<!doctype html>',
62
+ };
63
+
64
+ const params = new URLSearchParams();
65
+ params.append('test', 'test');
66
+ const init = {
67
+ method: 'POST',
68
+ credentials: 'include',
69
+ headers: {},
70
+ query: {},
71
+ body: params,
72
+ returnFullRes: false,
73
+ };
74
+ const error = await FetchError.create({ response, init });
75
+
76
+ expect(error).toHaveProperty('message');
77
+ expect(error.message).toContain('test=test');
78
+ });
79
+ });
@@ -0,0 +1,10 @@
1
+ const { BaseError } = require('./base-error');
2
+
3
+ class HaltError extends BaseError {
4
+ constructor(message, ...errorOptions) {
5
+ super(message, ...errorOptions);
6
+ this.isHaltError = true;
7
+ }
8
+ }
9
+
10
+ module.exports = { HaltError };
@@ -0,0 +1,11 @@
1
+ const { HaltError } = require('./halt-error');
2
+
3
+ describe('HaltError', () => {
4
+ it('can be instantiated', () => {
5
+ const rootError = new Error('Gremlinoids!!');
6
+ const error = new HaltError('STOP', { cause: rootError });
7
+ expect(error).toHaveProperty('message', 'STOP');
8
+ expect(error).toHaveProperty('cause', rootError);
9
+ expect(error).toHaveProperty('isHaltError', true);
10
+ });
11
+ });
@@ -0,0 +1,15 @@
1
+ const { BaseError } = require('./base-error');
2
+ const { FetchError } = require('./fetch-error');
3
+ const { HaltError } = require('./halt-error');
4
+ const {
5
+ RequiredPropertyError,
6
+ ParameterTypeError,
7
+ } = require('./validation-errors');
8
+
9
+ module.exports = {
10
+ BaseError,
11
+ FetchError,
12
+ HaltError,
13
+ RequiredPropertyError,
14
+ ParameterTypeError,
15
+ };
@@ -0,0 +1,5 @@
1
+ module.exports = async () => {
2
+ return {
3
+ preset: '@friggframework/test-environment',
4
+ };
5
+ };
@@ -0,0 +1,23 @@
1
+ const { BaseError } = require('./base-error');
2
+
3
+ class RequiredPropertyError extends BaseError {
4
+ constructor(options = {}, ...parentOptions) {
5
+ const { parent, key = '' } = options;
6
+ const parentText = parent ? `(${parent.name}) ` : '';
7
+ const message = `${parentText}Key "${key}" is a required parameter.`;
8
+ super(message, ...parentOptions);
9
+ }
10
+ }
11
+
12
+ class ParameterTypeError extends BaseError {
13
+ constructor(options = {}, ...parentOptions) {
14
+ const { parent, key = '', value = '', expectedType } = options;
15
+ const parentText = parent ? `(${parent.name}) ` : '';
16
+ const keyText = key ? `key "${key}" with ` : '';
17
+ const typeName = expectedType?.name ?? '';
18
+ const message = `${parentText}Expected ${keyText}value "${value}" to be of type "${typeName}"`;
19
+ super(message, ...parentOptions);
20
+ }
21
+ }
22
+
23
+ module.exports = { RequiredPropertyError, ParameterTypeError };
@@ -0,0 +1,120 @@
1
+ const {
2
+ RequiredPropertyError,
3
+ ParameterTypeError,
4
+ } = require('./validation-errors');
5
+
6
+ describe('RequiredPropertyError', () => {
7
+ it('can be instantiated with default arguments', () => {
8
+ const error = new RequiredPropertyError();
9
+ expect(error).toHaveProperty(
10
+ 'message',
11
+ 'Key "" is a required parameter.'
12
+ );
13
+ expect(error).not.toHaveProperty('cause');
14
+ });
15
+
16
+ it('allows setting the key name of the error', () => {
17
+ const error = new RequiredPropertyError({ key: 'abc' });
18
+ expect(error).toHaveProperty(
19
+ 'message',
20
+ 'Key "abc" is a required parameter.'
21
+ );
22
+ expect(error).not.toHaveProperty('cause');
23
+ });
24
+
25
+ it('allows setting the parent of the error', () => {
26
+ const error = new RequiredPropertyError({ parent: class Xyz {} });
27
+ expect(error).toHaveProperty(
28
+ 'message',
29
+ '(Xyz) Key "" is a required parameter.'
30
+ );
31
+ expect(error).not.toHaveProperty('cause');
32
+ });
33
+
34
+ it('passes cause through to the Error parent class', () => {
35
+ const error = new RequiredPropertyError(
36
+ {
37
+ parent: class Qrs {},
38
+ key: 'def',
39
+ },
40
+ { cause: new Error('Gremlins!!') }
41
+ );
42
+ const expectedMessage = '(Qrs) Key "def" is a required parameter.';
43
+ expect(error).toHaveProperty('message', expectedMessage);
44
+ expect(error).toHaveProperty('cause');
45
+ expect(error.cause).toHaveProperty('message', 'Gremlins!!');
46
+ });
47
+ });
48
+
49
+ describe('ParameterTypeError', () => {
50
+ it('can be instantiated with default arguments', () => {
51
+ const error = new ParameterTypeError();
52
+ expect(error).toHaveProperty(
53
+ 'message',
54
+ 'Expected value "" to be of type ""'
55
+ );
56
+ expect(error).not.toHaveProperty('cause');
57
+ });
58
+
59
+ it('allows setting the key name of the error', () => {
60
+ const error = new ParameterTypeError({ key: 'abc' });
61
+ expect(error).toHaveProperty(
62
+ 'message',
63
+ 'Expected key "abc" with value "" to be of type ""'
64
+ );
65
+ expect(error).not.toHaveProperty('cause');
66
+ });
67
+
68
+ it('allows setting the parent of the error', () => {
69
+ const error = new ParameterTypeError({ parent: class Xyz {} });
70
+ expect(error).toHaveProperty(
71
+ 'message',
72
+ '(Xyz) Expected value "" to be of type ""'
73
+ );
74
+ expect(error).not.toHaveProperty('cause');
75
+ });
76
+
77
+ it('allows setting the value of the error', () => {
78
+ const error = new ParameterTypeError({ value: 1 });
79
+ expect(error).toHaveProperty(
80
+ 'message',
81
+ 'Expected value "1" to be of type ""'
82
+ );
83
+ expect(error).not.toHaveProperty('cause');
84
+ });
85
+
86
+ it('allows setting the expected type of the error', () => {
87
+ const error = new ParameterTypeError({ expectedType: class Xyz {} });
88
+ expect(error).toHaveProperty(
89
+ 'message',
90
+ 'Expected value "" to be of type "Xyz"'
91
+ );
92
+ expect(error).not.toHaveProperty('cause');
93
+ });
94
+
95
+ it('allows setting the expected type of the error to Array', () => {
96
+ const error = new ParameterTypeError({ expectedType: Array });
97
+ expect(error).toHaveProperty(
98
+ 'message',
99
+ 'Expected value "" to be of type "Array"'
100
+ );
101
+ expect(error).not.toHaveProperty('cause');
102
+ });
103
+
104
+ it('passes cause through to the Error parent class', () => {
105
+ const rootError = new Error('Gremlins!!');
106
+ const error = new ParameterTypeError(
107
+ {
108
+ parent: class Parent {},
109
+ key: 'clé',
110
+ expectedType: class Expected {},
111
+ value: 'schmalue',
112
+ },
113
+ { cause: rootError }
114
+ );
115
+ const expectedMessage =
116
+ '(Parent) Expected key "clé" with value "schmalue" to be of type "Expected"';
117
+ expect(error).toHaveProperty('message', expectedMessage);
118
+ expect(error).toHaveProperty('cause', rootError);
119
+ });
120
+ });
@@ -0,0 +1,3 @@
1
+ {
2
+ "extends": "@friggframework/eslint-config"
3
+ }
@@ -0,0 +1,17 @@
1
+ # v1.0.8 (Mon Jan 09 2023)
2
+
3
+ #### 🐛 Bug Fix
4
+
5
+ - Merge remote-tracking branch 'origin/main' into gitbook-updates [#48](https://github.com/friggframework/frigg/pull/48) ([@seanspeaks](https://github.com/seanspeaks))
6
+ - Bump independent versions \[skip ci\] ([@seanspeaks](https://github.com/seanspeaks))
7
+ - Merge remote-tracking branch 'origin/main' into simplify-mongoose-models ([@seanspeaks](https://github.com/seanspeaks))
8
+ - Add READMEs for all packages and api-modules [#20](https://github.com/friggframework/frigg/pull/20) ([@seanspeaks](https://github.com/seanspeaks))
9
+ - Add READMEs for all packages and api-modules ([@seanspeaks](https://github.com/seanspeaks))
10
+
11
+ #### ⚠️ Pushed to `main`
12
+
13
+ - Refactored for more conventional naming (at least for packages) ([@seanspeaks](https://github.com/seanspeaks))
14
+
15
+ #### Authors: 1
16
+
17
+ - Sean Matthews ([@seanspeaks](https://github.com/seanspeaks))
@@ -0,0 +1,9 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Left Hook Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,3 @@
1
+ # eslint-config
2
+
3
+ This package exports the default `eslint-config` settings used in [Frigg](https://friggframework.org). You can find its documentation [on Frigg's website](https://docs.friggframework.org/packages/eslint-config).
File without changes