@cedarjs/api 0.0.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.
- package/LICENSE +21 -0
- package/README.md +51 -0
- package/dist/auth/index.d.ts +51 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +89 -0
- package/dist/auth/parseJWT.d.ts +6 -0
- package/dist/auth/parseJWT.d.ts.map +1 -0
- package/dist/auth/parseJWT.js +33 -0
- package/dist/auth/verifiers/base64Sha1Verifier.d.ts +19 -0
- package/dist/auth/verifiers/base64Sha1Verifier.d.ts.map +1 -0
- package/dist/auth/verifiers/base64Sha1Verifier.js +57 -0
- package/dist/auth/verifiers/base64Sha256Verifier.d.ts +19 -0
- package/dist/auth/verifiers/base64Sha256Verifier.d.ts.map +1 -0
- package/dist/auth/verifiers/base64Sha256Verifier.js +57 -0
- package/dist/auth/verifiers/common.d.ts +104 -0
- package/dist/auth/verifiers/common.d.ts.map +1 -0
- package/dist/auth/verifiers/common.js +59 -0
- package/dist/auth/verifiers/index.d.ts +8 -0
- package/dist/auth/verifiers/index.d.ts.map +1 -0
- package/dist/auth/verifiers/index.js +12 -0
- package/dist/auth/verifiers/jwtVerifier.d.ts +26 -0
- package/dist/auth/verifiers/jwtVerifier.d.ts.map +1 -0
- package/dist/auth/verifiers/jwtVerifier.js +55 -0
- package/dist/auth/verifiers/secretKeyVerifier.d.ts +14 -0
- package/dist/auth/verifiers/secretKeyVerifier.d.ts.map +1 -0
- package/dist/auth/verifiers/secretKeyVerifier.js +20 -0
- package/dist/auth/verifiers/sha1Verifier.d.ts +25 -0
- package/dist/auth/verifiers/sha1Verifier.d.ts.map +1 -0
- package/dist/auth/verifiers/sha1Verifier.js +65 -0
- package/dist/auth/verifiers/sha256Verifier.d.ts +25 -0
- package/dist/auth/verifiers/sha256Verifier.d.ts.map +1 -0
- package/dist/auth/verifiers/sha256Verifier.js +65 -0
- package/dist/auth/verifiers/skipVerifier.d.ts +13 -0
- package/dist/auth/verifiers/skipVerifier.d.ts.map +1 -0
- package/dist/auth/verifiers/skipVerifier.js +17 -0
- package/dist/auth/verifiers/timestampSchemeVerifier.d.ts +16 -0
- package/dist/auth/verifiers/timestampSchemeVerifier.d.ts.map +1 -0
- package/dist/auth/verifiers/timestampSchemeVerifier.js +65 -0
- package/dist/bins/redwood.d.ts +9 -0
- package/dist/bins/redwood.d.ts.map +1 -0
- package/dist/bins/rwfw.d.ts +3 -0
- package/dist/bins/rwfw.d.ts.map +1 -0
- package/dist/bins/tsc.d.ts +3 -0
- package/dist/bins/tsc.d.ts.map +1 -0
- package/dist/cache/clients/BaseClient.d.ts +11 -0
- package/dist/cache/clients/BaseClient.d.ts.map +1 -0
- package/dist/cache/clients/BaseClient.js +7 -0
- package/dist/cache/clients/InMemoryClient.d.ts +31 -0
- package/dist/cache/clients/InMemoryClient.d.ts.map +1 -0
- package/dist/cache/clients/InMemoryClient.js +70 -0
- package/dist/cache/clients/MemcachedClient.d.ts +16 -0
- package/dist/cache/clients/MemcachedClient.d.ts.map +1 -0
- package/dist/cache/clients/MemcachedClient.js +45 -0
- package/dist/cache/clients/RedisClient.d.ts +20 -0
- package/dist/cache/clients/RedisClient.d.ts.map +1 -0
- package/dist/cache/clients/RedisClient.js +49 -0
- package/dist/cache/errors.d.ts +4 -0
- package/dist/cache/errors.d.ts.map +1 -0
- package/dist/cache/errors.js +9 -0
- package/dist/cache/index.d.ts +35 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +132 -0
- package/dist/cjs/auth/index.d.ts +51 -0
- package/dist/cjs/auth/index.d.ts.map +1 -0
- package/dist/cjs/auth/index.js +129 -0
- package/dist/cjs/auth/parseJWT.d.ts +6 -0
- package/dist/cjs/auth/parseJWT.d.ts.map +1 -0
- package/dist/cjs/auth/parseJWT.js +57 -0
- package/dist/cjs/auth/verifiers/base64Sha1Verifier.d.ts +19 -0
- package/dist/cjs/auth/verifiers/base64Sha1Verifier.d.ts.map +1 -0
- package/dist/cjs/auth/verifiers/base64Sha1Verifier.js +77 -0
- package/dist/cjs/auth/verifiers/base64Sha256Verifier.d.ts +19 -0
- package/dist/cjs/auth/verifiers/base64Sha256Verifier.d.ts.map +1 -0
- package/dist/cjs/auth/verifiers/base64Sha256Verifier.js +77 -0
- package/dist/cjs/auth/verifiers/common.d.ts +104 -0
- package/dist/cjs/auth/verifiers/common.d.ts.map +1 -0
- package/dist/cjs/auth/verifiers/common.js +99 -0
- package/dist/cjs/auth/verifiers/index.d.ts +8 -0
- package/dist/cjs/auth/verifiers/index.d.ts.map +1 -0
- package/dist/cjs/auth/verifiers/index.js +38 -0
- package/dist/cjs/auth/verifiers/jwtVerifier.d.ts +26 -0
- package/dist/cjs/auth/verifiers/jwtVerifier.d.ts.map +1 -0
- package/dist/cjs/auth/verifiers/jwtVerifier.js +86 -0
- package/dist/cjs/auth/verifiers/secretKeyVerifier.d.ts +14 -0
- package/dist/cjs/auth/verifiers/secretKeyVerifier.d.ts.map +1 -0
- package/dist/cjs/auth/verifiers/secretKeyVerifier.js +40 -0
- package/dist/cjs/auth/verifiers/sha1Verifier.d.ts +25 -0
- package/dist/cjs/auth/verifiers/sha1Verifier.d.ts.map +1 -0
- package/dist/cjs/auth/verifiers/sha1Verifier.js +85 -0
- package/dist/cjs/auth/verifiers/sha256Verifier.d.ts +25 -0
- package/dist/cjs/auth/verifiers/sha256Verifier.d.ts.map +1 -0
- package/dist/cjs/auth/verifiers/sha256Verifier.js +85 -0
- package/dist/cjs/auth/verifiers/skipVerifier.d.ts +13 -0
- package/dist/cjs/auth/verifiers/skipVerifier.d.ts.map +1 -0
- package/dist/cjs/auth/verifiers/skipVerifier.js +37 -0
- package/dist/cjs/auth/verifiers/timestampSchemeVerifier.d.ts +16 -0
- package/dist/cjs/auth/verifiers/timestampSchemeVerifier.d.ts.map +1 -0
- package/dist/cjs/auth/verifiers/timestampSchemeVerifier.js +81 -0
- package/dist/cjs/bins/redwood.d.ts +9 -0
- package/dist/cjs/bins/redwood.d.ts.map +1 -0
- package/dist/cjs/bins/redwood.js +36 -0
- package/dist/cjs/bins/rwfw.d.ts +3 -0
- package/dist/cjs/bins/rwfw.d.ts.map +1 -0
- package/dist/cjs/bins/rwfw.js +36 -0
- package/dist/cjs/bins/tsc.d.ts +3 -0
- package/dist/cjs/bins/tsc.d.ts.map +1 -0
- package/dist/cjs/bins/tsc.js +30 -0
- package/dist/cjs/cache/clients/BaseClient.d.ts +11 -0
- package/dist/cjs/cache/clients/BaseClient.d.ts.map +1 -0
- package/dist/cjs/cache/clients/BaseClient.js +27 -0
- package/dist/cjs/cache/clients/InMemoryClient.d.ts +31 -0
- package/dist/cjs/cache/clients/InMemoryClient.d.ts.map +1 -0
- package/dist/cjs/cache/clients/InMemoryClient.js +100 -0
- package/dist/cjs/cache/clients/MemcachedClient.d.ts +16 -0
- package/dist/cjs/cache/clients/MemcachedClient.d.ts.map +1 -0
- package/dist/cjs/cache/clients/MemcachedClient.js +75 -0
- package/dist/cjs/cache/clients/RedisClient.d.ts +20 -0
- package/dist/cjs/cache/clients/RedisClient.d.ts.map +1 -0
- package/dist/cjs/cache/clients/RedisClient.js +79 -0
- package/dist/cjs/cache/errors.d.ts +4 -0
- package/dist/cjs/cache/errors.d.ts.map +1 -0
- package/dist/cjs/cache/errors.js +33 -0
- package/dist/cjs/cache/index.d.ts +35 -0
- package/dist/cjs/cache/index.d.ts.map +1 -0
- package/dist/cjs/cache/index.js +171 -0
- package/dist/cjs/cors.d.ts +16 -0
- package/dist/cjs/cors.d.ts.map +1 -0
- package/dist/cjs/cors.js +93 -0
- package/dist/cjs/errors.d.ts +5 -0
- package/dist/cjs/errors.d.ts.map +1 -0
- package/dist/cjs/errors.js +38 -0
- package/dist/cjs/event.d.ts +3 -0
- package/dist/cjs/event.d.ts.map +1 -0
- package/dist/cjs/event.js +34 -0
- package/dist/cjs/functions/fixtures/apiGatewayProxyEvent.fixture.d.ts +4 -0
- package/dist/cjs/functions/fixtures/apiGatewayProxyEvent.fixture.d.ts.map +1 -0
- package/dist/cjs/functions/fixtures/apiGatewayProxyEvent.fixture.js +72 -0
- package/dist/cjs/index.d.ts +11 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +82 -0
- package/dist/cjs/logger/index.d.ts +179 -0
- package/dist/cjs/logger/index.d.ts.map +1 -0
- package/dist/cjs/logger/index.js +195 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/transforms.d.ts +35 -0
- package/dist/cjs/transforms.d.ts.map +1 -0
- package/dist/cjs/transforms.js +98 -0
- package/dist/cjs/types.d.ts +25 -0
- package/dist/cjs/types.d.ts.map +1 -0
- package/dist/cjs/types.js +16 -0
- package/dist/cjs/validations/errors.d.ts +101 -0
- package/dist/cjs/validations/errors.d.ts.map +1 -0
- package/dist/cjs/validations/errors.js +298 -0
- package/dist/cjs/validations/validations.d.ts +222 -0
- package/dist/cjs/validations/validations.d.ts.map +1 -0
- package/dist/cjs/validations/validations.js +351 -0
- package/dist/cjs/webhooks/index.d.ts +76 -0
- package/dist/cjs/webhooks/index.d.ts.map +1 -0
- package/dist/cjs/webhooks/index.js +107 -0
- package/dist/cors.d.ts +16 -0
- package/dist/cors.d.ts.map +1 -0
- package/dist/cors.js +69 -0
- package/dist/errors.d.ts +5 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +14 -0
- package/dist/event.d.ts +3 -0
- package/dist/event.d.ts.map +1 -0
- package/dist/event.js +10 -0
- package/dist/functions/fixtures/apiGatewayProxyEvent.fixture.d.ts +4 -0
- package/dist/functions/fixtures/apiGatewayProxyEvent.fixture.d.ts.map +1 -0
- package/dist/functions/fixtures/apiGatewayProxyEvent.fixture.js +48 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/logger/index.d.ts +179 -0
- package/dist/logger/index.d.ts.map +1 -0
- package/dist/logger/index.js +152 -0
- package/dist/package.json +1 -0
- package/dist/transforms.d.ts +35 -0
- package/dist/transforms.d.ts.map +1 -0
- package/dist/transforms.js +70 -0
- package/dist/types.d.ts +25 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +0 -0
- package/dist/validations/errors.d.ts +101 -0
- package/dist/validations/errors.d.ts.map +1 -0
- package/dist/validations/errors.js +239 -0
- package/dist/validations/validations.d.ts +222 -0
- package/dist/validations/validations.d.ts.map +1 -0
- package/dist/validations/validations.js +314 -0
- package/dist/webhooks/index.d.ts +76 -0
- package/dist/webhooks/index.d.ts.map +1 -0
- package/dist/webhooks/index.js +85 -0
- package/package.json +130 -0
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import { PrismaClient } from "@prisma/client";
|
|
2
|
+
import pascalcase from "pascalcase";
|
|
3
|
+
import * as ValidationErrors from "./errors.js";
|
|
4
|
+
const VALIDATORS = {
|
|
5
|
+
// Requires that the given value is `null` or `undefined`
|
|
6
|
+
//
|
|
7
|
+
// `allowEmptyString`: if true, counts "" as being absent (does not throw)
|
|
8
|
+
//
|
|
9
|
+
// { absence: true }
|
|
10
|
+
// { absence: { allowEmptyString: true, message: '...' } }
|
|
11
|
+
absence: (value, name, options) => {
|
|
12
|
+
const absenceOptions = { allowEmptyString: false };
|
|
13
|
+
Object.assign(absenceOptions, options);
|
|
14
|
+
if (value === "") {
|
|
15
|
+
if (!absenceOptions.allowEmptyString) {
|
|
16
|
+
validationError("absence", name, options);
|
|
17
|
+
}
|
|
18
|
+
} else if (value != null) {
|
|
19
|
+
validationError("absence", name, options);
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
// Requires that the given field be `true` and nothing else, unless an array
|
|
23
|
+
// of valid values is included with an `in` option
|
|
24
|
+
//
|
|
25
|
+
// { acceptance: true }
|
|
26
|
+
// { acceptance: { in: ['true','1'], message: '...' } }
|
|
27
|
+
acceptance: (value, name, options) => {
|
|
28
|
+
let acceptedValues;
|
|
29
|
+
if (typeof options === "object") {
|
|
30
|
+
acceptedValues = options.in || [];
|
|
31
|
+
} else {
|
|
32
|
+
acceptedValues = [true];
|
|
33
|
+
}
|
|
34
|
+
if (!acceptedValues.includes(value)) {
|
|
35
|
+
validationError("acceptance", name, options);
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
// Requires that the given value be formatted like an email address. Uses a
|
|
39
|
+
// very simple regex which checks for at least 1 character that is not an @,
|
|
40
|
+
// then an @, then at least one character that isn't a period, then a period,
|
|
41
|
+
// then any character. There cannot be any spaces present.
|
|
42
|
+
//
|
|
43
|
+
// { email: true }
|
|
44
|
+
// { email: { message: '...' } }
|
|
45
|
+
email: (value, name, options) => {
|
|
46
|
+
const pattern = /^[^@\s]+@[^.\s]+\.[^\s]+$/;
|
|
47
|
+
if (!pattern.test(String(value))) {
|
|
48
|
+
validationError("email", name, options);
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
// Requires that the given value NOT be in the list of possible values
|
|
52
|
+
//
|
|
53
|
+
// { exclusion: ['foo', 'bar'] }
|
|
54
|
+
// { exclusion: { in: ['foo','bar'], message: '...' } }
|
|
55
|
+
exclusion: (value, name, options) => {
|
|
56
|
+
const [exclusionList, val] = prepareExclusionInclusion(value, options);
|
|
57
|
+
if (exclusionList.includes(val)) {
|
|
58
|
+
validationError("exclusion", name, options);
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
// Requires that the given value match a regular expression
|
|
62
|
+
//
|
|
63
|
+
// { format: /^foobar$/ }
|
|
64
|
+
// { format: { pattern: /^foobar$/, message: '...' } }
|
|
65
|
+
format: (value, name, options) => {
|
|
66
|
+
const pattern = options instanceof RegExp ? options : options.pattern;
|
|
67
|
+
if (pattern == null) {
|
|
68
|
+
throw new ValidationErrors.FormatValidationError(
|
|
69
|
+
name,
|
|
70
|
+
"No pattern for format validation"
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
if (!pattern.test(String(value))) {
|
|
74
|
+
validationError("format", name, options);
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
// Requires that the given value be in the list of possible values
|
|
78
|
+
//
|
|
79
|
+
// { inclusion: ['foo', 'bar'] }
|
|
80
|
+
// { inclusion: { in: ['foo','bar'], message: '...' } }
|
|
81
|
+
inclusion: (value, name, options) => {
|
|
82
|
+
const [inclusionList, val] = prepareExclusionInclusion(value, options);
|
|
83
|
+
if (!inclusionList.includes(val)) {
|
|
84
|
+
validationError("inclusion", name, options);
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
// Requires that the given string be a certain length:
|
|
88
|
+
//
|
|
89
|
+
// `min`: must be at least `min` characters
|
|
90
|
+
// `max`: must be no more than `max` characters
|
|
91
|
+
// `equal`: must be exactly `equal` characters
|
|
92
|
+
// `between`: an array consisting of the `min` and `max` length
|
|
93
|
+
//
|
|
94
|
+
// { length: { min: 4 } }
|
|
95
|
+
// { length: { min: 2, max: 16 } }
|
|
96
|
+
// { length: { between: [2, 16], message: '...' } }
|
|
97
|
+
length: (value, name, options) => {
|
|
98
|
+
const len = String(value).length;
|
|
99
|
+
if (options.min && len < options.min) {
|
|
100
|
+
validationError("minLength", name, options, { min: options.min });
|
|
101
|
+
}
|
|
102
|
+
if (options.max && len > options.max) {
|
|
103
|
+
validationError("maxLength", name, options, { max: options.max });
|
|
104
|
+
}
|
|
105
|
+
if (options.equal && len !== options.equal) {
|
|
106
|
+
validationError("equalLength", name, options, { equal: options.equal });
|
|
107
|
+
}
|
|
108
|
+
if (options.between && (len < options.between[0] || len > options.between[1])) {
|
|
109
|
+
validationError("betweenLength", name, options, {
|
|
110
|
+
min: options.between[0],
|
|
111
|
+
max: options.between[1]
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
// Requires that number value meets some criteria:
|
|
116
|
+
//
|
|
117
|
+
// `integer`: value must be an integer
|
|
118
|
+
// `lessThan`: value must be less than `lessThan`
|
|
119
|
+
// `lessThanOrEqual`: value must be less than or equal to `lessThanOrEqual`
|
|
120
|
+
// `greaterThan`: value must be greater than `greaterThan`
|
|
121
|
+
// `greaterThanOrEqual`: value must be greater than or equal to `greaterThanOrEqual`
|
|
122
|
+
// `equal`: value must equal `equal`
|
|
123
|
+
// `otherThan`: value must be anything other than `otherThan`
|
|
124
|
+
// `even`: value must be an even number
|
|
125
|
+
// `odd`: value must be an odd number
|
|
126
|
+
// `positive`: value must be a positive number
|
|
127
|
+
// `negative`: value must be a negative number
|
|
128
|
+
//
|
|
129
|
+
// { numericality: true }
|
|
130
|
+
// { numericality: { integer: true } }
|
|
131
|
+
// { numericality: { greaterThan: 3.5, message: '...' } }
|
|
132
|
+
numericality: (value, name, options) => {
|
|
133
|
+
if (typeof value !== "number") {
|
|
134
|
+
validationError("typeNumericality", name, options);
|
|
135
|
+
}
|
|
136
|
+
if (typeof options === "boolean") {
|
|
137
|
+
return;
|
|
138
|
+
} else {
|
|
139
|
+
if (options.integer && !Number.isInteger(value)) {
|
|
140
|
+
validationError("integerNumericality", name, options);
|
|
141
|
+
}
|
|
142
|
+
if (options.lessThan != null && value >= options.lessThan) {
|
|
143
|
+
validationError("lessThanNumericality", name, options, {
|
|
144
|
+
lessThan: options.lessThan
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
if (options.lessThanOrEqual != null && value > options.lessThanOrEqual) {
|
|
148
|
+
validationError("lessThanOrEqualNumericality", name, options, {
|
|
149
|
+
lessThanOrEqual: options.lessThanOrEqual
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
if (options.greaterThan != null && value <= options.greaterThan) {
|
|
153
|
+
validationError("greaterThanNumericality", name, options, {
|
|
154
|
+
greaterThan: options.greaterThan
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
if (options.greaterThanOrEqual != null && value < options.greaterThanOrEqual) {
|
|
158
|
+
validationError("greaterThanOrEqualNumericality", name, options, {
|
|
159
|
+
greaterThanOrEqual: options.greaterThanOrEqual
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
if (options.equal != null && value !== options.equal) {
|
|
163
|
+
validationError("equalNumericality", name, options, {
|
|
164
|
+
equal: options.equal
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
if (options.otherThan != null && value === options.otherThan) {
|
|
168
|
+
validationError("otherThanNumericality", name, options, {
|
|
169
|
+
otherThan: options.otherThan
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
if (options.even && value % 2 !== 0) {
|
|
173
|
+
validationError("evenNumericality", name, options);
|
|
174
|
+
}
|
|
175
|
+
if (options.odd && value % 2 !== 1) {
|
|
176
|
+
validationError("oddNumericality", name, options);
|
|
177
|
+
}
|
|
178
|
+
if (options.positive && value <= 0) {
|
|
179
|
+
validationError("positiveNumericality", name, options);
|
|
180
|
+
}
|
|
181
|
+
if (options.negative && value >= 0) {
|
|
182
|
+
validationError("negativeNumericality", name, options);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
// Requires that the given value is not `null` or `undefined`. By default will
|
|
187
|
+
// consider an empty string to pass
|
|
188
|
+
//
|
|
189
|
+
// `allowEmptyString`: if set to `false` will throw an error if value is ""
|
|
190
|
+
// `allowNull`: if `true` will allow `null`
|
|
191
|
+
// `allowUndefined`: if `true` will allow `undefined`
|
|
192
|
+
//
|
|
193
|
+
// Default behavior is equivalent to:
|
|
194
|
+
// { allowNull: false, allowUndefined: false, allowEmptyString: true }
|
|
195
|
+
//
|
|
196
|
+
// { presence: true }
|
|
197
|
+
// { presence: { allowEmptyString: false, message: '...' } }
|
|
198
|
+
presence: (value, name, options) => {
|
|
199
|
+
const presenceOptions = {
|
|
200
|
+
allowNull: false,
|
|
201
|
+
allowUndefined: false,
|
|
202
|
+
allowEmptyString: true
|
|
203
|
+
};
|
|
204
|
+
Object.assign(presenceOptions, options);
|
|
205
|
+
if (!presenceOptions.allowNull && value === null || !presenceOptions.allowUndefined && value === void 0 || !presenceOptions.allowEmptyString && value === "") {
|
|
206
|
+
validationError("presence", name, options);
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
custom: (_value, name, options) => {
|
|
210
|
+
try {
|
|
211
|
+
options.with();
|
|
212
|
+
} catch (e) {
|
|
213
|
+
const message = options.message || e.message || e;
|
|
214
|
+
validationError("custom", name, { message });
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
const fieldsToString = (fields) => {
|
|
219
|
+
const output = [];
|
|
220
|
+
for (const [key, _value] of Object.entries(fields)) {
|
|
221
|
+
output.push(key);
|
|
222
|
+
}
|
|
223
|
+
return output.join(", ");
|
|
224
|
+
};
|
|
225
|
+
const validationError = (type, name, options, substitutions = {}) => {
|
|
226
|
+
const errorClassName = `${pascalcase(
|
|
227
|
+
type
|
|
228
|
+
)}ValidationError`;
|
|
229
|
+
const ErrorClass = ValidationErrors[errorClassName];
|
|
230
|
+
const errorMessage = typeof options === "object" ? options.message : void 0;
|
|
231
|
+
throw new ErrorClass(name, errorMessage, substitutions);
|
|
232
|
+
};
|
|
233
|
+
const prepareExclusionInclusion = (value, options) => {
|
|
234
|
+
const inputList = Array.isArray(options) && options || options.in || [];
|
|
235
|
+
const caseSensitive = Array.isArray(options) ? true : options.caseSensitive ?? true;
|
|
236
|
+
return caseSensitive ? [inputList, value] : [
|
|
237
|
+
inputList.map((s) => s.toLowerCase()),
|
|
238
|
+
value.toLowerCase()
|
|
239
|
+
];
|
|
240
|
+
};
|
|
241
|
+
function validate(value, labelOrRecipe, recipe) {
|
|
242
|
+
let label, validationRecipe;
|
|
243
|
+
if (typeof labelOrRecipe === "object") {
|
|
244
|
+
label = "";
|
|
245
|
+
validationRecipe = labelOrRecipe;
|
|
246
|
+
} else {
|
|
247
|
+
label = labelOrRecipe;
|
|
248
|
+
validationRecipe = recipe;
|
|
249
|
+
}
|
|
250
|
+
for (const [validator, options] of Object.entries(validationRecipe)) {
|
|
251
|
+
if (typeof options === "undefined") {
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
VALIDATORS[validator](value, label, options);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
const validateWithSync = (func) => {
|
|
258
|
+
try {
|
|
259
|
+
func();
|
|
260
|
+
} catch (e) {
|
|
261
|
+
const message = e.message || e;
|
|
262
|
+
throw new ValidationErrors.ServiceValidationError(message);
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
const validateWith = async (func) => {
|
|
266
|
+
try {
|
|
267
|
+
await func();
|
|
268
|
+
} catch (e) {
|
|
269
|
+
const message = e.message || e;
|
|
270
|
+
throw new ValidationErrors.ServiceValidationError(message);
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
async function validateUniqueness(model, fields, optionsOrCallback, callback) {
|
|
274
|
+
const { $self, $scope, ...rest } = fields;
|
|
275
|
+
let options = {};
|
|
276
|
+
let validCallback;
|
|
277
|
+
let db = null;
|
|
278
|
+
if (typeof optionsOrCallback === "function") {
|
|
279
|
+
validCallback = optionsOrCallback;
|
|
280
|
+
} else {
|
|
281
|
+
options = optionsOrCallback;
|
|
282
|
+
validCallback = callback;
|
|
283
|
+
}
|
|
284
|
+
if (options.db) {
|
|
285
|
+
const { db: customDb, ...restOptions } = options;
|
|
286
|
+
options = restOptions;
|
|
287
|
+
db = customDb;
|
|
288
|
+
} else {
|
|
289
|
+
db = new PrismaClient();
|
|
290
|
+
}
|
|
291
|
+
const where = {
|
|
292
|
+
AND: [rest],
|
|
293
|
+
NOT: []
|
|
294
|
+
};
|
|
295
|
+
if ($scope) {
|
|
296
|
+
where.AND.push($scope);
|
|
297
|
+
}
|
|
298
|
+
if ($self) {
|
|
299
|
+
where.NOT.push($self);
|
|
300
|
+
}
|
|
301
|
+
return await db.$transaction(async (tx) => {
|
|
302
|
+
const found = await tx[model].findFirst({ where });
|
|
303
|
+
if (found) {
|
|
304
|
+
validationError("uniqueness", fieldsToString(fields), options);
|
|
305
|
+
}
|
|
306
|
+
return validCallback(tx);
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
export {
|
|
310
|
+
validate,
|
|
311
|
+
validateUniqueness,
|
|
312
|
+
validateWith,
|
|
313
|
+
validateWithSync
|
|
314
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { APIGatewayProxyEvent } from 'aws-lambda';
|
|
2
|
+
import type { VerifyOptions, SupportedVerifierTypes } from '../auth/verifiers/index.js';
|
|
3
|
+
import { WebhookVerificationError } from '../auth/verifiers/index.js';
|
|
4
|
+
export { VerifyOptions, WebhookVerificationError, DEFAULT_WEBHOOK_SECRET, SupportedVerifierTypes, } from '../auth/verifiers/index.js';
|
|
5
|
+
export declare const DEFAULT_WEBHOOK_SIGNATURE_HEADER = "RW-WEBHOOK-SIGNATURE";
|
|
6
|
+
/**
|
|
7
|
+
* Extracts signature from Lambda Event.
|
|
8
|
+
*
|
|
9
|
+
* @param {APIGatewayProxyEvent} event - The event that includes the request details, like headers
|
|
10
|
+
* @param {string} signatureHeader - The name of header key that contains the signature; defaults to DEFAULT_WEBHOOK_SIGNATURE_HEADER
|
|
11
|
+
* @return {string} - The signature found in the headers specified by signatureHeader
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
*
|
|
15
|
+
* signatureFromEvent({ event: event })
|
|
16
|
+
*/
|
|
17
|
+
export declare const signatureFromEvent: ({ event, signatureHeader, }: {
|
|
18
|
+
event: APIGatewayProxyEvent;
|
|
19
|
+
signatureHeader: string;
|
|
20
|
+
}) => string;
|
|
21
|
+
/**
|
|
22
|
+
* Verifies event payload is signed with a valid webhook signature.
|
|
23
|
+
*
|
|
24
|
+
* @param {APIGatewayProxyEvent} event - The event that includes the body for the verification payload and request details, like headers.
|
|
25
|
+
* @param {string} payload - If provided, the payload will be used to verify the signature instead of the event body.
|
|
26
|
+
* @param {string} secret - The secret that will verify the signature according to the verifier type
|
|
27
|
+
* @param {VerifyOptions} options - Options to specify the verifier type the header key that contains the signature, timestamp leeway.
|
|
28
|
+
* @return {boolean | WebhookVerificationError} - Returns true if the signature is verified, or raises WebhookVerificationError.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
*
|
|
32
|
+
* verifyEvent({ event: event, options: {} })*
|
|
33
|
+
*/
|
|
34
|
+
export declare const verifyEvent: (type: SupportedVerifierTypes, { event, payload, secret, options, }: {
|
|
35
|
+
event: APIGatewayProxyEvent;
|
|
36
|
+
payload?: string;
|
|
37
|
+
secret?: string;
|
|
38
|
+
options?: VerifyOptions | undefined;
|
|
39
|
+
}) => boolean | WebhookVerificationError;
|
|
40
|
+
/**
|
|
41
|
+
* Standalone verification of webhook signature given a payload, secret, verifier type and options.
|
|
42
|
+
*
|
|
43
|
+
* @param {string} payload - Body content of the event
|
|
44
|
+
* @param {string} secret - The secret that will verify the signature according to the verifier type
|
|
45
|
+
* @param {string} signature - Signature that verifies that the event
|
|
46
|
+
* @param {VerifyOptions} options - Options to specify the verifier type the header key that contains the signature, timestamp leeway.
|
|
47
|
+
* @return {boolean | WebhookVerificationError} - Returns true if the signature is verified, or raises WebhookVerificationError.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
*
|
|
51
|
+
* verifySignature({ payload, secret, signature, options: {} })*
|
|
52
|
+
*/
|
|
53
|
+
export declare const verifySignature: (type: SupportedVerifierTypes, { payload, secret, signature, options, }: {
|
|
54
|
+
payload: string | Record<string, unknown>;
|
|
55
|
+
secret: string;
|
|
56
|
+
signature: string;
|
|
57
|
+
options?: VerifyOptions | undefined;
|
|
58
|
+
}) => boolean | WebhookVerificationError;
|
|
59
|
+
/**
|
|
60
|
+
* Signs a payload with a secret and verifier type method
|
|
61
|
+
*
|
|
62
|
+
* @param {string} payload - Body content of the event to sign
|
|
63
|
+
* @param {string} secret - The secret that will verify the signature according to the verifier type
|
|
64
|
+
* @param {VerifyOptions} options - Options to specify the verifier type the header key that contains the signature, timestamp leeway.
|
|
65
|
+
* @return {string} - Returns signature
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
*
|
|
69
|
+
* signPayload({ payload, secret, options: {} })*
|
|
70
|
+
*/
|
|
71
|
+
export declare const signPayload: (type: SupportedVerifierTypes, { payload, secret, options, }: {
|
|
72
|
+
payload: string;
|
|
73
|
+
secret: string;
|
|
74
|
+
options?: VerifyOptions | undefined;
|
|
75
|
+
}) => string;
|
|
76
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/webhooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAEtD,OAAO,KAAK,EACV,aAAa,EACb,sBAAsB,EACvB,MAAM,4BAA4B,CAAA;AACnC,OAAO,EAEL,wBAAwB,EAGzB,MAAM,4BAA4B,CAAA;AAEnC,OAAO,EACL,aAAa,EACb,wBAAwB,EACxB,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,4BAA4B,CAAA;AAEnC,eAAO,MAAM,gCAAgC,yBAAyB,CAAA;AActE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kBAAkB,gCAG5B;IACD,KAAK,EAAE,oBAAoB,CAAA;IAC3B,eAAe,EAAE,MAAM,CAAA;CACxB,KAAG,MAGH,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,WAAW,SAChB,sBAAsB,wCAMzB;IACD,KAAK,EAAE,oBAAoB,CAAA;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,aAAa,GAAG,SAAS,CAAA;CACpC,KACA,OAAO,GAAG,wBAgCZ,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,eAAe,SACpB,sBAAsB,4CAMzB;IACD,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACzC,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,aAAa,GAAG,SAAS,CAAA;CACpC,KACA,OAAO,GAAG,wBAIZ,CAAA;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,WAAW,SAChB,sBAAsB,iCAKzB;IACD,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,aAAa,GAAG,SAAS,CAAA;CACpC,KACA,MAIF,CAAA"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createVerifier,
|
|
3
|
+
WebhookVerificationError,
|
|
4
|
+
DEFAULT_WEBHOOK_SECRET,
|
|
5
|
+
DEFAULT_TOLERANCE
|
|
6
|
+
} from "../auth/verifiers/index.js";
|
|
7
|
+
import {
|
|
8
|
+
VerifyOptions,
|
|
9
|
+
WebhookVerificationError as WebhookVerificationError2,
|
|
10
|
+
DEFAULT_WEBHOOK_SECRET as DEFAULT_WEBHOOK_SECRET2,
|
|
11
|
+
SupportedVerifierTypes
|
|
12
|
+
} from "../auth/verifiers/index.js";
|
|
13
|
+
const DEFAULT_WEBHOOK_SIGNATURE_HEADER = "RW-WEBHOOK-SIGNATURE";
|
|
14
|
+
const eventBody = (event) => {
|
|
15
|
+
if (event.isBase64Encoded) {
|
|
16
|
+
return Buffer.from(event.body || "", "base64").toString("utf-8");
|
|
17
|
+
} else {
|
|
18
|
+
return event.body || "";
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
const signatureFromEvent = ({
|
|
22
|
+
event,
|
|
23
|
+
signatureHeader = DEFAULT_WEBHOOK_SIGNATURE_HEADER
|
|
24
|
+
}) => {
|
|
25
|
+
const header = signatureHeader.toLocaleLowerCase();
|
|
26
|
+
return event.headers[header];
|
|
27
|
+
};
|
|
28
|
+
const verifyEvent = (type, {
|
|
29
|
+
event,
|
|
30
|
+
payload,
|
|
31
|
+
secret = DEFAULT_WEBHOOK_SECRET,
|
|
32
|
+
options
|
|
33
|
+
}) => {
|
|
34
|
+
let body = "";
|
|
35
|
+
if (payload) {
|
|
36
|
+
body = payload;
|
|
37
|
+
} else {
|
|
38
|
+
body = eventBody(event);
|
|
39
|
+
}
|
|
40
|
+
let signature = signatureFromEvent({
|
|
41
|
+
event,
|
|
42
|
+
signatureHeader: options?.signatureHeader || DEFAULT_WEBHOOK_SIGNATURE_HEADER
|
|
43
|
+
});
|
|
44
|
+
if (options?.signatureTransformer) {
|
|
45
|
+
signature = options.signatureTransformer(signature);
|
|
46
|
+
}
|
|
47
|
+
if (options?.eventTimestamp) {
|
|
48
|
+
const timestamp = options?.currentTimestampOverride ?? Date.now();
|
|
49
|
+
const difference = Math.abs(timestamp - options?.eventTimestamp);
|
|
50
|
+
const tolerance = options?.tolerance ?? DEFAULT_TOLERANCE;
|
|
51
|
+
if (difference > tolerance) {
|
|
52
|
+
throw new WebhookVerificationError();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const { verify } = createVerifier(type, options);
|
|
56
|
+
return verify({ payload: body, secret, signature });
|
|
57
|
+
};
|
|
58
|
+
const verifySignature = (type, {
|
|
59
|
+
payload,
|
|
60
|
+
secret = DEFAULT_WEBHOOK_SECRET,
|
|
61
|
+
signature,
|
|
62
|
+
options
|
|
63
|
+
}) => {
|
|
64
|
+
const { verify } = createVerifier(type, options);
|
|
65
|
+
return verify({ payload, secret, signature });
|
|
66
|
+
};
|
|
67
|
+
const signPayload = (type, {
|
|
68
|
+
payload,
|
|
69
|
+
secret = DEFAULT_WEBHOOK_SECRET,
|
|
70
|
+
options
|
|
71
|
+
}) => {
|
|
72
|
+
const { sign } = createVerifier(type, options);
|
|
73
|
+
return sign({ payload, secret });
|
|
74
|
+
};
|
|
75
|
+
export {
|
|
76
|
+
DEFAULT_WEBHOOK_SECRET2 as DEFAULT_WEBHOOK_SECRET,
|
|
77
|
+
DEFAULT_WEBHOOK_SIGNATURE_HEADER,
|
|
78
|
+
SupportedVerifierTypes,
|
|
79
|
+
VerifyOptions,
|
|
80
|
+
WebhookVerificationError2 as WebhookVerificationError,
|
|
81
|
+
signPayload,
|
|
82
|
+
signatureFromEvent,
|
|
83
|
+
verifyEvent,
|
|
84
|
+
verifySignature
|
|
85
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cedarjs/api",
|
|
3
|
+
"version": "0.0.4",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "git+https://github.com/cedarjs/cedar.git",
|
|
7
|
+
"directory": "packages/api"
|
|
8
|
+
},
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"type": "module",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"import": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"default": "./dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"require": {
|
|
18
|
+
"types": "./dist/cjs/index.d.ts",
|
|
19
|
+
"default": "./dist/cjs/index.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"./package.json": "./package.json",
|
|
23
|
+
"./auth": {
|
|
24
|
+
"import": {
|
|
25
|
+
"types": "./dist/auth/index.d.ts",
|
|
26
|
+
"default": "./dist/auth/index.js"
|
|
27
|
+
},
|
|
28
|
+
"require": {
|
|
29
|
+
"types": "./dist/cjs/auth/index.d.ts",
|
|
30
|
+
"default": "./dist/cjs/auth/index.js"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"./cache": {
|
|
34
|
+
"import": {
|
|
35
|
+
"types": "./dist/cache/index.d.ts",
|
|
36
|
+
"default": "./dist/cache/index.js"
|
|
37
|
+
},
|
|
38
|
+
"require": {
|
|
39
|
+
"types": "./dist/cjs/cache/index.d.ts",
|
|
40
|
+
"default": "./dist/cjs/cache/index.js"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"./logger": {
|
|
44
|
+
"import": {
|
|
45
|
+
"types": "./dist/logger/index.d.ts",
|
|
46
|
+
"default": "./dist/logger/index.js"
|
|
47
|
+
},
|
|
48
|
+
"require": {
|
|
49
|
+
"types": "./dist/cjs/logger/index.d.ts",
|
|
50
|
+
"default": "./dist/cjs/logger/index.js"
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"./webhooks": {
|
|
54
|
+
"import": {
|
|
55
|
+
"types": "./dist/webhooks/index.d.ts",
|
|
56
|
+
"default": "./dist/webhooks/index.js"
|
|
57
|
+
},
|
|
58
|
+
"require": {
|
|
59
|
+
"types": "./dist/cjs/webhooks/index.d.ts",
|
|
60
|
+
"default": "./dist/cjs/webhooks/index.js"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"main": "./dist/index.js",
|
|
65
|
+
"types": "./dist/index.d.ts",
|
|
66
|
+
"bin": {
|
|
67
|
+
"redwood": "./dist/cjs/bins/redwood.js",
|
|
68
|
+
"rw": "./dist/cjs/bins/redwood.js",
|
|
69
|
+
"rwfw": "./dist/cjs/bins/rwfw.js",
|
|
70
|
+
"tsc": "./dist/cjs/bins/tsc.js"
|
|
71
|
+
},
|
|
72
|
+
"files": [
|
|
73
|
+
"dist/",
|
|
74
|
+
"package.json"
|
|
75
|
+
],
|
|
76
|
+
"scripts": {
|
|
77
|
+
"build": "tsx ./build.mts && yarn build:types",
|
|
78
|
+
"build:pack": "yarn pack -o cedar-api.tgz",
|
|
79
|
+
"build:types": "tsc --build --verbose ./tsconfig.build.json ./tsconfig.cjs.json",
|
|
80
|
+
"build:watch": "nodemon --watch src --ext \"js,jsx,ts,tsx\" --ignore dist --exec \"yarn build\"",
|
|
81
|
+
"check:attw": "yarn rw-fwtools-attw",
|
|
82
|
+
"check:package": "concurrently npm:check:attw yarn:publint",
|
|
83
|
+
"prepublishOnly": "NODE_ENV=production yarn build",
|
|
84
|
+
"test": "vitest run",
|
|
85
|
+
"test:watch": "vitest watch"
|
|
86
|
+
},
|
|
87
|
+
"dependencies": {
|
|
88
|
+
"@prisma/client": "5.20.0",
|
|
89
|
+
"@whatwg-node/fetch": "0.9.21",
|
|
90
|
+
"cookie": "0.7.2",
|
|
91
|
+
"humanize-string": "2.1.0",
|
|
92
|
+
"jsonwebtoken": "9.0.2",
|
|
93
|
+
"pascalcase": "1.0.0",
|
|
94
|
+
"pino": "9.4.0",
|
|
95
|
+
"title-case": "3.0.3"
|
|
96
|
+
},
|
|
97
|
+
"devDependencies": {
|
|
98
|
+
"@cedarjs/framework-tools": "0.0.4",
|
|
99
|
+
"@types/aws-lambda": "8.10.145",
|
|
100
|
+
"@types/jsonwebtoken": "9.0.8",
|
|
101
|
+
"@types/memjs": "1",
|
|
102
|
+
"@types/pascalcase": "1.0.3",
|
|
103
|
+
"@types/split2": "4.2.3",
|
|
104
|
+
"concurrently": "8.2.2",
|
|
105
|
+
"memjs": "1.3.2",
|
|
106
|
+
"publint": "0.3.11",
|
|
107
|
+
"redis": "4.7.0",
|
|
108
|
+
"split2": "4.2.0",
|
|
109
|
+
"ts-toolbelt": "9.6.0",
|
|
110
|
+
"tsx": "4.19.3",
|
|
111
|
+
"typescript": "5.6.2",
|
|
112
|
+
"vitest": "2.1.9"
|
|
113
|
+
},
|
|
114
|
+
"peerDependencies": {
|
|
115
|
+
"memjs": "1.3.2",
|
|
116
|
+
"redis": "4.7.0"
|
|
117
|
+
},
|
|
118
|
+
"peerDependenciesMeta": {
|
|
119
|
+
"memjs": {
|
|
120
|
+
"optional": true
|
|
121
|
+
},
|
|
122
|
+
"redis": {
|
|
123
|
+
"optional": true
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
"publishConfig": {
|
|
127
|
+
"access": "public"
|
|
128
|
+
},
|
|
129
|
+
"gitHead": "5b4f77f985bd86ee31ee7338312627accf0cb85b"
|
|
130
|
+
}
|