@better-giving/fundraiser 1.0.0-rc.1
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/cloudsearch.d.mts +18 -0
- package/dist/cloudsearch.mjs +1 -0
- package/dist/db.d.mts +25 -0
- package/dist/db.mjs +1 -0
- package/dist/index.d.mts +11 -0
- package/dist/index.mjs +1 -0
- package/dist/schema.d.mts +121 -0
- package/dist/schema.mjs +37 -0
- package/package.json +29 -0
- package/src/cloudsearch.mts +42 -0
- package/src/db.mts +26 -0
- package/src/index.mts +28 -0
- package/src/schema.mts +82 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ToDoc, ToHitFields, ToUpdate } from "@better-giving/types/cloudsearch";
|
|
2
|
+
import type { DbRecord } from "./db.mjs";
|
|
3
|
+
export type Fields = Pick<DbRecord, "id" | "name" | "description" | "env" | "logo" | "featured" | "active" | "verified" | "donation_total_usd" | "members" | "target" | "approvers"> & {
|
|
4
|
+
/** iso | "9999-12-31T23:59:59.000Z" year 9999 */
|
|
5
|
+
expiration: string;
|
|
6
|
+
};
|
|
7
|
+
/** uuidv4 */
|
|
8
|
+
type DocId = string;
|
|
9
|
+
type FundDoc = {
|
|
10
|
+
documentId: DocId;
|
|
11
|
+
_score: number;
|
|
12
|
+
} & ToDoc<Fields>;
|
|
13
|
+
export type HitFields = ToHitFields<Omit<FundDoc, "documentId" | "_score">>;
|
|
14
|
+
export type Update = ToUpdate<DocId, Fields & {
|
|
15
|
+
/** not returned - query: endow only member */
|
|
16
|
+
members_csv: string;
|
|
17
|
+
}>;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/db.d.mts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Environment } from "@better-giving/types/list";
|
|
2
|
+
import type { NewFund } from "./schema.mjs";
|
|
3
|
+
export interface Keys {
|
|
4
|
+
/** Fund#${uuid} */
|
|
5
|
+
PK: `Fund#${string}`;
|
|
6
|
+
SK: `Fund#${string}`;
|
|
7
|
+
}
|
|
8
|
+
export interface Attributes extends NewFund {
|
|
9
|
+
/** uuid */
|
|
10
|
+
id: string;
|
|
11
|
+
env: Environment;
|
|
12
|
+
/** fund can be closed before expiration */
|
|
13
|
+
active: boolean;
|
|
14
|
+
verified: boolean;
|
|
15
|
+
/** to date received: initialized to `0` */
|
|
16
|
+
donation_total_usd: number;
|
|
17
|
+
/**
|
|
18
|
+
* approving NPO ids
|
|
19
|
+
* NPOs have a whitelist of fundraisers they support. thus, appears in their NPO profile page
|
|
20
|
+
* @default - [0]
|
|
21
|
+
* */
|
|
22
|
+
approvers: number[];
|
|
23
|
+
}
|
|
24
|
+
export interface DbRecord extends Keys, Attributes {
|
|
25
|
+
}
|
package/dist/db.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Attributes, DbRecord } from "./db.mjs";
|
|
2
|
+
export interface FundMember {
|
|
3
|
+
id: number;
|
|
4
|
+
name: string;
|
|
5
|
+
card_img?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface SingleFund extends Omit<DbRecord, "PK" | "SK" | "members"> {
|
|
8
|
+
members: FundMember[];
|
|
9
|
+
}
|
|
10
|
+
export interface FundCard extends Pick<Attributes, "id" | "name" | "description" | "env" | "logo" | "featured" | "active" | "verified" | "donation_total_usd" | "members" | "target" | "approvers"> {
|
|
11
|
+
}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { type InferOutput } from "valibot";
|
|
2
|
+
export declare const fundId: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UuidAction<string, undefined>]>;
|
|
3
|
+
export declare const settings: import("valibot").ObjectSchema<{
|
|
4
|
+
readonly allowBgTip: import("valibot").BooleanSchema<undefined>;
|
|
5
|
+
}, undefined>;
|
|
6
|
+
export declare const newFund: import("valibot").ObjectSchema<{
|
|
7
|
+
readonly name: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").NonEmptyAction<string, "required">]>;
|
|
8
|
+
readonly description: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").NonEmptyAction<string, "required">]>;
|
|
9
|
+
readonly banner: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>;
|
|
10
|
+
readonly logo: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>;
|
|
11
|
+
/** endowment ids */
|
|
12
|
+
readonly members: import("valibot").ArraySchema<import("valibot").SchemaWithPipe<[import("valibot").NumberSchema<undefined>, import("valibot").IntegerAction<number, undefined>, import("valibot").MinValueAction<number, 1, undefined>]>, undefined>;
|
|
13
|
+
readonly featured: import("valibot").BooleanSchema<undefined>;
|
|
14
|
+
readonly expiration: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").IsoTimestampAction<string, "invalid date">, import("valibot").MinValueAction<string, string, undefined>]>, never>;
|
|
15
|
+
/** `"0"` - none, {"number"} = fixed */
|
|
16
|
+
readonly target: import("valibot").UnionSchema<[import("valibot").LiteralSchema<"smart", undefined>, import("valibot").SchemaWithPipe<[import("valibot").NumberSchema<undefined>, import("valibot").MinValueAction<number, 0, undefined>, import("valibot").TransformAction<number, string>]>], undefined>;
|
|
17
|
+
}, undefined>;
|
|
18
|
+
export declare const fundUpdate: Omit<Omit<import("valibot").ObjectSchema<{
|
|
19
|
+
readonly name: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").NonEmptyAction<string, "required">]>;
|
|
20
|
+
readonly description: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").NonEmptyAction<string, "required">]>;
|
|
21
|
+
readonly banner: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>;
|
|
22
|
+
readonly logo: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>;
|
|
23
|
+
/** endowment ids */
|
|
24
|
+
readonly members: import("valibot").ArraySchema<import("valibot").SchemaWithPipe<[import("valibot").NumberSchema<undefined>, import("valibot").IntegerAction<number, undefined>, import("valibot").MinValueAction<number, 1, undefined>]>, undefined>;
|
|
25
|
+
readonly featured: import("valibot").BooleanSchema<undefined>;
|
|
26
|
+
readonly expiration: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").IsoTimestampAction<string, "invalid date">, import("valibot").MinValueAction<string, string, undefined>]>, never>;
|
|
27
|
+
/** `"0"` - none, {"number"} = fixed */
|
|
28
|
+
readonly target: import("valibot").UnionSchema<[import("valibot").LiteralSchema<"smart", undefined>, import("valibot").SchemaWithPipe<[import("valibot").NumberSchema<undefined>, import("valibot").MinValueAction<number, 0, undefined>, import("valibot").TransformAction<number, string>]>], undefined>;
|
|
29
|
+
}, undefined>, "_types" | "_run" | "entries"> & {
|
|
30
|
+
readonly entries: Pick<{
|
|
31
|
+
readonly name: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").NonEmptyAction<string, "required">]>;
|
|
32
|
+
readonly description: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").NonEmptyAction<string, "required">]>;
|
|
33
|
+
readonly banner: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>;
|
|
34
|
+
readonly logo: import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>;
|
|
35
|
+
/** endowment ids */
|
|
36
|
+
readonly members: import("valibot").ArraySchema<import("valibot").SchemaWithPipe<[import("valibot").NumberSchema<undefined>, import("valibot").IntegerAction<number, undefined>, import("valibot").MinValueAction<number, 1, undefined>]>, undefined>;
|
|
37
|
+
readonly featured: import("valibot").BooleanSchema<undefined>;
|
|
38
|
+
readonly expiration: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").IsoTimestampAction<string, "invalid date">, import("valibot").MinValueAction<string, string, undefined>]>, never>;
|
|
39
|
+
/** `"0"` - none, {"number"} = fixed */
|
|
40
|
+
readonly target: import("valibot").UnionSchema<[import("valibot").LiteralSchema<"smart", undefined>, import("valibot").SchemaWithPipe<[import("valibot").NumberSchema<undefined>, import("valibot").MinValueAction<number, 0, undefined>, import("valibot").TransformAction<number, string>]>], undefined>;
|
|
41
|
+
}, "name" | "description" | "banner" | "logo" | "target" | "featured">;
|
|
42
|
+
_run(dataset: import("valibot").Dataset<unknown, never>, config: import("valibot").Config<import("valibot").StringIssue | import("valibot").BooleanIssue | import("valibot").NonEmptyIssue<string> | import("valibot").UrlIssue<string> | import("valibot").NumberIssue | import("valibot").LiteralIssue | import("valibot").MinValueIssue<number, 0> | import("valibot").UnionIssue<import("valibot").NumberIssue | import("valibot").LiteralIssue | import("valibot").MinValueIssue<number, 0>> | import("valibot").ObjectIssue>): import("valibot").Dataset<{
|
|
43
|
+
name: string;
|
|
44
|
+
description: string;
|
|
45
|
+
banner: string;
|
|
46
|
+
logo: string;
|
|
47
|
+
target: string;
|
|
48
|
+
featured: boolean;
|
|
49
|
+
}, import("valibot").StringIssue | import("valibot").BooleanIssue | import("valibot").NonEmptyIssue<string> | import("valibot").UrlIssue<string> | import("valibot").NumberIssue | import("valibot").LiteralIssue | import("valibot").MinValueIssue<number, 0> | import("valibot").UnionIssue<import("valibot").NumberIssue | import("valibot").LiteralIssue | import("valibot").MinValueIssue<number, 0>> | import("valibot").ObjectIssue>;
|
|
50
|
+
readonly _types?: {
|
|
51
|
+
readonly input: {
|
|
52
|
+
name: string;
|
|
53
|
+
description: string;
|
|
54
|
+
banner: string;
|
|
55
|
+
logo: string;
|
|
56
|
+
target: number | "smart";
|
|
57
|
+
featured: boolean;
|
|
58
|
+
};
|
|
59
|
+
readonly output: {
|
|
60
|
+
name: string;
|
|
61
|
+
description: string;
|
|
62
|
+
banner: string;
|
|
63
|
+
logo: string;
|
|
64
|
+
target: string;
|
|
65
|
+
featured: boolean;
|
|
66
|
+
};
|
|
67
|
+
readonly issue: import("valibot").StringIssue | import("valibot").BooleanIssue | import("valibot").NonEmptyIssue<string> | import("valibot").UrlIssue<string> | import("valibot").NumberIssue | import("valibot").LiteralIssue | import("valibot").MinValueIssue<number, 0> | import("valibot").UnionIssue<import("valibot").NumberIssue | import("valibot").LiteralIssue | import("valibot").MinValueIssue<number, 0>> | import("valibot").ObjectIssue;
|
|
68
|
+
} | undefined;
|
|
69
|
+
}, "_types" | "_run" | "entries"> & {
|
|
70
|
+
readonly entries: {
|
|
71
|
+
readonly name: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").NonEmptyAction<string, "required">]>, never>;
|
|
72
|
+
readonly description: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").NonEmptyAction<string, "required">]>, never>;
|
|
73
|
+
readonly banner: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
|
|
74
|
+
readonly logo: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, import("valibot").UrlAction<string, undefined>]>, never>;
|
|
75
|
+
readonly target: import("valibot").OptionalSchema<import("valibot").UnionSchema<[import("valibot").LiteralSchema<"smart", undefined>, import("valibot").SchemaWithPipe<[import("valibot").NumberSchema<undefined>, import("valibot").MinValueAction<number, 0, undefined>, import("valibot").TransformAction<number, string>]>], undefined>, never>;
|
|
76
|
+
readonly featured: import("valibot").OptionalSchema<import("valibot").BooleanSchema<undefined>, never>;
|
|
77
|
+
};
|
|
78
|
+
_run(dataset: import("valibot").Dataset<unknown, never>, config: import("valibot").Config<import("valibot").StringIssue | import("valibot").BooleanIssue | import("valibot").NonEmptyIssue<string> | import("valibot").UrlIssue<string> | import("valibot").NumberIssue | import("valibot").LiteralIssue | import("valibot").MinValueIssue<number, 0> | import("valibot").UnionIssue<import("valibot").NumberIssue | import("valibot").LiteralIssue | import("valibot").MinValueIssue<number, 0>> | import("valibot").ObjectIssue>): import("valibot").Dataset<{
|
|
79
|
+
name?: string | undefined;
|
|
80
|
+
description?: string | undefined;
|
|
81
|
+
banner?: string | undefined;
|
|
82
|
+
logo?: string | undefined;
|
|
83
|
+
target?: string | undefined;
|
|
84
|
+
featured?: boolean | undefined;
|
|
85
|
+
}, import("valibot").StringIssue | import("valibot").BooleanIssue | import("valibot").NonEmptyIssue<string> | import("valibot").UrlIssue<string> | import("valibot").NumberIssue | import("valibot").LiteralIssue | import("valibot").MinValueIssue<number, 0> | import("valibot").UnionIssue<import("valibot").NumberIssue | import("valibot").LiteralIssue | import("valibot").MinValueIssue<number, 0>> | import("valibot").ObjectIssue>;
|
|
86
|
+
readonly _types?: {
|
|
87
|
+
readonly input: {
|
|
88
|
+
name?: string | undefined;
|
|
89
|
+
description?: string | undefined;
|
|
90
|
+
banner?: string | undefined;
|
|
91
|
+
logo?: string | undefined;
|
|
92
|
+
target?: number | "smart" | undefined;
|
|
93
|
+
featured?: boolean | undefined;
|
|
94
|
+
};
|
|
95
|
+
readonly output: {
|
|
96
|
+
name?: string | undefined;
|
|
97
|
+
description?: string | undefined;
|
|
98
|
+
banner?: string | undefined;
|
|
99
|
+
logo?: string | undefined;
|
|
100
|
+
target?: string | undefined;
|
|
101
|
+
featured?: boolean | undefined;
|
|
102
|
+
};
|
|
103
|
+
readonly issue: import("valibot").StringIssue | import("valibot").BooleanIssue | import("valibot").NonEmptyIssue<string> | import("valibot").UrlIssue<string> | import("valibot").NumberIssue | import("valibot").LiteralIssue | import("valibot").MinValueIssue<number, 0> | import("valibot").UnionIssue<import("valibot").NumberIssue | import("valibot").LiteralIssue | import("valibot").MinValueIssue<number, 0>> | import("valibot").ObjectIssue;
|
|
104
|
+
} | undefined;
|
|
105
|
+
};
|
|
106
|
+
export declare const fundsParams: import("valibot").ObjectSchema<{
|
|
107
|
+
/** search text */
|
|
108
|
+
readonly query: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").StringSchema<undefined>, import("valibot").TrimAction]>, never>;
|
|
109
|
+
readonly page: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<[import("valibot").NumberSchema<undefined>, import("valibot").IntegerAction<number, undefined>, import("valibot").MinValueAction<number, 1, undefined>]>, never>;
|
|
110
|
+
}, undefined>;
|
|
111
|
+
export declare const fundsEndowMemberOfParams: import("valibot").ObjectSchema<{
|
|
112
|
+
readonly npoProfileFeatured: import("valibot").BooleanSchema<undefined>;
|
|
113
|
+
}, undefined>;
|
|
114
|
+
export interface NewFund extends InferOutput<typeof newFund> {
|
|
115
|
+
}
|
|
116
|
+
export interface FundUpdate extends InferOutput<typeof fundUpdate> {
|
|
117
|
+
}
|
|
118
|
+
export interface FundsParams extends InferOutput<typeof fundsParams> {
|
|
119
|
+
}
|
|
120
|
+
export interface FundsEndowMemberOfParams extends InferOutput<typeof fundsEndowMemberOfParams> {
|
|
121
|
+
}
|
package/dist/schema.mjs
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { url, array, boolean, integer, isoTimestamp, literal, minValue, nonEmpty, number, object, optional, partial, pick, pipe, string, transform, trim, union, uuid, } from "valibot";
|
|
2
|
+
const str = pipe(string(), trim());
|
|
3
|
+
export const fundId = pipe(str, uuid());
|
|
4
|
+
export const settings = object({
|
|
5
|
+
allowBgTip: boolean(),
|
|
6
|
+
});
|
|
7
|
+
export const newFund = object({
|
|
8
|
+
name: pipe(str, nonEmpty("required")),
|
|
9
|
+
description: pipe(str, nonEmpty("required")),
|
|
10
|
+
banner: pipe(str, url()),
|
|
11
|
+
logo: pipe(str, url()),
|
|
12
|
+
/** endowment ids */
|
|
13
|
+
members: array(pipe(number(), integer(), minValue(1))),
|
|
14
|
+
featured: boolean(),
|
|
15
|
+
expiration: optional(pipe(str, isoTimestamp("invalid date"), minValue(new Date().toISOString()) //created each parsing
|
|
16
|
+
)),
|
|
17
|
+
/** `"0"` - none, {"number"} = fixed */
|
|
18
|
+
target: union([
|
|
19
|
+
literal("smart"),
|
|
20
|
+
pipe(number(), minValue(0), transform((v) => v.toString())),
|
|
21
|
+
]),
|
|
22
|
+
});
|
|
23
|
+
export const fundUpdate = partial(pick(newFund, ["name", "description", "banner", "logo", "featured", "target"]));
|
|
24
|
+
export const fundsParams = object({
|
|
25
|
+
/** search text */
|
|
26
|
+
query: optional(str),
|
|
27
|
+
page: optional(pipe(number(), integer(), minValue(1))),
|
|
28
|
+
});
|
|
29
|
+
export const fundsEndowMemberOfParams = object({
|
|
30
|
+
/*
|
|
31
|
+
* this endow is the only member (not an index fund),
|
|
32
|
+
* and is approved:
|
|
33
|
+
* either pre-approval in creation (creator has endow credential)
|
|
34
|
+
* or creator has no credential but later npo approved
|
|
35
|
+
*/
|
|
36
|
+
npoProfileFeatured: boolean(),
|
|
37
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@better-giving/fundraiser",
|
|
3
|
+
"version": "1.0.0-rc.1",
|
|
4
|
+
"dependencies": {
|
|
5
|
+
"valibot": "0.42.0"
|
|
6
|
+
},
|
|
7
|
+
"peerDependencies": {
|
|
8
|
+
"valibot": "0.42.0"
|
|
9
|
+
},
|
|
10
|
+
"devDependencies": {
|
|
11
|
+
"@better-giving/config": "workspace:*",
|
|
12
|
+
"@better-giving/types": "workspace:*"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"src",
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"exports": {
|
|
19
|
+
".": "./dist/index.mjs",
|
|
20
|
+
"./schema": "./dist/schema.mjs",
|
|
21
|
+
"./db": "./dist/db.mjs",
|
|
22
|
+
"./cloudsearch": "./dist/cloudsearch.mjs"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"publish": "npm publish --access public",
|
|
26
|
+
"build": "rm -rf ./dist && tsc --outDir dist",
|
|
27
|
+
"type-chek": "tsc --noEmit"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ToDoc,
|
|
3
|
+
ToHitFields,
|
|
4
|
+
ToUpdate,
|
|
5
|
+
} from "@better-giving/types/cloudsearch";
|
|
6
|
+
import type { DbRecord } from "./db.mjs";
|
|
7
|
+
|
|
8
|
+
export type Fields = Pick<
|
|
9
|
+
DbRecord,
|
|
10
|
+
| "id"
|
|
11
|
+
| "name"
|
|
12
|
+
| "description"
|
|
13
|
+
| "env"
|
|
14
|
+
| "logo"
|
|
15
|
+
| "featured"
|
|
16
|
+
| "active"
|
|
17
|
+
| "verified"
|
|
18
|
+
| "donation_total_usd"
|
|
19
|
+
| "members"
|
|
20
|
+
| "target"
|
|
21
|
+
| "approvers"
|
|
22
|
+
> & {
|
|
23
|
+
/** iso | "9999-12-31T23:59:59.000Z" year 9999 */
|
|
24
|
+
expiration: string;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/** uuidv4 */
|
|
28
|
+
type DocId = string;
|
|
29
|
+
type FundDoc = {
|
|
30
|
+
documentId: DocId;
|
|
31
|
+
_score: number;
|
|
32
|
+
} & ToDoc<Fields>;
|
|
33
|
+
|
|
34
|
+
export type HitFields = ToHitFields<Omit<FundDoc, "documentId" | "_score">>;
|
|
35
|
+
|
|
36
|
+
export type Update = ToUpdate<
|
|
37
|
+
DocId,
|
|
38
|
+
Fields & {
|
|
39
|
+
/** not returned - query: endow only member */
|
|
40
|
+
members_csv: string;
|
|
41
|
+
}
|
|
42
|
+
>;
|
package/src/db.mts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Environment } from "@better-giving/types/list";
|
|
2
|
+
import type { NewFund } from "./schema.mjs";
|
|
3
|
+
export interface Keys {
|
|
4
|
+
/** Fund#${uuid} */
|
|
5
|
+
PK: `Fund#${string}`;
|
|
6
|
+
SK: `Fund#${string}`;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface Attributes extends NewFund {
|
|
10
|
+
/** uuid */
|
|
11
|
+
id: string;
|
|
12
|
+
env: Environment;
|
|
13
|
+
/** fund can be closed before expiration */
|
|
14
|
+
active: boolean;
|
|
15
|
+
verified: boolean;
|
|
16
|
+
/** to date received: initialized to `0` */
|
|
17
|
+
donation_total_usd: number;
|
|
18
|
+
/**
|
|
19
|
+
* approving NPO ids
|
|
20
|
+
* NPOs have a whitelist of fundraisers they support. thus, appears in their NPO profile page
|
|
21
|
+
* @default - [0]
|
|
22
|
+
* */
|
|
23
|
+
approvers: number[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface DbRecord extends Keys, Attributes {}
|
package/src/index.mts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Attributes, DbRecord } from "./db.mjs";
|
|
2
|
+
|
|
3
|
+
export interface FundMember {
|
|
4
|
+
id: number;
|
|
5
|
+
name: string;
|
|
6
|
+
card_img?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface SingleFund extends Omit<DbRecord, "PK" | "SK" | "members"> {
|
|
10
|
+
members: FundMember[];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface FundCard
|
|
14
|
+
extends Pick<
|
|
15
|
+
Attributes,
|
|
16
|
+
| "id"
|
|
17
|
+
| "name"
|
|
18
|
+
| "description"
|
|
19
|
+
| "env"
|
|
20
|
+
| "logo"
|
|
21
|
+
| "featured"
|
|
22
|
+
| "active"
|
|
23
|
+
| "verified"
|
|
24
|
+
| "donation_total_usd"
|
|
25
|
+
| "members"
|
|
26
|
+
| "target"
|
|
27
|
+
| "approvers"
|
|
28
|
+
> {}
|
package/src/schema.mts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import {
|
|
2
|
+
url,
|
|
3
|
+
type InferOutput,
|
|
4
|
+
array,
|
|
5
|
+
boolean,
|
|
6
|
+
integer,
|
|
7
|
+
isoTimestamp,
|
|
8
|
+
literal,
|
|
9
|
+
minValue,
|
|
10
|
+
nonEmpty,
|
|
11
|
+
number,
|
|
12
|
+
object,
|
|
13
|
+
optional,
|
|
14
|
+
partial,
|
|
15
|
+
pick,
|
|
16
|
+
pipe,
|
|
17
|
+
string,
|
|
18
|
+
transform,
|
|
19
|
+
trim,
|
|
20
|
+
union,
|
|
21
|
+
uuid,
|
|
22
|
+
} from "valibot";
|
|
23
|
+
|
|
24
|
+
const str = pipe(string(), trim());
|
|
25
|
+
|
|
26
|
+
export const fundId = pipe(str, uuid());
|
|
27
|
+
|
|
28
|
+
export const settings = object({
|
|
29
|
+
allowBgTip: boolean(),
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
export const newFund = object({
|
|
33
|
+
name: pipe(str, nonEmpty("required")),
|
|
34
|
+
description: pipe(str, nonEmpty("required")),
|
|
35
|
+
banner: pipe(str, url()),
|
|
36
|
+
logo: pipe(str, url()),
|
|
37
|
+
/** endowment ids */
|
|
38
|
+
members: array(pipe(number(), integer(), minValue(1))),
|
|
39
|
+
featured: boolean(),
|
|
40
|
+
expiration: optional(
|
|
41
|
+
pipe(
|
|
42
|
+
str,
|
|
43
|
+
isoTimestamp("invalid date"),
|
|
44
|
+
minValue(new Date().toISOString()) //created each parsing
|
|
45
|
+
)
|
|
46
|
+
),
|
|
47
|
+
/** `"0"` - none, {"number"} = fixed */
|
|
48
|
+
target: union([
|
|
49
|
+
literal("smart"),
|
|
50
|
+
pipe(
|
|
51
|
+
number(),
|
|
52
|
+
minValue(0),
|
|
53
|
+
transform((v) => v.toString())
|
|
54
|
+
),
|
|
55
|
+
]),
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
export const fundUpdate = partial(
|
|
59
|
+
pick(newFund, ["name", "description", "banner", "logo", "featured", "target"])
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
export const fundsParams = object({
|
|
63
|
+
/** search text */
|
|
64
|
+
query: optional(str),
|
|
65
|
+
page: optional(pipe(number(), integer(), minValue(1))),
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
export const fundsEndowMemberOfParams = object({
|
|
69
|
+
/*
|
|
70
|
+
* this endow is the only member (not an index fund),
|
|
71
|
+
* and is approved:
|
|
72
|
+
* either pre-approval in creation (creator has endow credential)
|
|
73
|
+
* or creator has no credential but later npo approved
|
|
74
|
+
*/
|
|
75
|
+
npoProfileFeatured: boolean(),
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
export interface NewFund extends InferOutput<typeof newFund> {}
|
|
79
|
+
export interface FundUpdate extends InferOutput<typeof fundUpdate> {}
|
|
80
|
+
export interface FundsParams extends InferOutput<typeof fundsParams> {}
|
|
81
|
+
export interface FundsEndowMemberOfParams
|
|
82
|
+
extends InferOutput<typeof fundsEndowMemberOfParams> {}
|