@bolttech/form-engine-core 1.0.10 → 1.1.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 (64) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/credit-card.d.ts +743 -0
  3. package/credit-card.esm.js +1 -0
  4. package/currency.d.ts +131 -0
  5. package/currency.esm.js +1 -0
  6. package/date.d.ts +582 -0
  7. package/date.esm.js +1 -0
  8. package/document.d.ts +527 -0
  9. package/document.esm.js +1 -0
  10. package/index.d.ts +52 -5
  11. package/index.esm.js +1 -4570
  12. package/lite.d.ts +2393 -0
  13. package/lite.esm.js +1 -0
  14. package/package.json +34 -2
  15. package/src/constants/constants.d.ts +11 -0
  16. package/src/formatters/creditCard.d.ts +23 -0
  17. package/src/formatters/custom.d.ts +29 -0
  18. package/src/formatters/handler.d.ts +2 -0
  19. package/src/formatters/regex.d.ts +47 -0
  20. package/src/formatters/splitter.d.ts +17 -0
  21. package/src/formatters/string.d.ts +88 -0
  22. package/src/helpers/SafeSubject.d.ts +21 -0
  23. package/src/helpers/creditCard.d.ts +95 -0
  24. package/src/helpers/helpers.d.ts +66 -0
  25. package/src/helpers/lodash-replacements.d.ts +41 -0
  26. package/src/helpers/validation.d.ts +28 -0
  27. package/src/index.d.ts +15 -0
  28. package/src/interfaces/schema.d.ts +161 -0
  29. package/src/interfaces/state.d.ts +22 -0
  30. package/src/lite.d.ts +30 -0
  31. package/src/managers/field.d.ts +339 -0
  32. package/src/managers/form.d.ts +357 -0
  33. package/src/managers/formGroup.d.ts +110 -0
  34. package/src/managers/index.d.ts +3 -0
  35. package/src/masks/creditCard.d.ts +60 -0
  36. package/src/masks/currency.d.ts +29 -0
  37. package/src/masks/generic.d.ts +39 -0
  38. package/src/masks/handler.d.ts +2 -0
  39. package/src/masks/string.d.ts +37 -0
  40. package/src/plugins/credit-card.d.ts +4 -0
  41. package/src/plugins/currency.d.ts +2 -0
  42. package/src/plugins/date.d.ts +2 -0
  43. package/src/plugins/document.d.ts +2 -0
  44. package/src/registry.d.ts +20 -0
  45. package/src/types/event.d.ts +175 -0
  46. package/src/types/form.d.ts +55 -0
  47. package/src/types/mapper.d.ts +87 -0
  48. package/src/types/schema.d.ts +1001 -0
  49. package/src/types/template.d.ts +65 -0
  50. package/src/types/utility.d.ts +12 -0
  51. package/src/validations/creditCard.d.ts +52 -0
  52. package/src/validations/custom.d.ts +27 -0
  53. package/src/validations/date.d.ts +79 -0
  54. package/src/validations/document.d.ts +25 -0
  55. package/src/validations/handler.d.ts +2 -0
  56. package/src/validations/length.d.ts +39 -0
  57. package/src/validations/list.d.ts +32 -0
  58. package/src/validations/logical.d.ts +75 -0
  59. package/src/validations/multiple.d.ts +31 -0
  60. package/src/validations/namedRule.d.ts +22 -0
  61. package/src/validations/number.d.ts +145 -0
  62. package/src/validations/object.d.ts +44 -0
  63. package/src/validations/regex.d.ts +217 -0
  64. package/src/validations/string.d.ts +53 -0
package/lite.esm.js ADDED
@@ -0,0 +1 @@
1
+ import{BehaviorSubject as e,Subject as t,Subscription as i,groupBy as s,mergeMap as a,debounceTime as n,filter as r,combineLatest as l,startWith as o,map as u,distinctUntilKeyChanged as d}from"rxjs";var h;function c(e,t,i,s){return new(i||(i=Promise))(function(a,n){function r(e){try{o(s.next(e))}catch(e){n(e)}}function l(e){try{o(s.throw(e))}catch(e){n(e)}}function o(e){var t;e.done?a(e.value):(t=e.value,t instanceof i?t:new i(function(e){e(t)})).then(r,l)}o((s=s.apply(e,t||[])).next())})}!function(e){e.ON_VALUE="value",e.ON_PROPS="props",e.ON_VISIBILITY="visibility",e.ON_API="api",e.ON_IVARS="iVars",e.ON_FIELDS="fields"}(h||(h={})),"function"==typeof SuppressedError&&SuppressedError;const v=1e3,f=/^\$\{(?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})*\}$/,p=/\$\{((?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})*)\}/g,m=/\s*(\|\||&&|!+)\s*/g,b=/^\|\||&&|!+$/,S=["fields","iVars","form"],y=["api","apiSchema","props","validations","visibilityConditions","resetValues"],g=!1;function V(e){const t=p,i=[];let s;for(;null!==(s=t.exec(e));)i.push(s[1]);const a=m,n=i.map(e=>e.split(a).filter(e=>!a.test(e))).flat().filter(e=>e.split(".").length>1);return{originScopeKeys:Array.from(new Set(n.map(e=>e.split(".")[0]))),originFieldKeys:Array.from(new Set(n.map(e=>e.split(".")[1]))),originPropertyKeys:Array.from(new Set(n.map(e=>e.split(".")[2])))}}function $(e,t){const i=[];if(Array.isArray(e))e.forEach((e,s)=>{i.push(...$(e,`${t?`${t}.`:""}${s}`))});else if("object"==typeof e)for(const s in e)Object.prototype.hasOwnProperty.call(e,s)&&i.push(...$(e[s],`${t?`${t}.`:""}${s}`));else if("string"==typeof e&&e.includes("${")){const s=(t||"").split(".");V(e).originScopeKeys.every(e=>S.includes(e))?i.push(Object.assign(Object.assign({originExpression:e},V(e)),{destinationKey:s[0],destinationProperty:s[1],destinationPath:s.slice(2)})):console.warn(`scope malformed on this expression: ${e}, ignoring..`)}return i}const j={},E={},O={};function I(e){Object.assign(j,e)}function x(e){Object.assign(E,e)}function _(e){Object.assign(O,e)}function k(e){if(null===e||"object"!=typeof e)return e;if(e instanceof Date)return new Date(e.getTime());if(Array.isArray(e))return e.map(e=>k(e));const t={};for(const i in e)Object.prototype.hasOwnProperty.call(e,i)&&(t[i]=k(e[i]));return t}function F(e,t,i){if(null==e)return i;const s=Array.isArray(t)?t:t.split(".");let a=e;for(let e=0;e<s.length;e++){if(null==a)return i;a=a[s[e]]}return void 0===a?i:a}function N(e,t,i){if(null==e||"object"!=typeof e)return e;const s=Array.isArray(t)?t:t.split(".");let a=e;for(let e=0;e<s.length-1;e++){const t=s[e],i=s[e+1];null!=a[t]&&"object"==typeof a[t]||(a[t]="number"==typeof i||/^\d+$/.test(String(i))?[]:{}),a=a[t]}return a[s[s.length-1]]=i,e}function P(e,t){if(e===t)return!0;if(null==e||null==t)return e===t;if(typeof e!=typeof t)return!1;if(e instanceof Date&&t instanceof Date)return e.getTime()===t.getTime();if("object"!=typeof e)return!1;const i=Array.isArray(e);if(i!==Array.isArray(t))return!1;if(i){if(e.length!==t.length)return!1;for(let i=0;i<e.length;i++)if(!P(e[i],t[i]))return!1;return!0}const s=Object.keys(e),a=Object.keys(t);if(s.length!==a.length)return!1;for(const i of s){if(!Object.prototype.hasOwnProperty.call(t,i))return!1;if(!P(e[i],t[i]))return!1}return!0}function w(e){return null==e}class T extends t{constructor(e){super(),this.isMounted=e}next(e){this.isMounted()&&super.next(e)}}class A extends e{constructor(e){super(e),this.defaultValue=e}next(e){this.closed||super.next(e)}get value(){return this.closed?this.defaultValue:super.value}}function R(e,t,i,s,a){return function(e){return"function"==typeof e}(i[s])?i[s](e,t,a):((e,t,i)=>!!t&&function(e,t,i){const s=[];return Object.keys(t).forEach(a=>{s.push(i[a](e,{[a]:t[a]}))}),s}(e,t,i).some(e=>e))(e,t[s],i)}class M{constructor({formIndex:e,schemaComponent:t,config:s,children:a,validateVisibility:n,resetValue:r,resetProperty:l,templateSubject$:o,fieldEventSubject$:u,dataSubject$:d,fieldValidNotification$:h,mountSubject$:c,mapper:f,formValuesStateSubject$:p,submitEvent:m,visibility:b,persistValue:S}){var y,V,$,j,E,O;this.valueSubscription$=new i,this.fieldStateSubscription$=new i,this.formIndex=e,this.originalSchema=k(t),this.config={defaultAPIdebounceTimeMS:Number(null==s?void 0:s.defaultAPIdebounceTimeMS)?Number(null==s?void 0:s.defaultAPIdebounceTimeMS):v,defaultStateRefreshTimeMS:Number(null==s?void 0:s.defaultStateRefreshTimeMS)?Number(null==s?void 0:s.defaultStateRefreshTimeMS):100,defaultLogVerbose:(null==s?void 0:s.defaultLogVerbose)?s.defaultLogVerbose:g},this.name=t.name,this.nameToSubmit=t.nameToSubmit,this.component=t.component,this.children=a,this.validations=k(t.validations),this.visibilityConditions=k(t.visibilityConditions),this.resetValues=k(t.resetValues),this.resetPropertyValues=k(t.resetPropertyValues),this.apiSchema=k(t.api),this.formatters=k(t.formatters),this.masks=k(t.masks),f.valueChangeEvent&&(this.valueChangeEvent=f.valueChangeEvent),(null===(y=f.events)||void 0===y?void 0:y.setValue)&&(this.valuePropName=f.events.setValue),this.mapper=f,this.validateVisibility=n,this.resetValue=r,this.resetProperty=l,this.submitEvent=m,this.templateSubject$=o,this.fieldEventSubject$=u,this.dataSubject$=d,this.fieldValidNotification$=h,this.mountSubject$=c,this.formValuesStateSubject$=p,this.getFormValues=()=>this.formValuesStateSubject$.value,this._props=M.filterProps(k(t.props||{})),this._adapterProps=JSON.stringify(t.props||{}),this._metadata="",this.errorsString="",this.errorsList=[],this._visibility="boolean"!=typeof b||b,this._api={default:{response:(null===(j=null===($=null===(V=this.apiSchema)||void 0===V?void 0:V.defaultConfig)||void 0===$?void 0:$.config)||void 0===j?void 0:j.fallbackValue)||"",status:null},named:(null===(E=this.apiSchema)||void 0===E?void 0:E.configs)&&Object.keys(null===(O=this.apiSchema)||void 0===O?void 0:O.configs).reduce((e,t)=>{var i,s;return e[t]={response:(null===(s=null===(i=this.apiSchema)||void 0===i?void 0:i.configs)||void 0===s?void 0:s[t].config.fallbackValue)||"",status:null},e},{}),apiState:{loading:!1}},this._errors={},this._mounted=!1,this.valid=!0,this.persistValue=S,this.initializeObservers()}initializeObservers(){this.valueSubject$&&!this.valueSubject$.closed||(this.valueSubject$=new T(()=>this.mounted)),this.errorSubject$&&!this.errorSubject$.closed||(this.errorSubject$=new T(()=>this.mounted)),this.visibilitySubject$&&!this.visibilitySubject$.closed||(this.visibilitySubject$=new T(()=>this.mounted)),this.propsSubject$&&!this.propsSubject$.closed||(this.propsSubject$=new T(()=>this.mounted)),this.fieldStateSubscription$&&!this.fieldStateSubscription$.closed||(this.fieldStateSubscription$=new i),this.apiEventQueueSubject$&&!this.apiEventQueueSubject$.closed||(this.apiEventQueueSubject$=new T(()=>this.mounted)),this.apiEventQueueSubject$.observed||this.apiEventQueueSubject$.pipe(s(({event:e})=>e),a(e=>e.pipe(n(this.config.defaultAPIdebounceTimeMS))),r(()=>this.apiEventQueueSubject$&&!this.apiEventQueueSubject$.closed)).subscribe(e=>{this.apiRequest(e)})}get adapterProps(){return this._adapterProps}set adapterProps(e){const t=JSON.stringify(e||{});t!==this.adapterProps&&(this.props=M.filterProps(e),this._adapterProps=t)}get props(){return this._props}set props(e){void 0===e||P(e,this.props)||(this._props=e,this.propsSubject$.next(this.props),this.templateSubject$.next({scope:"fields",key:this.name,event:"ON_PROPS"}))}static filterProps(e){return Array.isArray(e)?e.filter(e=>"string"!=typeof e||!e.includes("${")).map(e=>M.filterProps(e)):"object"==typeof e&&null!==e?e instanceof Date?e:Object.keys(e).reduce((t,i)=>{const s=e[i];return"string"==typeof s&&s.includes("${")||(t[i]=M.filterProps(e[i])),t},{}):e}get stateValue(){return this._stateValue}get metadata(){return this._metadata}get value(){return this._value}set value(e){var t,i,s;let a;if(this.valueChangeEvent)try{a=this.valueChangeEvent(e,{props:this.props})}catch(t){a=e}else a=e;null!=a&&("object"==typeof a&&"_value"in a&&"_metadata"in a?(this._value=this.formatValue(a._value),this._stateValue=(null===(t=this.mapper.events)||void 0===t?void 0:t.setValue)?{[this.mapper.events.setValue]:this.maskValue(this.formatValue(a._value))}:{},this._metadata=a._metadata):(this._value=this.formatValue(a),this._stateValue=(null===(i=this.mapper.events)||void 0===i?void 0:i.setValue)?{[null===(s=this.mapper.events)||void 0===s?void 0:s.setValue]:this.maskValue(this.formatValue(a))}:{},this.maskValue(this.formatValue(a)),this._metadata=a),this.stateValue&&this.valueSubject$.next(this.stateValue),this.templateSubject$.next({scope:"fields",key:this.name,event:"ON_VALUE"}))}get visibility(){return this._visibility}set visibility(e){void 0!==e&&e!==this.visibility&&(this._visibility=e,this.visibilitySubject$.next(this.visibility),this.templateSubject$.next({scope:"fields",key:this.name,event:"ON_VISIBILITY"}))}set valid(e){"boolean"!=typeof e&&this.valid===e||(this._valid=e,this.triggerFieldValidNotification())}get valid(){return this._valid}triggerFieldValidNotification(){this.fieldValidNotification$.closed||this.fieldValidNotification$.next({fieldTrigger:this.name})}get errors(){return this._errors}set errors(e){var t;void 0===e||P(e,this.errors)||(this._errors=e,this.errorsList=Object.values(this.errors).filter(e=>null!=e),this.errorsString=this.errorsList.join(", "),(null===(t=this.mapper.events)||void 0===t?void 0:t.setErrorMessage)&&this.errorSubject$.next({[this.mapper.events.setErrorMessage]:this.errorsString}),this.templateSubject$.next({scope:"fields",key:this.name,event:"ON_PROPS"}))}get api(){return this._api}set api(e){void 0!==e&&(this._api=e,this.templateSubject$.next({scope:"fields",key:this.name,event:"ON_API_RESPONSE"}),this.emitEvents({event:"ON_API_FIELD_RESPONSE"}))}notifyApiRequest(){this._api.apiState.loading=!0,this.templateSubject$.next({scope:"fields",key:this.name,event:"ON_API_REQUEST"}),this.emitEvents({event:"ON_API_FIELD_REQUEST"})}get mounted(){return this._mounted}set mounted(e){void 0!==e&&e!==this.mounted&&(this._mounted=e,this.initializeObservers(),this.mountSubject$.closed||this.mountSubject$.next({key:this.name,status:this.mounted}))}mountField({valueSubscription:e,propsSubscription:t}){this.mounted=!0,this.subscribeValue(e),this.subscribeState(t),this.valueSubject$.next(this.stateValue),this.propsSubject$.next(this.props),this.visibilitySubject$.next(this.visibility),this.fieldEventSubject$.next({event:"ON_FIELD_MOUNT",fieldName:this.name,fieldInstance:this})}emitValue(e){this.visibility&&this.mounted&&(this.value=e.value,this.dataSubject$.next({event:e.event,fieldIndex:this.name,formIndex:this.formIndex}),this.emitEvents({event:e.event}))}emitEvents({event:e}){if("ON_FORM_SUBMIT"===e)return this.submitEvent();this.validateVisibility({event:e,key:this.name}),this.setFieldValidity({event:e}),this.resetValue({event:e,key:this.name}),this.resetProperty({event:e,key:this.name}),this.apiEventQueueSubject$.next({event:e}),this.fieldEventSubject$.next({event:e,fieldName:this.name,fieldInstance:this})}setFieldValidity({event:e}){var t,i,s,a;if(!this.validations||!this.visibility)return this.errors={},void(this.valid=!0);let n=!0;const r={},l=null===(t=this.validations)||void 0===t?void 0:t.methods;if(l&&Object.keys(l).forEach(e=>{var t,i;const s=R(this.value,l,j,e,null===(t=this.formValuesStateSubject$)||void 0===t?void 0:t.value);n=!s&&n,s&&(null===(i=this.validations)||void 0===i?void 0:i.messages)?e in this.validations.messages?r[e]=this.validations.messages[e]:"default"in this.validations.messages&&(r[e]=this.validations.messages.default):delete r[e]}),this.valid=n,null===(s=null===(i=this.validations)||void 0===i?void 0:i.eventMessages)||void 0===s?void 0:s[e]){const t={};null===(a=this.validations.eventMessages[e])||void 0===a||a.forEach(e=>{e in r&&(t[e]=r[e])}),this.errors=t}else"ON_FIELD_VALIDATION"===e&&(this.errors=r)}formatValue(e){return this.formatters?Object.keys(this.formatters).reduce((e,t)=>{const i=E[t];return i?i(e,this.formatters):e},e):e}maskValue(e){return this.masks?Object.keys(this.masks).reduce((e,t)=>{const i=O[t];return i?i(e,this.masks):e},e):e}checkApiRequestValidations(e){let t=!0;const i=e.preConditions;return i&&Object.keys(i).forEach(e=>{var s;const a=R(this.value,i,j,e,null===(s=this.formValuesStateSubject$)||void 0===s?void 0:s.value);t=t&&!a}),e.blockRequestWhenInvalid&&(t=t&&this.valid),t}apiRequest(e){return c(this,arguments,void 0,function*({event:e}){var t,i,s,a,n,r,l,o,u;let d=!1;const h=e=>c(this,void 0,void 0,function*(){var t,i;try{const{status:s,response:a}=yield function(e,t,i,s,a){return c(this,void 0,void 0,function*(){if(a){const[e,i]=t.split("?"),s=new URLSearchParams(i);Object.keys(a).forEach(e=>{s.append(e,a[e])}),t=`${e}?${s.toString()}`}const n=yield fetch(t,{method:e,headers:i,body:s?JSON.stringify(s):void 0}),r=yield n.text();return{status:n.status,response:r}})}(e.method,e.url,e.headers,e.body,e.queryParams),n=null===(t=e.transform)||void 0===t?void 0:t.callback,r=n?n({payload:JSON.parse(String(a)),formValues:null===(i=this.formValuesStateSubject$)||void 0===i?void 0:i.value}):JSON.parse(String(a));return{response:e.resultPath?F(r,e.resultPath):r,status:s}}catch(t){return{response:w(null==e?void 0:e.fallbackValue)?"error":e.fallbackValue,status:500}}});if("ON_API_FIELD_RESPONSE"===this.api.apiState.lastEvent&&"ON_API_FIELD_RESPONSE"===e||!(null===(i=null===(t=this.apiSchema)||void 0===t?void 0:t.defaultConfig)||void 0===i?void 0:i.events.includes(e))&&(!(null===(s=this.apiSchema)||void 0===s?void 0:s.configs)||!Object.keys(null===(a=this.apiSchema)||void 0===a?void 0:a.configs).some(t=>{var i,s;return null===(s=null===(i=this.apiSchema)||void 0===i?void 0:i.configs)||void 0===s?void 0:s[t].events.includes(e)})))return;const v={default:Object.assign({},this.api.default),named:Object.assign({},this.api.named),apiState:Object.assign({},this.api.apiState)},f=null===(n=this.apiSchema.defaultConfig)||void 0===n?void 0:n.config;if(f&&(null===(l=null===(r=this.apiSchema)||void 0===r?void 0:r.defaultConfig)||void 0===l?void 0:l.events.includes(e))&&this.checkApiRequestValidations(f)){d||this.notifyApiRequest();const{response:e,status:t}=yield h(f);d=!0,v.default={response:e,status:t}}if((null===(o=this.apiSchema)||void 0===o?void 0:o.configs)&&Object.keys(null===(u=this.apiSchema)||void 0===u?void 0:u.configs).some(t=>{var i,s;return null===(s=null===(i=this.apiSchema)||void 0===i?void 0:i.configs)||void 0===s?void 0:s[t].events.includes(e)})&&this.apiSchema.configs){const t=yield Promise.all(Object.keys(this.apiSchema.configs).map(t=>c(this,void 0,void 0,function*(){var i,s,a,n;const r=null===(s=null===(i=this.apiSchema)||void 0===i?void 0:i.configs)||void 0===s?void 0:s[t].config;if(r&&(null===(n=null===(a=this.apiSchema)||void 0===a?void 0:a.configs)||void 0===n?void 0:n[t].events.includes(e))&&this.checkApiRequestValidations(r)){d||this.notifyApiRequest();const{response:e,status:i}=yield h(r);return d=!0,{name:t,result:{response:e,status:i}}}return null})));t.forEach(e=>{e&&v.named&&(v.named[e.name]=e.result)})}d&&(v.apiState.lastEvent=e,v.apiState.loading=!1,this.api=v)})}destroyField(){this.mounted=!1,this.valueSubscription$.unsubscribe(),this.visibilitySubject$.unsubscribe(),this.fieldStateSubscription$.unsubscribe(),this.propsSubject$.unsubscribe(),this.errorSubject$.unsubscribe(),this.apiEventQueueSubject$.unsubscribe(),this.dataSubject$.closed||this.dataSubject$.next({event:"ON_FIELD_UNMOUNT",fieldIndex:this.name,formIndex:this.formIndex}),this.fieldEventSubject$.closed||this.fieldEventSubject$.next({event:"ON_FIELD_UNMOUNT",fieldName:this.name,fieldInstance:this})}subscribeState(e){var t;this.fieldStateSubscription$=l({visibility:this.visibilitySubject$.pipe(o(this.visibility)),props:this.propsSubject$.pipe(o(this.props)),errors:this.errorSubject$.pipe(o(Object.assign({},(null===(t=this.mapper.events)||void 0===t?void 0:t.setErrorMessage)&&{[this.mapper.events.setErrorMessage]:this.errorsString})))}).pipe(n(this.config.defaultStateRefreshTimeMS)).subscribe({next:e})}subscribeValue(e){this.valueSubscription$=this.valueSubject$.subscribe({next:e})}}class L{constructor(e){var s,a,n,r,l,o,u,d,h,c,f;this.templateSubscription$=new i,this.mappers=new Map,this.queuedFieldVisibilityEvents=new Map,this.queuedFieldResetValuesEvents=new Map,this.queuedFieldResetPropertyEvents=new Map,this.queuedInitialValues=new Map,this._valid=!1,this.stopEventsOnSubmit=!1,this.submitted=!1,this.isolatedFormInstance=!1,this.index=e.index,this.schema=e.schema,this.fields=new Map,this.action=e.action||(null===(s=e.schema)||void 0===s?void 0:s.action),this.method=e.method||(null===(a=e.schema)||void 0===a?void 0:a.method),this.config={defaultAPIdebounceTimeMS:Number(null===(n=e.config)||void 0===n?void 0:n.defaultAPIdebounceTimeMS)?Number(null===(r=e.config)||void 0===r?void 0:r.defaultAPIdebounceTimeMS):v,defaultStateRefreshTimeMS:Number(null===(l=e.config)||void 0===l?void 0:l.defaultStateRefreshTimeMS)?Number(null===(o=e.config)||void 0===o?void 0:o.defaultStateRefreshTimeMS):100,defaultLogVerbose:(null===(u=e.config)||void 0===u?void 0:u.defaultLogVerbose)?e.config.defaultLogVerbose:g},null===(d=e.mappers)||void 0===d||d.map(e=>{this.mappers.set(e.componentName,e)}),e.submitSubject$&&e.dataSubject$&&e.formValidSubject$||(this.isolatedFormInstance=!0,this.config.defaultLogVerbose&&console.warn(`some formGroup events are not properly instanciated, any onData, onValid, onSubmit events managed by formGroup won't trigger on form: ${this.index}`)),this.schema&&L.checkIndexes(this.schema.components),this.templateSubject$=new t,this.fieldEventSubject$=new t,this.mountSubject$=new t,this.fieldValidNotification$=new t,this.submitSubject$=e.submitSubject$?e.submitSubject$:new t,this.dataSubject$=e.dataSubject$?e.dataSubject$:new t,this.formValidSubject$=e.formValidSubject$?e.formValidSubject$:new t,this.formValuesStateSubject$=new A({erroredFields:[],isValid:!0,metadata:[],values:[]}),this.getFormValues=()=>this.formValuesStateSubject$.value,this.subscribedTemplates=[],this.templateSubscription$=this.templateSubject$.subscribe(this.refreshTemplates.bind(this)),this.fieldValidNotification$.subscribe(()=>{this.validateForm()}),this.fieldEventSubject$.subscribe(()=>{this.formValuesStateSubject$.next(this.getFormState())}),this.dataSubject$.subscribe(()=>{this.formValuesStateSubject$.next(this.getFormState())}),this.mountSubject$.subscribe(this.mountActions.bind(this)),this.prefetchedData=null===(h=e.schema)||void 0===h?void 0:h.prefetchedData,this.initialValues=e.initialValues||(null===(c=e.schema)||void 0===c?void 0:c.initialValues),this.iVars=e.iVars||(null===(f=e.schema)||void 0===f?void 0:f.iVars)||{},this.stopEventsOnSubmit=(null==e?void 0:e.stopEventsOnSubmit)||!1,this.submitted=!1}generateFields(){this.schema&&this.serializeStructure(this.schema.components),this.fields.forEach(e=>{e.mountField({valueSubscription:()=>null,propsSubscription:()=>null})})}submitChecker(){return!(this.stopEventsOnSubmit&&this.submitted)}mountActions({key:e,status:t}){if(t){const t=this.fields.get(e);if(!t)return void(this.config.defaultLogVerbose&&console.warn(`field ${e} was mounted but since it's parent has some visibility condition the field was already removed`));this.subscribeTemplates(),this.refreshTemplates({scope:"fields",event:"ON_FIELDS"}),this.templateSubject$.next({scope:"iVars",event:"ON_IVARS"}),this.queuedInitialValues.has(e)||(t.valuePropName&&!t.value?t.emitValue({event:"ON_FIELD_MOUNT",value:""}):t.emitEvents({event:"ON_FIELD_MOUNT"})),this.checkFieldEventQueues(e)}}set initialValues(e){e&&Object.keys(e).forEach(t=>{const i=this.fields.get(t);i&&(null==i?void 0:i.visibility)&&(null==i?void 0:i.mounted)?i.emitValue({value:null==e?void 0:e[t],event:"ON_FIELD_MOUNT"}):this.queuedInitialValues.set(t,null==e?void 0:e[t])})}get iVars(){return this._iVars}set iVars(e){this._iVars=e,this.templateSubject$.next({scope:"iVars",event:"ON_IVARS"})}validateForm(){if(0===this.fields.size)return this.valid=!1;for(const[,e]of this.fields)if(!e.valid)return this.valid=!1;return this.valid=!0}get valid(){return this._valid}set valid(e){this._valid!==e&&(this._valid=e,this.templateSubject$.next({event:"ON_FORM",scope:"form"}),this.formValidSubject$.next({formIndex:this.index,valid:this.valid}))}subscribeTemplates(){this.subscribedTemplates=[],this.fields.forEach(({originalSchema:{component:e,props:t,name:i,validations:s,visibilityConditions:a,resetValues:n,resetPropertyValues:r,api:l}},o)=>{$({component:e,props:t,name:i,validations:s,visibilityConditions:a,resetValues:n,resetPropertyValues:r,apiSchema:l},o).forEach(e=>this.subscribedTemplates.push(e))})}getValue({scope:e,key:t,property:i,path:s}){switch(e){case"iVars":return F(this.iVars,[t,...i?[i]:[],...s]);case"form":return F(this,[t,...i?[i]:[],...s]);case"fields":{const e=this.fields.get(t);return e?"props"===i&&s[0]===e.valuePropName?e.value:s.length>0?F(e[i],s):e[i]:this.config.defaultLogVerbose&&console.warn(`failed to get value from ${t}`)}}}setValue({key:e,property:t,path:i,originKey:s,value:a}){const n=this.fields.get(e);if(n){if(i.length>0){if("props"===t&&i[0]===n.valuePropName&&e!==s)return void n.emitValue({event:"ON_FIELD_CHANGE",value:a});const r=n[t];let l;return Array.isArray(r)||"object"==typeof r&&!w(r)?(l=k(r),N(l,i,a),void(n[t]=l)):void(this.config.defaultLogVerbose&&console.warn(`invalid template property, skipping evaluation of ${n.name} with ${r}`))}n[t]=a}else this.config.defaultLogVerbose&&console.warn(`failed to update field ${e}`)}extractParams(e){const t=function(e){const t=e.split(".");return t.length>1?this.getValue({scope:t[0],key:t[1],property:t[2],path:t.slice(3)}):t[0]}.bind(this),i=[];let s;for(;!w(s=p.exec(e));)i.push(s[1]);return i.map(e=>e.split(m)).map(e=>e.length<=1?{parse:!1,value:t(e[0])}:{parse:!0,value:e.filter(Boolean).reduce((e,i)=>{if(i.match(b))return`${e}${i}`;let s;const a=t(i);let n;try{n=JSON.parse(a)}catch(e){n=a}switch(typeof n){case"string":s=`\`${n}\``;break;case"boolean":case"undefined":case"number":default:s=n;break;case"object":if(null===n){s=null;break}if(n instanceof Date){s=`new Date(\`${n}\`)`;break}s=JSON.stringify(n)}return`${e}${s}`},"")}).map(({parse:t,value:i})=>{try{return t?new Function(`return ${i}`)():i}catch(t){return this.config.defaultLogVerbose&&(console.warn(`unhandled parsing on ${e} returning`),console.warn(i)),i}})}replaceExpression(e,t){return e.replace(p,()=>String(t.shift())||"")}hasStringConcatenation(e){return!f.test(e)}refreshTemplates({key:e,event:t}){this.subscribedTemplates.forEach(({destinationKey:i,destinationPath:s,destinationProperty:a,originExpression:n,originFieldKeys:r})=>{if(!e||r.includes(e)){const r=this.extractParams(n);let l;l=this.hasStringConcatenation(n)?this.replaceExpression(n,[...r]):null==r?void 0:r[0],P(this.getValue({scope:"fields",key:i,property:a,path:s}),l)||this.setValue({key:i,property:a,path:s,originKey:e,value:l,event:t})}})}checkFieldEventQueues(e){var t;if(null===(t=this.fields.get(e))||void 0===t?void 0:t.mounted){if(this.queuedFieldVisibilityEvents.has(e)&&(this.setFieldVisibility(Object.assign({field:e},this.queuedFieldVisibilityEvents.get(e))),this.queuedFieldVisibilityEvents.delete(e)),this.queuedInitialValues.has(e)){const t=this.queuedInitialValues.get(e);this.queuedInitialValues.delete(e),this.initialValues={[e]:t}}this.queuedFieldResetValuesEvents.has(e)&&(this.setResetFieldValue(Object.assign({key:e},this.queuedFieldResetValuesEvents.get(e))),this.queuedFieldResetValuesEvents.delete(e)),this.queuedFieldResetPropertyEvents.has(e)&&(this.setResetPathValue(Object.assign({key:e},this.queuedFieldResetPropertyEvents.get(e))),this.queuedFieldResetPropertyEvents.delete(e))}}setFieldVisibility({field:e,hasError:t,showOnlyIfTrue:i}){const s=this.fields.get(e);if(s&&s.mounted){const a=s.visibility,n=i?t:!t;if(s.visibility=n,a===n)return;s.visibility?this.queuedInitialValues.has(e)?(null==s||s.emitValue({value:this.queuedInitialValues.get(e)||"",event:"ON_FIELD_MOUNT"}),this.queuedInitialValues.delete(e)):s.emitEvents({event:"ON_FIELD_MOUNT"}):(s.emitEvents({event:"ON_FIELD_UNMOUNT"}),s.persistValue&&this.queuedInitialValues.set(s.name,s.value),s.value="",s.valid=!0)}else this.queuedFieldVisibilityEvents.set(e,{hasError:t,showOnlyIfTrue:i})}validateVisibility({event:e,key:t}){const i=this.fields.get(t),s=null==i?void 0:i.visibilityConditions;s&&(null==s?void 0:s.some(t=>t.events.includes(e)))&&s.forEach(t=>{t.events.includes(e)&&Object.keys(t.validations).forEach(e=>{const s=R(i.value,t.validations,j,e,this.formValuesStateSubject$.value);Array.isArray(t.fields)?t.fields.forEach(e=>{this.setFieldVisibility({field:e,hasError:s,showOnlyIfTrue:!(!i.value||!t.showOnlyIfTrue)})}):t.fields&&this.setFieldVisibility({field:t.fields,hasError:s,showOnlyIfTrue:!(!i.value||!t.showOnlyIfTrue)})})})}setResetFieldValue({key:e,value:t}){const i=this.fields.get(e);i&&(null==i?void 0:i.mounted)?i.emitValue({value:t,event:"ON_FIELD_CLEARED"}):this.queuedFieldResetValuesEvents.set(e,{value:t})}resetValue({event:e,key:t}){const i=this.fields.get(t),s=null==i?void 0:i.resetValues;s&&(null==s?void 0:s.some(t=>t.events.includes(e)))&&s.forEach(t=>{if(!t.events.includes(e))return;const s=()=>{Array.isArray(t.fields)?t.fields.forEach((e,i)=>{const s=Array.isArray(t.resettledValue)?t.resettledValue[i]:t.resettledValue;this.setResetFieldValue({key:e,value:s})}):t.fields&&this.setResetFieldValue({key:t.fields,value:t.resettledValue})};if(!t.validations)return s();Object.keys(t.validations).forEach(e=>{R(i.value,t.validations,j,e,this.formValuesStateSubject$.value)||s()})})}setResetPathValue({key:e,property:t,path:i,value:s}){this.fields.get(e)?this.setValue({key:e,property:t,path:i.split("."),value:s,event:"ON_RESET"}):this.queuedFieldResetPropertyEvents.set(e,{property:t,path:i,value:s})}resetProperty({event:e,key:t}){const i=this.fields.get(t),s=null==i?void 0:i.resetPropertyValues;s&&(null==s?void 0:s.some(t=>t.events.includes(e)))&&s.forEach(t=>{if(t.events.includes(e)&&y.includes(t.property))return t.validations?void Object.keys(t.validations).forEach(e=>{R(i.value,t.validations,j,e,this.formValuesStateSubject$.value)||this.setResetPathValue({key:t.field,path:t.path,property:t.property,value:t.resettledValue})}):this.setResetPathValue({key:t.field,path:t.path,property:t.property,value:t.resettledValue})})}addField({fieldSchema:e,mapperElement:t,path:i}){var s,a,n,r,l;if(this.fields.has(e.name))throw new Error(`field name ${e.name} already defined`);const o=t||(null===(s=this.mappers)||void 0===s?void 0:s.get(e.component));if(!o)throw new Error(`mapper not found for ${e.component}, add it to the mappers configuration`);if(null===(a=o.events)||void 0===a?void 0:a.setValue){const t=null===(n=null==e?void 0:e.props)||void 0===n?void 0:n[null===(r=null==o?void 0:o.events)||void 0===r?void 0:r.setValue];void 0===t||this.queuedInitialValues.has(e.name)||"string"==typeof t&&t.includes("${")||this.queuedInitialValues.set(e.name,k(t))}if(this.fields.set(e.name,new M({formIndex:this.index,schemaComponent:e,mapper:o,children:e.children?e.children.map(e=>e.name):[],validateVisibility:this.validateVisibility.bind(this),resetValue:this.resetValue.bind(this),resetProperty:this.resetProperty.bind(this),formValuesStateSubject$:this.formValuesStateSubject$,templateSubject$:this.templateSubject$,fieldEventSubject$:this.fieldEventSubject$,dataSubject$:this.dataSubject$,fieldValidNotification$:this.fieldValidNotification$,mountSubject$:this.mountSubject$,config:this.config,submitEvent:this.submit.bind(this),visibility:e.visibility,persistValue:e.persistValue,path:i})),null===(l=this.prefetchedData)||void 0===l?void 0:l[e.name]){const t=this.fields.get(e.name);if(t){const i=this.prefetchedData[e.name],s=Object.assign({},t.api);void 0!==i.defaultResponse&&(s.default={response:i.defaultResponse,status:200}),i.namedResponses&&(s.named=s.named||{},Object.keys(i.namedResponses).forEach(e=>{s.named[e]={response:i.namedResponses[e],status:200}})),t._api=s}}}removeField({key:e}){var t;null===(t=this.fields.get(e))||void 0===t||t.destroyField(),this.fields.delete(e),this.subscribeTemplates(),this.templateSubject$.next({scope:"fields",key:e,event:"ON_FIELDS"}),this.validateForm()}serializeStructure(e,t){e&&e.forEach(e=>{var i;const s=this.fields.get(e.name);s?(s.children=(null===(i=null==e?void 0:e.children)||void 0===i?void 0:i.map(e=>e.name))||(null==s?void 0:s.children)||[],s.originalSchema=e,s.templateSubject$=this.templateSubject$):this.addField({fieldSchema:e,mapperElement:e.mapper,path:t}),e.children&&this.serializeStructure(e.children,`${t?`${t}.`:""}${e.name}`)})}refreshFields(e){const t=Array.from(this.fields.keys());this.serializeStructure(e);const i=L.checkIndexes(e);this.fields.forEach((e,t)=>{var s;i.includes(t)||(null===(s=this.fields.get(t))||void 0===s||s.destroyField(),this.fields.delete(t))}),this.subscribeTemplates(),this.fields.forEach((e,i)=>{var s;t.includes(i)||(null===(s=this.fields.get(i))||void 0===s||s.emitEvents({event:"ON_FIELD_MOUNT"}),this.checkFieldEventQueues(i))}),this.subscribedTemplates.forEach(e=>{e.originFieldKeys.forEach(e=>{this.templateSubject$.next({scope:"fields",key:e,event:"ON_FIELDS"})})})}getField({key:e}){return this.fields.get(e)}printValues(){console.table(this.formValuesStateSubject$.value.values)}getFormState(){const e={},t={},i=[];return this.fields.forEach((s,a)=>{"string"==typeof s.value&&0===s.value.length||null==s.value||(N(e,s.nameToSubmit||a,s.value),t[a]=s.metadata),s.valid||i.push(a)}),{values:e,metadata:t,erroredFields:i,isValid:this.valid}}subscribeFieldEvent({callback:e}){return this.fieldEventSubject$.pipe(r(()=>this.submitChecker()),s(e=>`${e.event}|${e.fieldName}`),a(e=>e.pipe(n(this.config.defaultStateRefreshTimeMS)))).subscribe({next:e})}subscribeOnMount(e){return this.mountSubject$.pipe(u(()=>this.formValuesStateSubject$.value)).subscribe({next:e})}subscribeData(e){return this.dataSubject$.pipe(r(({formIndex:e})=>this.index===e&&this.submitChecker()),s(e=>e.event),a(e=>e.pipe(n(this.config.defaultStateRefreshTimeMS))),u(({fieldIndex:e})=>({field:e,data:this.formValuesStateSubject$.value}))).subscribe({next:e})}subscribeOnSubmit(e){return this.submitSubject$.pipe(r(({formIndex:e})=>e===this.index&&this.submitChecker()),u(({values:e})=>e)).subscribe({next:e})}subscribeFormValidation(e){return this.formValidSubject$.pipe(r(({formIndex:e})=>this.index===e),u(()=>({formIndex:this.index,valid:this.valid})),d("valid"),o({formIndex:this.index,valid:this.valid})).subscribe({next:e})}submit(){this.fields.forEach(e=>{e.emitEvents({event:"ON_FIELD_VALIDATION"})}),this.valid&&(this.submitSubject$.next({formIndex:this.index,values:this.formValuesStateSubject$.value}),this.submitted=!0)}destroy(){this.templateSubject$.unsubscribe(),this.templateSubscription$.unsubscribe(),this.mountSubject$.unsubscribe(),this.fieldEventSubject$.unsubscribe(),this.fieldValidNotification$.unsubscribe(),this.formValuesStateSubject$.unsubscribe(),this.isolatedFormInstance&&(this.submitSubject$.unsubscribe(),this.dataSubject$.unsubscribe(),this.formValidSubject$.unsubscribe()),this.fields.forEach(e=>e.destroyField())}}L.checkIndexes=(e,t=[])=>{if(!e)return t;const i=(e,t)=>{for(let s=0;s<e.length;s++){const a=e[s];t.push(a.name),a.children&&i(a.children,t)}};i(e,t);const s=t.filter((e,i)=>t.indexOf(e)!==i);if(s.length>0)throw new Error(`duplicated indexes found on schema: ${JSON.stringify(s)}`);return t};class D{constructor(e){var i,s,a,n,r;this.destroy=()=>{this.forms.forEach(e=>e.destroy()),this.dataSubject$.unsubscribe(),this.formValidSubject$.unsubscribe(),this.submitSubject$.unsubscribe()},this.forms=new Map,this.config={defaultAPIdebounceTimeMS:Number(null===(i=null==e?void 0:e.config)||void 0===i?void 0:i.defaultAPIdebounceTimeMS)?Number(null===(s=null==e?void 0:e.config)||void 0===s?void 0:s.defaultAPIdebounceTimeMS):v,defaultStateRefreshTimeMS:Number(null===(a=null==e?void 0:e.config)||void 0===a?void 0:a.defaultStateRefreshTimeMS)?Number(null===(n=null==e?void 0:e.config)||void 0===n?void 0:n.defaultStateRefreshTimeMS):100,defaultLogVerbose:(null===(r=null==e?void 0:e.config)||void 0===r?void 0:r.defaultLogVerbose)?e.config.defaultLogVerbose:g},this.dataSubject$=new t,this.formValidSubject$=new t,this.submitSubject$=new t,this.mappers=null==e?void 0:e.mappers}createFormWithIndex({index:e,mappers:t}){this.addForm({key:e,params:{index:e,mappers:t,config:this.config}})}addForm({key:e,params:t}){this.checkIndexes({key:e});const i=new L(Object.assign(Object.assign({},t),{dataSubject$:this.dataSubject$,formValidSubject$:this.formValidSubject$,submitSubject$:this.submitSubject$}));i.config||(i.config=this.config),this.forms.set(e,i)}getForm({key:e}){return this.forms.get(e)}removeForm({key:e}){var t;null===(t=this.forms.get(e))||void 0===t||t.destroy(),this.forms.delete(e)}removeField({formIndex:e,fieldIndex:t}){const i=this.forms.get(e);null==i||i.removeField({key:t}),0===(null==i?void 0:i.fields.size)&&this.removeForm({key:e})}checkIndexes({key:e}){if(this.forms.has(e))throw new Error(`duplicate index ${e} on form group`)}printFormGroupInstance(){console.table(this.forms)}submitMultipleFormsByIndex(e,t){let i=!0,s={},a={},n=[];e.forEach(e=>{var t,r;null===(t=this.forms.get(e))||void 0===t||t.submit();const l=null===(r=this.forms.get(e))||void 0===r?void 0:r.formValuesStateSubject$.value,o="object"==typeof(null==l?void 0:l.metadata)&&null!==l.metadata?l.metadata:{};i=i&&((null==l?void 0:l.isValid)||!1),s=Object.assign(Object.assign({},s),(null==l?void 0:l.values)||{}),a=Object.assign(Object.assign({},a),o),n=[...n,...(null==l?void 0:l.erroredFields)||[]]}),i&&t&&t({erroredFields:n,isValid:i,values:s,metadata:a})}onDataSubscription({ids:e,callback:t}){return this.dataSubject$.pipe(r(({formIndex:t})=>e.includes(t)),s(({event:e,formIndex:t})=>`${e}.${t}`),a(e=>e.pipe(n(this.config.defaultStateRefreshTimeMS))),u(({fieldIndex:t,formIndex:i})=>e.reduce((e,s)=>{const a=this.forms.get(s);return a&&(e[s]={formId:i,formField:t,values:a.formValuesStateSubject$.value}),e},{}))).subscribe(t)}onValidSubscription({ids:e,callback:t}){return this.formValidSubject$.pipe(r(({formIndex:t})=>e.includes(t)),s(({formIndex:e})=>e),a(e=>e.pipe(n(0))),o({fieldTrigger:null}),u(()=>({groupValid:e.every(e=>{var t;return!this.forms.get(e)||(null===(t=this.forms.get(e))||void 0===t?void 0:t.valid)}),forms:e.reduce((e,t)=>{const i=this.forms.get(t);return i&&(e[t]=i.valid),e},{})}))).subscribe(t)}onSubmitSubscription({ids:e,callback:t}){return this.submitSubject$.pipe(r(({formIndex:t})=>e.includes(t)),u(()=>e.reduce((e,t)=>{const i=this.forms.get(t);return i&&(e[t]=i.formValuesStateSubject$.value),e},{}))).subscribe(t)}}export{L as FormCore,M as FormField,D as FormGroup,h as TMutationEnum,E as formatterRegistry,O as maskRegistry,x as registerFormatters,_ as registerMasks,I as registerValidations,j as validationRegistry};
package/package.json CHANGED
@@ -1,10 +1,42 @@
1
1
  {
2
2
  "name": "@bolttech/form-engine-core",
3
- "version": "1.0.10",
3
+ "version": "1.1.0",
4
+ "sideEffects": false,
5
+ "exports": {
6
+ ".": {
7
+ "types": "./index.d.ts",
8
+ "import": "./index.esm.js",
9
+ "default": "./index.esm.js"
10
+ },
11
+ "./lite": {
12
+ "types": "./lite.d.ts",
13
+ "import": "./lite.esm.js",
14
+ "default": "./lite.esm.js"
15
+ },
16
+ "./credit-card": {
17
+ "types": "./credit-card.d.ts",
18
+ "import": "./credit-card.esm.js",
19
+ "default": "./credit-card.esm.js"
20
+ },
21
+ "./document": {
22
+ "types": "./document.d.ts",
23
+ "import": "./document.esm.js",
24
+ "default": "./document.esm.js"
25
+ },
26
+ "./currency": {
27
+ "types": "./currency.d.ts",
28
+ "import": "./currency.esm.js",
29
+ "default": "./currency.esm.js"
30
+ },
31
+ "./date": {
32
+ "types": "./date.d.ts",
33
+ "import": "./date.esm.js",
34
+ "default": "./date.esm.js"
35
+ }
36
+ },
4
37
  "dependencies": {
5
38
  "@gaignoux/currency": "^1.1.0",
6
39
  "credit-card-type": "^10.0.0",
7
- "lodash": "4.18.1",
8
40
  "rxjs": "7.8.2"
9
41
  },
10
42
  "module": "./index.esm.js",
@@ -0,0 +1,11 @@
1
+ import { IFormField } from "../managers/field";
2
+ declare const DEFAULT_API_DEBOUNCE_TIME = 1000;
3
+ declare const DEFAULT_STATE_REFRESH_TIME = 100;
4
+ declare const TEMPLATE_REGEX_STRING_CONCATENATION_DETECTOR: RegExp;
5
+ declare const TEMPLATE_REGEX_DELIMITATOR: RegExp;
6
+ declare const TEMPLATE_REGEX_OPERATOR_SPLITTER: RegExp;
7
+ declare const TEMPLATE_REGEX_OPERATOR_MATCHER: RegExp;
8
+ declare const TEMPLATE_AVALIABLE_SCOPES: readonly ["fields", "iVars", "form"];
9
+ declare const ALLOWED_RESET_PROPS_MUTATIONS: (keyof Pick<IFormField, "api" | "apiSchema" | "props" | "validations" | "visibilityConditions" | "resetValues">)[];
10
+ declare const DEFAULT_LOG_VERBOSE = false;
11
+ export { DEFAULT_API_DEBOUNCE_TIME, DEFAULT_STATE_REFRESH_TIME, DEFAULT_LOG_VERBOSE, TEMPLATE_REGEX_STRING_CONCATENATION_DETECTOR, TEMPLATE_REGEX_DELIMITATOR, TEMPLATE_REGEX_OPERATOR_SPLITTER, TEMPLATE_REGEX_OPERATOR_MATCHER, TEMPLATE_AVALIABLE_SCOPES, ALLOWED_RESET_PROPS_MUTATIONS, };
@@ -0,0 +1,23 @@
1
+ import { TFormatters } from '../types/schema';
2
+ /**
3
+ * Formats a credit card number by adding gaps based on the card type.
4
+ *
5
+ * @param {unknown} value - The input value to be formatted, expected to be a string representing a credit card number.
6
+ * @param {TFormatters} formatters - An object containing formatting options.
7
+ * @param {boolean} formatters.gapsCreditCard - A flag indicating whether to apply credit card gap formatting.
8
+ * @returns {unknown} - The formatted credit card number with appropriate gaps, or the original value if formatting is not applied.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * const formatters = { gapsCreditCard: true };
13
+ * const result = gapsCreditCard('4111111111111111', formatters);
14
+ * console.log(result); // "4111 1111 1111 1111" (formatted based on card type, e.g., Visa)
15
+ * ```
16
+ * @example
17
+ * ```typescript
18
+ * const formatters = { gapsCreditCard: false };
19
+ * const result = gapsCreditCard('4111111111111111', formatters);
20
+ * console.log(result); // "4111111111111111" (no formatting applied)
21
+ * ```
22
+ */
23
+ export declare const gapsCreditCard: (value: unknown, formatters: TFormatters) => unknown;
@@ -0,0 +1,29 @@
1
+ import { TFormatters } from '../types/schema';
2
+ /**
3
+ * Applies a custom callback function to format a value.
4
+ *
5
+ * @param {unknown} value - The input value to be formatted.
6
+ * @param {TFormatters} formatters - An object containing formatting options.
7
+ * @param {(value: unknown) => unknown} formatters.callback - A custom callback function to apply to the value.
8
+ * @returns {unknown} - The value after applying the custom callback function, or the original value if no callback is provided.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * const formatters = { callback: (val) => `Formatted: ${val}` };
13
+ * const result = callback('example', formatters);
14
+ * console.log(result); // "Formatted: example"
15
+ * ```
16
+ * @example
17
+ * ```typescript
18
+ * const formatters = { callback: (val) => val.toString().toUpperCase() };
19
+ * const result = callback('example', formatters);
20
+ * console.log(result); // "EXAMPLE"
21
+ * ```
22
+ * @example
23
+ * ```typescript
24
+ * const formatters = { callback: null };
25
+ * const result = callback('example', formatters);
26
+ * console.log(result); // "example" (no formatting applied)
27
+ * ```
28
+ */
29
+ export declare const callback: (value: unknown, formatters: TFormatters) => unknown;
@@ -0,0 +1,2 @@
1
+ import { TFormatters } from '../types/schema';
2
+ export declare const formatters: Record<keyof TFormatters, (value: unknown, formatters?: TFormatters) => unknown>;
@@ -0,0 +1,47 @@
1
+ import { TFormatters } from '../types/schema';
2
+ /**
3
+ * Removes all non-numeric characters from a string.
4
+ *
5
+ * @param value - The value to be processed.
6
+ * @returns The processed value with only numbers.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { onlyNumbers } from './path/to/formatterFunctions';
11
+ *
12
+ * const processedValue = onlyNumbers('abc123def456');
13
+ * console.log(processedValue); // Output: '123456'
14
+ * ```
15
+ */
16
+ export declare const onlyNumbers: (value: unknown) => string;
17
+ /**
18
+ * Removes all non-letter characters from a string.
19
+ *
20
+ * @param value - The value to be processed.
21
+ * @returns The processed value with only letters.
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * import { onlyLetters } from './path/to/formatterFunctions';
26
+ *
27
+ * const processedValue = onlyLetters('abc123def456');
28
+ * console.log(processedValue); // Output: 'abcdef'
29
+ * ```
30
+ */
31
+ export declare const onlyLetters: (value: unknown) => string;
32
+ /**
33
+ * Applies a regular expression pattern to remove matching substrings from a string.
34
+ *
35
+ * @param value - The value to be processed.
36
+ * @param formatters - An object containing formatting options.
37
+ * @returns The processed value with matched substrings removed.
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * import { regex } from './path/to/formatterFunctions';
42
+ *
43
+ * const processedValue = regex('abc123def456', { regex: '\\d+' });
44
+ * console.log(processedValue); // Output: 'abcdef'
45
+ * ```
46
+ */
47
+ export declare const regex: (value: unknown, formatters: TFormatters) => unknown;
@@ -0,0 +1,17 @@
1
+ import { TFormatters } from '../types/schema';
2
+ /**
3
+ * Splits a string by inserting specified values at given positions.
4
+ *
5
+ * @param value - The value to be processed.
6
+ * @param formatters - An object containing formatting options.
7
+ * @returns The processed value with splitters applied.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * import { splitter } from './path/to/formatterFunctions';
12
+ *
13
+ * const processedValue = splitter('HelloWorld', { splitter: [{ position: 5, value: '_' }] });
14
+ * console.log(processedValue); // Output: 'Hello_World'
15
+ * ```
16
+ */
17
+ export declare const splitter: (value: unknown, formatters: TFormatters) => unknown;
@@ -0,0 +1,88 @@
1
+ import { TFormatters } from '../types/schema';
2
+ /**
3
+ * Capitalizes the first letter of a string.
4
+ *
5
+ * @param value - The value to be capitalized.
6
+ * @returns The value with the first letter capitalized.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { capitalize } from './path/to/formatterFunctions';
11
+ *
12
+ * const capitalizedValue = capitalize('hello world');
13
+ * console.log(capitalizedValue); // Output: 'Hello world'
14
+ * ```
15
+ */
16
+ export declare const capitalize: (value: unknown) => string;
17
+ /**
18
+ * Converts a string to uppercase.
19
+ *
20
+ * @param value - The value to be converted.
21
+ * @returns The value in uppercase.
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * import { uppercase } from './path/to/formatterFunctions';
26
+ *
27
+ * const uppercasedValue = uppercase('hello world');
28
+ * console.log(uppercasedValue); // Output: 'HELLO WORLD'
29
+ * ```
30
+ */
31
+ export declare const uppercase: (value: unknown) => string;
32
+ /**
33
+ * Formats a string as a float number with a specific precision and decimal separator.
34
+ *
35
+ * @param value - The value to be formatted.
36
+ * @param formatters - An object containing formatting options.
37
+ * @returns The formatted float number.
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * import { onlyFloatNumber } from './path/to/formatterFunctions';
42
+ *
43
+ * const formattedNumber = onlyFloatNumber('1234567.89', { onlyFloatNumber: { precision: 2, decimal: '.' } });
44
+ * console.log(formattedNumber); // Output: '1234567.89'
45
+ * ```
46
+ */
47
+ export declare const onlyFloatNumber: (value: unknown, formatters: TFormatters) => unknown;
48
+ /**
49
+ * Trims whitespace from the beginning and end of a string.
50
+ *
51
+ * @param value - The value to be trimmed.
52
+ * @param formatters - An object containing formatting options.
53
+ * @returns The trimmed value.
54
+ *
55
+ * @example
56
+ * ```typescript
57
+ * import { trim } from './path/to/formatterFunctions';
58
+ *
59
+ * const trimmedValue = trim(' hello world ');
60
+ * console.log(trimmedValue); // Output: 'hello world'
61
+ * ```
62
+ */
63
+ export declare const trim: (value: unknown, formatters?: TFormatters) => unknown;
64
+ /**
65
+ * Truncates the input value to a specified maximum length if necessary.
66
+ *
67
+ * @param {string | number} value - The input value to be formatted.
68
+ * @param {TFormatters} formatters - An object containing formatting options.
69
+ * @param {number} formatters.maxLength - The maximum allowed length for the input value.
70
+ * @returns {string | number} - The formatted value truncated to the maximum length, if applicable.
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * const result = maxLength('Hello, World!', { maxLength: 5 });
75
+ * console.log(result); // "Hello"
76
+ * ```
77
+ * @example
78
+ * ```typescript
79
+ * const result = maxLength(123456789, { maxLength: 4 });
80
+ * console.log(result); // "1234"
81
+ * ```
82
+ * @example
83
+ * ```typescript
84
+ * const result = maxLength('Short', { maxLength: 10 });
85
+ * console.log(result); // "Short" (no truncation since input is shorter than maxLength)
86
+ * ```
87
+ */
88
+ export declare const maxLength: (value: string | number | null | undefined, formatters: TFormatters) => string | number | null | undefined;
@@ -0,0 +1,21 @@
1
+ import { BehaviorSubject, Subject } from 'rxjs';
2
+ /**
3
+ * Custom RXJS Subject to gracefully handle errors on unsubscribed Subjects
4
+ * that were unmounted due to adapter external handling such as visibility
5
+ */
6
+ declare class SafeSubject<T> extends Subject<T> {
7
+ private isMounted;
8
+ constructor(isMounted: () => boolean);
9
+ next(value: T): void;
10
+ }
11
+ /**
12
+ * Custom RXJS BehaviourSubject to gracefully handle errors on unsubscribed Subjects
13
+ * since its fire and forget, no mount status needed to check if its available or not
14
+ */
15
+ declare class SafeBehaviourSubject<T> extends BehaviorSubject<T> {
16
+ defaultValue: T;
17
+ constructor(value: T);
18
+ next(value: T): void;
19
+ get value(): T;
20
+ }
21
+ export { SafeSubject, SafeBehaviourSubject };
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Represents the properties of a credit card type.
3
+ */
4
+ export interface ICreditCardType {
5
+ /**
6
+ * A human-readable name for the credit card type.
7
+ * For example, "Visa", "Mastercard", "American Express", etc.
8
+ */
9
+ niceType: string;
10
+ /**
11
+ * A unique identifier for the credit card type.
12
+ * Typically, follows industry standards such as "visa", "mastercard", "amex", etc.
13
+ */
14
+ type: string;
15
+ /**
16
+ * An array of patterns (regular expressions) that match valid card numbers for this type.
17
+ * Each pattern corresponds to a specific length of card number.
18
+ */
19
+ patterns: number[] | [number[]];
20
+ /**
21
+ * An array representing the positions in the card number where spaces (gaps) should be added
22
+ * to format the number nicely. These positions are counted from the beginning of the number.
23
+ */
24
+ gaps: number[];
25
+ /**
26
+ * An array of possible lengths for valid card numbers of this type.
27
+ * Typically, this array contains only one element, but some card types may have multiple lengths.
28
+ */
29
+ lengths: number[];
30
+ /**
31
+ * Information about the card's security code (CVV/CVC/CID).
32
+ */
33
+ code: {
34
+ /**
35
+ * The size (length) of the security code for this card type.
36
+ */
37
+ size: number;
38
+ /**
39
+ * A descriptive name for the security code, such as "CVV" or "CVC".
40
+ */
41
+ name: string;
42
+ };
43
+ /**
44
+ * An optional value representing the match strength of the card type detection.
45
+ * Higher values indicate stronger matches, while lower values indicate weaker matches.
46
+ * This property is typically provided by the credit card type detection library.
47
+ */
48
+ matchStrength?: number;
49
+ }
50
+ /**
51
+ * Represents the return type of the `getTypeCard` function.
52
+ */
53
+ export type TGetTypeCard = [ICreditCardType, string];
54
+ /**
55
+ * Retrieves the type of the credit card and the raw value without spaces.
56
+ *
57
+ * @param value - The credit card number as a string.
58
+ * @param availableOptions - An optional array of credit card types to consider.
59
+ * @returns An array containing the detected credit card type and the raw value without spaces.
60
+ *
61
+ * @example
62
+ * ```typescript
63
+ * import { getTypeCard } from './path/to/helperFunctions';
64
+ *
65
+ * const [creditCardType, rawValue] = getTypeCard('4111 1111 1111 1111');
66
+ * console.log(creditCardType); // Output: { niceType: 'Visa', type: 'visa', ... }
67
+ * console.log(rawValue); // Output: '4111111111111111'
68
+ * ```
69
+ */
70
+ export declare const getTypeCard: (value: string, availableOptions?: string[] | boolean) => TGetTypeCard;
71
+ /**
72
+ * Formats a credit card number according to its type's gaps and lengths.
73
+ *
74
+ * @param value - The credit card number as a string.
75
+ * @param type - The type of the credit card.
76
+ * @returns The formatted credit card number.
77
+ */
78
+ export declare const formatValue: (value: string, type: ICreditCardType) => string;
79
+ /**
80
+ * Formats a date string by adding a prefix and/or trimming the string based on its length.
81
+ *
82
+ * @param value - The date string to be formatted.
83
+ * @param end - The ending index to slice the string to.
84
+ * @param prefix - The prefix to add between date components.
85
+ * @returns The formatted date string.
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * import { formatDateCard } from './path/to/helperFunctions';
90
+ *
91
+ * const formattedDate = formatDateCard('1223', 4, '/');
92
+ * console.log(formattedDate); // Output: '12/23'
93
+ * ```
94
+ */
95
+ export declare const formatDateCard: (value: string, end?: number, prefix?: string) => string;
@@ -0,0 +1,66 @@
1
+ import { TApiResponsePayload } from '../types/schema';
2
+ import { TSubscribedTemplates, TTemplateAvaliableScopes } from '../types/template';
3
+ /**
4
+ * Makes an HTTP request using the Fetch API.
5
+ * Works in both browser and server (Node 18+) environments.
6
+ *
7
+ * @param {string} method - The HTTP method (GET, POST, PUT, DELETE, etc.).
8
+ * @param {string} url - The URL to which the request is sent.
9
+ * @param {Record<string, string>} [headers] - Optional request headers.
10
+ * @param {Record<string,unknown>} [body] - Optional object body.
11
+ * @param {Record<string, string>} [queryParams] - Optional query parameters.
12
+ * @returns {Promise<TApiResponsePayload>} A promise that resolves with the response text and status.
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * const response = await makeRequest('GET', 'https://api.example.com/data');
17
+ * ```
18
+ */
19
+ declare function makeRequest(method: string, url: string, headers?: Record<string, string>, body?: Record<string, unknown>, queryParams?: Record<string, string>): Promise<TApiResponsePayload>;
20
+ /**
21
+ * Extracts keys enclosed in `${}` from a given expression.
22
+ *
23
+ * @param {string} expression - The expression to extract keys from.
24
+ * @returns {
25
+ * originFieldKeys: string[];
26
+ * originPropertyKeys: string[];
27
+ * } An object containing the field names and properties from the template expression.
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * const keys = extractFieldKeys('Hello ${name.value}, your age is ${age.props.label}.');
32
+ * // keys will be {originFieldKeys:['name', 'age'],originPropertyKeys:[value,props]}
33
+ * ```
34
+ */
35
+ declare function extractFieldKeys(expression: string): {
36
+ originScopeKeys: TTemplateAvaliableScopes[];
37
+ originFieldKeys: string[];
38
+ originPropertyKeys: string[];
39
+ };
40
+ /**
41
+ * Traverses an object and extracts expressions containing keys.
42
+ *
43
+ * @param {any} obj - The object to traverse.
44
+ * @param {string} [path] - Optional path within the object (used internally during recursion).
45
+ * @returns {TSubscribedTemplates[]} An array of extracted expressions along with their keys and paths.
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * const data = {
50
+ * user: {
51
+ * name: 'John',
52
+ * age: 30,
53
+ * address: {
54
+ * street: '123 Main St',
55
+ * city: 'Example City'
56
+ * }
57
+ * },
58
+ * message: 'Hello ${user.name}, your age is ${user.age}.'
59
+ * };
60
+ *
61
+ * const expressions = traverseObject(data);
62
+ * // expressions will contain an array of objects with origin expressions, field keys, and destination paths.
63
+ * ```
64
+ */
65
+ declare function traverseObject(element: any, path?: string): TSubscribedTemplates[];
66
+ export { makeRequest, traverseObject, extractFieldKeys };
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Lightweight replacements for lodash functions used in form-engine-core.
3
+ * These cover the specific usage patterns in this codebase.
4
+ */
5
+ /**
6
+ * Deep clones a value. Handles objects, arrays, dates, and primitives.
7
+ * Equivalent to lodash/cloneDeep for the patterns used in this codebase.
8
+ */
9
+ export declare function cloneDeep<T>(value: T): T;
10
+ /**
11
+ * Gets the value at a path of an object. If the resolved value is undefined,
12
+ * the defaultValue is returned in its place.
13
+ * Equivalent to lodash/get.
14
+ */
15
+ export declare function get(obj: any, path: string | (string | number)[], defaultValue?: any): any;
16
+ /**
17
+ * Sets the value at a path of an object. If a portion of the path doesn't exist,
18
+ * it's created. Arrays are created for numeric keys, objects otherwise.
19
+ * Equivalent to lodash/set.
20
+ */
21
+ export declare function set(obj: any, path: string | (string | number)[], value: any): any;
22
+ /**
23
+ * Performs a deep comparison between two values to determine if they are equivalent.
24
+ * Equivalent to lodash/isEqual for the patterns used in this codebase.
25
+ */
26
+ export declare function isEqual(a: any, b: any): boolean;
27
+ /**
28
+ * Checks if value is null or undefined.
29
+ * Equivalent to lodash/isNil.
30
+ */
31
+ export declare function isNil(value: any): value is null | undefined;
32
+ /**
33
+ * Checks if value is classified as a Function object.
34
+ * Equivalent to lodash/isFunction.
35
+ */
36
+ export declare function isFunction(value: any): value is (...args: any[]) => any;
37
+ /**
38
+ * Checks if value is classified as a Number primitive or object.
39
+ * Equivalent to lodash/isNumber.
40
+ */
41
+ export declare function isNumber(value: any): value is number;
@@ -0,0 +1,28 @@
1
+ import { TSchemaValidation, TValidationMethods } from '../types/schema';
2
+ import { TValidationHandler } from '../types/utility';
3
+ import { TFormValues } from '../types/form';
4
+ /**
5
+ * @internal
6
+ * Handles the validation of a given value based on specified validation methods and rules.
7
+ *
8
+ * @param {string | number | boolean | unknown} value - The value to be validated.
9
+ * @param {TSchemaValidation} validations - The schema validations to be applied.
10
+ * @param {TValidationHandler} methods - The validation handler methods.
11
+ * @param {keyof TValidationMethods} key - The specific key of the validation method to be used.
12
+ * @returns {boolean} - Returns true if the value passes the validation, otherwise false.
13
+ *
14
+ * @example
15
+ * const value = 'example@example.com';
16
+ * const validations = {
17
+ * required: true,
18
+ * customName: { email: true }
19
+ * };
20
+ * const methods = {
21
+ * email: (value) => /\S+@\S+\.\S+/.test(value)
22
+ * };
23
+ * const key = 'required';
24
+ *
25
+ * const isValid = handleValidation(value, validations, methods, key);
26
+ * console.log(isValid); // Output: true
27
+ */
28
+ export default function handleValidation(value: string | number | boolean | unknown, validations: TSchemaValidation, methods: TValidationHandler, key: keyof TValidationMethods, formValues: TFormValues<unknown>): boolean;
package/src/index.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ export * from './types/event';
2
+ export * from './types/form';
3
+ export * from './types/schema';
4
+ export * from './types/template';
5
+ export * from './types/mapper';
6
+ export * from './types/utility';
7
+ export * from './interfaces/schema';
8
+ export * from './interfaces/state';
9
+ export * from './managers/form';
10
+ export * from './managers/formGroup';
11
+ export * from './managers/field';
12
+ export { registerValidations, registerFormatters, registerMasks, validationRegistry, formatterRegistry, maskRegistry } from './registry';
13
+ import './validations/handler';
14
+ import './formatters/handler';
15
+ import './masks/handler';