@drawbridge/drawbridge-utils 0.0.102 → 0.0.104
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/ai.cjs +4 -0
- package/dist/ai.js +4 -0
- package/dist/billing.cjs +16 -0
- package/dist/billing.d.cts +7 -1
- package/dist/billing.d.ts +7 -1
- package/dist/billing.js +10 -0
- package/dist/features.cjs +5 -0
- package/dist/features.d.cts +5 -0
- package/dist/features.d.ts +5 -0
- package/dist/features.js +5 -0
- package/dist/fields-validate.cjs +121 -0
- package/dist/fields-validate.d.cts +116 -0
- package/dist/fields-validate.d.ts +116 -0
- package/dist/fields-validate.js +94 -0
- package/dist/plans.cjs +40 -8
- package/dist/plans.d.cts +58 -8
- package/dist/plans.d.ts +58 -8
- package/dist/plans.js +38 -7
- package/dist/pricing.cjs +807 -0
- package/dist/pricing.d.cts +72 -0
- package/dist/pricing.d.ts +72 -0
- package/dist/pricing.js +757 -0
- package/package.json +14 -3
package/dist/ai.cjs
CHANGED
|
@@ -268,6 +268,10 @@ var billRequest = async ({ db, user, model, usage, tools }) => {
|
|
|
268
268
|
});
|
|
269
269
|
};
|
|
270
270
|
var ai = {
|
|
271
|
+
// The rate tables themselves, in cents per 1,000,000 tokens (`tools` in cents
|
|
272
|
+
// per request). Read-only surface for lib/pricing.js — the fee math above is
|
|
273
|
+
// still the only thing that should compute from them.
|
|
274
|
+
rates: { wholesale: cost, retail: pricing, tools: { wholesale: toolCost, retail: toolPricing } },
|
|
271
275
|
// Retail cents for a request (what the user pays).
|
|
272
276
|
price: priceForRequest,
|
|
273
277
|
// Wholesale cents for a request (what we pay the provider).
|
package/dist/ai.js
CHANGED
|
@@ -234,6 +234,10 @@ var billRequest = async ({ db, user, model, usage, tools }) => {
|
|
|
234
234
|
});
|
|
235
235
|
};
|
|
236
236
|
var ai = {
|
|
237
|
+
// The rate tables themselves, in cents per 1,000,000 tokens (`tools` in cents
|
|
238
|
+
// per request). Read-only surface for lib/pricing.js — the fee math above is
|
|
239
|
+
// still the only thing that should compute from them.
|
|
240
|
+
rates: { wholesale: cost, retail: pricing, tools: { wholesale: toolCost, retail: toolPricing } },
|
|
237
241
|
// Retail cents for a request (what the user pays).
|
|
238
242
|
price: priceForRequest,
|
|
239
243
|
// Wholesale cents for a request (what we pay the provider).
|
package/dist/billing.cjs
CHANGED
|
@@ -19,7 +19,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
19
19
|
// lib/billing.js
|
|
20
20
|
var billing_exports = {};
|
|
21
21
|
__export(billing_exports, {
|
|
22
|
+
LOCAL_FLAT_CENTS: () => LOCAL_FLAT_CENTS,
|
|
22
23
|
MARKUP: () => MARKUP,
|
|
24
|
+
PREMIUM_CPM_CENTS: () => PREMIUM_CPM_CENTS,
|
|
25
|
+
PREMIUM_RATE_PER_GB: () => PREMIUM_RATE_PER_GB,
|
|
26
|
+
REUSE_FLAT_CENTS: () => REUSE_FLAT_CENTS,
|
|
27
|
+
STANDARD_CPM_CENTS: () => STANDARD_CPM_CENTS,
|
|
28
|
+
STANDARD_RATE_PER_GB: () => STANDARD_RATE_PER_GB,
|
|
23
29
|
action: () => action,
|
|
24
30
|
ai: () => ai,
|
|
25
31
|
balance: () => balance,
|
|
@@ -268,6 +274,10 @@ var billRequest = async ({ db, user, model, usage, tools }) => {
|
|
|
268
274
|
});
|
|
269
275
|
};
|
|
270
276
|
var ai = {
|
|
277
|
+
// The rate tables themselves, in cents per 1,000,000 tokens (`tools` in cents
|
|
278
|
+
// per request). Read-only surface for lib/pricing.js — the fee math above is
|
|
279
|
+
// still the only thing that should compute from them.
|
|
280
|
+
rates: { wholesale: cost, retail: pricing, tools: { wholesale: toolCost, retail: toolPricing } },
|
|
271
281
|
// Retail cents for a request (what the user pays).
|
|
272
282
|
price: priceForRequest,
|
|
273
283
|
// Wholesale cents for a request (what we pay the provider).
|
|
@@ -511,7 +521,13 @@ var action = {
|
|
|
511
521
|
};
|
|
512
522
|
// Annotate the CommonJS export names for ESM import in node:
|
|
513
523
|
0 && (module.exports = {
|
|
524
|
+
LOCAL_FLAT_CENTS,
|
|
514
525
|
MARKUP,
|
|
526
|
+
PREMIUM_CPM_CENTS,
|
|
527
|
+
PREMIUM_RATE_PER_GB,
|
|
528
|
+
REUSE_FLAT_CENTS,
|
|
529
|
+
STANDARD_CPM_CENTS,
|
|
530
|
+
STANDARD_RATE_PER_GB,
|
|
515
531
|
action,
|
|
516
532
|
ai,
|
|
517
533
|
balance,
|
package/dist/billing.d.cts
CHANGED
|
@@ -185,6 +185,11 @@ const billRequest = async ({ db, user, model, usage, tools }) => {
|
|
|
185
185
|
|
|
186
186
|
const ai = {
|
|
187
187
|
|
|
188
|
+
// The rate tables themselves, in cents per 1,000,000 tokens (`tools` in cents
|
|
189
|
+
// per request). Read-only surface for lib/pricing.js — the fee math above is
|
|
190
|
+
// still the only thing that should compute from them.
|
|
191
|
+
rates : { wholesale : cost, retail : pricing, tools : { wholesale : toolCost, retail : toolPricing } },
|
|
192
|
+
|
|
188
193
|
// Retail cents for a request (what the user pays).
|
|
189
194
|
price : priceForRequest,
|
|
190
195
|
|
|
@@ -211,6 +216,7 @@ const ai = {
|
|
|
211
216
|
// Both carry the same 30% margin (MARKUP). A cold local render and a cache reuse
|
|
212
217
|
// have no external cost, so they're small flat fees (set to 0 to make either
|
|
213
218
|
// free). Tune the rates against real BrightData invoices.
|
|
219
|
+
// Exported so lib/pricing.js can index every customer-facing rate in one place.
|
|
214
220
|
const STANDARD_RATE_PER_GB = 8;
|
|
215
221
|
const PREMIUM_RATE_PER_GB = 11;
|
|
216
222
|
// Web Unlocker CPM in cents-per-request: $1.50/1,000 = 0.15¢, $2.50/1,000 = 0.25¢.
|
|
@@ -577,4 +583,4 @@ const action = {
|
|
|
577
583
|
|
|
578
584
|
};
|
|
579
585
|
|
|
580
|
-
export { MARKUP, action, ai, balance, grant, scrape };
|
|
586
|
+
export { LOCAL_FLAT_CENTS, MARKUP, PREMIUM_CPM_CENTS, PREMIUM_RATE_PER_GB, REUSE_FLAT_CENTS, STANDARD_CPM_CENTS, STANDARD_RATE_PER_GB, action, ai, balance, grant, scrape };
|
package/dist/billing.d.ts
CHANGED
|
@@ -185,6 +185,11 @@ const billRequest = async ({ db, user, model, usage, tools }) => {
|
|
|
185
185
|
|
|
186
186
|
const ai = {
|
|
187
187
|
|
|
188
|
+
// The rate tables themselves, in cents per 1,000,000 tokens (`tools` in cents
|
|
189
|
+
// per request). Read-only surface for lib/pricing.js — the fee math above is
|
|
190
|
+
// still the only thing that should compute from them.
|
|
191
|
+
rates : { wholesale : cost, retail : pricing, tools : { wholesale : toolCost, retail : toolPricing } },
|
|
192
|
+
|
|
188
193
|
// Retail cents for a request (what the user pays).
|
|
189
194
|
price : priceForRequest,
|
|
190
195
|
|
|
@@ -211,6 +216,7 @@ const ai = {
|
|
|
211
216
|
// Both carry the same 30% margin (MARKUP). A cold local render and a cache reuse
|
|
212
217
|
// have no external cost, so they're small flat fees (set to 0 to make either
|
|
213
218
|
// free). Tune the rates against real BrightData invoices.
|
|
219
|
+
// Exported so lib/pricing.js can index every customer-facing rate in one place.
|
|
214
220
|
const STANDARD_RATE_PER_GB = 8;
|
|
215
221
|
const PREMIUM_RATE_PER_GB = 11;
|
|
216
222
|
// Web Unlocker CPM in cents-per-request: $1.50/1,000 = 0.15¢, $2.50/1,000 = 0.25¢.
|
|
@@ -577,4 +583,4 @@ const action = {
|
|
|
577
583
|
|
|
578
584
|
};
|
|
579
585
|
|
|
580
|
-
export { MARKUP, action, ai, balance, grant, scrape };
|
|
586
|
+
export { LOCAL_FLAT_CENTS, MARKUP, PREMIUM_CPM_CENTS, PREMIUM_RATE_PER_GB, REUSE_FLAT_CENTS, STANDARD_CPM_CENTS, STANDARD_RATE_PER_GB, action, ai, balance, grant, scrape };
|
package/dist/billing.js
CHANGED
|
@@ -238,6 +238,10 @@ var billRequest = async ({ db, user, model, usage, tools }) => {
|
|
|
238
238
|
});
|
|
239
239
|
};
|
|
240
240
|
var ai = {
|
|
241
|
+
// The rate tables themselves, in cents per 1,000,000 tokens (`tools` in cents
|
|
242
|
+
// per request). Read-only surface for lib/pricing.js — the fee math above is
|
|
243
|
+
// still the only thing that should compute from them.
|
|
244
|
+
rates: { wholesale: cost, retail: pricing, tools: { wholesale: toolCost, retail: toolPricing } },
|
|
241
245
|
// Retail cents for a request (what the user pays).
|
|
242
246
|
price: priceForRequest,
|
|
243
247
|
// Wholesale cents for a request (what we pay the provider).
|
|
@@ -480,7 +484,13 @@ var action = {
|
|
|
480
484
|
}
|
|
481
485
|
};
|
|
482
486
|
export {
|
|
487
|
+
LOCAL_FLAT_CENTS,
|
|
483
488
|
MARKUP,
|
|
489
|
+
PREMIUM_CPM_CENTS,
|
|
490
|
+
PREMIUM_RATE_PER_GB,
|
|
491
|
+
REUSE_FLAT_CENTS,
|
|
492
|
+
STANDARD_CPM_CENTS,
|
|
493
|
+
STANDARD_RATE_PER_GB,
|
|
484
494
|
action,
|
|
485
495
|
ai,
|
|
486
496
|
balance,
|
package/dist/features.cjs
CHANGED
|
@@ -99,6 +99,11 @@ var connection = {
|
|
|
99
99
|
error: "Plan does not include Mailchimp connection",
|
|
100
100
|
feature: "Mailchimp connection"
|
|
101
101
|
},
|
|
102
|
+
sender: {
|
|
103
|
+
key: "organization:connection:sender",
|
|
104
|
+
error: "Plan does not include a verified sending domain",
|
|
105
|
+
feature: "Sending domain connection"
|
|
106
|
+
},
|
|
102
107
|
sendgrid: {
|
|
103
108
|
key: "organization:connection:sendgrid",
|
|
104
109
|
error: "Plan does not include SendGrid connection",
|
package/dist/features.d.cts
CHANGED
|
@@ -73,6 +73,11 @@ const connection = {
|
|
|
73
73
|
error : 'Plan does not include Mailchimp connection',
|
|
74
74
|
feature : 'Mailchimp connection'
|
|
75
75
|
},
|
|
76
|
+
sender : {
|
|
77
|
+
key : 'organization:connection:sender',
|
|
78
|
+
error : 'Plan does not include a verified sending domain',
|
|
79
|
+
feature : 'Sending domain connection'
|
|
80
|
+
},
|
|
76
81
|
sendgrid : {
|
|
77
82
|
key : 'organization:connection:sendgrid',
|
|
78
83
|
error : 'Plan does not include SendGrid connection',
|
package/dist/features.d.ts
CHANGED
|
@@ -73,6 +73,11 @@ const connection = {
|
|
|
73
73
|
error : 'Plan does not include Mailchimp connection',
|
|
74
74
|
feature : 'Mailchimp connection'
|
|
75
75
|
},
|
|
76
|
+
sender : {
|
|
77
|
+
key : 'organization:connection:sender',
|
|
78
|
+
error : 'Plan does not include a verified sending domain',
|
|
79
|
+
feature : 'Sending domain connection'
|
|
80
|
+
},
|
|
76
81
|
sendgrid : {
|
|
77
82
|
key : 'organization:connection:sendgrid',
|
|
78
83
|
error : 'Plan does not include SendGrid connection',
|
package/dist/features.js
CHANGED
|
@@ -71,6 +71,11 @@ var connection = {
|
|
|
71
71
|
error: "Plan does not include Mailchimp connection",
|
|
72
72
|
feature: "Mailchimp connection"
|
|
73
73
|
},
|
|
74
|
+
sender: {
|
|
75
|
+
key: "organization:connection:sender",
|
|
76
|
+
error: "Plan does not include a verified sending domain",
|
|
77
|
+
feature: "Sending domain connection"
|
|
78
|
+
},
|
|
74
79
|
sendgrid: {
|
|
75
80
|
key: "organization:connection:sendgrid",
|
|
76
81
|
error: "Plan does not include SendGrid connection",
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
|
|
19
|
+
// lib/fields-validate.js
|
|
20
|
+
var fields_validate_exports = {};
|
|
21
|
+
__export(fields_validate_exports, {
|
|
22
|
+
errors: () => errors,
|
|
23
|
+
validators: () => validators
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(fields_validate_exports);
|
|
26
|
+
|
|
27
|
+
// lib/phone.js
|
|
28
|
+
var import_libphonenumber_js = require("libphonenumber-js");
|
|
29
|
+
var isValid = (value, country) => {
|
|
30
|
+
if (!value) return false;
|
|
31
|
+
try {
|
|
32
|
+
return (0, import_libphonenumber_js.isValidPhoneNumber)(String(value), country);
|
|
33
|
+
} catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// lib/fields-validate.js
|
|
39
|
+
var errors = {
|
|
40
|
+
country: "Field is not an accepted value",
|
|
41
|
+
email: "Field value must be a valid email",
|
|
42
|
+
length: (length) => "Field must be less than or equal to " + length + " characters",
|
|
43
|
+
max: (val) => "Field value must be less than or equal to " + val,
|
|
44
|
+
min: (val) => "Field value must be greater than or equal to " + val,
|
|
45
|
+
option: "Field is not an accepted value",
|
|
46
|
+
phone: "Field value is not valid",
|
|
47
|
+
required: "Field is required"
|
|
48
|
+
};
|
|
49
|
+
var required = (field, schema) => {
|
|
50
|
+
var _a;
|
|
51
|
+
return ((_a = field == null ? void 0 : field.attributes) == null ? void 0 : _a.required) === false ? schema.nullable() : schema.required(errors.required);
|
|
52
|
+
};
|
|
53
|
+
var validators = {
|
|
54
|
+
// An agreement that is not required is not an agreement - consent stays
|
|
55
|
+
// affirmative regardless of the toggle.
|
|
56
|
+
agreement: (field, yup) => {
|
|
57
|
+
return yup.bool().required(errors.required).oneOf([true], errors.required);
|
|
58
|
+
},
|
|
59
|
+
email: (field, yup) => {
|
|
60
|
+
const max = 320;
|
|
61
|
+
return required(field, yup.string().email(errors.email).max(max, errors.length(max)));
|
|
62
|
+
},
|
|
63
|
+
name: (field, yup) => {
|
|
64
|
+
var _a;
|
|
65
|
+
const max = 150;
|
|
66
|
+
const object = (((_a = field == null ? void 0 : field.settings) == null ? void 0 : _a.capture) || []).reduce(
|
|
67
|
+
(accumulator, item) => {
|
|
68
|
+
accumulator[item] = yup.string().required(errors.required).max(max, errors.length(max));
|
|
69
|
+
return accumulator;
|
|
70
|
+
},
|
|
71
|
+
{}
|
|
72
|
+
);
|
|
73
|
+
return required(field, yup.object(object));
|
|
74
|
+
},
|
|
75
|
+
number: (field, yup) => {
|
|
76
|
+
var _a, _b, _c, _d, _e, _f;
|
|
77
|
+
let validate = yup.number();
|
|
78
|
+
if ((_a = field == null ? void 0 : field.attributes) == null ? void 0 : _a.min) {
|
|
79
|
+
validate = validate.min((_b = field == null ? void 0 : field.attributes) == null ? void 0 : _b.min, errors.min((_c = field == null ? void 0 : field.attributes) == null ? void 0 : _c.min));
|
|
80
|
+
}
|
|
81
|
+
;
|
|
82
|
+
if ((_d = field == null ? void 0 : field.attributes) == null ? void 0 : _d.max) {
|
|
83
|
+
validate = validate.max((_e = field == null ? void 0 : field.attributes) == null ? void 0 : _e.max, errors.max((_f = field == null ? void 0 : field.attributes) == null ? void 0 : _f.max));
|
|
84
|
+
}
|
|
85
|
+
;
|
|
86
|
+
return required(field, validate);
|
|
87
|
+
},
|
|
88
|
+
phone: (field, yup) => {
|
|
89
|
+
var _a;
|
|
90
|
+
return required(
|
|
91
|
+
field,
|
|
92
|
+
yup.object({
|
|
93
|
+
country: yup.string().required(errors.required).oneOf((_a = field == null ? void 0 : field.settings) == null ? void 0 : _a.countries, errors.country),
|
|
94
|
+
number: yup.string().required(errors.required)
|
|
95
|
+
}).test("phone", errors.phone, (value) => isValid(value == null ? void 0 : value.number, value == null ? void 0 : value.country))
|
|
96
|
+
);
|
|
97
|
+
},
|
|
98
|
+
// The in-list check the share form never had: the answer must be one of the
|
|
99
|
+
// field's own options. null rides the whitelist so an optional select can be
|
|
100
|
+
// left blank - required() still rejects null when the field is required.
|
|
101
|
+
select: (field, yup) => {
|
|
102
|
+
var _a;
|
|
103
|
+
const options = (((_a = field == null ? void 0 : field.settings) == null ? void 0 : _a.options) || []).map((item) => item == null ? void 0 : item.option);
|
|
104
|
+
return required(field, yup.string().oneOf([...options, null], errors.option));
|
|
105
|
+
},
|
|
106
|
+
text: (field, yup) => {
|
|
107
|
+
var _a;
|
|
108
|
+
const max = ((_a = field == null ? void 0 : field.attributes) == null ? void 0 : _a.max) || 150;
|
|
109
|
+
return required(field, yup.string().max(max, errors.length(max)));
|
|
110
|
+
},
|
|
111
|
+
textarea: (field, yup) => {
|
|
112
|
+
var _a;
|
|
113
|
+
const max = ((_a = field == null ? void 0 : field.attributes) == null ? void 0 : _a.max) || 150;
|
|
114
|
+
return required(field, yup.string().max(max, errors.length(max)));
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
118
|
+
0 && (module.exports = {
|
|
119
|
+
errors,
|
|
120
|
+
validators
|
|
121
|
+
});
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { isValid } from './phone.cjs';
|
|
2
|
+
import 'libphonenumber-js';
|
|
3
|
+
|
|
4
|
+
// Field validators shared by the share form (client) and the api submission
|
|
5
|
+
// route (server). They lived only in drawbridge-share, so every additional-field
|
|
6
|
+
// answer - number, select, text, textarea - was validated in the browser and
|
|
7
|
+
// stored as submitted; the api only ever validated lead fields.
|
|
8
|
+
//
|
|
9
|
+
// yup is passed in rather than imported so each consumer keeps its own copy
|
|
10
|
+
// (share bundles one, api has its own in lib/validate).
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
const errors = {
|
|
14
|
+
country : 'Field is not an accepted value',
|
|
15
|
+
email : 'Field value must be a valid email',
|
|
16
|
+
length : ( length ) => 'Field must be less than or equal to ' + length + ' characters',
|
|
17
|
+
max : ( val ) => 'Field value must be less than or equal to ' + val,
|
|
18
|
+
min : ( val ) => 'Field value must be greater than or equal to ' + val,
|
|
19
|
+
option : 'Field is not an accepted value',
|
|
20
|
+
phone : 'Field value is not valid',
|
|
21
|
+
required : 'Field is required'
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// Every stored attributes.required is currently true, so this is a no-op today -
|
|
25
|
+
// it is here so the optional-field toggle does not need a second pass over
|
|
26
|
+
// every builder.
|
|
27
|
+
const required = ( field, schema ) => ( field?.attributes?.required === false ) ? schema.nullable() : schema.required( errors.required );
|
|
28
|
+
|
|
29
|
+
const validators = {
|
|
30
|
+
// An agreement that is not required is not an agreement - consent stays
|
|
31
|
+
// affirmative regardless of the toggle.
|
|
32
|
+
agreement : ( field, yup ) => {
|
|
33
|
+
|
|
34
|
+
return yup.bool().required( errors.required ).oneOf( [ true ], errors.required );
|
|
35
|
+
|
|
36
|
+
},
|
|
37
|
+
email : ( field, yup ) => {
|
|
38
|
+
|
|
39
|
+
const max = 320;
|
|
40
|
+
|
|
41
|
+
return required( field, yup.string().email( errors.email ).max( max, errors.length( max ) ) );
|
|
42
|
+
|
|
43
|
+
},
|
|
44
|
+
name : ( field, yup ) => {
|
|
45
|
+
|
|
46
|
+
const max = 150;
|
|
47
|
+
|
|
48
|
+
const object = ( field?.settings?.capture || [] ).reduce(
|
|
49
|
+
( accumulator, item ) => {
|
|
50
|
+
|
|
51
|
+
accumulator[ item ] = yup.string().required( errors.required ).max( max, errors.length( max ) );
|
|
52
|
+
|
|
53
|
+
return accumulator;
|
|
54
|
+
|
|
55
|
+
},
|
|
56
|
+
{}
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
return required( field, yup.object( object ) );
|
|
60
|
+
|
|
61
|
+
},
|
|
62
|
+
number : ( field, yup ) => {
|
|
63
|
+
|
|
64
|
+
let validate = yup.number();
|
|
65
|
+
|
|
66
|
+
if( field?.attributes?.min ){
|
|
67
|
+
|
|
68
|
+
validate = validate.min( field?.attributes?.min, errors.min( field?.attributes?.min ) );
|
|
69
|
+
|
|
70
|
+
}
|
|
71
|
+
if( field?.attributes?.max ){
|
|
72
|
+
|
|
73
|
+
validate = validate.max( field?.attributes?.max, errors.max( field?.attributes?.max ) );
|
|
74
|
+
|
|
75
|
+
}
|
|
76
|
+
return required( field, validate );
|
|
77
|
+
|
|
78
|
+
},
|
|
79
|
+
phone : ( field, yup ) => {
|
|
80
|
+
|
|
81
|
+
return required(
|
|
82
|
+
field,
|
|
83
|
+
yup.object({
|
|
84
|
+
country : yup.string().required( errors.required ).oneOf( field?.settings?.countries, errors.country ),
|
|
85
|
+
number : yup.string().required( errors.required )
|
|
86
|
+
}).test( 'phone', errors.phone, ( value ) => isValid( value?.number, value?.country ) )
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
},
|
|
90
|
+
// The in-list check the share form never had: the answer must be one of the
|
|
91
|
+
// field's own options. null rides the whitelist so an optional select can be
|
|
92
|
+
// left blank - required() still rejects null when the field is required.
|
|
93
|
+
select : ( field, yup ) => {
|
|
94
|
+
|
|
95
|
+
const options = ( field?.settings?.options || [] ).map( ( item ) => item?.option );
|
|
96
|
+
|
|
97
|
+
return required( field, yup.string().oneOf( [ ...options, null ], errors.option ) );
|
|
98
|
+
|
|
99
|
+
},
|
|
100
|
+
text : ( field, yup ) => {
|
|
101
|
+
|
|
102
|
+
const max = field?.attributes?.max || 150;
|
|
103
|
+
|
|
104
|
+
return required( field, yup.string().max( max, errors.length( max ) ) );
|
|
105
|
+
|
|
106
|
+
},
|
|
107
|
+
textarea : ( field, yup ) => {
|
|
108
|
+
|
|
109
|
+
const max = field?.attributes?.max || 150;
|
|
110
|
+
|
|
111
|
+
return required( field, yup.string().max( max, errors.length( max ) ) );
|
|
112
|
+
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export { errors, validators };
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { isValid } from './phone.js';
|
|
2
|
+
import 'libphonenumber-js';
|
|
3
|
+
|
|
4
|
+
// Field validators shared by the share form (client) and the api submission
|
|
5
|
+
// route (server). They lived only in drawbridge-share, so every additional-field
|
|
6
|
+
// answer - number, select, text, textarea - was validated in the browser and
|
|
7
|
+
// stored as submitted; the api only ever validated lead fields.
|
|
8
|
+
//
|
|
9
|
+
// yup is passed in rather than imported so each consumer keeps its own copy
|
|
10
|
+
// (share bundles one, api has its own in lib/validate).
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
const errors = {
|
|
14
|
+
country : 'Field is not an accepted value',
|
|
15
|
+
email : 'Field value must be a valid email',
|
|
16
|
+
length : ( length ) => 'Field must be less than or equal to ' + length + ' characters',
|
|
17
|
+
max : ( val ) => 'Field value must be less than or equal to ' + val,
|
|
18
|
+
min : ( val ) => 'Field value must be greater than or equal to ' + val,
|
|
19
|
+
option : 'Field is not an accepted value',
|
|
20
|
+
phone : 'Field value is not valid',
|
|
21
|
+
required : 'Field is required'
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// Every stored attributes.required is currently true, so this is a no-op today -
|
|
25
|
+
// it is here so the optional-field toggle does not need a second pass over
|
|
26
|
+
// every builder.
|
|
27
|
+
const required = ( field, schema ) => ( field?.attributes?.required === false ) ? schema.nullable() : schema.required( errors.required );
|
|
28
|
+
|
|
29
|
+
const validators = {
|
|
30
|
+
// An agreement that is not required is not an agreement - consent stays
|
|
31
|
+
// affirmative regardless of the toggle.
|
|
32
|
+
agreement : ( field, yup ) => {
|
|
33
|
+
|
|
34
|
+
return yup.bool().required( errors.required ).oneOf( [ true ], errors.required );
|
|
35
|
+
|
|
36
|
+
},
|
|
37
|
+
email : ( field, yup ) => {
|
|
38
|
+
|
|
39
|
+
const max = 320;
|
|
40
|
+
|
|
41
|
+
return required( field, yup.string().email( errors.email ).max( max, errors.length( max ) ) );
|
|
42
|
+
|
|
43
|
+
},
|
|
44
|
+
name : ( field, yup ) => {
|
|
45
|
+
|
|
46
|
+
const max = 150;
|
|
47
|
+
|
|
48
|
+
const object = ( field?.settings?.capture || [] ).reduce(
|
|
49
|
+
( accumulator, item ) => {
|
|
50
|
+
|
|
51
|
+
accumulator[ item ] = yup.string().required( errors.required ).max( max, errors.length( max ) );
|
|
52
|
+
|
|
53
|
+
return accumulator;
|
|
54
|
+
|
|
55
|
+
},
|
|
56
|
+
{}
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
return required( field, yup.object( object ) );
|
|
60
|
+
|
|
61
|
+
},
|
|
62
|
+
number : ( field, yup ) => {
|
|
63
|
+
|
|
64
|
+
let validate = yup.number();
|
|
65
|
+
|
|
66
|
+
if( field?.attributes?.min ){
|
|
67
|
+
|
|
68
|
+
validate = validate.min( field?.attributes?.min, errors.min( field?.attributes?.min ) );
|
|
69
|
+
|
|
70
|
+
}
|
|
71
|
+
if( field?.attributes?.max ){
|
|
72
|
+
|
|
73
|
+
validate = validate.max( field?.attributes?.max, errors.max( field?.attributes?.max ) );
|
|
74
|
+
|
|
75
|
+
}
|
|
76
|
+
return required( field, validate );
|
|
77
|
+
|
|
78
|
+
},
|
|
79
|
+
phone : ( field, yup ) => {
|
|
80
|
+
|
|
81
|
+
return required(
|
|
82
|
+
field,
|
|
83
|
+
yup.object({
|
|
84
|
+
country : yup.string().required( errors.required ).oneOf( field?.settings?.countries, errors.country ),
|
|
85
|
+
number : yup.string().required( errors.required )
|
|
86
|
+
}).test( 'phone', errors.phone, ( value ) => isValid( value?.number, value?.country ) )
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
},
|
|
90
|
+
// The in-list check the share form never had: the answer must be one of the
|
|
91
|
+
// field's own options. null rides the whitelist so an optional select can be
|
|
92
|
+
// left blank - required() still rejects null when the field is required.
|
|
93
|
+
select : ( field, yup ) => {
|
|
94
|
+
|
|
95
|
+
const options = ( field?.settings?.options || [] ).map( ( item ) => item?.option );
|
|
96
|
+
|
|
97
|
+
return required( field, yup.string().oneOf( [ ...options, null ], errors.option ) );
|
|
98
|
+
|
|
99
|
+
},
|
|
100
|
+
text : ( field, yup ) => {
|
|
101
|
+
|
|
102
|
+
const max = field?.attributes?.max || 150;
|
|
103
|
+
|
|
104
|
+
return required( field, yup.string().max( max, errors.length( max ) ) );
|
|
105
|
+
|
|
106
|
+
},
|
|
107
|
+
textarea : ( field, yup ) => {
|
|
108
|
+
|
|
109
|
+
const max = field?.attributes?.max || 150;
|
|
110
|
+
|
|
111
|
+
return required( field, yup.string().max( max, errors.length( max ) ) );
|
|
112
|
+
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export { errors, validators };
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// lib/phone.js
|
|
2
|
+
import { parsePhoneNumberFromString, isValidPhoneNumber } from "libphonenumber-js";
|
|
3
|
+
var isValid = (value, country) => {
|
|
4
|
+
if (!value) return false;
|
|
5
|
+
try {
|
|
6
|
+
return isValidPhoneNumber(String(value), country);
|
|
7
|
+
} catch {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
// lib/fields-validate.js
|
|
13
|
+
var errors = {
|
|
14
|
+
country: "Field is not an accepted value",
|
|
15
|
+
email: "Field value must be a valid email",
|
|
16
|
+
length: (length) => "Field must be less than or equal to " + length + " characters",
|
|
17
|
+
max: (val) => "Field value must be less than or equal to " + val,
|
|
18
|
+
min: (val) => "Field value must be greater than or equal to " + val,
|
|
19
|
+
option: "Field is not an accepted value",
|
|
20
|
+
phone: "Field value is not valid",
|
|
21
|
+
required: "Field is required"
|
|
22
|
+
};
|
|
23
|
+
var required = (field, schema) => {
|
|
24
|
+
var _a;
|
|
25
|
+
return ((_a = field == null ? void 0 : field.attributes) == null ? void 0 : _a.required) === false ? schema.nullable() : schema.required(errors.required);
|
|
26
|
+
};
|
|
27
|
+
var validators = {
|
|
28
|
+
// An agreement that is not required is not an agreement - consent stays
|
|
29
|
+
// affirmative regardless of the toggle.
|
|
30
|
+
agreement: (field, yup) => {
|
|
31
|
+
return yup.bool().required(errors.required).oneOf([true], errors.required);
|
|
32
|
+
},
|
|
33
|
+
email: (field, yup) => {
|
|
34
|
+
const max = 320;
|
|
35
|
+
return required(field, yup.string().email(errors.email).max(max, errors.length(max)));
|
|
36
|
+
},
|
|
37
|
+
name: (field, yup) => {
|
|
38
|
+
var _a;
|
|
39
|
+
const max = 150;
|
|
40
|
+
const object = (((_a = field == null ? void 0 : field.settings) == null ? void 0 : _a.capture) || []).reduce(
|
|
41
|
+
(accumulator, item) => {
|
|
42
|
+
accumulator[item] = yup.string().required(errors.required).max(max, errors.length(max));
|
|
43
|
+
return accumulator;
|
|
44
|
+
},
|
|
45
|
+
{}
|
|
46
|
+
);
|
|
47
|
+
return required(field, yup.object(object));
|
|
48
|
+
},
|
|
49
|
+
number: (field, yup) => {
|
|
50
|
+
var _a, _b, _c, _d, _e, _f;
|
|
51
|
+
let validate = yup.number();
|
|
52
|
+
if ((_a = field == null ? void 0 : field.attributes) == null ? void 0 : _a.min) {
|
|
53
|
+
validate = validate.min((_b = field == null ? void 0 : field.attributes) == null ? void 0 : _b.min, errors.min((_c = field == null ? void 0 : field.attributes) == null ? void 0 : _c.min));
|
|
54
|
+
}
|
|
55
|
+
;
|
|
56
|
+
if ((_d = field == null ? void 0 : field.attributes) == null ? void 0 : _d.max) {
|
|
57
|
+
validate = validate.max((_e = field == null ? void 0 : field.attributes) == null ? void 0 : _e.max, errors.max((_f = field == null ? void 0 : field.attributes) == null ? void 0 : _f.max));
|
|
58
|
+
}
|
|
59
|
+
;
|
|
60
|
+
return required(field, validate);
|
|
61
|
+
},
|
|
62
|
+
phone: (field, yup) => {
|
|
63
|
+
var _a;
|
|
64
|
+
return required(
|
|
65
|
+
field,
|
|
66
|
+
yup.object({
|
|
67
|
+
country: yup.string().required(errors.required).oneOf((_a = field == null ? void 0 : field.settings) == null ? void 0 : _a.countries, errors.country),
|
|
68
|
+
number: yup.string().required(errors.required)
|
|
69
|
+
}).test("phone", errors.phone, (value) => isValid(value == null ? void 0 : value.number, value == null ? void 0 : value.country))
|
|
70
|
+
);
|
|
71
|
+
},
|
|
72
|
+
// The in-list check the share form never had: the answer must be one of the
|
|
73
|
+
// field's own options. null rides the whitelist so an optional select can be
|
|
74
|
+
// left blank - required() still rejects null when the field is required.
|
|
75
|
+
select: (field, yup) => {
|
|
76
|
+
var _a;
|
|
77
|
+
const options = (((_a = field == null ? void 0 : field.settings) == null ? void 0 : _a.options) || []).map((item) => item == null ? void 0 : item.option);
|
|
78
|
+
return required(field, yup.string().oneOf([...options, null], errors.option));
|
|
79
|
+
},
|
|
80
|
+
text: (field, yup) => {
|
|
81
|
+
var _a;
|
|
82
|
+
const max = ((_a = field == null ? void 0 : field.attributes) == null ? void 0 : _a.max) || 150;
|
|
83
|
+
return required(field, yup.string().max(max, errors.length(max)));
|
|
84
|
+
},
|
|
85
|
+
textarea: (field, yup) => {
|
|
86
|
+
var _a;
|
|
87
|
+
const max = ((_a = field == null ? void 0 : field.attributes) == null ? void 0 : _a.max) || 150;
|
|
88
|
+
return required(field, yup.string().max(max, errors.length(max)));
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
export {
|
|
92
|
+
errors,
|
|
93
|
+
validators
|
|
94
|
+
};
|