@better-giving/endowment 1.0.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.
@@ -0,0 +1,14 @@
1
+ import type { ToDoc, ToHitFields, ToUpdate } from "@better-giving/types/cloudsearch";
2
+ import type { Endow, Environment } from "./db.mjs";
3
+ export type Fields = Pick<Endow.DBRecord, "card_img" | "name" | "tagline" | "hq_country" | "sdgs" | "active_in_countries" | "endow_designation" | "registration_number" | "kyc_donors_only" | "claimed" | "env" | "id" | "published" | "fund_opt_in"> & {
4
+ contributions_total: number;
5
+ contributions_count: number;
6
+ };
7
+ type DocId = `${Environment}-${number}`;
8
+ type Doc = {
9
+ documentId: DocId;
10
+ _score: number;
11
+ } & ToDoc<Fields>;
12
+ export type HitFields = ToHitFields<Omit<Doc, "documentId" | "_score">>;
13
+ export type Update = ToUpdate<DocId, Fields>;
14
+ export {};
@@ -0,0 +1 @@
1
+ export {};
package/dist/db.d.mts ADDED
@@ -0,0 +1,60 @@
1
+ import type { EndowId, Endowment as EndowmentShape, Environment, Milestone as MilestoneShape, MilestoneId, Program as ProgramShape, ProgramId } from "./schema.mjs";
2
+ export type { EndowId, SocialMediaURLs, Allocation, Increment, EndowDesignation, Environment, ProgramId, } from "./schema.mjs";
3
+ export declare namespace EndowCount {
4
+ interface Keys {
5
+ PK: "Count";
6
+ SK: Environment;
7
+ }
8
+ interface NonKeyAttributes {
9
+ count: number;
10
+ }
11
+ }
12
+ export declare namespace Endow {
13
+ type Keys = {
14
+ PK: `Endow#${EndowId}`;
15
+ SK: Environment;
16
+ };
17
+ type NonKeyAttributes = EndowmentShape & {
18
+ env: Environment;
19
+ kyc_donors_only: boolean;
20
+ fiscal_sponsored: boolean;
21
+ claimed: boolean;
22
+ /** in USD @deprecated */
23
+ payout_minimum?: number;
24
+ /** @deprecated */
25
+ splitLiqPct?: number;
26
+ /** @deprecated */
27
+ splitFixed?: boolean;
28
+ };
29
+ type DBRecord = Keys & NonKeyAttributes;
30
+ }
31
+ export declare namespace RegNumEnvGsi {
32
+ type Name = "regnum-env-gsi";
33
+ type Keys = Pick<Endow.NonKeyAttributes, "registration_number" | "env">;
34
+ type DBRecord = Keys & Endow.Keys & Pick<Endow.NonKeyAttributes, "claimed" | "name" | "hq_country" | "id">;
35
+ }
36
+ export declare namespace SlugEnvGsi {
37
+ type Name = "slug-env-gsi";
38
+ type Keys = Pick<Endow.NonKeyAttributes, "slug" | "env">;
39
+ type DBRecord = Endow.DBRecord;
40
+ }
41
+ export declare namespace Program {
42
+ type Keys = {
43
+ PK: `Endow#${number}#${Environment}`;
44
+ SK: `Prog#${ProgramId}`;
45
+ };
46
+ type NonKeyAttributes = ProgramShape & {
47
+ /** in USD */
48
+ totalDonations?: number;
49
+ };
50
+ export type DBRecord = Keys & NonKeyAttributes;
51
+ export {};
52
+ }
53
+ export declare namespace Milestone {
54
+ type Keys = {
55
+ PK: `Prog#${string}#${Environment}`;
56
+ SK: `Mile#${MilestoneId}`;
57
+ };
58
+ export type DBRecord = Keys & MilestoneShape;
59
+ export {};
60
+ }
package/dist/db.mjs ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ import type { Fields as FundItem } from "./cloudsearch.mjs";
2
+ import type { Endow as NEndow } from "./db.mjs";
3
+ export type { FundItem };
4
+ export type Endow = Pick<NEndow.DBRecord, "id" | "slug" | "active_in_countries" | "endow_designation" | "fiscal_sponsored" | "hide_bg_tip" | "hq_country" | "image" | "card_img" | "kyc_donors_only" | "logo" | "name" | "overview" | "published" | "registration_number" | "sdgs" | "social_media_urls" | "street_address" | "tagline" | "url" | "claimed" | "sfCompounded" | "progDonationsAllowed" | "donateMethods" | "allocation" | "increments">;
package/dist/index.mjs ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,285 @@
1
+ export type { OrgDesignation as EndowDesignation, Environment, } from "@better-giving/schemas";
2
+ import { type InferInput, type InferOutput } from "valibot";
3
+ export declare const allocation: import("valibot").SchemaWithPipe<[import("valibot").ObjectSchema<{
4
+ readonly cash: import("valibot").SchemaWithPipe<[import("valibot").NumberSchema<undefined>, import("valibot").IntegerAction<number, undefined>, import("valibot").MinValueAction<number, 0, undefined>, import("valibot").MaxValueAction<number, 100, undefined>]>;
5
+ readonly liq: import("valibot").SchemaWithPipe<[import("valibot").NumberSchema<undefined>, import("valibot").IntegerAction<number, undefined>, import("valibot").MinValueAction<number, 0, undefined>, import("valibot").MaxValueAction<number, 100, undefined>]>;
6
+ readonly lock: import("valibot").SchemaWithPipe<[import("valibot").NumberSchema<undefined>, import("valibot").IntegerAction<number, undefined>, import("valibot").MinValueAction<number, 0, undefined>, import("valibot").MaxValueAction<number, 100, undefined>]>;
7
+ }, undefined>, import("valibot").CheckAction<{
8
+ cash: number;
9
+ liq: number;
10
+ lock: number;
11
+ }, "must total to 100">]>;
12
+ export type Allocation = InferOutput<typeof allocation>;
13
+ export declare const endowId: import("valibot").SchemaWithPipe<[import("valibot").NumberSchema<undefined>, import("valibot").IntegerAction<number, undefined>, import("valibot").MinValueAction<number, 1, undefined>]>;
14
+ export type EndowId = InferOutput<typeof endowId>;
15
+ export declare const endowIdParam: import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TransformAction<string, number>, import("valibot").SchemaWithPipe<[import("valibot").NumberSchema<undefined>, import("valibot").IntegerAction<number, undefined>, import("valibot").MinValueAction<number, 1, undefined>]>]>;
16
+ export declare const segment: import("valibot").LazySchema<import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]> | import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").MaxLengthAction<string, 30, "max 30 characters">, import("valibot").RegexAction<string, "should not be an id">, import("valibot").RegexAction<string, "allowed: numbers | letters | - | . | _ | ~">, import("valibot").ExcludesAction<string, "..", "should not contain double periods">, import("valibot").CustomSchema<string, "should not start with dot">, import("valibot").CustomSchema<string, "should not end with dot">]>>;
17
+ export declare const reg_number: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").NonEmptyAction<string, "required">, import("valibot").RegexAction<string, "must only contain letters and numbers">]>;
18
+ export declare const donateMethodIds: readonly ["stripe", "crypto", "daf", "stocks"];
19
+ export declare const donateMethodId: import("valibot").PicklistSchema<readonly ["stripe", "crypto", "daf", "stocks"], undefined>;
20
+ export type DonateMethodId = InferOutput<typeof donateMethodId>;
21
+ declare const social_media_urls: import("valibot").ObjectSchema<{
22
+ readonly facebook: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
23
+ readonly twitter: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
24
+ readonly linkedin: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
25
+ readonly discord: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
26
+ readonly instagram: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
27
+ readonly youtube: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
28
+ readonly tiktok: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
29
+ }, undefined>;
30
+ export type SocialMediaURLs = InferOutput<typeof social_media_urls>;
31
+ export declare const MAX_RECEIPT_MSG_CHAR = 500;
32
+ export declare const incrementVal: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").NonEmptyAction<string, "required">, import("valibot").TransformAction<string, number>, import("valibot").NumberSchema<"must be a number">, import("valibot").MinValueAction<number, 0, "must be greater than 0">, import("valibot").TransformAction<number, string>]>;
33
+ export declare const MAX_NUM_INCREMENTS = 4;
34
+ export declare const incrementLabelMaxChars = 30;
35
+ export declare const incrementLabel: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").MaxLengthAction<string, 30, ({ requirement: r }: import("valibot").MaxLengthIssue<string, 30>) => string>]>;
36
+ export declare const increment: import("valibot").ObjectSchema<{
37
+ readonly value: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").NonEmptyAction<string, "required">, import("valibot").TransformAction<string, number>, import("valibot").NumberSchema<"must be a number">, import("valibot").MinValueAction<number, 0, "must be greater than 0">, import("valibot").TransformAction<number, string>]>;
38
+ readonly label: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").MaxLengthAction<string, 30, ({ requirement: r }: import("valibot").MaxLengthIssue<string, 30>) => string>]>;
39
+ }, undefined>;
40
+ export type Increment = InferOutput<typeof increment>;
41
+ export declare const endowment: import("valibot").ObjectSchema<{
42
+ readonly id: import("valibot").SchemaWithPipe<[import("valibot").NumberSchema<undefined>, import("valibot").IntegerAction<number, undefined>, import("valibot").MinValueAction<number, 1, undefined>]>;
43
+ readonly slug: import("valibot").OptionalSchema<import("valibot").LazySchema<import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]> | import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").MaxLengthAction<string, 30, "max 30 characters">, import("valibot").RegexAction<string, "should not be an id">, import("valibot").RegexAction<string, "allowed: numbers | letters | - | . | _ | ~">, import("valibot").ExcludesAction<string, "..", "should not contain double periods">, import("valibot").CustomSchema<string, "should not start with dot">, import("valibot").CustomSchema<string, "should not end with dot">]>>, never>;
44
+ readonly registration_number: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").NonEmptyAction<string, "required">, import("valibot").RegexAction<string, "must only contain letters and numbers">]>;
45
+ readonly name: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").NonEmptyAction<string, "required">]>;
46
+ readonly endow_designation: import("valibot").PicklistSchema<readonly ["Charity", "Religious Organization", "University", "Hospital", "Other"], undefined>;
47
+ readonly overview: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, never>;
48
+ readonly tagline: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, never>;
49
+ readonly image: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
50
+ readonly logo: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
51
+ readonly card_img: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
52
+ readonly hq_country: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").NonEmptyAction<string, "required">]>;
53
+ readonly active_in_countries: import("valibot").SchemaWithPipe<[import("valibot").ArraySchema<import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, undefined>, import("valibot").NonEmptyAction<string[], "required">]>;
54
+ readonly street_address: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, never>;
55
+ readonly social_media_urls: import("valibot").ObjectSchema<{
56
+ readonly facebook: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
57
+ readonly twitter: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
58
+ readonly linkedin: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
59
+ readonly discord: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
60
+ readonly instagram: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
61
+ readonly youtube: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
62
+ readonly tiktok: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
63
+ }, undefined>;
64
+ /** website */
65
+ readonly url: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
66
+ readonly sdgs: import("valibot").SchemaWithPipe<[import("valibot").ArraySchema<import("valibot").PicklistSchema<readonly [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17], undefined>, undefined>, import("valibot").MinLengthAction<(2 | 1 | 4 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17)[], 1, undefined>]>;
67
+ readonly receiptMsg: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").MaxLengthAction<string, 500, undefined>]>, never>;
68
+ readonly hide_bg_tip: import("valibot").OptionalSchema<import("valibot").BooleanSchema<undefined>, never>;
69
+ readonly sfCompounded: import("valibot").OptionalSchema<import("valibot").BooleanSchema<undefined>, never>;
70
+ readonly published: import("valibot").OptionalSchema<import("valibot").BooleanSchema<undefined>, never>;
71
+ /** allowed by default */
72
+ readonly progDonationsAllowed: import("valibot").OptionalSchema<import("valibot").BooleanSchema<undefined>, never>;
73
+ readonly allocation: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").ObjectSchema<{
74
+ readonly cash: import("valibot").SchemaWithPipe<[import("valibot").NumberSchema<undefined>, import("valibot").IntegerAction<number, undefined>, import("valibot").MinValueAction<number, 0, undefined>, import("valibot").MaxValueAction<number, 100, undefined>]>;
75
+ readonly liq: import("valibot").SchemaWithPipe<[import("valibot").NumberSchema<undefined>, import("valibot").IntegerAction<number, undefined>, import("valibot").MinValueAction<number, 0, undefined>, import("valibot").MaxValueAction<number, 100, undefined>]>;
76
+ readonly lock: import("valibot").SchemaWithPipe<[import("valibot").NumberSchema<undefined>, import("valibot").IntegerAction<number, undefined>, import("valibot").MinValueAction<number, 0, undefined>, import("valibot").MaxValueAction<number, 100, undefined>]>;
77
+ }, undefined>, import("valibot").CheckAction<{
78
+ cash: number;
79
+ liq: number;
80
+ lock: number;
81
+ }, "must total to 100">]>, never>;
82
+ readonly donateMethods: import("valibot").OptionalSchema<import("valibot").ArraySchema<import("valibot").PicklistSchema<readonly ["stripe", "crypto", "daf", "stocks"], undefined>, undefined>, never>;
83
+ readonly increments: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").ArraySchema<import("valibot").ObjectSchema<{
84
+ readonly value: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").NonEmptyAction<string, "required">, import("valibot").TransformAction<string, number>, import("valibot").NumberSchema<"must be a number">, import("valibot").MinValueAction<number, 0, "must be greater than 0">, import("valibot").TransformAction<number, string>]>;
85
+ readonly label: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").MaxLengthAction<string, 30, ({ requirement: r }: import("valibot").MaxLengthIssue<string, 30>) => string>]>;
86
+ }, undefined>, undefined>, import("valibot").MaxLengthAction<{
87
+ value: string;
88
+ label: string;
89
+ }[], 4, undefined>]>, never>;
90
+ readonly fund_opt_in: import("valibot").OptionalSchema<import("valibot").BooleanSchema<undefined>, never>;
91
+ }, undefined>;
92
+ export declare const endowFields: import("valibot").PicklistSchema<["url", "slug", "name", "overview", "tagline", "image", "logo", "card_img", "hq_country", "active_in_countries", "street_address", "sdgs", "receiptMsg", "hide_bg_tip", "sfCompounded", "published", "progDonationsAllowed", "allocation", "donateMethods", "increments", "fund_opt_in", "id", "registration_number", "endow_designation", "social_media_urls"], undefined>;
93
+ export type Endowment = InferOutput<typeof endowment>;
94
+ export type EndowmentFields = InferOutput<typeof endowFields>;
95
+ export declare const endowsQueryParams: import("valibot").ObjectSchema<{
96
+ readonly query: import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>;
97
+ readonly page: import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TransformAction<string, number>, import("valibot").IntegerAction<number, undefined>, import("valibot").MinValueAction<number, 1, undefined>]>;
98
+ readonly endow_designation: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").LazySchema<import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]> | import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").RegexAction<string, "invalid csv">]>>, import("valibot").TransformAction<string, string[]>, import("valibot").ArraySchema<import("valibot").PicklistSchema<readonly ["Charity", "Religious Organization", "University", "Hospital", "Other"], undefined>, undefined>]>, never>;
99
+ readonly sdgs: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").LazySchema<import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]> | import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").RegexAction<string, "invalid csv">]>>, import("valibot").TransformAction<string, number[]>, import("valibot").ArraySchema<import("valibot").PicklistSchema<readonly [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17], undefined>, undefined>]>, never>;
100
+ readonly kyc_only: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").LazySchema<import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]> | import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").RegexAction<string, "invalid csv">]>>, import("valibot").TransformAction<string, boolean[]>, import("valibot").ArraySchema<import("valibot").BooleanSchema<undefined>, undefined>]>, never>;
101
+ readonly fund_opt_in: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").LazySchema<import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]> | import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").RegexAction<string, "invalid csv">]>>, import("valibot").TransformAction<string, boolean[]>, import("valibot").ArraySchema<import("valibot").BooleanSchema<undefined>, undefined>]>, never>;
102
+ readonly claimed: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").LazySchema<import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]> | import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").RegexAction<string, "invalid csv">]>>, import("valibot").TransformAction<string, boolean[]>, import("valibot").ArraySchema<import("valibot").BooleanSchema<undefined>, undefined>]>, never>;
103
+ readonly countries: import("valibot").OptionalSchema<import("valibot").LazySchema<import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]> | import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").RegexAction<string, "invalid csv">]>>, never>;
104
+ readonly fields: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").LazySchema<import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]> | import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").RegexAction<string, "invalid csv">]>>, import("valibot").TransformAction<string, string[]>, import("valibot").ArraySchema<import("valibot").PicklistSchema<["url", "slug", "name", "overview", "tagline", "image", "logo", "card_img", "hq_country", "active_in_countries", "street_address", "sdgs", "receiptMsg", "hide_bg_tip", "sfCompounded", "published", "progDonationsAllowed", "allocation", "donateMethods", "increments", "fund_opt_in", "id", "registration_number", "endow_designation", "social_media_urls"], undefined>, undefined>]>, never>;
105
+ }, undefined>;
106
+ export type EndowsQueryParams = InferInput<typeof endowsQueryParams>;
107
+ export declare const endowQueryParam: import("valibot").ObjectSchema<{
108
+ readonly fields: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").LazySchema<import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]> | import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").RegexAction<string, "invalid csv">]>>, import("valibot").TransformAction<string, string[]>, import("valibot").ArraySchema<import("valibot").PicklistSchema<["url", "slug", "name", "overview", "tagline", "image", "logo", "card_img", "hq_country", "active_in_countries", "street_address", "sdgs", "receiptMsg", "hide_bg_tip", "sfCompounded", "published", "progDonationsAllowed", "allocation", "donateMethods", "increments", "fund_opt_in", "id", "registration_number", "endow_designation", "social_media_urls"], undefined>, undefined>]>, never>;
109
+ readonly slug: import("valibot").OptionalSchema<import("valibot").LazySchema<import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]> | import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").MaxLengthAction<string, 30, "max 30 characters">, import("valibot").RegexAction<string, "should not be an id">, import("valibot").RegexAction<string, "allowed: numbers | letters | - | . | _ | ~">, import("valibot").ExcludesAction<string, "..", "should not contain double periods">, import("valibot").CustomSchema<string, "should not start with dot">, import("valibot").CustomSchema<string, "should not end with dot">]>>, never>;
110
+ readonly env: import("valibot").PicklistSchema<readonly ["staging", "production"], undefined>;
111
+ }, undefined>;
112
+ export type EndowQueryParam = InferInput<typeof endowQueryParam>;
113
+ export declare const endowByEinParams: import("valibot").ObjectSchema<{
114
+ readonly env: import("valibot").PicklistSchema<readonly ["staging", "production"], undefined>;
115
+ readonly ein: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").NonEmptyAction<string, "required">, import("valibot").RegexAction<string, "must only contain letters and numbers">]>;
116
+ }, undefined>;
117
+ export type EndowByEinParams = InferInput<typeof endowByEinParams>;
118
+ export declare const programId: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UuidAction<string, undefined>]>;
119
+ export type ProgramId = InferOutput<typeof programId>;
120
+ export declare const milestoneId: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UuidAction<string, undefined>]>;
121
+ export type MilestoneId = InferOutput<typeof milestoneId>;
122
+ export declare const newMilestone: import("valibot").ObjectSchema<{
123
+ readonly date: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").IsoDateAction<string, undefined>]>;
124
+ readonly title: import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>;
125
+ readonly description: import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>;
126
+ readonly media: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
127
+ }, undefined>;
128
+ export declare const milestoneUpdate: Omit<import("valibot").ObjectSchema<{
129
+ readonly date: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").IsoDateAction<string, undefined>]>;
130
+ readonly title: import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>;
131
+ readonly description: import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>;
132
+ readonly media: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
133
+ }, undefined>, "_types" | "_run" | "entries"> & {
134
+ readonly entries: {
135
+ readonly date: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").IsoDateAction<string, undefined>]>, never>;
136
+ readonly title: import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>;
137
+ readonly description: import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>;
138
+ readonly media: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
139
+ };
140
+ _run(dataset: import("valibot").Dataset<unknown, never>, config: import("valibot").Config<import("valibot").StringIssue | import("valibot").ObjectIssue | import("valibot").UrlIssue<string> | import("valibot").IsoDateIssue<string>>): import("valibot").Dataset<{
141
+ title: string;
142
+ description: string;
143
+ date?: string | undefined;
144
+ media?: string | undefined;
145
+ }, import("valibot").StringIssue | import("valibot").ObjectIssue | import("valibot").UrlIssue<string> | import("valibot").IsoDateIssue<string>>;
146
+ readonly _types?: {
147
+ readonly input: {
148
+ title: string;
149
+ description: string;
150
+ date?: string | undefined;
151
+ media?: string | undefined;
152
+ };
153
+ readonly output: {
154
+ title: string;
155
+ description: string;
156
+ date?: string | undefined;
157
+ media?: string | undefined;
158
+ };
159
+ readonly issue: import("valibot").StringIssue | import("valibot").ObjectIssue | import("valibot").UrlIssue<string> | import("valibot").IsoDateIssue<string>;
160
+ } | undefined;
161
+ };
162
+ export type MilestoneUpdate = InferOutput<typeof milestoneUpdate>;
163
+ export type NewMilestone = InferOutput<typeof newMilestone>;
164
+ export declare const milestone: import("valibot").ObjectSchema<{
165
+ readonly id: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UuidAction<string, undefined>]>;
166
+ readonly date: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").IsoDateAction<string, undefined>]>;
167
+ readonly title: import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>;
168
+ readonly description: import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>;
169
+ readonly media: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
170
+ }, undefined>;
171
+ export type Milestone = InferOutput<typeof milestone>;
172
+ export declare const newProgram: import("valibot").ObjectSchema<{
173
+ readonly title: import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>;
174
+ readonly description: import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>;
175
+ readonly banner: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
176
+ /** null unsets target */
177
+ readonly targetRaise: import("valibot").NullishSchema<import("valibot").SchemaWithPipe<[import("valibot").NumberSchema<undefined>, import("valibot").MinValueAction<number, 0, undefined>]>, never>;
178
+ readonly milestones: import("valibot").SchemaWithPipe<[import("valibot").ArraySchema<import("valibot").ObjectSchema<{
179
+ readonly date: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").IsoDateAction<string, undefined>]>;
180
+ readonly title: import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>;
181
+ readonly description: import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>;
182
+ readonly media: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
183
+ }, undefined>, undefined>, import("valibot").MaxLengthAction<{
184
+ date: string;
185
+ title: string;
186
+ description: string;
187
+ media?: string | undefined;
188
+ }[], 24, undefined>]>;
189
+ }, undefined>;
190
+ export declare const program: import("valibot").ObjectSchema<{
191
+ readonly id: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UuidAction<string, undefined>]>;
192
+ readonly title: import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>;
193
+ readonly description: import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>;
194
+ readonly banner: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
195
+ readonly targetRaise: import("valibot").NullishSchema<import("valibot").SchemaWithPipe<[import("valibot").NumberSchema<undefined>, import("valibot").MinValueAction<number, 0, undefined>]>, never>;
196
+ }, undefined>;
197
+ export declare const programUpdate: Omit<Omit<import("valibot").ObjectSchema<{
198
+ readonly title: import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>;
199
+ readonly description: import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>;
200
+ readonly banner: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
201
+ /** null unsets target */
202
+ readonly targetRaise: import("valibot").NullishSchema<import("valibot").SchemaWithPipe<[import("valibot").NumberSchema<undefined>, import("valibot").MinValueAction<number, 0, undefined>]>, never>;
203
+ readonly milestones: import("valibot").SchemaWithPipe<[import("valibot").ArraySchema<import("valibot").ObjectSchema<{
204
+ readonly date: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").IsoDateAction<string, undefined>]>;
205
+ readonly title: import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>;
206
+ readonly description: import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>;
207
+ readonly media: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
208
+ }, undefined>, undefined>, import("valibot").MaxLengthAction<{
209
+ date: string;
210
+ title: string;
211
+ description: string;
212
+ media?: string | undefined;
213
+ }[], 24, undefined>]>;
214
+ }, undefined>, "_types" | "_run" | "entries"> & {
215
+ readonly entries: Omit<{
216
+ readonly title: import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>;
217
+ readonly description: import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>;
218
+ readonly banner: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
219
+ /** null unsets target */
220
+ readonly targetRaise: import("valibot").NullishSchema<import("valibot").SchemaWithPipe<[import("valibot").NumberSchema<undefined>, import("valibot").MinValueAction<number, 0, undefined>]>, never>;
221
+ readonly milestones: import("valibot").SchemaWithPipe<[import("valibot").ArraySchema<import("valibot").ObjectSchema<{
222
+ readonly date: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").IsoDateAction<string, undefined>]>;
223
+ readonly title: import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>;
224
+ readonly description: import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>;
225
+ readonly media: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
226
+ }, undefined>, undefined>, import("valibot").MaxLengthAction<{
227
+ date: string;
228
+ title: string;
229
+ description: string;
230
+ media?: string | undefined;
231
+ }[], 24, undefined>]>;
232
+ }, "milestones">;
233
+ _run(dataset: import("valibot").Dataset<unknown, never>, config: import("valibot").Config<import("valibot").StringIssue | import("valibot").NumberIssue | import("valibot").MinValueIssue<number, 0> | import("valibot").ObjectIssue | import("valibot").UrlIssue<string>>): import("valibot").Dataset<{
234
+ title: string;
235
+ description: string;
236
+ banner?: string | undefined;
237
+ targetRaise?: number | null | undefined;
238
+ }, import("valibot").StringIssue | import("valibot").NumberIssue | import("valibot").MinValueIssue<number, 0> | import("valibot").ObjectIssue | import("valibot").UrlIssue<string>>;
239
+ readonly _types?: {
240
+ readonly input: {
241
+ title: string;
242
+ description: string;
243
+ banner?: string | undefined;
244
+ targetRaise?: number | null | undefined;
245
+ };
246
+ readonly output: {
247
+ title: string;
248
+ description: string;
249
+ banner?: string | undefined;
250
+ targetRaise?: number | null | undefined;
251
+ };
252
+ readonly issue: import("valibot").StringIssue | import("valibot").NumberIssue | import("valibot").MinValueIssue<number, 0> | import("valibot").ObjectIssue | import("valibot").UrlIssue<string>;
253
+ } | undefined;
254
+ }, "_types" | "_run" | "entries"> & {
255
+ readonly entries: {
256
+ readonly title: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, never>;
257
+ readonly description: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, never>;
258
+ readonly banner: import("valibot").OptionalSchema<import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>, never>;
259
+ readonly targetRaise: import("valibot").OptionalSchema<import("valibot").NullishSchema<import("valibot").SchemaWithPipe<[import("valibot").NumberSchema<undefined>, import("valibot").MinValueAction<number, 0, undefined>]>, never>, never>;
260
+ };
261
+ _run(dataset: import("valibot").Dataset<unknown, never>, config: import("valibot").Config<import("valibot").StringIssue | import("valibot").NumberIssue | import("valibot").MinValueIssue<number, 0> | import("valibot").ObjectIssue | import("valibot").UrlIssue<string>>): import("valibot").Dataset<{
262
+ title?: string | undefined;
263
+ description?: string | undefined;
264
+ banner?: string | undefined;
265
+ targetRaise?: number | null | undefined;
266
+ }, import("valibot").StringIssue | import("valibot").NumberIssue | import("valibot").MinValueIssue<number, 0> | import("valibot").ObjectIssue | import("valibot").UrlIssue<string>>;
267
+ readonly _types?: {
268
+ readonly input: {
269
+ title?: string | undefined;
270
+ description?: string | undefined;
271
+ banner?: string | undefined;
272
+ targetRaise?: number | null | undefined;
273
+ };
274
+ readonly output: {
275
+ title?: string | undefined;
276
+ description?: string | undefined;
277
+ banner?: string | undefined;
278
+ targetRaise?: number | null | undefined;
279
+ };
280
+ readonly issue: import("valibot").StringIssue | import("valibot").NumberIssue | import("valibot").MinValueIssue<number, 0> | import("valibot").ObjectIssue | import("valibot").UrlIssue<string>;
281
+ } | undefined;
282
+ };
283
+ export type NewProgram = InferOutput<typeof newProgram>;
284
+ export type Program = InferOutput<typeof program>;
285
+ export type ProgramUpdate = InferOutput<typeof programUpdate>;
@@ -0,0 +1,125 @@
1
+ import { env, orgDesignation, unSdgNum } from "@better-giving/schemas";
2
+ import { url, array, boolean, check, custom, excludes, integer, isoDate, keyof, lazy, maxLength, maxValue, minLength, minValue, nonEmpty, nullish, number, object, omit, optional, partial, picklist, pipe, regex, string, transform, trim, uuid, } from "valibot";
3
+ const str = pipe(string(), trim());
4
+ const pct = pipe(number(), integer(), minValue(0), maxValue(100));
5
+ export const allocation = pipe(object({
6
+ cash: pct,
7
+ liq: pct,
8
+ lock: pct,
9
+ }), check((x) => x.cash + x.liq + x.lock === 100, "must total to 100"));
10
+ export const endowId = pipe(number(), integer(), minValue(1));
11
+ export const endowIdParam = pipe(string(), transform((x) => +x), endowId);
12
+ export const segment = lazy((x) => {
13
+ if (!x)
14
+ return str;
15
+ return pipe(str, maxLength(30, "max 30 characters"),
16
+ //must not be id-like
17
+ regex(/^(?!^\d+$)/, "should not be an id"),
18
+ //valid characters
19
+ 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"));
20
+ });
21
+ export const reg_number = pipe(str, nonEmpty("required"), regex(/^[a-zA-Z0-9]+$/, "must only contain letters and numbers"));
22
+ export const donateMethodIds = ["stripe", "crypto", "daf", "stocks"];
23
+ export const donateMethodId = picklist(donateMethodIds);
24
+ const _url = pipe(str, url());
25
+ const social_media_urls = object({
26
+ facebook: optional(_url),
27
+ twitter: optional(_url),
28
+ linkedin: optional(_url),
29
+ discord: optional(_url),
30
+ instagram: optional(_url),
31
+ youtube: optional(_url),
32
+ tiktok: optional(_url),
33
+ });
34
+ export const MAX_RECEIPT_MSG_CHAR = 500;
35
+ export const incrementVal = pipe(str, nonEmpty("required"), transform((x) => +x), number("must be a number"), minValue(0, "must be greater than 0"),
36
+ //parsed output
37
+ transform((x) => x.toString()));
38
+ export const MAX_NUM_INCREMENTS = 4;
39
+ export const incrementLabelMaxChars = 30;
40
+ export const incrementLabel = pipe(str, maxLength(incrementLabelMaxChars, ({ requirement: r }) => `cannot exceed ${r} characters`));
41
+ export const increment = object({
42
+ value: incrementVal,
43
+ label: incrementLabel,
44
+ });
45
+ export const endowment = object({
46
+ id: endowId,
47
+ slug: optional(segment),
48
+ registration_number: reg_number,
49
+ name: pipe(str, nonEmpty("required")),
50
+ endow_designation: orgDesignation,
51
+ overview: optional(str),
52
+ tagline: optional(str),
53
+ image: optional(_url),
54
+ logo: optional(_url),
55
+ card_img: optional(_url),
56
+ hq_country: pipe(str, nonEmpty("required")),
57
+ active_in_countries: pipe(array(str), nonEmpty("required")),
58
+ street_address: optional(str),
59
+ social_media_urls,
60
+ /** website */
61
+ url: optional(_url),
62
+ sdgs: pipe(array(unSdgNum), minLength(1)),
63
+ receiptMsg: optional(pipe(str, maxLength(MAX_RECEIPT_MSG_CHAR))),
64
+ //can be optional, default false and need not be explicit
65
+ hide_bg_tip: optional(boolean()),
66
+ sfCompounded: optional(boolean()),
67
+ published: optional(boolean()),
68
+ /** allowed by default */
69
+ progDonationsAllowed: optional(boolean()),
70
+ allocation: optional(allocation),
71
+ donateMethods: optional(array(donateMethodId)),
72
+ increments: optional(pipe(array(increment), maxLength(MAX_NUM_INCREMENTS))),
73
+ fund_opt_in: optional(boolean()),
74
+ });
75
+ export const endowFields = keyof(endowment);
76
+ const csv = lazy((x) => {
77
+ if (!x)
78
+ return str;
79
+ return pipe(str, regex(/^[^,]+(?:,[^,]+)*$/, "invalid csv"));
80
+ });
81
+ const boolCsv = pipe(csv, transform((x) => x.split(",").map(Boolean)), array(boolean()));
82
+ export const endowsQueryParams = object({
83
+ query: str,
84
+ page: pipe(string(), transform((x) => +x), integer(), minValue(1)),
85
+ endow_designation: optional(pipe(csv, transform((x) => x.split(",")), array(orgDesignation))),
86
+ sdgs: optional(pipe(csv, transform((x) => x.split(",").map((s) => +s)), array(unSdgNum))),
87
+ kyc_only: optional(boolCsv),
88
+ fund_opt_in: optional(boolCsv),
89
+ claimed: optional(boolCsv),
90
+ countries: optional(csv),
91
+ fields: optional(pipe(csv, transform((x) => x.split(",")), array(endowFields))),
92
+ });
93
+ export const endowQueryParam = object({
94
+ fields: optional(pipe(csv, transform((x) => x.split(",")), array(endowFields))),
95
+ slug: optional(segment),
96
+ env,
97
+ });
98
+ export const endowByEinParams = object({
99
+ env,
100
+ ein: reg_number,
101
+ });
102
+ const amnt = pipe(number(), minValue(0));
103
+ export const programId = pipe(str, uuid());
104
+ export const milestoneId = pipe(str, uuid());
105
+ export const newMilestone = object({
106
+ date: pipe(str, isoDate()),
107
+ title: str,
108
+ description: str,
109
+ media: optional(_url),
110
+ });
111
+ export const milestoneUpdate = partial(newMilestone, ["date"]);
112
+ export const milestone = object({ ...newMilestone.entries, id: milestoneId });
113
+ export const newProgram = object({
114
+ title: str,
115
+ description: str,
116
+ banner: optional(_url),
117
+ /** null unsets target */
118
+ targetRaise: nullish(amnt),
119
+ milestones: pipe(array(newMilestone), maxLength(24)),
120
+ });
121
+ export const program = object({
122
+ ...omit(newProgram, ["milestones"]).entries,
123
+ id: programId,
124
+ });
125
+ export const programUpdate = partial(omit(newProgram, ["milestones"]));
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "@better-giving/endowment",
3
+ "version": "1.0.0",
4
+ "peerDependencies": {
5
+ "@better-giving/schemas": "1.0.1",
6
+ "@better-giving/types": "1.0.1"
7
+ },
8
+ "devDependencies": {
9
+ "@better-giving/config": "workspace:*"
10
+ },
11
+ "files": [
12
+ "src",
13
+ "dist"
14
+ ],
15
+ "exports": {
16
+ ".": "./dist/index.mjs",
17
+ "./schema": "./dist/schema.mjs",
18
+ "./db": "./dist/db.mjs",
19
+ "./cloudsearch": "./dist/cloudsearch.mjs"
20
+ },
21
+ "scripts": {
22
+ "publish": "npm publish --access public",
23
+ "build": "tsc --outDir dist"
24
+ }
25
+ }
@@ -0,0 +1,39 @@
1
+ import type {
2
+ ToDoc,
3
+ ToHitFields,
4
+ ToUpdate,
5
+ } from "@better-giving/types/cloudsearch";
6
+ import type { Endow, Environment } from "./db.mjs";
7
+
8
+ export type Fields = Pick<
9
+ Endow.DBRecord,
10
+ //card UI attribures
11
+ | "card_img"
12
+ | "name"
13
+ | "tagline"
14
+ | "hq_country"
15
+ | "sdgs"
16
+ | "active_in_countries"
17
+ | "endow_designation"
18
+ | "registration_number"
19
+ //icons
20
+ | "kyc_donors_only"
21
+ | "claimed"
22
+ //filters
23
+ | "env"
24
+ | "id"
25
+ | "published"
26
+ | "fund_opt_in"
27
+ // balance data
28
+ > & { contributions_total: number; contributions_count: number };
29
+
30
+ type DocId = `${Environment}-${number}`;
31
+
32
+ type Doc = {
33
+ documentId: DocId;
34
+ _score: number;
35
+ } & ToDoc<Fields>;
36
+
37
+ export type HitFields = ToHitFields<Omit<Doc, "documentId" | "_score">>;
38
+
39
+ export type Update = ToUpdate<DocId, Fields>;
package/src/db.mts ADDED
@@ -0,0 +1,89 @@
1
+ import type {
2
+ EndowId,
3
+ Endowment as EndowmentShape,
4
+ Environment,
5
+ Milestone as MilestoneShape,
6
+ MilestoneId,
7
+ Program as ProgramShape,
8
+ ProgramId,
9
+ } from "./schema.mjs";
10
+ export type {
11
+ EndowId,
12
+ SocialMediaURLs,
13
+ Allocation,
14
+ Increment,
15
+ EndowDesignation,
16
+ Environment,
17
+ ProgramId,
18
+ } from "./schema.mjs";
19
+
20
+ export namespace EndowCount {
21
+ export interface Keys {
22
+ PK: "Count";
23
+ SK: Environment;
24
+ }
25
+ export interface NonKeyAttributes {
26
+ count: number;
27
+ }
28
+ }
29
+
30
+ export namespace Endow {
31
+ export type Keys = {
32
+ PK: `Endow#${EndowId}`;
33
+ SK: Environment;
34
+ };
35
+
36
+ export type NonKeyAttributes = EndowmentShape & {
37
+ env: Environment;
38
+ kyc_donors_only: boolean;
39
+ fiscal_sponsored: boolean;
40
+ claimed: boolean;
41
+
42
+ /** in USD @deprecated */
43
+ payout_minimum?: number;
44
+ /** @deprecated */
45
+ splitLiqPct?: number;
46
+ /** @deprecated */
47
+ splitFixed?: boolean;
48
+ };
49
+
50
+ export type DBRecord = Keys & NonKeyAttributes;
51
+ }
52
+
53
+ export namespace RegNumEnvGsi {
54
+ export type Name = "regnum-env-gsi";
55
+ export type Keys = Pick<
56
+ Endow.NonKeyAttributes,
57
+ "registration_number" | "env"
58
+ >;
59
+ export type DBRecord = Keys &
60
+ Endow.Keys &
61
+ Pick<Endow.NonKeyAttributes, "claimed" | "name" | "hq_country" | "id">;
62
+ }
63
+
64
+ export namespace SlugEnvGsi {
65
+ export type Name = "slug-env-gsi";
66
+ export type Keys = Pick<Endow.NonKeyAttributes, "slug" | "env">;
67
+ export type DBRecord = Endow.DBRecord; //all attributes are copied to this index
68
+ }
69
+
70
+ export namespace Program {
71
+ type Keys = {
72
+ PK: `Endow#${number}#${Environment}`;
73
+ SK: `Prog#${ProgramId}`;
74
+ };
75
+
76
+ type NonKeyAttributes = ProgramShape & {
77
+ /** in USD */
78
+ totalDonations?: number;
79
+ };
80
+ export type DBRecord = Keys & NonKeyAttributes;
81
+ }
82
+
83
+ export namespace Milestone {
84
+ type Keys = {
85
+ PK: `Prog#${string}#${Environment}`;
86
+ SK: `Mile#${MilestoneId}`;
87
+ };
88
+ export type DBRecord = Keys & MilestoneShape;
89
+ }
package/src/index.mts ADDED
@@ -0,0 +1,33 @@
1
+ import type { Fields as FundItem } from "./cloudsearch.mjs";
2
+ import type { Endow as NEndow } from "./db.mjs";
3
+ export type { FundItem };
4
+
5
+ export type Endow = Pick<
6
+ NEndow.DBRecord,
7
+ | "id"
8
+ | "slug"
9
+ | "active_in_countries"
10
+ | "endow_designation"
11
+ | "fiscal_sponsored"
12
+ | "hide_bg_tip"
13
+ | "hq_country"
14
+ | "image"
15
+ | "card_img"
16
+ | "kyc_donors_only"
17
+ | "logo"
18
+ | "name"
19
+ | "overview"
20
+ | "published"
21
+ | "registration_number"
22
+ | "sdgs"
23
+ | "social_media_urls"
24
+ | "street_address"
25
+ | "tagline"
26
+ | "url"
27
+ | "claimed"
28
+ | "sfCompounded"
29
+ | "progDonationsAllowed"
30
+ | "donateMethods"
31
+ | "allocation"
32
+ | "increments"
33
+ >;
package/src/schema.mts ADDED
@@ -0,0 +1,273 @@
1
+ import { env, orgDesignation, unSdgNum } from "@better-giving/schemas";
2
+ export type {
3
+ OrgDesignation as EndowDesignation,
4
+ Environment,
5
+ } from "@better-giving/schemas";
6
+ import {
7
+ url,
8
+ type InferInput,
9
+ type InferOutput,
10
+ array,
11
+ boolean,
12
+ check,
13
+ custom,
14
+ excludes,
15
+ integer,
16
+ isoDate,
17
+ keyof,
18
+ lazy,
19
+ maxLength,
20
+ maxValue,
21
+ minLength,
22
+ minValue,
23
+ nonEmpty,
24
+ nullish,
25
+ number,
26
+ object,
27
+ omit,
28
+ optional,
29
+ partial,
30
+ picklist,
31
+ pipe,
32
+ regex,
33
+ string,
34
+ transform,
35
+ trim,
36
+ uuid,
37
+ } from "valibot";
38
+
39
+ const str = pipe(string(), trim());
40
+
41
+ const pct = pipe(number(), integer(), minValue(0), maxValue(100));
42
+ export const allocation = pipe(
43
+ object({
44
+ cash: pct,
45
+ liq: pct,
46
+ lock: pct,
47
+ }),
48
+ check((x) => x.cash + x.liq + x.lock === 100, "must total to 100")
49
+ );
50
+
51
+ export type Allocation = InferOutput<typeof allocation>;
52
+
53
+ export const endowId = pipe(number(), integer(), minValue(1));
54
+ export type EndowId = InferOutput<typeof endowId>;
55
+ export const endowIdParam = pipe(
56
+ string(),
57
+ transform((x) => +x),
58
+ endowId
59
+ );
60
+
61
+ export const segment = lazy((x) => {
62
+ if (!x) return str;
63
+ return pipe(
64
+ str,
65
+ maxLength(30, "max 30 characters"),
66
+ //must not be id-like
67
+ regex(/^(?!^\d+$)/, "should not be an id"),
68
+ //valid characters
69
+ regex(/^[a-zA-Z0-9-._~]+$/, "allowed: numbers | letters | - | . | _ | ~"),
70
+ excludes("..", "should not contain double periods"),
71
+ custom((x) => !(x as string).startsWith("."), "should not start with dot"),
72
+ custom((x) => !(x as string).endsWith("."), "should not end with dot")
73
+ );
74
+ });
75
+
76
+ export const reg_number = pipe(
77
+ str,
78
+ nonEmpty("required"),
79
+ regex(/^[a-zA-Z0-9]+$/, "must only contain letters and numbers")
80
+ );
81
+
82
+ export const donateMethodIds = ["stripe", "crypto", "daf", "stocks"] as const;
83
+ export const donateMethodId = picklist(donateMethodIds);
84
+ export type DonateMethodId = InferOutput<typeof donateMethodId>;
85
+
86
+ const _url = pipe(str, url());
87
+
88
+ const social_media_urls = object({
89
+ facebook: optional(_url),
90
+ twitter: optional(_url),
91
+ linkedin: optional(_url),
92
+ discord: optional(_url),
93
+ instagram: optional(_url),
94
+ youtube: optional(_url),
95
+ tiktok: optional(_url),
96
+ });
97
+
98
+ export type SocialMediaURLs = InferOutput<typeof social_media_urls>;
99
+
100
+ export const MAX_RECEIPT_MSG_CHAR = 500;
101
+
102
+ export const incrementVal = pipe(
103
+ str,
104
+ nonEmpty("required"),
105
+ transform((x) => +x),
106
+ number("must be a number"),
107
+ minValue(0, "must be greater than 0"),
108
+ //parsed output
109
+ transform((x) => x.toString())
110
+ );
111
+
112
+ export const MAX_NUM_INCREMENTS = 4;
113
+ export const incrementLabelMaxChars = 30;
114
+ export const incrementLabel = pipe(
115
+ str,
116
+ maxLength(
117
+ incrementLabelMaxChars,
118
+ ({ requirement: r }) => `cannot exceed ${r} characters`
119
+ )
120
+ );
121
+
122
+ export const increment = object({
123
+ value: incrementVal,
124
+ label: incrementLabel,
125
+ });
126
+
127
+ export type Increment = InferOutput<typeof increment>;
128
+
129
+ export const endowment = object({
130
+ id: endowId,
131
+ slug: optional(segment),
132
+ registration_number: reg_number,
133
+ name: pipe(str, nonEmpty("required")),
134
+ endow_designation: orgDesignation,
135
+ overview: optional(str),
136
+ tagline: optional(str),
137
+ image: optional(_url),
138
+ logo: optional(_url),
139
+ card_img: optional(_url),
140
+ hq_country: pipe(str, nonEmpty("required")),
141
+ active_in_countries: pipe(array(str), nonEmpty("required")),
142
+ street_address: optional(str),
143
+ social_media_urls,
144
+ /** website */
145
+ url: optional(_url),
146
+ sdgs: pipe(array(unSdgNum), minLength(1)),
147
+ receiptMsg: optional(pipe(str, maxLength(MAX_RECEIPT_MSG_CHAR))),
148
+ //can be optional, default false and need not be explicit
149
+ hide_bg_tip: optional(boolean()),
150
+ sfCompounded: optional(boolean()),
151
+ published: optional(boolean()),
152
+ /** allowed by default */
153
+ progDonationsAllowed: optional(boolean()),
154
+
155
+ allocation: optional(allocation),
156
+ donateMethods: optional(array(donateMethodId)),
157
+ increments: optional(pipe(array(increment), maxLength(MAX_NUM_INCREMENTS))),
158
+ fund_opt_in: optional(boolean()),
159
+ });
160
+
161
+ export const endowFields = keyof(endowment);
162
+
163
+ export type Endowment = InferOutput<typeof endowment>;
164
+ export type EndowmentFields = InferOutput<typeof endowFields>;
165
+
166
+ const csv = lazy((x) => {
167
+ if (!x) return str;
168
+ return pipe(str, regex(/^[^,]+(?:,[^,]+)*$/, "invalid csv"));
169
+ });
170
+
171
+ const boolCsv = pipe(
172
+ csv,
173
+ transform((x) => x.split(",").map(Boolean)),
174
+ array(boolean())
175
+ );
176
+
177
+ export const endowsQueryParams = object({
178
+ query: str,
179
+ page: pipe(
180
+ string(),
181
+ transform((x) => +x),
182
+ integer(),
183
+ minValue(1)
184
+ ),
185
+ endow_designation: optional(
186
+ pipe(
187
+ csv,
188
+ transform((x) => x.split(",")),
189
+ array(orgDesignation)
190
+ )
191
+ ),
192
+ sdgs: optional(
193
+ pipe(
194
+ csv,
195
+ transform((x) => x.split(",").map((s) => +s)),
196
+ array(unSdgNum)
197
+ )
198
+ ),
199
+ kyc_only: optional(boolCsv),
200
+ fund_opt_in: optional(boolCsv),
201
+ claimed: optional(boolCsv),
202
+ countries: optional(csv),
203
+ fields: optional(
204
+ pipe(
205
+ csv,
206
+ transform((x) => x.split(",")),
207
+ array(endowFields)
208
+ )
209
+ ),
210
+ });
211
+
212
+ export type EndowsQueryParams = InferInput<typeof endowsQueryParams>;
213
+
214
+ export const endowQueryParam = object({
215
+ fields: optional(
216
+ pipe(
217
+ csv,
218
+ transform((x) => x.split(",")),
219
+ array(endowFields)
220
+ )
221
+ ),
222
+ slug: optional(segment),
223
+ env,
224
+ });
225
+
226
+ export type EndowQueryParam = InferInput<typeof endowQueryParam>;
227
+
228
+ export const endowByEinParams = object({
229
+ env,
230
+ ein: reg_number,
231
+ });
232
+
233
+ export type EndowByEinParams = InferInput<typeof endowByEinParams>;
234
+
235
+ const amnt = pipe(number(), minValue(0));
236
+ export const programId = pipe(str, uuid());
237
+ export type ProgramId = InferOutput<typeof programId>;
238
+ export const milestoneId = pipe(str, uuid());
239
+ export type MilestoneId = InferOutput<typeof milestoneId>;
240
+
241
+ export const newMilestone = object({
242
+ date: pipe(str, isoDate()),
243
+ title: str,
244
+ description: str,
245
+ media: optional(_url),
246
+ });
247
+
248
+ export const milestoneUpdate = partial(newMilestone, ["date"]);
249
+ export type MilestoneUpdate = InferOutput<typeof milestoneUpdate>;
250
+
251
+ export type NewMilestone = InferOutput<typeof newMilestone>;
252
+ export const milestone = object({ ...newMilestone.entries, id: milestoneId });
253
+ export type Milestone = InferOutput<typeof milestone>;
254
+
255
+ export const newProgram = object({
256
+ title: str,
257
+ description: str,
258
+ banner: optional(_url),
259
+ /** null unsets target */
260
+ targetRaise: nullish(amnt),
261
+ milestones: pipe(array(newMilestone), maxLength(24)),
262
+ });
263
+
264
+ export const program = object({
265
+ ...omit(newProgram, ["milestones"]).entries,
266
+ id: programId,
267
+ });
268
+
269
+ export const programUpdate = partial(omit(newProgram, ["milestones"]));
270
+
271
+ export type NewProgram = InferOutput<typeof newProgram>;
272
+ export type Program = InferOutput<typeof program>;
273
+ export type ProgramUpdate = InferOutput<typeof programUpdate>;