@rebilly/instruments 3.29.2 → 3.30.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rebilly/instruments",
3
- "version": "3.29.2",
3
+ "version": "3.30.0",
4
4
  "author": "Rebilly",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -9,6 +9,7 @@
9
9
  "build": "yarn prefetch && yarn rollup -c --environment NODE_ENV:production",
10
10
  "dev": "yarn prefetch && yarn rollup -c --watch --environment NODE_ENV:development",
11
11
  "test": "yarn jest",
12
+ "test:unit": "yarn jest",
12
13
  "test:watch": "yarn jest --watchAll",
13
14
  "prefetch": "node --experimental-modules service/prefetch/prefetch.mjs"
14
15
  },
@@ -18,6 +19,7 @@
18
19
  "@babel/preset-env": "^7.21.5",
19
20
  "@rebilly/risk-data-collector": "*",
20
21
  "@vue/reactivity": "^3.2.39",
22
+ "ajv": "^8.12.0",
21
23
  "jwt-decode": "^3.1.2",
22
24
  "lodash.camelcase": "^4.3.0",
23
25
  "lodash.clonedeep": "^4.5.0",
@@ -39,7 +41,7 @@
39
41
  "component-emitter": "^1.3.0",
40
42
  "core-js": "^3.23.3",
41
43
  "jest": "^29.5.0",
42
- "msw": "0.45.0",
44
+ "msw": "^1.2.1",
43
45
  "msw-when-then": "^1.5.1",
44
46
  "rollup": "^2.35.1",
45
47
  "rollup-plugin-ignore": "^1.0.10",
@@ -0,0 +1,93 @@
1
+ import schema from './schemas/options-schema';
2
+ import AJV from 'ajv/dist/2019';
3
+
4
+ export class RebillyInstrumentsConfigError extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = "Rebilly Instruments Configuration Error";
8
+ }
9
+
10
+ trimStack() {
11
+ Error.captureStackTrace(this, RebillyInstrumentsConfigError)
12
+ return this
13
+ }
14
+ }
15
+
16
+ const ajv = new AJV({
17
+ allErrors: true,
18
+ removeAdditional: true,
19
+ useDefaults: true
20
+ });
21
+ const validate = ajv.compile(schema);
22
+
23
+ export function sanitize(data) {
24
+ // cast data to be only json object
25
+ return JSON.parse(
26
+ JSON.stringify(data)
27
+ )
28
+ }
29
+
30
+ export function validateOptions(data) {
31
+ const sanitizedData = sanitize(data);
32
+ const valid = validate(sanitizedData);
33
+ if (valid) {
34
+ return sanitizedData;
35
+ }
36
+
37
+ validate.errors.forEach(error => {
38
+ let errorMessage = ``;
39
+ let instancePathReadable = error.instancePath.substring(1).replace(/\//gi, '.');
40
+ instancePathReadable = instancePathReadable.replace(/\.\d+/ig, (match) => {
41
+ return `[${match.replace('.', '')}]`;
42
+ });
43
+ if (!instancePathReadable.length) {
44
+ instancePathReadable = 'options'
45
+ }
46
+
47
+ switch(error.keyword) {
48
+ case 'if':
49
+ case 'false schema':
50
+ // ignore keywords
51
+ break;
52
+ case 'required':
53
+ if (error.schemaPath.match(/(oneOf|anyOf)/)) {
54
+ // ignore and allow their oneOf or anyOf keywords to handle error message
55
+ break;
56
+ }
57
+ errorMessage = `${instancePathReadable} ${error.message}`;
58
+ break;
59
+ case 'oneOf':
60
+ case 'anyOf':
61
+ console.error(
62
+ new RebillyInstrumentsConfigError(`${instancePathReadable} ${error.message}, see schemas below.`)
63
+ .trimStack()
64
+ );
65
+ const schemaPath = error.schemaPath.replace('#/', '').split('/');
66
+ let nodes = schema;
67
+ schemaPath.forEach(item => nodes = nodes[item]);
68
+ nodes.forEach(node => {
69
+ const displayNode = JSON.stringify(node, null, 2);
70
+ console.error(`${instancePathReadable} ${error.keyword} schema.\n${displayNode}`, );
71
+ });
72
+ break;
73
+ case 'enum':
74
+ errorMessage = `${instancePathReadable} ${error.message}: ${error.params.allowedValues}. received: ${data[instancePathReadable]}`
75
+ break;
76
+ case 'dependentRequired':
77
+ case 'maxLength':
78
+ case 'minItems':
79
+ case 'pattern':
80
+ errorMessage = `${instancePathReadable} ${error.message}`;
81
+ break;
82
+ default:
83
+ errorMessage = `Error with ${instancePathReadable} - See error message`;
84
+ console.error(error);
85
+ break;
86
+ }
87
+ if (errorMessage) {
88
+ console.error(new RebillyInstrumentsConfigError(errorMessage).trimStack());
89
+ }
90
+ });
91
+
92
+ throw new RebillyInstrumentsConfigError('Configuration is invalid');
93
+ }
@@ -0,0 +1,425 @@
1
+ export default {
2
+ title: 'Mount Options Schema',
3
+ type: 'object',
4
+ properties: {
5
+ form: {
6
+ type: 'string',
7
+ default: '.rebilly-instruments',
8
+ },
9
+ summary: {
10
+ type: 'string',
11
+ default: '.rebilly-instruments-summary',
12
+ },
13
+ apiMode: {
14
+ type: 'string',
15
+ enum: ['sandbox', 'live'],
16
+ },
17
+ publishableKey: {type: 'string',},
18
+ jwt: {type: 'string'},
19
+ websiteId: {type: 'string',},
20
+ organizationId: {type: 'string',},
21
+ items: {
22
+ type: 'array',
23
+ items: {
24
+ type: 'object',
25
+ properties: {
26
+ planId: {type: 'string'},
27
+ thumbnail: {type: 'string'},
28
+ },
29
+ oneOf: [
30
+ {
31
+ properties: {
32
+ quantity: { type: 'number' },
33
+ },
34
+ }, {
35
+ properties: {
36
+ quantity: {
37
+ type: 'object',
38
+ properties: {
39
+ default: {type: 'number'},
40
+ minimum: {type: 'number'},
41
+ maximum: {type: 'number'},
42
+ multipleOf: {type: 'number'}
43
+ }
44
+ }
45
+ }
46
+ }
47
+ ],
48
+ required: ['planId', 'quantity'],
49
+ },
50
+ minItems: 1,
51
+ },
52
+ addons: {
53
+ type: 'array',
54
+ items: {
55
+ type: 'object',
56
+ properties: {
57
+ planId: {type: 'string'},
58
+ quantity: {type: 'number'},
59
+ thumbnail: {type: 'string'},
60
+ },
61
+ required: ['planId', 'quantity']
62
+ },
63
+ default: [],
64
+ },
65
+ bumpOffer: {
66
+ type: 'array',
67
+ items: {
68
+ type: 'object',
69
+ properties: {
70
+ planId: {type: 'string'},
71
+ quantity: {type: 'number'},
72
+ thumbnail: {type: 'string'},
73
+ },
74
+ required: ['planId', 'quantity']
75
+ },
76
+ default: [],
77
+ },
78
+ money: {
79
+ type: 'object',
80
+ properties: {
81
+ amount: {type: 'number'},
82
+ currency: {
83
+ type: 'string',
84
+ minLength: 3,
85
+ maxLength: 3,
86
+ },
87
+ },
88
+ required: ['amount', 'currency'],
89
+ },
90
+ invoiceId: {type: 'string'},
91
+ transactionId: {type: 'string'},
92
+ deposit: {
93
+ oneOf: [
94
+ {
95
+ type: 'object',
96
+ properties: {
97
+ depositRequestId: {type: 'string'},
98
+ },
99
+ required: ['depositRequestId']
100
+ }, {
101
+ type: 'object',
102
+ properties: {
103
+ currency: {
104
+ type: 'string',
105
+ minLength: 3,
106
+ maxLength: 3,
107
+ },
108
+ amount: {type: 'number'},
109
+ buttons: {
110
+ type: 'array',
111
+ items: {
112
+ type: 'number'
113
+ }
114
+ },
115
+ editable: {type: 'boolean'},
116
+ customAmount: {
117
+ type: 'object',
118
+ properties: {
119
+ minimum: {type: 'number'},
120
+ maximum: {type: 'number'},
121
+ increment: {type: 'number'}
122
+ },
123
+ }
124
+ },
125
+ required: ['currency']
126
+ }
127
+ ]
128
+ },
129
+ transactionType: {
130
+ type: 'string',
131
+ enum: ['purchase', 'setup'],
132
+ default: 'purchase',
133
+ },
134
+ css: {type: 'string'},
135
+ theme: {
136
+ type: 'object',
137
+ properties: {
138
+ labels: {
139
+ type: 'string',
140
+ enum: ['stacked', 'floating'],
141
+ default: 'stacked'
142
+ },
143
+ // TODO: split file add schema for all tokens
144
+ },
145
+ default: {},
146
+ },
147
+ countryCode: {
148
+ type: 'string',
149
+ default: 'US',
150
+ },
151
+ locale: {
152
+ type: 'string',
153
+ default: 'auto',
154
+ },
155
+ i18n: {
156
+ type: 'object',
157
+ patternProperties: {
158
+ "^[a-z]{2}(-[A-Z]{2})?$": {
159
+ type: "object",
160
+ properties: {
161
+ // TODO: split file add schema for all translation keys
162
+ summary: {type: 'object'},
163
+ form: {type: 'object'},
164
+ confirmation: {type: 'object'},
165
+ result: {type: 'object'},
166
+ validations: {type: 'object'},
167
+ paymentMethods: {type: 'object'},
168
+ }
169
+ },
170
+ }
171
+ },
172
+ paymentInstruments: {
173
+ type: 'object',
174
+ properties: {
175
+ compactExpressInstruments: {
176
+ type: 'boolean',
177
+ default: false
178
+ },
179
+ address: {
180
+ type: 'object',
181
+ properties: {
182
+ name: {
183
+ type: 'string',
184
+ enum: ['default', 'combined', 'stacked'],
185
+ default: 'default',
186
+ },
187
+ region: {
188
+ type: 'string',
189
+ enum: ['default', 'split', 'stacked'],
190
+ default: 'default',
191
+ },
192
+ show: {
193
+ type: 'array',
194
+ default: [],
195
+ items: {
196
+ type: 'string',
197
+ enum: ['email', 'organization', 'phoneNumber', 'city', 'country', 'region', 'postalCode']
198
+ }
199
+ },
200
+ hide: {
201
+ type: 'array',
202
+ default: [],
203
+ items: {
204
+ type: 'string',
205
+ enum: ['address2']
206
+ }
207
+ },
208
+ require: {
209
+ type: 'array',
210
+ default: [],
211
+ items: {
212
+ type: 'string',
213
+ enum: [
214
+ 'organization',
215
+ 'email',
216
+ 'phoneNumber',
217
+ 'address',
218
+ 'address2',
219
+ 'city',
220
+ 'country',
221
+ 'region',
222
+ 'postalCode'
223
+ ]
224
+ }
225
+ },
226
+ },
227
+ default: {},
228
+ },
229
+ paypal: {
230
+ type: 'object',
231
+ properties: {
232
+ buttonHeight: {
233
+ type: 'number',
234
+ default: 48
235
+ },
236
+ },
237
+ default: {}
238
+ },
239
+ googlePay: {
240
+ type: 'object',
241
+ properties: {
242
+ displayOptions: {
243
+ type: 'object',
244
+ properties: {
245
+ buttonColor: {
246
+ type: 'string',
247
+ enum: ['black', 'white'],
248
+ default: 'black',
249
+ },
250
+ buttonHeight: {
251
+ type: 'string',
252
+ pattern: '^[0-9]+px$',
253
+ default: '48px',
254
+ },
255
+ buttonType: {
256
+ type: 'string',
257
+ enum: ['book', 'buy', 'checkout', 'donate', 'order', 'pay', 'plain', 'subscribe'],
258
+ default: 'plain',
259
+ }
260
+ },
261
+ default: {},
262
+ }
263
+ },
264
+ default: {},
265
+ },
266
+ applePay: {
267
+ type: 'object',
268
+ properties: {
269
+ displayOptions: {
270
+ type: 'object',
271
+ properties: {
272
+ buttonColor: {
273
+ type: 'string',
274
+ enum: ['black', 'white', 'white-outline'],
275
+ default: 'black',
276
+ },
277
+ buttonHeight: {
278
+ type: 'string',
279
+ pattern: '^[0-9]+px$',
280
+ default: '48px',
281
+ },
282
+ buttonType: {
283
+ type: 'string',
284
+ enum: [
285
+ 'add-money',
286
+ 'book',
287
+ 'buy',
288
+ 'check-out',
289
+ 'continue',
290
+ 'contribute',
291
+ 'donate',
292
+ 'order',
293
+ 'pay',
294
+ 'plain',
295
+ 'reload',
296
+ 'rent',
297
+ 'set-up',
298
+ 'subscribe',
299
+ 'support',
300
+ 'tip',
301
+ 'top-up'
302
+ ],
303
+ default: 'plain',
304
+ }
305
+ },
306
+ default: {},
307
+ }
308
+ },
309
+ default: {},
310
+ },
311
+ paymentCard: {
312
+ type: 'object',
313
+ properties: {
314
+ popup: {
315
+ type: 'boolean',
316
+ default: false,
317
+ },
318
+ },
319
+ default: {},
320
+ },
321
+ },
322
+ default: {},
323
+ },
324
+ features: {
325
+ type: 'object',
326
+ properties: {
327
+ autoConfirmation: {
328
+ type: 'boolean',
329
+ default: true,
330
+ },
331
+ autoResult: {
332
+ type: 'boolean',
333
+ default: true,
334
+ },
335
+ showCoupons: {
336
+ type: 'array',
337
+ items: {
338
+ type: 'string',
339
+ enum: ['summary', 'confirmation']
340
+ }
341
+ }
342
+ },
343
+ default: {},
344
+ },
345
+ _dev: {
346
+ type: 'object',
347
+ properties: {
348
+ paymentMethodsUrl: {
349
+ type: 'string',
350
+ default: 'https://forms.local.rebilly.dev:3000',
351
+ },
352
+ liveUrl: {type: 'string'},
353
+ sandboxUrl: {type: 'string'},
354
+ framePayScriptLink: {type: 'string'},
355
+ framePayStyleLink: {type: 'string'},
356
+ },
357
+ }
358
+ },
359
+ required: ['apiMode'],
360
+ dependentRequired: {
361
+ invoiceId: ['jwt'],
362
+ transactionId: ['jwt'],
363
+ deposit: ['jwt'],
364
+ },
365
+ anyOf: [
366
+ {
367
+ if: {required: ['items']},
368
+ then: {
369
+ properties: {
370
+ transactionId: false,
371
+ invoiceId: false,
372
+ deposit: false,
373
+ money: false,
374
+ }
375
+ },
376
+ else: false
377
+ }, {
378
+ if: {required: ['money']},
379
+ then: {
380
+ properties: {
381
+ transactionId: false,
382
+ invoiceId: false,
383
+ deposit: false,
384
+ items: false,
385
+ }
386
+ },
387
+ else: false
388
+ }, {
389
+ if: {required: ['transactionId']},
390
+ then: {
391
+ properties: {
392
+ invoiceId: false,
393
+ deposit: false,
394
+ items: false,
395
+ money: false,
396
+ }
397
+ },
398
+ else: false
399
+ },{
400
+ if: {required: ['invoiceId']},
401
+ then: {
402
+ properties: {
403
+ transactionId: false,
404
+ deposit: false,
405
+ items: false,
406
+ money: false,
407
+ }
408
+ },
409
+ else: false
410
+ }, {
411
+ if: {required: ['deposit']},
412
+ then: {
413
+ properties: {
414
+ invoiceId: false,
415
+ transactionId: false,
416
+ items: false,
417
+ money: false,
418
+ }
419
+ },
420
+ else: false
421
+ }, {
422
+ required: ['jwt']
423
+ }
424
+ ]
425
+ }