@ponchopay/pp-browser 1.2.0 → 1.3.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/dist/src/PpForm.d.ts +2 -0
- package/dist/src/PpForm.js +57 -26
- package/dist/src/PpForm.js.map +1 -1
- package/dist/src/PpPayment.js +6 -1
- package/dist/src/PpPayment.js.map +1 -1
- package/dist/src/utils.d.ts +4 -0
- package/dist/src/utils.js +18 -0
- package/dist/src/utils.js.map +1 -1
- package/dist/src/validation.d.ts +3 -1
- package/dist/src/validation.js +5 -2
- package/dist/src/validation.js.map +1 -1
- package/package.json +1 -1
package/dist/src/PpForm.d.ts
CHANGED
|
@@ -12,6 +12,8 @@ export declare abstract class PpForm extends HTMLElement {
|
|
|
12
12
|
disconnectedCallback(): void;
|
|
13
13
|
attributeChangedCallback(): void;
|
|
14
14
|
submit(): void;
|
|
15
|
+
private validateField;
|
|
16
|
+
checkArrayIsValid(attribute: string, field: Field): boolean;
|
|
15
17
|
checkValidity(): boolean;
|
|
16
18
|
static get observedAttributes(): string[];
|
|
17
19
|
}
|
package/dist/src/PpForm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createInputsForField, joinPaths } from './utils.js';
|
|
2
2
|
import { mandatory, single } from './validation.js';
|
|
3
3
|
const DEFAULT_BASE = 'https://pay.ponchopay.com/';
|
|
4
4
|
export class PpForm extends HTMLElement {
|
|
@@ -22,22 +22,23 @@ export class PpForm extends HTMLElement {
|
|
|
22
22
|
const base = this.getAttributeWithFallback('base', DEFAULT_BASE);
|
|
23
23
|
form.action = joinPaths(base, this.path);
|
|
24
24
|
form.replaceChildren();
|
|
25
|
-
Object.entries(this.fields).forEach(([attribute,
|
|
25
|
+
Object.entries(this.fields).forEach(([attribute, field]) => {
|
|
26
|
+
if (field.type === 'array') {
|
|
27
|
+
const matchingAttributes = Array.from(this.attributes).filter(attr => attr.name.startsWith(`${attribute}.`));
|
|
28
|
+
matchingAttributes.forEach(attr => {
|
|
29
|
+
var _a;
|
|
30
|
+
const parts = attr.name.split('.');
|
|
31
|
+
const fieldName = parts[parts.length - 1];
|
|
32
|
+
const subField = (_a = field.schema) === null || _a === void 0 ? void 0 : _a[fieldName];
|
|
33
|
+
if (!subField)
|
|
34
|
+
return;
|
|
35
|
+
createInputsForField(form, attr.name, attr.value, subField.type);
|
|
36
|
+
});
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
26
39
|
if (this.hasAttribute(attribute)) {
|
|
27
40
|
const attr = this.getAttribute(attribute);
|
|
28
|
-
|
|
29
|
-
let values = attr.length > 0 ? [attr] : [];
|
|
30
|
-
if (collection) {
|
|
31
|
-
name = `${name}[]`;
|
|
32
|
-
values = split(attr, ',');
|
|
33
|
-
}
|
|
34
|
-
values.forEach(value => {
|
|
35
|
-
const input = document.createElement('input');
|
|
36
|
-
input.type = 'hidden';
|
|
37
|
-
input.name = name;
|
|
38
|
-
input.value = value;
|
|
39
|
-
form.appendChild(input);
|
|
40
|
-
});
|
|
41
|
+
createInputsForField(form, attribute, attr, field.type);
|
|
41
42
|
}
|
|
42
43
|
});
|
|
43
44
|
const slot = document.createElement('slot');
|
|
@@ -121,19 +122,49 @@ export class PpForm extends HTMLElement {
|
|
|
121
122
|
var _a;
|
|
122
123
|
(_a = this.shadowRoot.querySelector('form')) === null || _a === void 0 ? void 0 : _a.requestSubmit();
|
|
123
124
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
return this.isAttributeSet(attribute);
|
|
134
|
-
}
|
|
125
|
+
validateField(fieldPath, field) {
|
|
126
|
+
if (field.required === true) {
|
|
127
|
+
return this.isAttributeSet(fieldPath);
|
|
128
|
+
}
|
|
129
|
+
if (Array.isArray(field.required)) {
|
|
130
|
+
const [dependant, value] = field.required;
|
|
131
|
+
if ((value === true || this.getAttribute(dependant) === value) &&
|
|
132
|
+
this.isAttributeSet(dependant)) {
|
|
133
|
+
return this.isAttributeSet(fieldPath);
|
|
135
134
|
}
|
|
135
|
+
}
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
checkArrayIsValid(attribute, field) {
|
|
139
|
+
const matchingAttributes = Array.from(this.attributes).filter(attr => attr.name.startsWith(`${attribute}.`));
|
|
140
|
+
const indexes = matchingAttributes.map(attr => {
|
|
141
|
+
const match = attr.name.match(new RegExp(`^${attribute}\\.(\\d+)\\.`));
|
|
142
|
+
return match ? parseInt(match[1], 10) : null;
|
|
143
|
+
});
|
|
144
|
+
const uniqueIndexes = Array.from(new Set(indexes));
|
|
145
|
+
// If array is required and no items exist fail validation
|
|
146
|
+
if (field.required === true && uniqueIndexes.length === 0) {
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
// If no items exist but array is optional, validation passes
|
|
150
|
+
if (uniqueIndexes.length === 0) {
|
|
136
151
|
return true;
|
|
152
|
+
}
|
|
153
|
+
return uniqueIndexes.every(index => Object.entries(field.schema).every(([key, subField]) => {
|
|
154
|
+
const fullPath = `${attribute}.${index}.${key}`;
|
|
155
|
+
return this.validateField(fullPath, subField);
|
|
156
|
+
}));
|
|
157
|
+
}
|
|
158
|
+
checkValidity() {
|
|
159
|
+
return Object.entries(this.fields).every(([attribute, { type, schema, required }]) => {
|
|
160
|
+
if (type === 'array') {
|
|
161
|
+
return this.checkArrayIsValid(attribute, {
|
|
162
|
+
type,
|
|
163
|
+
schema,
|
|
164
|
+
required,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
return this.validateField(attribute, { type, required, schema });
|
|
137
168
|
});
|
|
138
169
|
}
|
|
139
170
|
static get observedAttributes() {
|
package/dist/src/PpForm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PpForm.js","sourceRoot":"","sources":["../../src/PpForm.ts"],"names":[],"mappings":"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","sourcesContent":["import { formatName, joinPaths, split } from './utils.js';\nimport { Field, mandatory, single } from './validation.js';\n\nconst DEFAULT_BASE = 'https://pay.ponchopay.com/';\n\nexport abstract class PpForm extends HTMLElement {\n private readonly path: string;\n private readonly label: string;\n private readonly fields: Record<string, Field>;\n\n protected constructor(\n path: string,\n label: string,\n fields: Record<string, Field>\n ) {\n super();\n this.path = path;\n this.label = label;\n this.fields = { ...fields, token: mandatory(single()) };\n this.attachShadow({ mode: 'open' });\n }\n\n private getAttributeWithFallback(name: string, fallback: string): string {\n return this.getAttribute(name) ?? fallback;\n }\n\n private isAttributeSet(name: string): boolean {\n return this.getAttributeWithFallback(name, '').length > 0;\n }\n\n private syncAttributes(): void {\n const form = this.shadowRoot!.querySelector('form');\n if (form) {\n const base = this.getAttributeWithFallback('base', DEFAULT_BASE);\n\n form.action = joinPaths(base, this.path);\n form.replaceChildren();\n\n Object.entries(this.fields).forEach(([attribute, { collection }]) => {\n if (this.hasAttribute(attribute)) {\n const attr = this.getAttribute(attribute)!;\n\n let name = formatName(attribute);\n let values = attr.length > 0 ? [attr] : [];\n if (collection) {\n name = `${name}[]`;\n values = split(attr, ',');\n }\n\n values.forEach(value => {\n const input = document.createElement('input');\n input.type = 'hidden';\n input.name = name;\n input.value = value;\n form.appendChild(input);\n });\n }\n });\n\n const slot = document.createElement('slot');\n slot.innerHTML = this.label;\n\n const button = document.createElement('button');\n button.setAttribute('part', 'button');\n button.type = 'submit';\n button.appendChild(slot);\n form.appendChild(button);\n }\n }\n\n private showErrorMessage(): void {\n const form = this.shadowRoot!.querySelector('form');\n if (form) {\n form.querySelector('div')?.remove();\n\n const div = document.createElement('div');\n div.setAttribute('part', 'error');\n div.className = 'error';\n div.innerHTML = 'Some attributes are incorrect. Please, review them.';\n form.appendChild(div);\n }\n }\n\n public connectedCallback(): void {\n const base = this.getAttributeWithFallback('base', DEFAULT_BASE);\n\n const style = document.createElement('style');\n style.textContent = `\n form {\n display: contents;\n }\n\n button {\n width: 100%;\n background-color: #02C2A0;\n white-space: nowrap;\n text-decoration-line: none;\n border-radius: .25rem;\n box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n text-align: center;\n font-size: 1.25rem;\n line-height: 1.75rem;\n color: white;\n margin-top: .5rem;\n margin-bottom: .75rem;\n padding: .75rem 1rem;\n display: flex;\n flex-wrap: nowrap;\n align-items: center;\n justify-content: space-evenly;\n cursor: pointer;\n text-transform: none;\n box-sizing: border-box;\n border-width: 0;\n border-style: solid;\n border-color: currentColor;\n }\n\n div.error {\n color: #EB3B50;\n font-size: 0.875rem;\n }`;\n\n const form = document.createElement('form');\n form.action = joinPaths(base, this.path);\n form.method = 'post';\n form.onsubmit = event => {\n if (!this.checkValidity()) {\n event.preventDefault();\n this.showErrorMessage();\n }\n };\n this.shadowRoot!.append(style, form);\n\n this.syncAttributes();\n }\n\n public disconnectedCallback(): void {\n this.shadowRoot!.replaceChildren();\n }\n\n public attributeChangedCallback(): void {\n this.syncAttributes();\n }\n\n public submit(): void {\n this.shadowRoot!.querySelector('form')?.requestSubmit();\n }\n\n public checkValidity(): boolean {\n return Object.entries(this.fields).every(([attribute, { required }]) => {\n if (required === true) {\n return this.isAttributeSet(attribute);\n }\n\n if (Array.isArray(required)) {\n const [dependant, value] = required;\n\n if (\n (value === true || this.getAttribute(dependant) === value) &&\n this.isAttributeSet(dependant)\n ) {\n return this.isAttributeSet(attribute);\n }\n }\n\n return true;\n });\n }\n\n public static get observedAttributes() {\n return ['base', 'token'];\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"PpForm.js","sourceRoot":"","sources":["../../src/PpForm.ts"],"names":[],"mappings":"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","sourcesContent":["import { createInputsForField, joinPaths } from './utils.js';\nimport { Field, mandatory, single } from './validation.js';\n\nconst DEFAULT_BASE = 'https://pay.ponchopay.com/';\n\nexport abstract class PpForm extends HTMLElement {\n private readonly path: string;\n private readonly label: string;\n private readonly fields: Record<string, Field>;\n\n protected constructor(\n path: string,\n label: string,\n fields: Record<string, Field>\n ) {\n super();\n this.path = path;\n this.label = label;\n this.fields = { ...fields, token: mandatory(single()) };\n this.attachShadow({ mode: 'open' });\n }\n\n private getAttributeWithFallback(name: string, fallback: string): string {\n return this.getAttribute(name) ?? fallback;\n }\n\n private isAttributeSet(name: string): boolean {\n return this.getAttributeWithFallback(name, '').length > 0;\n }\n\n private syncAttributes(): void {\n const form = this.shadowRoot!.querySelector('form');\n if (form) {\n const base = this.getAttributeWithFallback('base', DEFAULT_BASE);\n\n form.action = joinPaths(base, this.path);\n form.replaceChildren();\n\n Object.entries(this.fields).forEach(([attribute, field]) => {\n if (field.type === 'array') {\n const matchingAttributes = Array.from(this.attributes).filter(attr =>\n attr.name.startsWith(`${attribute}.`)\n );\n\n matchingAttributes.forEach(attr => {\n const parts = attr.name.split('.');\n const fieldName = parts[parts.length - 1];\n\n const subField = field.schema?.[fieldName];\n if (!subField) return;\n\n createInputsForField(form, attr.name, attr.value, subField.type);\n });\n\n return;\n }\n\n if (this.hasAttribute(attribute)) {\n const attr = this.getAttribute(attribute)!;\n createInputsForField(form, attribute, attr, field.type);\n }\n });\n\n const slot = document.createElement('slot');\n slot.innerHTML = this.label;\n\n const button = document.createElement('button');\n button.setAttribute('part', 'button');\n button.type = 'submit';\n button.appendChild(slot);\n form.appendChild(button);\n }\n }\n\n private showErrorMessage(): void {\n const form = this.shadowRoot!.querySelector('form');\n if (form) {\n form.querySelector('div')?.remove();\n\n const div = document.createElement('div');\n div.setAttribute('part', 'error');\n div.className = 'error';\n div.innerHTML = 'Some attributes are incorrect. Please, review them.';\n form.appendChild(div);\n }\n }\n\n public connectedCallback(): void {\n const base = this.getAttributeWithFallback('base', DEFAULT_BASE);\n\n const style = document.createElement('style');\n style.textContent = `\n form {\n display: contents;\n }\n\n button {\n width: 100%;\n background-color: #02C2A0;\n white-space: nowrap;\n text-decoration-line: none;\n border-radius: .25rem;\n box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n text-align: center;\n font-size: 1.25rem;\n line-height: 1.75rem;\n color: white;\n margin-top: .5rem;\n margin-bottom: .75rem;\n padding: .75rem 1rem;\n display: flex;\n flex-wrap: nowrap;\n align-items: center;\n justify-content: space-evenly;\n cursor: pointer;\n text-transform: none;\n box-sizing: border-box;\n border-width: 0;\n border-style: solid;\n border-color: currentColor;\n }\n\n div.error {\n color: #EB3B50;\n font-size: 0.875rem;\n }`;\n\n const form = document.createElement('form');\n form.action = joinPaths(base, this.path);\n form.method = 'post';\n form.onsubmit = event => {\n if (!this.checkValidity()) {\n event.preventDefault();\n this.showErrorMessage();\n }\n };\n this.shadowRoot!.append(style, form);\n\n this.syncAttributes();\n }\n\n public disconnectedCallback(): void {\n this.shadowRoot!.replaceChildren();\n }\n\n public attributeChangedCallback(): void {\n this.syncAttributes();\n }\n\n public submit(): void {\n this.shadowRoot!.querySelector('form')?.requestSubmit();\n }\n\n private validateField(fieldPath: string, field: Field): boolean {\n if (field.required === true) {\n return this.isAttributeSet(fieldPath);\n }\n\n if (Array.isArray(field.required)) {\n const [dependant, value] = field.required;\n\n if (\n (value === true || this.getAttribute(dependant) === value) &&\n this.isAttributeSet(dependant)\n ) {\n return this.isAttributeSet(fieldPath);\n }\n }\n\n return true;\n }\n\n public checkArrayIsValid(attribute: string, field: Field): boolean {\n const matchingAttributes = Array.from(this.attributes).filter(attr =>\n attr.name.startsWith(`${attribute}.`)\n );\n\n const indexes = matchingAttributes.map(attr => {\n const match = attr.name.match(new RegExp(`^${attribute}\\\\.(\\\\d+)\\\\.`));\n return match ? parseInt(match[1], 10) : null;\n });\n\n const uniqueIndexes = Array.from(new Set(indexes));\n\n // If array is required and no items exist fail validation\n if (field.required === true && uniqueIndexes.length === 0) {\n return false;\n }\n\n // If no items exist but array is optional, validation passes\n if (uniqueIndexes.length === 0) {\n return true;\n }\n\n return uniqueIndexes.every(index =>\n Object.entries(field.schema!).every(([key, subField]) => {\n const fullPath = `${attribute}.${index}.${key}`;\n return this.validateField(fullPath, subField);\n })\n );\n }\n\n public checkValidity(): boolean {\n return Object.entries(this.fields).every(\n ([attribute, { type, schema, required }]) => {\n if (type === 'array') {\n return this.checkArrayIsValid(attribute, {\n type,\n schema,\n required,\n });\n }\n\n return this.validateField(attribute, { type, required, schema });\n }\n );\n }\n\n public static get observedAttributes() {\n return ['base', 'token'];\n }\n}\n"]}
|
package/dist/src/PpPayment.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PpForm } from './PpForm.js';
|
|
2
|
-
import { mandatory, optional, single } from './validation.js';
|
|
2
|
+
import { array, mandatory, optional, single } from './validation.js';
|
|
3
3
|
const fields = {
|
|
4
4
|
amount: mandatory(single()),
|
|
5
5
|
metadata: mandatory(single()),
|
|
@@ -8,6 +8,11 @@ const fields = {
|
|
|
8
8
|
note: optional(single()),
|
|
9
9
|
expiry: optional(single()),
|
|
10
10
|
'constraints.minimum_card_amount': optional(single()),
|
|
11
|
+
line_items: optional(array({
|
|
12
|
+
quantity: mandatory(single()),
|
|
13
|
+
amount: mandatory(single()),
|
|
14
|
+
description: mandatory(single()),
|
|
15
|
+
})),
|
|
11
16
|
};
|
|
12
17
|
export class PpPayment extends PpForm {
|
|
13
18
|
constructor() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PpPayment.js","sourceRoot":"","sources":["../../src/PpPayment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"PpPayment.js","sourceRoot":"","sources":["../../src/PpPayment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAErE,MAAM,MAAM,GAAG;IACb,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC;IAC3B,QAAQ,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC;IAC7B,GAAG,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC;IACxB,KAAK,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC;IAC1B,IAAI,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;IACxB,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;IAC1B,iCAAiC,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;IACrD,UAAU,EAAE,QAAQ,CAClB,KAAK,CAAC;QACJ,QAAQ,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC;QAC7B,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC;QAC3B,WAAW,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC;KACjC,CAAC,CACH;CACF,CAAC;AAEF,MAAM,OAAO,SAAU,SAAQ,MAAM;IACnC;QACE,KAAK,CAAC,mCAAmC,EAAE,oBAAoB,EAAE,MAAM,CAAC,CAAC;IAC3E,CAAC;IAEM,MAAM,KAAK,kBAAkB;QAClC,OAAO,CAAC,GAAG,MAAM,CAAC,kBAAkB,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAChE,CAAC;CACF","sourcesContent":["import { PpForm } from './PpForm.js';\nimport { array, mandatory, optional, single } from './validation.js';\n\nconst fields = {\n amount: mandatory(single()),\n metadata: mandatory(single()),\n urn: mandatory(single()),\n email: mandatory(single()),\n note: optional(single()),\n expiry: optional(single()),\n 'constraints.minimum_card_amount': optional(single()),\n line_items: optional(\n array({\n quantity: mandatory(single()),\n amount: mandatory(single()),\n description: mandatory(single()),\n })\n ),\n};\n\nexport class PpPayment extends PpForm {\n public constructor() {\n super('/api/integration/generic/initiate', 'Pay with PonchoPay', fields);\n }\n\n public static get observedAttributes() {\n return [...PpForm.observedAttributes, ...Object.keys(fields)];\n }\n}\n"]}
|
package/dist/src/utils.d.ts
CHANGED
|
@@ -11,3 +11,7 @@ export declare function formatName(name: string): string;
|
|
|
11
11
|
* Splits a haystack by the needle. If the haystack is an empty string, it will return an empty array
|
|
12
12
|
*/
|
|
13
13
|
export declare function split(haystack: string, needle: string): string[];
|
|
14
|
+
/**
|
|
15
|
+
* Creates hidden input elements for a field and appends them to the form
|
|
16
|
+
*/
|
|
17
|
+
export declare function createInputsForField(form: HTMLFormElement, attributeName: string, attributeValue: string, fieldType: 'single' | 'multiple' | 'array'): void;
|
package/dist/src/utils.js
CHANGED
|
@@ -38,4 +38,22 @@ export function split(haystack, needle) {
|
|
|
38
38
|
}
|
|
39
39
|
return haystack.split(needle);
|
|
40
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Creates hidden input elements for a field and appends them to the form
|
|
43
|
+
*/
|
|
44
|
+
export function createInputsForField(form, attributeName, attributeValue, fieldType) {
|
|
45
|
+
let name = formatName(attributeName);
|
|
46
|
+
let values = attributeValue.length > 0 ? [attributeValue] : [];
|
|
47
|
+
if (fieldType === 'multiple') {
|
|
48
|
+
name = `${name}[]`;
|
|
49
|
+
values = split(attributeValue, ',');
|
|
50
|
+
}
|
|
51
|
+
values.forEach(value => {
|
|
52
|
+
const input = document.createElement('input');
|
|
53
|
+
input.type = 'hidden';
|
|
54
|
+
input.name = name;
|
|
55
|
+
input.value = value;
|
|
56
|
+
form.appendChild(input);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
41
59
|
//# sourceMappingURL=utils.js.map
|
package/dist/src/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,SAAS,SAAS,CAAC,QAAgB,EAAE,MAAc;IACjD,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,KAAK,MAAM,IAAI,CAAC,CAAC;IAC1C,OAAO,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,SAAS,OAAO,CAAC,QAAgB,EAAE,MAAc;IAC/C,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,IAAI,MAAM,KAAK,CAAC,CAAC;IAC1C,OAAO,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,KAAa;IACnD,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC;AAC1D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,MAAM,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACxC,IAAI,UAAU,GAAG,EAAE,CAAC;IACpB,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE;QACnB,UAAU,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;KACrC;IAED,OAAO,GAAG,IAAI,GAAG,UAAU,EAAE,CAAC;AAChC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,KAAK,CAAC,QAAgB,EAAE,MAAc;IACpD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE;QACzB,OAAO,EAAE,CAAC;KACX;IAED,OAAO,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AAChC,CAAC","sourcesContent":["export type Maybe<T> = T | undefined;\n\n/**\n * Clears the start of the string from any matching character\n */\nfunction trimStart(haystack: string, needle: string): string {\n const regex = new RegExp(`^[${needle}]+`);\n return haystack.replace(regex, '');\n}\n\n/**\n * Clears the end of the string from any matching character\n */\nfunction trimEnd(haystack: string, needle: string): string {\n const regex = new RegExp(`[${needle}]+$`);\n return haystack.replace(regex, '');\n}\n\n/**\n * Joins two paths with a single forward slash in the middle\n */\nexport function joinPaths(left: string, right: string): string {\n return `${trimEnd(left, '/')}/${trimStart(right, '/')}`;\n}\n\n/**\n * Prepares the property name for the API's format\n */\nexport function formatName(name: string): string {\n const [root, ...path] = name.split('.');\n let properties = '';\n if (path.length > 0) {\n properties = `[${path.join('][')}]`;\n }\n\n return `${root}${properties}`;\n}\n\n/**\n * Splits a haystack by the needle. If the haystack is an empty string, it will return an empty array\n */\nexport function split(haystack: string, needle: string): string[] {\n if (haystack.length === 0) {\n return [];\n }\n\n return haystack.split(needle);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,SAAS,SAAS,CAAC,QAAgB,EAAE,MAAc;IACjD,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,KAAK,MAAM,IAAI,CAAC,CAAC;IAC1C,OAAO,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,SAAS,OAAO,CAAC,QAAgB,EAAE,MAAc;IAC/C,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,IAAI,MAAM,KAAK,CAAC,CAAC;IAC1C,OAAO,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,KAAa;IACnD,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC;AAC1D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,MAAM,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACxC,IAAI,UAAU,GAAG,EAAE,CAAC;IACpB,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE;QACnB,UAAU,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;KACrC;IAED,OAAO,GAAG,IAAI,GAAG,UAAU,EAAE,CAAC;AAChC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,KAAK,CAAC,QAAgB,EAAE,MAAc;IACpD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE;QACzB,OAAO,EAAE,CAAC;KACX;IAED,OAAO,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AAChC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAClC,IAAqB,EACrB,aAAqB,EACrB,cAAsB,EACtB,SAA0C;IAE1C,IAAI,IAAI,GAAG,UAAU,CAAC,aAAa,CAAC,CAAC;IACrC,IAAI,MAAM,GAAG,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAE/D,IAAI,SAAS,KAAK,UAAU,EAAE;QAC5B,IAAI,GAAG,GAAG,IAAI,IAAI,CAAC;QACnB,MAAM,GAAG,KAAK,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;KACrC;IAED,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;QACrB,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAC9C,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC;QACtB,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;QAClB,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["export type Maybe<T> = T | undefined;\n\n/**\n * Clears the start of the string from any matching character\n */\nfunction trimStart(haystack: string, needle: string): string {\n const regex = new RegExp(`^[${needle}]+`);\n return haystack.replace(regex, '');\n}\n\n/**\n * Clears the end of the string from any matching character\n */\nfunction trimEnd(haystack: string, needle: string): string {\n const regex = new RegExp(`[${needle}]+$`);\n return haystack.replace(regex, '');\n}\n\n/**\n * Joins two paths with a single forward slash in the middle\n */\nexport function joinPaths(left: string, right: string): string {\n return `${trimEnd(left, '/')}/${trimStart(right, '/')}`;\n}\n\n/**\n * Prepares the property name for the API's format\n */\nexport function formatName(name: string): string {\n const [root, ...path] = name.split('.');\n let properties = '';\n if (path.length > 0) {\n properties = `[${path.join('][')}]`;\n }\n\n return `${root}${properties}`;\n}\n\n/**\n * Splits a haystack by the needle. If the haystack is an empty string, it will return an empty array\n */\nexport function split(haystack: string, needle: string): string[] {\n if (haystack.length === 0) {\n return [];\n }\n\n return haystack.split(needle);\n}\n\n/**\n * Creates hidden input elements for a field and appends them to the form\n */\nexport function createInputsForField(\n form: HTMLFormElement,\n attributeName: string,\n attributeValue: string,\n fieldType: 'single' | 'multiple' | 'array'\n): void {\n let name = formatName(attributeName);\n let values = attributeValue.length > 0 ? [attributeValue] : [];\n\n if (fieldType === 'multiple') {\n name = `${name}[]`;\n values = split(attributeValue, ',');\n }\n\n values.forEach(value => {\n const input = document.createElement('input');\n input.type = 'hidden';\n input.name = name;\n input.value = value;\n form.appendChild(input);\n });\n}\n"]}
|
package/dist/src/validation.d.ts
CHANGED
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
* is a string, it also needs to match that value. Optional otherwise.
|
|
11
11
|
*/
|
|
12
12
|
export type Field = {
|
|
13
|
-
|
|
13
|
+
type: 'single' | 'multiple' | 'array';
|
|
14
14
|
required: boolean | [string, string | true];
|
|
15
|
+
schema?: Record<string, Field>;
|
|
15
16
|
};
|
|
16
17
|
/**
|
|
17
18
|
* Marks the attribute as representing a single value.
|
|
@@ -35,3 +36,4 @@ export declare function optional(attribute: Field): Field;
|
|
|
35
36
|
* Marks the attribute's requirement as dependant on another attribute's existance.
|
|
36
37
|
*/
|
|
37
38
|
export declare function dependant(name: string, value: string | true, attribute: Field): Field;
|
|
39
|
+
export declare function array(itemSchema: Record<string, Field>): Field;
|
package/dist/src/validation.js
CHANGED
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
* Note: By default it makes the attribute optional. Use the other functions to change this.
|
|
4
4
|
*/
|
|
5
5
|
export function single() {
|
|
6
|
-
return {
|
|
6
|
+
return { type: 'single', required: false };
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
9
|
* Marks the attribute as representing multiple values.
|
|
10
10
|
* Note: By default it makes the attribute optional. Use the other functions to change this.
|
|
11
11
|
*/
|
|
12
12
|
export function multiple() {
|
|
13
|
-
return {
|
|
13
|
+
return { type: 'multiple', required: false };
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
16
|
* Marks the attribute as mandatory.
|
|
@@ -30,4 +30,7 @@ export function optional(attribute) {
|
|
|
30
30
|
export function dependant(name, value, attribute) {
|
|
31
31
|
return { ...attribute, required: [name, value] };
|
|
32
32
|
}
|
|
33
|
+
export function array(itemSchema) {
|
|
34
|
+
return { type: 'array', required: false, schema: itemSchema };
|
|
35
|
+
}
|
|
33
36
|
//# sourceMappingURL=validation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/validation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/validation.ts"],"names":[],"mappings":"AAiBA;;;GAGG;AACH,MAAM,UAAU,MAAM;IACpB,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAC7C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ;IACtB,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAC/C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,SAAgB;IACxC,OAAO,EAAE,GAAG,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAC1C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,SAAgB;IACvC,OAAO,EAAE,GAAG,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAC3C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CACvB,IAAY,EACZ,KAAoB,EACpB,SAAgB;IAEhB,OAAO,EAAE,GAAG,SAAS,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,UAAiC;IACrD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AAChE,CAAC","sourcesContent":["/**\n * Collection: Whether the attribute is expected to have comma-separated values ot nor.\n * - false: Single\n * - true: Multiple\n *\n * Required: Whether the attribute is required to submit the form or not.\n * - false: Optional\n * - true: Mandatory\n * - [string, string | true]: Mandatory if the attribute in the first index is set. If the second\n * is a string, it also needs to match that value. Optional otherwise.\n */\nexport type Field = {\n type: 'single' | 'multiple' | 'array';\n required: boolean | [string, string | true];\n schema?: Record<string, Field>;\n};\n\n/**\n * Marks the attribute as representing a single value.\n * Note: By default it makes the attribute optional. Use the other functions to change this.\n */\nexport function single(): Field {\n return { type: 'single', required: false };\n}\n\n/**\n * Marks the attribute as representing multiple values.\n * Note: By default it makes the attribute optional. Use the other functions to change this.\n */\nexport function multiple(): Field {\n return { type: 'multiple', required: false };\n}\n\n/**\n * Marks the attribute as mandatory.\n */\nexport function mandatory(attribute: Field): Field {\n return { ...attribute, required: true };\n}\n\n/**\n * Marks the attribute as optional.\n */\nexport function optional(attribute: Field): Field {\n return { ...attribute, required: false };\n}\n\n/**\n * Marks the attribute's requirement as dependant on another attribute's existance.\n */\nexport function dependant(\n name: string,\n value: string | true,\n attribute: Field\n): Field {\n return { ...attribute, required: [name, value] };\n}\n\nexport function array(itemSchema: Record<string, Field>): Field {\n return { type: 'array', required: false, schema: itemSchema };\n}\n"]}
|