@better-giving/endowment 1.1.13 → 1.1.15
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/schema.d.mts +348 -338
- package/dist/schema.mjs +93 -92
- package/package.json +1 -1
- package/src/schema.mts +157 -187
package/dist/schema.mjs
CHANGED
|
@@ -1,152 +1,153 @@
|
|
|
1
1
|
import { donateMethodId, donateMethodIds, env, orgDesignation, unSdgNum, } from "@better-giving/schemas";
|
|
2
2
|
export { orgDesignation as endowDesignation, env, unSdgNum, donateMethodId, donateMethodIds, };
|
|
3
|
-
import
|
|
4
|
-
export const str = pipe(string(), trim());
|
|
5
|
-
export const csv = lazy((x) => {
|
|
3
|
+
import * as v from "valibot";
|
|
4
|
+
export const str = v.pipe(v.string(), v.trim());
|
|
5
|
+
export const csv = v.lazy((x) => {
|
|
6
6
|
if (!x)
|
|
7
7
|
return str;
|
|
8
|
-
return pipe(str, regex(/^[^,]+(?:,[^,]+)*$/, "invalid csv"));
|
|
8
|
+
return v.pipe(str, v.regex(/^[^,]+(?:,[^,]+)*$/, "invalid csv"));
|
|
9
9
|
});
|
|
10
|
-
export const csvStrs = pipe(csv, transform((x) => x.split(",")), filterItems((x) => x.length > 0));
|
|
11
|
-
const pct = pipe(number(), integer(), minValue(0), maxValue(100));
|
|
12
|
-
export const allocation = pipe(object({
|
|
10
|
+
export const csvStrs = v.pipe(csv, v.transform((x) => x.split(",")), v.filterItems((x) => x.length > 0));
|
|
11
|
+
const pct = v.pipe(v.number(), v.integer(), v.minValue(0), v.maxValue(100));
|
|
12
|
+
export const allocation = v.pipe(v.object({
|
|
13
13
|
cash: pct,
|
|
14
14
|
liq: pct,
|
|
15
15
|
lock: pct,
|
|
16
|
-
}), check((x) => x.cash + x.liq + x.lock === 100, "must total to 100"));
|
|
17
|
-
export const
|
|
18
|
-
export const endowIdParam = pipe(string(), transform((x) => +x),
|
|
16
|
+
}), v.check((x) => x.cash + x.liq + x.lock === 100, "must total to 100"));
|
|
17
|
+
export const int_id = v.pipe(v.number(), v.integer(), v.minValue(1));
|
|
18
|
+
export const endowIdParam = v.pipe(v.string(), v.transform((x) => +x), int_id);
|
|
19
19
|
export const segmentMaxChars = 30;
|
|
20
|
-
export const segment = pipe(str, maxLength(segmentMaxChars, ({ requirement: r }) => `cannot exceed ${r} chars`),
|
|
20
|
+
export const segment = v.pipe(str, v.maxLength(segmentMaxChars, ({ requirement: r }) => `cannot exceed ${r} chars`),
|
|
21
21
|
//must not be id-like
|
|
22
|
-
regex(/^(?!^\d+$)/, "should not be an id"),
|
|
22
|
+
v.regex(/^(?!^\d+$)/, "should not be an id"),
|
|
23
23
|
//valid characters
|
|
24
|
-
regex(/^[a-zA-Z0-9-._~]+$/, "allowed: numbers | letters | - | . | _ | ~"), excludes("..", "should not contain double periods"), custom((x) => !x.startsWith("."), "should not start with dot"), custom((x) => !x.endsWith("."), "should not end with dot"));
|
|
25
|
-
export const slug = lazy((x) => (x ? segment : str));
|
|
26
|
-
export const reg_number = pipe(str, nonEmpty("required"), regex(/^[a-zA-Z0-9]+$/, "must only contain letters and numbers"));
|
|
27
|
-
export const _url = pipe(str, url());
|
|
28
|
-
export const httpsUrl = pipe(str, startsWith("https://", "should start with https://"), custom((x) => x !== "https://", "incomplete url"), url("invalid url"));
|
|
29
|
-
export const maybeEmptyHttpsUrl = lazy((x) => {
|
|
24
|
+
v.regex(/^[a-zA-Z0-9-._~]+$/, "allowed: numbers | letters | - | . | _ | ~"), v.excludes("..", "should not contain double periods"), v.custom((x) => !x.startsWith("."), "should not start with dot"), v.custom((x) => !x.endsWith("."), "should not end with dot"));
|
|
25
|
+
export const slug = v.lazy((x) => (x ? segment : str));
|
|
26
|
+
export const reg_number = v.pipe(str, v.nonEmpty("required"), v.regex(/^[a-zA-Z0-9]+$/, "must only contain letters and numbers"));
|
|
27
|
+
export const _url = v.pipe(str, v.url());
|
|
28
|
+
export const httpsUrl = v.pipe(str, v.startsWith("https://", "should start with https://"), v.custom((x) => x !== "https://", "incomplete url"), v.url("invalid url"));
|
|
29
|
+
export const maybeEmptyHttpsUrl = v.lazy((x) => {
|
|
30
30
|
if (!x)
|
|
31
31
|
return str;
|
|
32
32
|
return httpsUrl;
|
|
33
33
|
});
|
|
34
|
-
export const social_media_urls = object({
|
|
35
|
-
facebook: optional(maybeEmptyHttpsUrl),
|
|
36
|
-
twitter: optional(maybeEmptyHttpsUrl),
|
|
37
|
-
linkedin: optional(maybeEmptyHttpsUrl),
|
|
38
|
-
discord: optional(maybeEmptyHttpsUrl),
|
|
39
|
-
instagram: optional(maybeEmptyHttpsUrl),
|
|
40
|
-
youtube: optional(maybeEmptyHttpsUrl),
|
|
41
|
-
tiktok: optional(maybeEmptyHttpsUrl),
|
|
34
|
+
export const social_media_urls = v.object({
|
|
35
|
+
facebook: v.optional(maybeEmptyHttpsUrl),
|
|
36
|
+
twitter: v.optional(maybeEmptyHttpsUrl),
|
|
37
|
+
linkedin: v.optional(maybeEmptyHttpsUrl),
|
|
38
|
+
discord: v.optional(maybeEmptyHttpsUrl),
|
|
39
|
+
instagram: v.optional(maybeEmptyHttpsUrl),
|
|
40
|
+
youtube: v.optional(maybeEmptyHttpsUrl),
|
|
41
|
+
tiktok: v.optional(maybeEmptyHttpsUrl),
|
|
42
42
|
});
|
|
43
43
|
export const MAX_RECEIPT_MSG_CHAR = 500;
|
|
44
|
-
export const incrementVal = pipe(str, nonEmpty("required"), transform((x) => +x), number("must be a number"), minValue(0, "must be greater than 0"),
|
|
44
|
+
export const incrementVal = v.pipe(str, v.nonEmpty("required"), v.transform((x) => +x), v.number("must be a number"), v.minValue(0, "must be greater than 0"),
|
|
45
45
|
//parsed output
|
|
46
|
-
transform((x) => x.toString()));
|
|
46
|
+
v.transform((x) => x.toString()));
|
|
47
47
|
export const MAX_NUM_INCREMENTS = 4;
|
|
48
48
|
export const incrementLabelMaxChars = 60;
|
|
49
49
|
export const taglineMaxChars = 140;
|
|
50
|
-
export const incrementLabel = pipe(str, maxLength(incrementLabelMaxChars, ({ requirement: r }) => `cannot exceed ${r} characters`));
|
|
51
|
-
export const increment = object({
|
|
50
|
+
export const incrementLabel = v.pipe(str, v.maxLength(incrementLabelMaxChars, ({ requirement: r }) => `cannot exceed ${r} characters`));
|
|
51
|
+
export const increment = v.object({
|
|
52
52
|
value: incrementVal,
|
|
53
53
|
label: incrementLabel,
|
|
54
54
|
});
|
|
55
|
-
export const endowment = object({
|
|
56
|
-
id:
|
|
55
|
+
export const endowment = v.object({
|
|
56
|
+
id: int_id,
|
|
57
57
|
env,
|
|
58
|
-
slug: optional(slug),
|
|
58
|
+
slug: v.optional(slug),
|
|
59
59
|
registration_number: reg_number,
|
|
60
|
-
name: pipe(str, nonEmpty("required")),
|
|
60
|
+
name: v.pipe(str, v.nonEmpty("required")),
|
|
61
61
|
endow_designation: orgDesignation,
|
|
62
|
-
overview: optional(str),
|
|
63
|
-
tagline: optional(pipe(str, maxLength(taglineMaxChars))),
|
|
64
|
-
image: optional(_url),
|
|
65
|
-
logo: optional(_url),
|
|
66
|
-
card_img: optional(_url),
|
|
67
|
-
hq_country: pipe(str, nonEmpty("required")),
|
|
68
|
-
active_in_countries: pipe(array(str), nonEmpty("required")),
|
|
69
|
-
street_address: optional(str),
|
|
62
|
+
overview: v.optional(str),
|
|
63
|
+
tagline: v.optional(v.pipe(str, v.maxLength(taglineMaxChars))),
|
|
64
|
+
image: v.optional(_url),
|
|
65
|
+
logo: v.optional(_url),
|
|
66
|
+
card_img: v.optional(_url),
|
|
67
|
+
hq_country: v.pipe(str, v.nonEmpty("required")),
|
|
68
|
+
active_in_countries: v.pipe(v.array(str), v.nonEmpty("required")),
|
|
69
|
+
street_address: v.optional(str),
|
|
70
70
|
social_media_urls,
|
|
71
71
|
/** website */
|
|
72
|
-
url: optional(maybeEmptyHttpsUrl),
|
|
73
|
-
sdgs: pipe(array(unSdgNum), minLength(1)),
|
|
74
|
-
receiptMsg: optional(pipe(str, maxLength(MAX_RECEIPT_MSG_CHAR))),
|
|
72
|
+
url: v.optional(maybeEmptyHttpsUrl),
|
|
73
|
+
sdgs: v.pipe(v.array(unSdgNum), v.minLength(1)),
|
|
74
|
+
receiptMsg: v.optional(v.pipe(str, v.maxLength(MAX_RECEIPT_MSG_CHAR))),
|
|
75
75
|
//can be optional, default false and need not be explicit
|
|
76
|
-
hide_bg_tip: optional(boolean()),
|
|
77
|
-
published: optional(boolean()),
|
|
76
|
+
hide_bg_tip: v.optional(v.boolean()),
|
|
77
|
+
published: v.optional(v.boolean()),
|
|
78
78
|
/** allowed by default */
|
|
79
|
-
progDonationsAllowed: optional(boolean()),
|
|
80
|
-
allocation: optional(allocation),
|
|
81
|
-
donateMethods: optional(array(donateMethodId)),
|
|
82
|
-
increments: optional(pipe(array(increment), maxLength(MAX_NUM_INCREMENTS))),
|
|
83
|
-
fund_opt_in: optional(boolean()),
|
|
84
|
-
target: optional(union([
|
|
85
|
-
literal("smart"),
|
|
79
|
+
progDonationsAllowed: v.optional(v.boolean()),
|
|
80
|
+
allocation: v.optional(allocation),
|
|
81
|
+
donateMethods: v.optional(v.array(donateMethodId)),
|
|
82
|
+
increments: v.optional(v.pipe(v.array(increment), v.maxLength(MAX_NUM_INCREMENTS))),
|
|
83
|
+
fund_opt_in: v.optional(v.boolean()),
|
|
84
|
+
target: v.optional(v.union([
|
|
85
|
+
v.literal("smart"),
|
|
86
86
|
// "0" - none, `${number}` - fixed
|
|
87
|
-
pipe(string(), transform((v) => +v), number(), minValue(0), transform((v) => v.toString())),
|
|
87
|
+
v.pipe(v.string(), v.transform((v) => +v), v.number(), v.minValue(0), v.transform((v) => v.toString())),
|
|
88
88
|
])),
|
|
89
89
|
/** endowment is not claimed if `false` only */
|
|
90
|
-
claimed: boolean(),
|
|
91
|
-
kyc_donors_only: boolean(),
|
|
92
|
-
fiscal_sponsored: boolean(),
|
|
93
|
-
referral_id: optional(pipe(str, nonEmpty("required"))),
|
|
94
|
-
referrer: optional(pipe(str, nonEmpty("required"))),
|
|
95
|
-
referrer_expiry: optional(pipe(str, isoTimestamp())),
|
|
90
|
+
claimed: v.boolean(),
|
|
91
|
+
kyc_donors_only: v.boolean(),
|
|
92
|
+
fiscal_sponsored: v.boolean(),
|
|
93
|
+
referral_id: v.optional(v.pipe(str, v.nonEmpty("required"))),
|
|
94
|
+
referrer: v.optional(v.pipe(str, v.nonEmpty("required"))),
|
|
95
|
+
referrer_expiry: v.optional(v.pipe(str, v.isoTimestamp())),
|
|
96
|
+
w_form: v.optional(v.string()),
|
|
96
97
|
});
|
|
97
|
-
export const endowUpdate = partial(omit(endowment, [
|
|
98
|
+
export const endowUpdate = v.partial(v.omit(endowment, [
|
|
98
99
|
"id",
|
|
99
100
|
"claimed",
|
|
100
101
|
"kyc_donors_only",
|
|
101
102
|
"env",
|
|
102
103
|
"fiscal_sponsored",
|
|
103
104
|
]));
|
|
104
|
-
export const endowFields = keyof(endowment);
|
|
105
|
+
export const endowFields = v.keyof(endowment);
|
|
105
106
|
/** for ein path, only fields in reg-num/env gsi is available */
|
|
106
|
-
export const endowQueryParams = object({
|
|
107
|
-
fields: optional(pipe(csvStrs, array(endowFields))),
|
|
107
|
+
export const endowQueryParams = v.object({
|
|
108
|
+
fields: v.optional(v.pipe(csvStrs, v.array(endowFields))),
|
|
108
109
|
});
|
|
109
|
-
const amnt = pipe(number(), minValue(0));
|
|
110
|
-
export const programId = pipe(str, uuid());
|
|
111
|
-
export const milestoneId = pipe(str, uuid());
|
|
112
|
-
export const newMilestone = object({
|
|
113
|
-
date: pipe(str, isoTimestamp()),
|
|
110
|
+
const amnt = v.pipe(v.number(), v.minValue(0));
|
|
111
|
+
export const programId = v.pipe(str, v.uuid());
|
|
112
|
+
export const milestoneId = v.pipe(str, v.uuid());
|
|
113
|
+
export const newMilestone = v.object({
|
|
114
|
+
date: v.pipe(str, v.isoTimestamp()),
|
|
114
115
|
title: str,
|
|
115
116
|
description: str,
|
|
116
|
-
media: optional(_url),
|
|
117
|
+
media: v.optional(_url),
|
|
117
118
|
});
|
|
118
|
-
export const milestoneUpdate = partial(newMilestone, ["date"]);
|
|
119
|
-
export const milestone = object({ ...newMilestone.entries, id: milestoneId });
|
|
120
|
-
export const newProgram = object({
|
|
119
|
+
export const milestoneUpdate = v.partial(newMilestone, ["date"]);
|
|
120
|
+
export const milestone = v.object({ ...newMilestone.entries, id: milestoneId });
|
|
121
|
+
export const newProgram = v.object({
|
|
121
122
|
title: str,
|
|
122
123
|
description: str,
|
|
123
|
-
banner: optional(_url),
|
|
124
|
+
banner: v.optional(_url),
|
|
124
125
|
/** null unsets target */
|
|
125
|
-
targetRaise: nullish(amnt),
|
|
126
|
-
milestones: pipe(array(newMilestone), maxLength(24)),
|
|
126
|
+
targetRaise: v.nullish(amnt),
|
|
127
|
+
milestones: v.pipe(v.array(newMilestone), v.maxLength(24)),
|
|
127
128
|
});
|
|
128
|
-
export const program = object({
|
|
129
|
-
...omit(newProgram, ["milestones"]).entries,
|
|
129
|
+
export const program = v.object({
|
|
130
|
+
...v.omit(newProgram, ["milestones"]).entries,
|
|
130
131
|
/** in USD */
|
|
131
|
-
totalDonations: optional(number()),
|
|
132
|
+
totalDonations: v.optional(v.number()),
|
|
132
133
|
id: programId,
|
|
133
134
|
});
|
|
134
|
-
export const programUpdate = partial(omit(newProgram, ["milestones"]));
|
|
135
|
-
export const mediaUrl = pipe(str, url());
|
|
135
|
+
export const programUpdate = v.partial(v.omit(newProgram, ["milestones"]));
|
|
136
|
+
export const mediaUrl = v.pipe(str, v.url());
|
|
136
137
|
/**
|
|
137
138
|
* so that media is automatically sorted by date
|
|
138
139
|
* @see https://github.com/segmentio/ksuid
|
|
139
140
|
* */
|
|
140
|
-
export const mediaKsuid = pipe(str, nonEmpty() /** base62? */);
|
|
141
|
+
export const mediaKsuid = v.pipe(str, v.nonEmpty() /** base62? */);
|
|
141
142
|
export const mediaTypes = ["album", "article", "video"];
|
|
142
|
-
export const mediaType = picklist(mediaTypes);
|
|
143
|
-
export const mediaUpdate = object({
|
|
144
|
-
url: optional(mediaUrl),
|
|
145
|
-
featured: optional(boolean()),
|
|
143
|
+
export const mediaType = v.picklist(mediaTypes);
|
|
144
|
+
export const mediaUpdate = v.object({
|
|
145
|
+
url: v.optional(mediaUrl),
|
|
146
|
+
featured: v.optional(v.boolean()),
|
|
146
147
|
});
|
|
147
|
-
export const mediaQueryParams = object({
|
|
148
|
-
type: optional(mediaType),
|
|
149
|
-
nextPageKey: optional(pipe(str, base64())),
|
|
150
|
-
featured: optional(pipe(str, transform((x) => Boolean(x)), boolean())),
|
|
151
|
-
limit: optional(pipe(string(), transform((x) => +x), number(), integer(), minValue(1))),
|
|
148
|
+
export const mediaQueryParams = v.object({
|
|
149
|
+
type: v.optional(mediaType),
|
|
150
|
+
nextPageKey: v.optional(v.pipe(str, v.base64())),
|
|
151
|
+
featured: v.optional(v.pipe(str, v.transform((x) => Boolean(x)), v.boolean())),
|
|
152
|
+
limit: v.optional(v.pipe(v.string(), v.transform((x) => +x), v.number(), v.integer(), v.minValue(1))),
|
|
152
153
|
});
|