@xsolla/payment-client-core 0.1.2 → 0.1.3

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 (51) hide show
  1. package/esm2020/lib/core/payment/actions/next-action.interface.mjs +1 -1
  2. package/esm2020/lib/core/payment/actions/next-actions.mjs +1 -3
  3. package/esm2020/lib/core/payment/actions/show-fields/show-fields.action.token.mjs +3 -2
  4. package/esm2020/lib/core/payment/form/converters/converter.abstract.mjs +8 -6
  5. package/esm2020/lib/core/payment/form/converters/email.converter.mjs +3 -3
  6. package/esm2020/lib/core/payment/form/converters/zip.converter.mjs +4 -5
  7. package/esm2020/lib/core/payment/form/field-status.interface.mjs +2 -0
  8. package/esm2020/lib/core/payment/form/form-fields-status.interface.mjs +2 -0
  9. package/esm2020/lib/core/payment/form/input-event.enum.mjs +6 -0
  10. package/esm2020/lib/core/payment/form/validators/async-validator-fn.type.mjs +2 -0
  11. package/esm2020/lib/core/payment/form/validators/convert.function.mjs +6 -14
  12. package/esm2020/lib/core/payment/form/validators/email-validator.mjs +3 -4
  13. package/esm2020/lib/core/payment/form/validators/required-validator.mjs +3 -4
  14. package/esm2020/lib/core/payment/form/validators/validation-error.interface.mjs +1 -1
  15. package/esm2020/lib/core/payment/payment.interface.mjs +1 -1
  16. package/esm2020/lib/core/payment/payment.service.mjs +35 -40
  17. package/esm2020/lib/core/payment/sync/sync-response.class.mjs +7 -4
  18. package/esm2020/lib/core/payment/sync/sync.service.mjs +4 -10
  19. package/esm2020/lib/core-library.service.mjs +3 -4
  20. package/fesm2015/xsolla-payment-client-core.mjs +65 -110
  21. package/fesm2015/xsolla-payment-client-core.mjs.map +1 -1
  22. package/fesm2020/xsolla-payment-client-core.mjs +65 -109
  23. package/fesm2020/xsolla-payment-client-core.mjs.map +1 -1
  24. package/lib/core/payment/actions/next-action.interface.d.ts +1 -2
  25. package/lib/core/payment/form/converters/converter.abstract.d.ts +4 -1
  26. package/lib/core/payment/form/converters/email.converter.d.ts +1 -1
  27. package/lib/core/payment/form/field-status.interface.d.ts +7 -0
  28. package/lib/core/payment/form/form-fields-status.interface.d.ts +4 -0
  29. package/lib/core/payment/form/validators/async-validator-fn.type.d.ts +4 -0
  30. package/lib/core/payment/form/validators/convert.function.d.ts +1 -1
  31. package/lib/core/payment/form/validators/email-validator.d.ts +1 -1
  32. package/lib/core/payment/form/validators/required-validator.d.ts +1 -1
  33. package/lib/core/payment/form/validators/validation-error.interface.d.ts +0 -1
  34. package/lib/core/payment/payment.interface.d.ts +3 -1
  35. package/lib/core/payment/payment.service.d.ts +8 -3
  36. package/lib/core/payment/sync/sync-response.class.d.ts +2 -4
  37. package/package.json +1 -1
  38. package/xsolla-payment-client-core-0.1.3.tgz +0 -0
  39. package/esm2020/lib/core/payment/actions/show-field-state/show-field-state.action.class.mjs +0 -12
  40. package/esm2020/lib/core/payment/actions/show-field-state/show-field-state.action.token.mjs +0 -13
  41. package/esm2020/lib/core/payment/actions/show-field-state/show-field-state.action.type.mjs +0 -2
  42. package/esm2020/lib/core/payment/form/input-events.enum.mjs +0 -6
  43. package/esm2020/lib/core/payment/form/validators/errors-codes.enum.mjs +0 -8
  44. package/esm2020/lib/core/payment/show-field-state.interface.mjs +0 -2
  45. package/lib/core/payment/actions/show-field-state/show-field-state.action.class.d.ts +0 -8
  46. package/lib/core/payment/actions/show-field-state/show-field-state.action.token.d.ts +0 -4
  47. package/lib/core/payment/actions/show-field-state/show-field-state.action.type.d.ts +0 -11
  48. package/lib/core/payment/form/validators/errors-codes.enum.d.ts +0 -6
  49. package/lib/core/payment/show-field-state.interface.d.ts +0 -8
  50. package/xsolla-payment-client-core-0.1.2.tgz +0 -0
  51. /package/lib/core/payment/form/{input-events.enum.d.ts → input-event.enum.d.ts} +0 -0
@@ -1,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { InjectionToken, Injectable, Inject, isDevMode, NgModule } from '@angular/core';
3
- import { firstValueFrom, lastValueFrom, map, Subject, tap, BehaviorSubject, filter as filter$1, takeUntil, skip, distinctUntilChanged, throwError } from 'rxjs';
3
+ import { firstValueFrom, lastValueFrom, map, Subject, tap, BehaviorSubject, filter as filter$1, takeUntil, skip, throwError } from 'rxjs';
4
4
  import * as i1 from '@angular/common/http';
5
5
  import { HttpParams, HttpHeaders, HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
6
6
  import { UntypedFormGroup, Validators, UntypedFormControl, ReactiveFormsModule } from '@angular/forms';
@@ -573,18 +573,6 @@ const isSubmitResponse = (value) => {
573
573
  return value instanceof SubmitResponse;
574
574
  };
575
575
 
576
- class ShowFieldStateAction {
577
- constructor(control) {
578
- this.type = 'show_field_state';
579
- this.data = {
580
- fieldName: control.fieldName,
581
- fieldState: control.fieldState,
582
- error: control.error,
583
- isFocused: control.isFocused,
584
- };
585
- }
586
- }
587
-
588
576
  var InputEventName;
589
577
  (function (InputEventName) {
590
578
  InputEventName["blur"] = "blur";
@@ -671,7 +659,8 @@ const showFieldsActionFactoryProvider = {
671
659
  useValue: {
672
660
  factory: (...args) => new ShowFieldsAction(...args),
673
661
  isSuitable: (response) => {
674
- return response.currentCommand === XpsCommand.check;
662
+ return (response.currentCommand === XpsCommand.check ||
663
+ response.currentCommand === XpsCommand.form);
675
664
  },
676
665
  },
677
666
  };
@@ -769,17 +758,6 @@ const showErrorsActionFactoryProvider = {
769
758
  },
770
759
  };
771
760
 
772
- const showFieldStateActionFactoryToken = new InjectionToken('ShowFieldStateAction');
773
- const showFieldStateActionFactoryProvider = {
774
- provide: showFieldStateActionFactoryToken,
775
- useValue: {
776
- factory: (...args) => new ShowFieldStateAction(...args),
777
- isSuitable: () => {
778
- return true;
779
- },
780
- },
781
- };
782
-
783
761
  const nextActionsToken = new InjectionToken('Action');
784
762
  const nextActions = [
785
763
  showFieldsActionFactoryProvider,
@@ -789,7 +767,6 @@ const nextActions = [
789
767
  const flowUpdateNextActions = [
790
768
  statusUpdatedActionFactoryProvider,
791
769
  showErrorsActionFactoryProvider,
792
- showFieldStateActionFactoryProvider,
793
770
  ];
794
771
 
795
772
  class NextActionService {
@@ -1217,11 +1194,14 @@ const syncRequestFactoryProvider = {
1217
1194
 
1218
1195
  class SyncResponse {
1219
1196
  constructor(changedField, response) {
1197
+ this.error = null;
1220
1198
  const fieldError = response?.errors?.find((error) => error.element_name === changedField.name);
1221
1199
  if (fieldError) {
1222
- this.rewritableError = {
1223
- code: fieldError.code,
1224
- message: fieldError.message,
1200
+ this.error = {
1201
+ asyncError: {
1202
+ code: fieldError.code,
1203
+ message: fieldError.message,
1204
+ },
1225
1205
  };
1226
1206
  }
1227
1207
  this.fields = Object.keys(response.form).map((key) => response.form[key]);
@@ -1271,24 +1251,18 @@ class SyncService extends EmitDataService {
1271
1251
  }
1272
1252
  if (prevFieldState && value === prevFieldState.value) {
1273
1253
  return Promise.resolve(prevFieldState.result).then((response) => {
1274
- return response?.rewritableError ?? null;
1254
+ return response?.error ?? null;
1275
1255
  });
1276
1256
  }
1277
1257
  const requestPromise = this.request(field);
1278
1258
  this.setPrevFieldSyncState(field, value, requestPromise);
1279
1259
  return requestPromise.then((response) => {
1280
- return response.rewritableError ?? null;
1260
+ return response.error ?? null;
1281
1261
  });
1282
1262
  }
1283
1263
  getSyncValidationErrors(field) {
1284
1264
  const control = this.form.get(field.name);
1285
- if (!control) {
1286
- return null;
1287
- }
1288
- const rewritableError = control.errors?.rewritableError;
1289
- return rewritableError
1290
- ? { message: rewritableError.message, code: rewritableError.code }
1291
- : null;
1265
+ return control?.errors ?? null;
1292
1266
  }
1293
1267
  async request(field) {
1294
1268
  const requestParams = this.requestFactory({
@@ -1348,44 +1322,28 @@ class TextControlConfig extends ControlConfig {
1348
1322
  }
1349
1323
  }
1350
1324
 
1351
- function convert(validator, message, errorCode) {
1325
+ function convert(validator, message) {
1352
1326
  return (control) => {
1353
1327
  const errors = validator(control);
1354
1328
  if (!errors) {
1355
1329
  return errors;
1356
1330
  }
1357
1331
  const firstErrorKey = Object.keys(errors)[0];
1358
- let error = errors[firstErrorKey];
1359
- error = typeof error === 'object' && error !== null ? error : {};
1360
- const rewritableError = { ...error };
1361
- rewritableError.message = message;
1362
- rewritableError.code = errorCode;
1363
- if (error[firstErrorKey] != null) {
1364
- rewritableError.value = error[firstErrorKey];
1365
- }
1366
- if (rewritableError.requiredLength) {
1367
- rewritableError.number = rewritableError.requiredLength;
1368
- }
1369
- errors.rewritableError = rewritableError;
1332
+ const firstError = errors[firstErrorKey];
1333
+ const error = typeof firstError === 'object' && firstError !== null ? firstError : {};
1334
+ error.message = message;
1335
+ errors[firstErrorKey] = error;
1370
1336
  return errors;
1371
1337
  };
1372
1338
  }
1373
1339
 
1374
- var ErrorsCodes;
1375
- (function (ErrorsCodes) {
1376
- ErrorsCodes["minLength"] = "min-length";
1377
- ErrorsCodes["maxLength"] = "max-length";
1378
- ErrorsCodes["invalidValue"] = "invalid-value";
1379
- ErrorsCodes["required"] = "required";
1380
- })(ErrorsCodes || (ErrorsCodes = {}));
1381
-
1382
1340
  const emailRegexp = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i; // eslint-disable-line
1383
- function emailValidator() {
1384
- return convert(Validators.pattern(emailRegexp), 'Enter a valid email', ErrorsCodes.invalidValue);
1341
+ function convertedEmailValidator() {
1342
+ return convert(Validators.pattern(emailRegexp), 'Enter a valid email');
1385
1343
  }
1386
1344
 
1387
- function requiredValidator() {
1388
- return convert(Validators.required, 'Required', ErrorsCodes.required);
1345
+ function convertedRequiredValidator() {
1346
+ return convert(Validators.required, 'Required');
1389
1347
  }
1390
1348
 
1391
1349
  class Converter {
@@ -1400,12 +1358,12 @@ class Converter {
1400
1358
  return config;
1401
1359
  }
1402
1360
  convertToFormControl(field) {
1403
- return new UntypedFormControl(this.getValue(field), this.getValidators(field));
1361
+ return new UntypedFormControl(this.getValue(field), this.getValidators(field), this.getAsyncValidators(field));
1404
1362
  }
1405
1363
  getValidators(field) {
1406
1364
  const validators = [];
1407
1365
  if (field.isMandatory === "1" /* XpsBoolean.true */) {
1408
- validators.push(requiredValidator());
1366
+ validators.push(convertedRequiredValidator());
1409
1367
  }
1410
1368
  if (field.regex) {
1411
1369
  const match = /^\/(.*)\/([gim]*)$/.exec(field.regex);
@@ -1414,11 +1372,14 @@ class Converter {
1414
1372
  const errorMessage = field.validation_error_msg
1415
1373
  ? field.validation_error_msg
1416
1374
  : 'Enter valid data';
1417
- validators.push(convert(Validators.pattern(pattern), errorMessage, ErrorsCodes.invalidValue));
1375
+ validators.push(convert(Validators.pattern(pattern), errorMessage));
1418
1376
  }
1419
1377
  }
1420
1378
  return validators;
1421
1379
  }
1380
+ getAsyncValidators(field) {
1381
+ return async () => this.syncService.validate(field);
1382
+ }
1422
1383
  createDefaultControlConfig(controlConfigClass, field) {
1423
1384
  const config = new controlConfigClass();
1424
1385
  this.copyCommonOptions(config, field);
@@ -1462,7 +1423,7 @@ class EmailConverter extends Converter {
1462
1423
  super(syncService);
1463
1424
  }
1464
1425
  getValidators(field) {
1465
- return super.getValidators(field).concat([emailValidator()]);
1426
+ return super.getValidators(field).concat([convertedEmailValidator()]);
1466
1427
  }
1467
1428
  createControlConfig(field) {
1468
1429
  const config = this.createDefaultControlConfig(TextControlConfig, field);
@@ -1503,11 +1464,11 @@ class ZipConverter extends Converter {
1503
1464
  const validators = super
1504
1465
  .getValidators(field)
1505
1466
  .concat([
1506
- convert(Validators.minLength(minLength), `Enter at least ${minLength} characters`, ErrorsCodes.minLength),
1507
- convert(Validators.maxLength(maxLength), `Enter no more than ${maxLength} characters`, ErrorsCodes.maxLength),
1467
+ convert(Validators.minLength(minLength), `Enter at least ${minLength} characters`),
1468
+ convert(Validators.maxLength(maxLength), `Enter no more than ${maxLength} characters`),
1508
1469
  ]);
1509
1470
  if (this.isUsCountry) {
1510
- validators.push(convert(restrictedValueValidator('00000'), 'Enter a valid ZIP code', ErrorsCodes.invalidValue));
1471
+ validators.push(convert(restrictedValueValidator('00000'), 'Enter a valid ZIP code'));
1511
1472
  }
1512
1473
  return validators;
1513
1474
  }
@@ -3008,6 +2969,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.7", ngImpor
3008
2969
  }] }]; } });
3009
2970
 
3010
2971
  class PaymentService {
2972
+ get formFieldsStatus$() {
2973
+ return this.formFieldsStatusSubject.asObservable().pipe(filter$1(Boolean));
2974
+ }
3011
2975
  constructor(initializeService, submitService, syncService, formService, statusService, financeDetailsService, nextActionService, controlConfigService) {
3012
2976
  this.initializeService = initializeService;
3013
2977
  this.submitService = submitService;
@@ -3020,9 +2984,11 @@ class PaymentService {
3020
2984
  this.form = null;
3021
2985
  this.data = null;
3022
2986
  this.financeDetails = null;
2987
+ this.focusFieldName = null;
3023
2988
  this.fields = [];
3024
2989
  this.destroy$ = new Subject();
3025
2990
  this.formDestroy$ = new Subject();
2991
+ this.formFieldsStatusSubject = new BehaviorSubject(null);
3026
2992
  }
3027
2993
  async initialize(config) {
3028
2994
  this.destroy$ = new Subject();
@@ -3032,9 +2998,10 @@ class PaymentService {
3032
2998
  this.data = await this.initializeService.request(config);
3033
2999
  this.fields = this.getFields();
3034
3000
  this.form = this.formService.createForm(this.fields);
3035
- this.listenSyncValidationErrors(this.form);
3036
- this.emitFinanceDetails(this.data.paymentForm?.summary);
3037
3001
  this.setupSyncService(this.form, this.fields);
3002
+ this.listenFormStatusChanges(this.form);
3003
+ this.emitFinanceDetails(this.data.paymentForm?.summary);
3004
+ this.emitFormFieldsStatus(this.form);
3038
3005
  return this.fields.filter((field) => field?.isVisible === "1" /* XpsBoolean.true */);
3039
3006
  }
3040
3007
  async submit() {
@@ -3043,13 +3010,7 @@ class PaymentService {
3043
3010
  }
3044
3011
  if (!this.form.valid) {
3045
3012
  this.form.markAllAsTouched();
3046
- Object.keys(this.form.controls).forEach((controlKey) => {
3047
- const control = this.form?.get(controlKey);
3048
- if (control) {
3049
- const controlObject = this.getControlState(controlKey, control);
3050
- this.nextActionService.emitFlowUpdates(new ShowFieldStateAction({ ...controlObject, isFocused: true }));
3051
- }
3052
- });
3013
+ this.emitFormFieldsStatus(this.form);
3053
3014
  return;
3054
3015
  }
3055
3016
  const submitResponse = await this.submitService.request(this.fields, this.form);
@@ -3098,22 +3059,22 @@ class PaymentService {
3098
3059
  }
3099
3060
  changeFieldState(name, state) {
3100
3061
  const formControl = this.form?.get(name);
3101
- if (!formControl) {
3062
+ if (!this.form || !formControl) {
3102
3063
  return;
3103
3064
  }
3104
- const controlObject = this.getControlState(name, formControl);
3105
3065
  switch (state) {
3106
3066
  case InputEventName.blur: {
3107
3067
  formControl.markAsTouched();
3108
- this.nextActionService.emitFlowUpdates(new ShowFieldStateAction({ ...controlObject, isFocused: true }));
3109
- return;
3068
+ this.focusFieldName = null;
3069
+ break;
3110
3070
  }
3111
3071
  case InputEventName.focus: {
3112
3072
  formControl.markAsUntouched();
3113
- this.nextActionService.emitFlowUpdates(new ShowFieldStateAction({ ...controlObject, isFocused: false }));
3114
- return;
3073
+ this.focusFieldName = name;
3074
+ break;
3115
3075
  }
3116
3076
  }
3077
+ this.emitFormFieldsStatus(this.form);
3117
3078
  }
3118
3079
  destroy() {
3119
3080
  this.data = null;
@@ -3126,6 +3087,19 @@ class PaymentService {
3126
3087
  emitFinanceDetails(summary) {
3127
3088
  this.financeDetailsService.emit(summary);
3128
3089
  }
3090
+ emitFormFieldsStatus(form) {
3091
+ const formFieldsStatus = {};
3092
+ Object.keys(form.controls).forEach((name) => {
3093
+ const control = form.controls[name];
3094
+ formFieldsStatus[name] = {
3095
+ name: name,
3096
+ validationStatus: control.status,
3097
+ errors: control.errors,
3098
+ isFocused: this.focusFieldName === name,
3099
+ };
3100
+ });
3101
+ this.formFieldsStatusSubject.next(formFieldsStatus);
3102
+ }
3129
3103
  setupSyncService(form, fields) {
3130
3104
  this.syncService.setup(form, fields);
3131
3105
  this.syncService.data$
@@ -3137,27 +3111,10 @@ class PaymentService {
3137
3111
  .pipe(takeUntil(this.destroy$))
3138
3112
  .subscribe((financeDetails) => (this.financeDetails = financeDetails));
3139
3113
  }
3140
- listenSyncValidationErrors(form) {
3141
- Object.keys(form.controls).forEach((key) => {
3142
- const control = form.get(key);
3143
- if (control) {
3144
- control.statusChanges
3145
- .pipe(distinctUntilChanged(), takeUntil(this.formDestroy$))
3146
- .subscribe((status) => {
3147
- const controlObject = this.getControlState(key, control, status);
3148
- this.nextActionService.emitFlowUpdates(new ShowFieldStateAction(controlObject));
3149
- });
3150
- }
3151
- });
3152
- }
3153
- getControlState(controlName, controlObject, status) {
3154
- const controlError = controlObject.errors?.['rewritableError'] ??
3155
- null;
3156
- return {
3157
- fieldName: controlName,
3158
- fieldState: status ?? controlObject.status,
3159
- error: controlError,
3160
- };
3114
+ listenFormStatusChanges(form) {
3115
+ form.statusChanges
3116
+ .pipe(takeUntil(this.formDestroy$))
3117
+ .subscribe(() => this.emitFormFieldsStatus(form));
3161
3118
  }
3162
3119
  }
3163
3120
  PaymentService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.7", ngImport: i0, type: PaymentService, deps: [{ token: InitializeService }, { token: SubmitService }, { token: SyncService }, { token: FormService }, { token: StatusService }, { token: FinanceDetailsService }, { token: NextActionService }, { token: ControlConfigService }], target: i0.ɵɵFactoryTarget.Injectable });
@@ -3315,11 +3272,10 @@ class CoreLibraryService {
3315
3272
  flowUpdates$: this.nextActionService.flowUpdates$,
3316
3273
  financeDetailsUpdates$: this.financeDetailsService.data$,
3317
3274
  form: {
3275
+ fieldsStatus$: this.paymentService.formFieldsStatus$,
3318
3276
  getControlConfig: (field) => this.paymentService.getFieldConfig(field),
3319
3277
  changeFieldValue: (name, value) => this.paymentService.changeFieldValue(name, value),
3320
- changeFieldState: (name, state) => {
3321
- this.paymentService.changeFieldState(name, state);
3322
- },
3278
+ changeFieldState: (name, state) => this.paymentService.changeFieldState(name, state),
3323
3279
  },
3324
3280
  };
3325
3281
  }