founder-schema 0.18.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +110 -3
- package/dist/access/permissions.d.ts +3 -3
- package/dist/access/permissions.d.ts.map +1 -1
- package/dist/access/permissions.js.map +1 -1
- package/dist/core/common.d.ts +49 -28
- package/dist/core/common.d.ts.map +1 -1
- package/dist/core/common.js +65 -26
- package/dist/core/common.js.map +1 -1
- package/dist/core/deletion.d.ts +40 -0
- package/dist/core/deletion.d.ts.map +1 -0
- package/dist/core/deletion.js +39 -0
- package/dist/core/deletion.js.map +1 -0
- package/dist/core/limits.d.ts +25 -0
- package/dist/core/limits.d.ts.map +1 -1
- package/dist/core/limits.js +25 -0
- package/dist/core/limits.js.map +1 -1
- package/dist/core/validation.d.ts +13 -0
- package/dist/core/validation.d.ts.map +1 -1
- package/dist/core/validation.js +13 -0
- package/dist/core/validation.js.map +1 -1
- package/dist/domains/audit/audit.d.ts +36 -12
- package/dist/domains/audit/audit.d.ts.map +1 -1
- package/dist/domains/audit/audit.js +9 -10
- package/dist/domains/audit/audit.js.map +1 -1
- package/dist/domains/billing/billing.d.ts +29 -13
- package/dist/domains/billing/billing.d.ts.map +1 -1
- package/dist/domains/billing/billing.js +2 -3
- package/dist/domains/billing/billing.js.map +1 -1
- package/dist/domains/chat/chat.d.ts +19 -5
- package/dist/domains/chat/chat.d.ts.map +1 -1
- package/dist/domains/chat/chat.js +10 -10
- package/dist/domains/chat/chat.js.map +1 -1
- package/dist/domains/communities/communities.d.ts +95 -57
- package/dist/domains/communities/communities.d.ts.map +1 -1
- package/dist/domains/contributions/contributions.d.ts +28 -12
- package/dist/domains/contributions/contributions.d.ts.map +1 -1
- package/dist/domains/contributions/contributions.js +3 -0
- package/dist/domains/contributions/contributions.js.map +1 -1
- package/dist/domains/discover/discover.d.ts +2 -2
- package/dist/domains/feed/feed.d.ts +111 -63
- package/dist/domains/feed/feed.d.ts.map +1 -1
- package/dist/domains/feed/feed.js +3 -0
- package/dist/domains/feed/feed.js.map +1 -1
- package/dist/domains/location/areas.d.ts +338 -0
- package/dist/domains/location/areas.d.ts.map +1 -0
- package/dist/domains/location/areas.js +241 -0
- package/dist/domains/location/areas.js.map +1 -0
- package/dist/domains/location/india.d.ts +31 -123
- package/dist/domains/location/india.d.ts.map +1 -1
- package/dist/domains/location/india.js +98 -64
- package/dist/domains/location/india.js.map +1 -1
- package/dist/domains/media/media.d.ts +22 -0
- package/dist/domains/media/media.d.ts.map +1 -1
- package/dist/domains/media/media.js +20 -0
- package/dist/domains/media/media.js.map +1 -1
- package/dist/domains/members/members.d.ts +26 -9
- package/dist/domains/members/members.d.ts.map +1 -1
- package/dist/domains/members/members.js +9 -10
- package/dist/domains/members/members.js.map +1 -1
- package/dist/domains/membership/membership.d.ts +19 -0
- package/dist/domains/membership/membership.d.ts.map +1 -1
- package/dist/domains/membership/membership.js +10 -0
- package/dist/domains/membership/membership.js.map +1 -1
- package/dist/domains/moderation/moderation.d.ts +8 -2
- package/dist/domains/moderation/moderation.d.ts.map +1 -1
- package/dist/domains/moderation/moderation.js +3 -6
- package/dist/domains/moderation/moderation.js.map +1 -1
- package/dist/domains/notifications/notifications.d.ts +10 -6
- package/dist/domains/notifications/notifications.d.ts.map +1 -1
- package/dist/domains/onboarding/onboarding-answers.d.ts +9 -12
- package/dist/domains/onboarding/onboarding-answers.d.ts.map +1 -1
- package/dist/domains/onboarding/onboarding-answers.js +12 -19
- package/dist/domains/onboarding/onboarding-answers.js.map +1 -1
- package/dist/domains/onboarding/onboarding.d.ts +121 -98
- package/dist/domains/onboarding/onboarding.d.ts.map +1 -1
- package/dist/domains/onboarding/onboarding.js +30 -28
- package/dist/domains/onboarding/onboarding.js.map +1 -1
- package/dist/domains/people/person.d.ts +54 -0
- package/dist/domains/people/person.d.ts.map +1 -0
- package/dist/domains/people/person.js +73 -0
- package/dist/domains/people/person.js.map +1 -0
- package/dist/domains/products/products.d.ts +62 -33
- package/dist/domains/products/products.d.ts.map +1 -1
- package/dist/domains/products/products.js +3 -0
- package/dist/domains/products/products.js.map +1 -1
- package/dist/domains/profile/founder-profile.d.ts +93 -60
- package/dist/domains/profile/founder-profile.d.ts.map +1 -1
- package/dist/domains/profile/founder-profile.js +55 -25
- package/dist/domains/profile/founder-profile.js.map +1 -1
- package/dist/domains/reviews/reviews.d.ts +25 -15
- package/dist/domains/reviews/reviews.d.ts.map +1 -1
- package/dist/domains/support/support.d.ts +47 -10
- package/dist/domains/support/support.d.ts.map +1 -1
- package/dist/domains/support/support.js +4 -2
- package/dist/domains/support/support.js.map +1 -1
- package/dist/domains/team/team.d.ts +9 -3
- package/dist/domains/team/team.d.ts.map +1 -1
- package/dist/domains/team/team.js +3 -6
- package/dist/domains/team/team.js.map +1 -1
- package/dist/index.d.ts +13 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -11
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
- package/dist/account.d.ts +0 -40
- package/dist/account.d.ts.map +0 -1
- package/dist/account.js +0 -39
- package/dist/account.js.map +0 -1
- package/dist/chat.d.ts +0 -187
- package/dist/chat.d.ts.map +0 -1
- package/dist/chat.js +0 -189
- package/dist/chat.js.map +0 -1
- package/dist/common.d.ts +0 -304
- package/dist/common.d.ts.map +0 -1
- package/dist/common.js +0 -340
- package/dist/common.js.map +0 -1
- package/dist/discover.d.ts +0 -245
- package/dist/discover.d.ts.map +0 -1
- package/dist/discover.js +0 -68
- package/dist/discover.js.map +0 -1
- package/dist/errors.d.ts +0 -85
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js +0 -89
- package/dist/errors.js.map +0 -1
- package/dist/feed.d.ts +0 -1658
- package/dist/feed.d.ts.map +0 -1
- package/dist/feed.js +0 -623
- package/dist/feed.js.map +0 -1
- package/dist/founder-profile.d.ts +0 -387
- package/dist/founder-profile.d.ts.map +0 -1
- package/dist/founder-profile.js +0 -180
- package/dist/founder-profile.js.map +0 -1
- package/dist/limits.d.ts +0 -76
- package/dist/limits.d.ts.map +0 -1
- package/dist/limits.js +0 -84
- package/dist/limits.js.map +0 -1
- package/dist/onboarding.d.ts +0 -1018
- package/dist/onboarding.d.ts.map +0 -1
- package/dist/onboarding.js +0 -717
- package/dist/onboarding.js.map +0 -1
- package/dist/responses/common.d.ts +0 -167
- package/dist/responses/common.d.ts.map +0 -1
- package/dist/responses/common.js +0 -67
- package/dist/responses/common.js.map +0 -1
- package/dist/responses/index.d.ts +0 -7
- package/dist/responses/index.d.ts.map +0 -1
- package/dist/responses/index.js +0 -7
- package/dist/responses/index.js.map +0 -1
- package/dist/uploads.d.ts +0 -113
- package/dist/uploads.d.ts.map +0 -1
- package/dist/uploads.js +0 -106
- package/dist/uploads.js.map +0 -1
- package/dist/validation.d.ts +0 -136
- package/dist/validation.d.ts.map +0 -1
- package/dist/validation.js +0 -142
- package/dist/validation.js.map +0 -1
package/dist/validation.d.ts
DELETED
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* founder-schema — How a validation failure is described, on both sides
|
|
3
|
-
*
|
|
4
|
-
* TWO RULES, and they are what let the web client show any error, its own or
|
|
5
|
-
* the server's, on the right field in the member's language:
|
|
6
|
-
*
|
|
7
|
-
* 1. A CUSTOM MESSAGE IS A KEY, NEVER A SENTENCE. Where a schema needs its own
|
|
8
|
-
* message (a refine, a regex), the message is one of `VALIDATION_MESSAGE`,
|
|
9
|
-
* such as `phoneInvalid`. The client turns the key into text in English or
|
|
10
|
-
* Hindi. Before 0.2.0 these were English sentences, so a Hindi screen showed
|
|
11
|
-
* an English error, and a client that wanted to translate one had to match
|
|
12
|
-
* on the wording.
|
|
13
|
-
*
|
|
14
|
-
* Plain bounds carry NO custom message. `.min(1)` and `.max(80)` produce
|
|
15
|
-
* Zod's own `too_small` / `too_big` issues, which already say which bound
|
|
16
|
-
* and what it was (`minimum`, `maximum`, `origin`), and the client words
|
|
17
|
-
* them from those. A hand-written "at most 80 characters" would only
|
|
18
|
-
* restate the number in one language.
|
|
19
|
-
*
|
|
20
|
-
* 2. THE SERVER SENDS EVERY ISSUE, IN THIS SHAPE. A 400 answers with
|
|
21
|
-
* `error.details.issues`, built by `toValidationIssues`, so the client can
|
|
22
|
-
* put each one under its field. Until 0.2.0 the backend sent only the
|
|
23
|
-
* first issue's message, with no path at all.
|
|
24
|
-
*
|
|
25
|
-
* ⚠️ `toValidationIssues` COPIES A WHITELIST OF FIELDS, it never spreads an
|
|
26
|
-
* issue. Zod can carry the rejected `input` on an issue, and these bodies hold a
|
|
27
|
-
* date of birth and a phone number. Echoing them into an error response sends
|
|
28
|
-
* them back to the client, into logs and into any proxy in between. A test
|
|
29
|
-
* proves `input` never survives.
|
|
30
|
-
*
|
|
31
|
-
* @module founder-schema/validation
|
|
32
|
-
*/
|
|
33
|
-
import { z } from 'zod';
|
|
34
|
-
/**
|
|
35
|
-
* Every custom message a schema in this package can produce. Each is a
|
|
36
|
-
* translation key the clients define in every language they ship.
|
|
37
|
-
*
|
|
38
|
-
* ⚠️ Append only, and add the translation in the same change. Renaming one
|
|
39
|
-
* shows the raw key to every member until each client ships the new name.
|
|
40
|
-
*/
|
|
41
|
-
export declare const VALIDATION_MESSAGE: {
|
|
42
|
-
/** Not a 24-hex Mongo id. */
|
|
43
|
-
readonly invalidId: "invalidId";
|
|
44
|
-
/** Handle: wrong characters, or a dot in the wrong place. */
|
|
45
|
-
readonly usernameInvalid: "usernameInvalid";
|
|
46
|
-
/** Not a 10-digit Indian mobile number. */
|
|
47
|
-
readonly phoneInvalid: "phoneInvalid";
|
|
48
|
-
/** Not a `YYYY-MM-DD` date. */
|
|
49
|
-
readonly dateInvalid: "dateInvalid";
|
|
50
|
-
/** A date that does not exist, such as 30 February. */
|
|
51
|
-
readonly dobInvalid: "dobInvalid";
|
|
52
|
-
/** Under the minimum age. */
|
|
53
|
-
readonly dobUnderAge: "dobUnderAge";
|
|
54
|
-
/** Over the sanity ceiling: almost always a mistyped year. */
|
|
55
|
-
readonly dobTooOld: "dobTooOld";
|
|
56
|
-
/** A founding year after this year. */
|
|
57
|
-
readonly foundedYearFuture: "foundedYearFuture";
|
|
58
|
-
/** An upload key that is not one this product mints. */
|
|
59
|
-
readonly uploadKeyInvalid: "uploadKeyInvalid";
|
|
60
|
-
/** A post with neither text nor media. */
|
|
61
|
-
readonly postEmpty: "postEmpty";
|
|
62
|
-
/** Two poll options with the same label. */
|
|
63
|
-
readonly pollOptionsDuplicate: "pollOptionsDuplicate";
|
|
64
|
-
/** An empty string sent to clear a patch field; clearing is `null`. */
|
|
65
|
-
readonly clearWithNull: "clearWithNull";
|
|
66
|
-
/** Not a plain http(s) URL on a real domain (`javascript:`, `localhost`, an IP...). */
|
|
67
|
-
readonly urlInvalid: "urlInvalid";
|
|
68
|
-
/** A handle this product keeps for itself (`admin`, `support`...). */
|
|
69
|
-
readonly usernameReserved: "usernameReserved";
|
|
70
|
-
/** Agreed to a version of the guidelines that is not the current one. */
|
|
71
|
-
readonly guidelinesOutdated: "guidelinesOutdated";
|
|
72
|
-
};
|
|
73
|
-
export type ValidationMessageKey = (typeof VALIDATION_MESSAGE)[keyof typeof VALIDATION_MESSAGE];
|
|
74
|
-
/**
|
|
75
|
-
* Which part of the request an issue is about.
|
|
76
|
-
*
|
|
77
|
-
* ONE PATH CONVENTION: `path` is ALWAYS relative to this part, so a body field
|
|
78
|
-
* reads `['venture', 'name']` with `location: 'body'`, never
|
|
79
|
-
* `['body', 'venture', 'name']`. A form maps body issues straight onto its
|
|
80
|
-
* fields without stripping a prefix, and a client that sees `query` or
|
|
81
|
-
* `params` knows the problem is the URL, not anything the member typed.
|
|
82
|
-
*/
|
|
83
|
-
export declare const REQUEST_PART_VALUES: readonly ["body", "query", "params"];
|
|
84
|
-
export declare const requestPartSchema: z.ZodEnum<{
|
|
85
|
-
body: "body";
|
|
86
|
-
query: "query";
|
|
87
|
-
params: "params";
|
|
88
|
-
}>;
|
|
89
|
-
export type RequestPart = z.infer<typeof requestPartSchema>;
|
|
90
|
-
/**
|
|
91
|
-
* One problem with one field, as it crosses the wire.
|
|
92
|
-
*
|
|
93
|
-
* `code` is Zod's issue code (`too_small`, `too_big`, `invalid_type`,
|
|
94
|
-
* `invalid_format`, `custom`...). `message` is either one of
|
|
95
|
-
* `VALIDATION_MESSAGE` or, for a plain bound, Zod's own English text, which the
|
|
96
|
-
* client ignores in favour of `code` plus `minimum` / `maximum`.
|
|
97
|
-
*/
|
|
98
|
-
export declare const validationIssueSchema: z.ZodObject<{
|
|
99
|
-
location: z.ZodOptional<z.ZodEnum<{
|
|
100
|
-
body: "body";
|
|
101
|
-
query: "query";
|
|
102
|
-
params: "params";
|
|
103
|
-
}>>;
|
|
104
|
-
path: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
|
|
105
|
-
code: z.ZodString;
|
|
106
|
-
message: z.ZodString;
|
|
107
|
-
minimum: z.ZodOptional<z.ZodNumber>;
|
|
108
|
-
maximum: z.ZodOptional<z.ZodNumber>;
|
|
109
|
-
origin: z.ZodOptional<z.ZodString>;
|
|
110
|
-
format: z.ZodOptional<z.ZodString>;
|
|
111
|
-
}, z.core.$strip>;
|
|
112
|
-
export type ValidationIssue = z.infer<typeof validationIssueSchema>;
|
|
113
|
-
/** The loosest shape this needs from a Zod issue, so it works across 4.x. */
|
|
114
|
-
interface ZodIssueLike {
|
|
115
|
-
path: readonly PropertyKey[];
|
|
116
|
-
code: string;
|
|
117
|
-
message: string;
|
|
118
|
-
minimum?: unknown;
|
|
119
|
-
maximum?: unknown;
|
|
120
|
-
origin?: unknown;
|
|
121
|
-
format?: unknown;
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* A Zod error as the wire shape. Use this on the server for every 400, and on
|
|
125
|
-
* the client to treat its own errors and the server's the same way.
|
|
126
|
-
*
|
|
127
|
-
* `location` is stamped on every issue when given; the server always gives it.
|
|
128
|
-
*
|
|
129
|
-
* Copies a WHITELIST of fields (see the module note). A path segment that is a
|
|
130
|
-
* symbol, which JSON cannot carry, becomes its description.
|
|
131
|
-
*/
|
|
132
|
-
export declare function toValidationIssues(error: {
|
|
133
|
-
issues: readonly ZodIssueLike[];
|
|
134
|
-
}, location?: RequestPart): ValidationIssue[];
|
|
135
|
-
export {};
|
|
136
|
-
//# sourceMappingURL=validation.d.ts.map
|
package/dist/validation.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB;IAC7B,6BAA6B;;IAE7B,6DAA6D;;IAE7D,2CAA2C;;IAE3C,+BAA+B;;IAE/B,uDAAuD;;IAEvD,6BAA6B;;IAE7B,8DAA8D;;IAE9D,uCAAuC;;IAEvC,wDAAwD;;IAExD,0CAA0C;;IAE1C,4CAA4C;;IAE5C,uEAAuE;;IAEvE,uFAAuF;;IAEvF,sEAAsE;;IAEtE,yEAAyE;;CAEjE,CAAC;AACX,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,OAAO,kBAAkB,CAAC,CAAC;AAEhG;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,sCAAuC,CAAC;AACxE,eAAO,MAAM,iBAAiB;;;;EAA8B,CAAC;AAC7D,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;iBAkBhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,6EAA6E;AAC7E,UAAU,YAAY;IACpB,IAAI,EAAE,SAAS,WAAW,EAAE,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAKD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE;IAAE,MAAM,EAAE,SAAS,YAAY,EAAE,CAAA;CAAE,EAC1C,QAAQ,CAAC,EAAE,WAAW,GACrB,eAAe,EAAE,CAkBnB"}
|
package/dist/validation.js
DELETED
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* founder-schema — How a validation failure is described, on both sides
|
|
3
|
-
*
|
|
4
|
-
* TWO RULES, and they are what let the web client show any error, its own or
|
|
5
|
-
* the server's, on the right field in the member's language:
|
|
6
|
-
*
|
|
7
|
-
* 1. A CUSTOM MESSAGE IS A KEY, NEVER A SENTENCE. Where a schema needs its own
|
|
8
|
-
* message (a refine, a regex), the message is one of `VALIDATION_MESSAGE`,
|
|
9
|
-
* such as `phoneInvalid`. The client turns the key into text in English or
|
|
10
|
-
* Hindi. Before 0.2.0 these were English sentences, so a Hindi screen showed
|
|
11
|
-
* an English error, and a client that wanted to translate one had to match
|
|
12
|
-
* on the wording.
|
|
13
|
-
*
|
|
14
|
-
* Plain bounds carry NO custom message. `.min(1)` and `.max(80)` produce
|
|
15
|
-
* Zod's own `too_small` / `too_big` issues, which already say which bound
|
|
16
|
-
* and what it was (`minimum`, `maximum`, `origin`), and the client words
|
|
17
|
-
* them from those. A hand-written "at most 80 characters" would only
|
|
18
|
-
* restate the number in one language.
|
|
19
|
-
*
|
|
20
|
-
* 2. THE SERVER SENDS EVERY ISSUE, IN THIS SHAPE. A 400 answers with
|
|
21
|
-
* `error.details.issues`, built by `toValidationIssues`, so the client can
|
|
22
|
-
* put each one under its field. Until 0.2.0 the backend sent only the
|
|
23
|
-
* first issue's message, with no path at all.
|
|
24
|
-
*
|
|
25
|
-
* ⚠️ `toValidationIssues` COPIES A WHITELIST OF FIELDS, it never spreads an
|
|
26
|
-
* issue. Zod can carry the rejected `input` on an issue, and these bodies hold a
|
|
27
|
-
* date of birth and a phone number. Echoing them into an error response sends
|
|
28
|
-
* them back to the client, into logs and into any proxy in between. A test
|
|
29
|
-
* proves `input` never survives.
|
|
30
|
-
*
|
|
31
|
-
* @module founder-schema/validation
|
|
32
|
-
*/
|
|
33
|
-
import { z } from 'zod';
|
|
34
|
-
/**
|
|
35
|
-
* Every custom message a schema in this package can produce. Each is a
|
|
36
|
-
* translation key the clients define in every language they ship.
|
|
37
|
-
*
|
|
38
|
-
* ⚠️ Append only, and add the translation in the same change. Renaming one
|
|
39
|
-
* shows the raw key to every member until each client ships the new name.
|
|
40
|
-
*/
|
|
41
|
-
export const VALIDATION_MESSAGE = {
|
|
42
|
-
/** Not a 24-hex Mongo id. */
|
|
43
|
-
invalidId: 'invalidId',
|
|
44
|
-
/** Handle: wrong characters, or a dot in the wrong place. */
|
|
45
|
-
usernameInvalid: 'usernameInvalid',
|
|
46
|
-
/** Not a 10-digit Indian mobile number. */
|
|
47
|
-
phoneInvalid: 'phoneInvalid',
|
|
48
|
-
/** Not a `YYYY-MM-DD` date. */
|
|
49
|
-
dateInvalid: 'dateInvalid',
|
|
50
|
-
/** A date that does not exist, such as 30 February. */
|
|
51
|
-
dobInvalid: 'dobInvalid',
|
|
52
|
-
/** Under the minimum age. */
|
|
53
|
-
dobUnderAge: 'dobUnderAge',
|
|
54
|
-
/** Over the sanity ceiling: almost always a mistyped year. */
|
|
55
|
-
dobTooOld: 'dobTooOld',
|
|
56
|
-
/** A founding year after this year. */
|
|
57
|
-
foundedYearFuture: 'foundedYearFuture',
|
|
58
|
-
/** An upload key that is not one this product mints. */
|
|
59
|
-
uploadKeyInvalid: 'uploadKeyInvalid',
|
|
60
|
-
/** A post with neither text nor media. */
|
|
61
|
-
postEmpty: 'postEmpty',
|
|
62
|
-
/** Two poll options with the same label. */
|
|
63
|
-
pollOptionsDuplicate: 'pollOptionsDuplicate',
|
|
64
|
-
/** An empty string sent to clear a patch field; clearing is `null`. */
|
|
65
|
-
clearWithNull: 'clearWithNull',
|
|
66
|
-
/** Not a plain http(s) URL on a real domain (`javascript:`, `localhost`, an IP...). */
|
|
67
|
-
urlInvalid: 'urlInvalid',
|
|
68
|
-
/** A handle this product keeps for itself (`admin`, `support`...). */
|
|
69
|
-
usernameReserved: 'usernameReserved',
|
|
70
|
-
/** Agreed to a version of the guidelines that is not the current one. */
|
|
71
|
-
guidelinesOutdated: 'guidelinesOutdated',
|
|
72
|
-
};
|
|
73
|
-
/**
|
|
74
|
-
* Which part of the request an issue is about.
|
|
75
|
-
*
|
|
76
|
-
* ONE PATH CONVENTION: `path` is ALWAYS relative to this part, so a body field
|
|
77
|
-
* reads `['venture', 'name']` with `location: 'body'`, never
|
|
78
|
-
* `['body', 'venture', 'name']`. A form maps body issues straight onto its
|
|
79
|
-
* fields without stripping a prefix, and a client that sees `query` or
|
|
80
|
-
* `params` knows the problem is the URL, not anything the member typed.
|
|
81
|
-
*/
|
|
82
|
-
export const REQUEST_PART_VALUES = ['body', 'query', 'params'];
|
|
83
|
-
export const requestPartSchema = z.enum(REQUEST_PART_VALUES);
|
|
84
|
-
/**
|
|
85
|
-
* One problem with one field, as it crosses the wire.
|
|
86
|
-
*
|
|
87
|
-
* `code` is Zod's issue code (`too_small`, `too_big`, `invalid_type`,
|
|
88
|
-
* `invalid_format`, `custom`...). `message` is either one of
|
|
89
|
-
* `VALIDATION_MESSAGE` or, for a plain bound, Zod's own English text, which the
|
|
90
|
-
* client ignores in favour of `code` plus `minimum` / `maximum`.
|
|
91
|
-
*/
|
|
92
|
-
export const validationIssueSchema = z.object({
|
|
93
|
-
/** Set by the server on every issue it sends; absent on a client's own parse. */
|
|
94
|
-
location: requestPartSchema.optional(),
|
|
95
|
-
/**
|
|
96
|
-
* Where the problem is, RELATIVE TO `location`: `['venture', 'name']`,
|
|
97
|
-
* `['options', 2, 'label']`, `['contentId']`.
|
|
98
|
-
*/
|
|
99
|
-
path: z.array(z.union([z.string(), z.number()])),
|
|
100
|
-
code: z.string(),
|
|
101
|
-
message: z.string(),
|
|
102
|
-
/** `too_small`: the bound that was missed. */
|
|
103
|
-
minimum: z.number().optional(),
|
|
104
|
-
/** `too_big`: the bound that was passed. */
|
|
105
|
-
maximum: z.number().optional(),
|
|
106
|
-
/** What was measured: `string`, `array`, `number`... */
|
|
107
|
-
origin: z.string().optional(),
|
|
108
|
-
/** `invalid_format`: which format, e.g. `url`, `regex`, `email`. */
|
|
109
|
-
format: z.string().optional(),
|
|
110
|
-
});
|
|
111
|
-
const toNumber = (v) => typeof v === 'number' ? v : typeof v === 'bigint' ? Number(v) : undefined;
|
|
112
|
-
/**
|
|
113
|
-
* A Zod error as the wire shape. Use this on the server for every 400, and on
|
|
114
|
-
* the client to treat its own errors and the server's the same way.
|
|
115
|
-
*
|
|
116
|
-
* `location` is stamped on every issue when given; the server always gives it.
|
|
117
|
-
*
|
|
118
|
-
* Copies a WHITELIST of fields (see the module note). A path segment that is a
|
|
119
|
-
* symbol, which JSON cannot carry, becomes its description.
|
|
120
|
-
*/
|
|
121
|
-
export function toValidationIssues(error, location) {
|
|
122
|
-
return error.issues.map((issue) => {
|
|
123
|
-
const out = {
|
|
124
|
-
...(location ? { location } : {}),
|
|
125
|
-
path: issue.path.map((p) => typeof p === 'number' ? p : typeof p === 'string' ? p : String(p.description ?? '')),
|
|
126
|
-
code: issue.code,
|
|
127
|
-
message: issue.message,
|
|
128
|
-
};
|
|
129
|
-
const minimum = toNumber(issue.minimum);
|
|
130
|
-
const maximum = toNumber(issue.maximum);
|
|
131
|
-
if (minimum !== undefined)
|
|
132
|
-
out.minimum = minimum;
|
|
133
|
-
if (maximum !== undefined)
|
|
134
|
-
out.maximum = maximum;
|
|
135
|
-
if (typeof issue.origin === 'string')
|
|
136
|
-
out.origin = issue.origin;
|
|
137
|
-
if (typeof issue.format === 'string')
|
|
138
|
-
out.format = issue.format;
|
|
139
|
-
return out;
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
//# sourceMappingURL=validation.js.map
|
package/dist/validation.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * founder-schema — How a validation failure is described, on both sides\n *\n * TWO RULES, and they are what let the web client show any error, its own or\n * the server's, on the right field in the member's language:\n *\n * 1. A CUSTOM MESSAGE IS A KEY, NEVER A SENTENCE. Where a schema needs its own\n * message (a refine, a regex), the message is one of `VALIDATION_MESSAGE`,\n * such as `phoneInvalid`. The client turns the key into text in English or\n * Hindi. Before 0.2.0 these were English sentences, so a Hindi screen showed\n * an English error, and a client that wanted to translate one had to match\n * on the wording.\n *\n * Plain bounds carry NO custom message. `.min(1)` and `.max(80)` produce\n * Zod's own `too_small` / `too_big` issues, which already say which bound\n * and what it was (`minimum`, `maximum`, `origin`), and the client words\n * them from those. A hand-written \"at most 80 characters\" would only\n * restate the number in one language.\n *\n * 2. THE SERVER SENDS EVERY ISSUE, IN THIS SHAPE. A 400 answers with\n * `error.details.issues`, built by `toValidationIssues`, so the client can\n * put each one under its field. Until 0.2.0 the backend sent only the\n * first issue's message, with no path at all.\n *\n * ⚠️ `toValidationIssues` COPIES A WHITELIST OF FIELDS, it never spreads an\n * issue. Zod can carry the rejected `input` on an issue, and these bodies hold a\n * date of birth and a phone number. Echoing them into an error response sends\n * them back to the client, into logs and into any proxy in between. A test\n * proves `input` never survives.\n *\n * @module founder-schema/validation\n */\n\nimport { z } from 'zod';\n\n/**\n * Every custom message a schema in this package can produce. Each is a\n * translation key the clients define in every language they ship.\n *\n * ⚠️ Append only, and add the translation in the same change. Renaming one\n * shows the raw key to every member until each client ships the new name.\n */\nexport const VALIDATION_MESSAGE = {\n /** Not a 24-hex Mongo id. */\n invalidId: 'invalidId',\n /** Handle: wrong characters, or a dot in the wrong place. */\n usernameInvalid: 'usernameInvalid',\n /** Not a 10-digit Indian mobile number. */\n phoneInvalid: 'phoneInvalid',\n /** Not a `YYYY-MM-DD` date. */\n dateInvalid: 'dateInvalid',\n /** A date that does not exist, such as 30 February. */\n dobInvalid: 'dobInvalid',\n /** Under the minimum age. */\n dobUnderAge: 'dobUnderAge',\n /** Over the sanity ceiling: almost always a mistyped year. */\n dobTooOld: 'dobTooOld',\n /** A founding year after this year. */\n foundedYearFuture: 'foundedYearFuture',\n /** An upload key that is not one this product mints. */\n uploadKeyInvalid: 'uploadKeyInvalid',\n /** A post with neither text nor media. */\n postEmpty: 'postEmpty',\n /** Two poll options with the same label. */\n pollOptionsDuplicate: 'pollOptionsDuplicate',\n /** An empty string sent to clear a patch field; clearing is `null`. */\n clearWithNull: 'clearWithNull',\n /** Not a plain http(s) URL on a real domain (`javascript:`, `localhost`, an IP...). */\n urlInvalid: 'urlInvalid',\n /** A handle this product keeps for itself (`admin`, `support`...). */\n usernameReserved: 'usernameReserved',\n /** Agreed to a version of the guidelines that is not the current one. */\n guidelinesOutdated: 'guidelinesOutdated',\n} as const;\nexport type ValidationMessageKey = (typeof VALIDATION_MESSAGE)[keyof typeof VALIDATION_MESSAGE];\n\n/**\n * Which part of the request an issue is about.\n *\n * ONE PATH CONVENTION: `path` is ALWAYS relative to this part, so a body field\n * reads `['venture', 'name']` with `location: 'body'`, never\n * `['body', 'venture', 'name']`. A form maps body issues straight onto its\n * fields without stripping a prefix, and a client that sees `query` or\n * `params` knows the problem is the URL, not anything the member typed.\n */\nexport const REQUEST_PART_VALUES = ['body', 'query', 'params'] as const;\nexport const requestPartSchema = z.enum(REQUEST_PART_VALUES);\nexport type RequestPart = z.infer<typeof requestPartSchema>;\n\n/**\n * One problem with one field, as it crosses the wire.\n *\n * `code` is Zod's issue code (`too_small`, `too_big`, `invalid_type`,\n * `invalid_format`, `custom`...). `message` is either one of\n * `VALIDATION_MESSAGE` or, for a plain bound, Zod's own English text, which the\n * client ignores in favour of `code` plus `minimum` / `maximum`.\n */\nexport const validationIssueSchema = z.object({\n /** Set by the server on every issue it sends; absent on a client's own parse. */\n location: requestPartSchema.optional(),\n /**\n * Where the problem is, RELATIVE TO `location`: `['venture', 'name']`,\n * `['options', 2, 'label']`, `['contentId']`.\n */\n path: z.array(z.union([z.string(), z.number()])),\n code: z.string(),\n message: z.string(),\n /** `too_small`: the bound that was missed. */\n minimum: z.number().optional(),\n /** `too_big`: the bound that was passed. */\n maximum: z.number().optional(),\n /** What was measured: `string`, `array`, `number`... */\n origin: z.string().optional(),\n /** `invalid_format`: which format, e.g. `url`, `regex`, `email`. */\n format: z.string().optional(),\n});\nexport type ValidationIssue = z.infer<typeof validationIssueSchema>;\n\n/** The loosest shape this needs from a Zod issue, so it works across 4.x. */\ninterface ZodIssueLike {\n path: readonly PropertyKey[];\n code: string;\n message: string;\n minimum?: unknown;\n maximum?: unknown;\n origin?: unknown;\n format?: unknown;\n}\n\nconst toNumber = (v: unknown): number | undefined =>\n typeof v === 'number' ? v : typeof v === 'bigint' ? Number(v) : undefined;\n\n/**\n * A Zod error as the wire shape. Use this on the server for every 400, and on\n * the client to treat its own errors and the server's the same way.\n *\n * `location` is stamped on every issue when given; the server always gives it.\n *\n * Copies a WHITELIST of fields (see the module note). A path segment that is a\n * symbol, which JSON cannot carry, becomes its description.\n */\nexport function toValidationIssues(\n error: { issues: readonly ZodIssueLike[] },\n location?: RequestPart,\n): ValidationIssue[] {\n return error.issues.map((issue) => {\n const out: ValidationIssue = {\n ...(location ? { location } : {}),\n path: issue.path.map((p) =>\n typeof p === 'number' ? p : typeof p === 'string' ? p : String(p.description ?? ''),\n ),\n code: issue.code,\n message: issue.message,\n };\n const minimum = toNumber(issue.minimum);\n const maximum = toNumber(issue.maximum);\n if (minimum !== undefined) out.minimum = minimum;\n if (maximum !== undefined) out.maximum = maximum;\n if (typeof issue.origin === 'string') out.origin = issue.origin;\n if (typeof issue.format === 'string') out.format = issue.format;\n return out;\n });\n}\n"]}
|