founder-schema 0.14.0 → 0.16.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 +90 -3
- package/dist/core/common.d.ts +30 -4
- package/dist/core/common.d.ts.map +1 -1
- package/dist/core/common.js +37 -3
- package/dist/core/common.js.map +1 -1
- package/dist/core/errors.d.ts +9 -1
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +19 -0
- package/dist/core/errors.js.map +1 -1
- package/dist/core/limits.d.ts +11 -0
- package/dist/core/limits.d.ts.map +1 -1
- package/dist/core/limits.js +18 -0
- package/dist/core/limits.js.map +1 -1
- package/dist/core/responses.d.ts +8 -0
- package/dist/core/responses.d.ts.map +1 -1
- package/dist/domains/communities/communities.d.ts +9 -9
- package/dist/domains/discover/discover.d.ts +7 -0
- package/dist/domains/discover/discover.d.ts.map +1 -1
- package/dist/domains/feed/feed.d.ts +11 -11
- package/dist/domains/onboarding/onboarding.d.ts +245 -21
- package/dist/domains/onboarding/onboarding.d.ts.map +1 -1
- package/dist/domains/onboarding/onboarding.js +104 -16
- package/dist/domains/onboarding/onboarding.js.map +1 -1
- package/dist/domains/products/products.d.ts +3 -3
- package/dist/domains/profile/founder-profile.d.ts +28 -0
- package/dist/domains/profile/founder-profile.d.ts.map +1 -1
- package/dist/domains/profile/founder-profile.js +3 -0
- package/dist/domains/profile/founder-profile.js.map +1 -1
- package/dist/domains/profile/my-profile.d.ts +386 -0
- package/dist/domains/profile/my-profile.d.ts.map +1 -0
- package/dist/domains/profile/my-profile.js +52 -0
- package/dist/domains/profile/my-profile.js.map +1 -0
- package/dist/domains/waitlist/waitlist.d.ts +68 -0
- package/dist/domains/waitlist/waitlist.d.ts.map +1 -0
- package/dist/domains/waitlist/waitlist.js +64 -0
- package/dist/domains/waitlist/waitlist.js.map +1 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The member's own answers that NOBODY ELSE sees (0.16.0): their business's
|
|
3
|
+
* type and registration, and their interests. The Me tab reads and writes
|
|
4
|
+
* them on routes of their own, like the personal details, and they travel on
|
|
5
|
+
* no other response: not on `founderProfileSchema` (the app shell reads that on
|
|
6
|
+
* every page), not on a card, a member's page, a byline or Discover.
|
|
7
|
+
*
|
|
8
|
+
* GET /api/v1/profiles/me/business `myBusinessSchema`
|
|
9
|
+
* PUT /api/v1/profiles/me/business `putMyBusinessBodySchema`, answers `myBusinessSchema`
|
|
10
|
+
* GET /api/v1/profiles/me/interests `myInterestsSchema`
|
|
11
|
+
* PUT /api/v1/profiles/me/interests `putMyInterestsBodySchema`, answers `myInterestsSchema`
|
|
12
|
+
*
|
|
13
|
+
* In its own file because it joins two domains: the profile's venture and
|
|
14
|
+
* onboarding's vocabularies (business types, registrations, topics), and
|
|
15
|
+
* onboarding already imports the profile.
|
|
16
|
+
*
|
|
17
|
+
* @module domains/profile/my-profile
|
|
18
|
+
*/
|
|
19
|
+
import { z } from 'zod';
|
|
20
|
+
/**
|
|
21
|
+
* The member's venture as only they see it: what everyone sees
|
|
22
|
+
* (`ventureSchema`) plus its business type and how it is registered, which are
|
|
23
|
+
* PRIVATE (the Me tab marks them so). Stored together on the profile's
|
|
24
|
+
* venture, so they live and go with it: no business, no type, no registration.
|
|
25
|
+
*
|
|
26
|
+
* ONE RULE PER FIELD: the very schemas onboarding finishes with.
|
|
27
|
+
*/
|
|
28
|
+
export declare const myVentureSchema: z.ZodObject<{
|
|
29
|
+
name: z.ZodString;
|
|
30
|
+
tagline: z.ZodPreprocess<z.ZodOptional<z.ZodString>, unknown>;
|
|
31
|
+
website: z.ZodOptional<z.ZodURL>;
|
|
32
|
+
industry: z.ZodEnum<{
|
|
33
|
+
agritech: "agritech";
|
|
34
|
+
ai_ml: "ai_ml";
|
|
35
|
+
b2b_saas: "b2b_saas";
|
|
36
|
+
consumer: "consumer";
|
|
37
|
+
climate: "climate";
|
|
38
|
+
d2c: "d2c";
|
|
39
|
+
deeptech: "deeptech";
|
|
40
|
+
edtech: "edtech";
|
|
41
|
+
fintech: "fintech";
|
|
42
|
+
gaming: "gaming";
|
|
43
|
+
healthtech: "healthtech";
|
|
44
|
+
logistics: "logistics";
|
|
45
|
+
manufacturing: "manufacturing";
|
|
46
|
+
marketplace: "marketplace";
|
|
47
|
+
media: "media";
|
|
48
|
+
mobility: "mobility";
|
|
49
|
+
proptech: "proptech";
|
|
50
|
+
robotics: "robotics";
|
|
51
|
+
services: "services";
|
|
52
|
+
space: "space";
|
|
53
|
+
other: "other";
|
|
54
|
+
}>;
|
|
55
|
+
stage: z.ZodEnum<{
|
|
56
|
+
idea: "idea";
|
|
57
|
+
validation: "validation";
|
|
58
|
+
mvp: "mvp";
|
|
59
|
+
pre_seed: "pre_seed";
|
|
60
|
+
seed: "seed";
|
|
61
|
+
series_a_plus: "series_a_plus";
|
|
62
|
+
profitable: "profitable";
|
|
63
|
+
exited: "exited";
|
|
64
|
+
}>;
|
|
65
|
+
teamSize: z.ZodOptional<z.ZodNumber>;
|
|
66
|
+
foundedYear: z.ZodOptional<z.ZodNumber>;
|
|
67
|
+
businessType: z.ZodOptional<z.ZodEnum<{
|
|
68
|
+
startup: "startup";
|
|
69
|
+
sme: "sme";
|
|
70
|
+
enterprise: "enterprise";
|
|
71
|
+
freelancer: "freelancer";
|
|
72
|
+
agency: "agency";
|
|
73
|
+
social_enterprise: "social_enterprise";
|
|
74
|
+
family_business: "family_business";
|
|
75
|
+
franchise: "franchise";
|
|
76
|
+
}>>;
|
|
77
|
+
legalStructure: z.ZodOptional<z.ZodEnum<{
|
|
78
|
+
not_registered: "not_registered";
|
|
79
|
+
sole_proprietorship: "sole_proprietorship";
|
|
80
|
+
partnership: "partnership";
|
|
81
|
+
llp: "llp";
|
|
82
|
+
opc: "opc";
|
|
83
|
+
private_limited: "private_limited";
|
|
84
|
+
public_limited: "public_limited";
|
|
85
|
+
section_8: "section_8";
|
|
86
|
+
trust_or_society: "trust_or_society";
|
|
87
|
+
cooperative: "cooperative";
|
|
88
|
+
registered_abroad: "registered_abroad";
|
|
89
|
+
}>>;
|
|
90
|
+
}, z.core.$strip>;
|
|
91
|
+
export type MyVenture = z.infer<typeof myVentureSchema>;
|
|
92
|
+
/** `GET /api/v1/profiles/me/business`: absent `venture` = no business added. */
|
|
93
|
+
export declare const myBusinessSchema: z.ZodObject<{
|
|
94
|
+
venture: z.ZodOptional<z.ZodObject<{
|
|
95
|
+
name: z.ZodString;
|
|
96
|
+
tagline: z.ZodPreprocess<z.ZodOptional<z.ZodString>, unknown>;
|
|
97
|
+
website: z.ZodOptional<z.ZodURL>;
|
|
98
|
+
industry: z.ZodEnum<{
|
|
99
|
+
agritech: "agritech";
|
|
100
|
+
ai_ml: "ai_ml";
|
|
101
|
+
b2b_saas: "b2b_saas";
|
|
102
|
+
consumer: "consumer";
|
|
103
|
+
climate: "climate";
|
|
104
|
+
d2c: "d2c";
|
|
105
|
+
deeptech: "deeptech";
|
|
106
|
+
edtech: "edtech";
|
|
107
|
+
fintech: "fintech";
|
|
108
|
+
gaming: "gaming";
|
|
109
|
+
healthtech: "healthtech";
|
|
110
|
+
logistics: "logistics";
|
|
111
|
+
manufacturing: "manufacturing";
|
|
112
|
+
marketplace: "marketplace";
|
|
113
|
+
media: "media";
|
|
114
|
+
mobility: "mobility";
|
|
115
|
+
proptech: "proptech";
|
|
116
|
+
robotics: "robotics";
|
|
117
|
+
services: "services";
|
|
118
|
+
space: "space";
|
|
119
|
+
other: "other";
|
|
120
|
+
}>;
|
|
121
|
+
stage: z.ZodEnum<{
|
|
122
|
+
idea: "idea";
|
|
123
|
+
validation: "validation";
|
|
124
|
+
mvp: "mvp";
|
|
125
|
+
pre_seed: "pre_seed";
|
|
126
|
+
seed: "seed";
|
|
127
|
+
series_a_plus: "series_a_plus";
|
|
128
|
+
profitable: "profitable";
|
|
129
|
+
exited: "exited";
|
|
130
|
+
}>;
|
|
131
|
+
teamSize: z.ZodOptional<z.ZodNumber>;
|
|
132
|
+
foundedYear: z.ZodOptional<z.ZodNumber>;
|
|
133
|
+
businessType: z.ZodOptional<z.ZodEnum<{
|
|
134
|
+
startup: "startup";
|
|
135
|
+
sme: "sme";
|
|
136
|
+
enterprise: "enterprise";
|
|
137
|
+
freelancer: "freelancer";
|
|
138
|
+
agency: "agency";
|
|
139
|
+
social_enterprise: "social_enterprise";
|
|
140
|
+
family_business: "family_business";
|
|
141
|
+
franchise: "franchise";
|
|
142
|
+
}>>;
|
|
143
|
+
legalStructure: z.ZodOptional<z.ZodEnum<{
|
|
144
|
+
not_registered: "not_registered";
|
|
145
|
+
sole_proprietorship: "sole_proprietorship";
|
|
146
|
+
partnership: "partnership";
|
|
147
|
+
llp: "llp";
|
|
148
|
+
opc: "opc";
|
|
149
|
+
private_limited: "private_limited";
|
|
150
|
+
public_limited: "public_limited";
|
|
151
|
+
section_8: "section_8";
|
|
152
|
+
trust_or_society: "trust_or_society";
|
|
153
|
+
cooperative: "cooperative";
|
|
154
|
+
registered_abroad: "registered_abroad";
|
|
155
|
+
}>>;
|
|
156
|
+
}, z.core.$strip>>;
|
|
157
|
+
}, z.core.$strip>;
|
|
158
|
+
export type MyBusiness = z.infer<typeof myBusinessSchema>;
|
|
159
|
+
/**
|
|
160
|
+
* `PUT /api/v1/profiles/me/business`: the WHOLE business as the editor holds
|
|
161
|
+
* it, or `null` to remove it. A key left out of the venture is removed (a
|
|
162
|
+
* tagline, a website, the type, the registration): PUT, not a patch, because
|
|
163
|
+
* the editor always holds all of it.
|
|
164
|
+
*/
|
|
165
|
+
export declare const putMyBusinessBodySchema: z.ZodObject<{
|
|
166
|
+
venture: z.ZodNullable<z.ZodObject<{
|
|
167
|
+
name: z.ZodString;
|
|
168
|
+
tagline: z.ZodPreprocess<z.ZodOptional<z.ZodString>, unknown>;
|
|
169
|
+
website: z.ZodOptional<z.ZodURL>;
|
|
170
|
+
industry: z.ZodEnum<{
|
|
171
|
+
agritech: "agritech";
|
|
172
|
+
ai_ml: "ai_ml";
|
|
173
|
+
b2b_saas: "b2b_saas";
|
|
174
|
+
consumer: "consumer";
|
|
175
|
+
climate: "climate";
|
|
176
|
+
d2c: "d2c";
|
|
177
|
+
deeptech: "deeptech";
|
|
178
|
+
edtech: "edtech";
|
|
179
|
+
fintech: "fintech";
|
|
180
|
+
gaming: "gaming";
|
|
181
|
+
healthtech: "healthtech";
|
|
182
|
+
logistics: "logistics";
|
|
183
|
+
manufacturing: "manufacturing";
|
|
184
|
+
marketplace: "marketplace";
|
|
185
|
+
media: "media";
|
|
186
|
+
mobility: "mobility";
|
|
187
|
+
proptech: "proptech";
|
|
188
|
+
robotics: "robotics";
|
|
189
|
+
services: "services";
|
|
190
|
+
space: "space";
|
|
191
|
+
other: "other";
|
|
192
|
+
}>;
|
|
193
|
+
stage: z.ZodEnum<{
|
|
194
|
+
idea: "idea";
|
|
195
|
+
validation: "validation";
|
|
196
|
+
mvp: "mvp";
|
|
197
|
+
pre_seed: "pre_seed";
|
|
198
|
+
seed: "seed";
|
|
199
|
+
series_a_plus: "series_a_plus";
|
|
200
|
+
profitable: "profitable";
|
|
201
|
+
exited: "exited";
|
|
202
|
+
}>;
|
|
203
|
+
teamSize: z.ZodOptional<z.ZodNumber>;
|
|
204
|
+
foundedYear: z.ZodOptional<z.ZodNumber>;
|
|
205
|
+
businessType: z.ZodOptional<z.ZodEnum<{
|
|
206
|
+
startup: "startup";
|
|
207
|
+
sme: "sme";
|
|
208
|
+
enterprise: "enterprise";
|
|
209
|
+
freelancer: "freelancer";
|
|
210
|
+
agency: "agency";
|
|
211
|
+
social_enterprise: "social_enterprise";
|
|
212
|
+
family_business: "family_business";
|
|
213
|
+
franchise: "franchise";
|
|
214
|
+
}>>;
|
|
215
|
+
legalStructure: z.ZodOptional<z.ZodEnum<{
|
|
216
|
+
not_registered: "not_registered";
|
|
217
|
+
sole_proprietorship: "sole_proprietorship";
|
|
218
|
+
partnership: "partnership";
|
|
219
|
+
llp: "llp";
|
|
220
|
+
opc: "opc";
|
|
221
|
+
private_limited: "private_limited";
|
|
222
|
+
public_limited: "public_limited";
|
|
223
|
+
section_8: "section_8";
|
|
224
|
+
trust_or_society: "trust_or_society";
|
|
225
|
+
cooperative: "cooperative";
|
|
226
|
+
registered_abroad: "registered_abroad";
|
|
227
|
+
}>>;
|
|
228
|
+
}, z.core.$strip>>;
|
|
229
|
+
}, z.core.$strip>;
|
|
230
|
+
export type PutMyBusinessBody = z.infer<typeof putMyBusinessBodySchema>;
|
|
231
|
+
/**
|
|
232
|
+
* `GET /api/v1/profiles/me/interests`: the topics the member wants to read
|
|
233
|
+
* about. A read shape, plain: a list stored under an older rule still reads.
|
|
234
|
+
*/
|
|
235
|
+
export declare const myInterestsSchema: z.ZodObject<{
|
|
236
|
+
interests: z.ZodArray<z.ZodEnum<{
|
|
237
|
+
ai_ml: "ai_ml";
|
|
238
|
+
b2b_saas: "b2b_saas";
|
|
239
|
+
d2c: "d2c";
|
|
240
|
+
deeptech: "deeptech";
|
|
241
|
+
robotics: "robotics";
|
|
242
|
+
growth: "growth";
|
|
243
|
+
sales: "sales";
|
|
244
|
+
marketing: "marketing";
|
|
245
|
+
supply_chain: "supply_chain";
|
|
246
|
+
fundraising: "fundraising";
|
|
247
|
+
social_enterprise: "social_enterprise";
|
|
248
|
+
mentoring: "mentoring";
|
|
249
|
+
leadership: "leadership";
|
|
250
|
+
networking: "networking";
|
|
251
|
+
public_speaking: "public_speaking";
|
|
252
|
+
teaching: "teaching";
|
|
253
|
+
hiring_talent: "hiring_talent";
|
|
254
|
+
personal_branding: "personal_branding";
|
|
255
|
+
career_transition: "career_transition";
|
|
256
|
+
remote_work: "remote_work";
|
|
257
|
+
blockchain: "blockchain";
|
|
258
|
+
crypto_web3: "crypto_web3";
|
|
259
|
+
data_science: "data_science";
|
|
260
|
+
cybersecurity: "cybersecurity";
|
|
261
|
+
game_dev: "game_dev";
|
|
262
|
+
ux_design: "ux_design";
|
|
263
|
+
app_development: "app_development";
|
|
264
|
+
open_source: "open_source";
|
|
265
|
+
electronics: "electronics";
|
|
266
|
+
space_exploration: "space_exploration";
|
|
267
|
+
green_tech: "green_tech";
|
|
268
|
+
no_code: "no_code";
|
|
269
|
+
entrepreneurship: "entrepreneurship";
|
|
270
|
+
investing: "investing";
|
|
271
|
+
stock_trading: "stock_trading";
|
|
272
|
+
personal_finance: "personal_finance";
|
|
273
|
+
consulting: "consulting";
|
|
274
|
+
ecommerce: "ecommerce";
|
|
275
|
+
retail: "retail";
|
|
276
|
+
real_estate: "real_estate";
|
|
277
|
+
product_management: "product_management";
|
|
278
|
+
meditation: "meditation";
|
|
279
|
+
journaling: "journaling";
|
|
280
|
+
self_improvement: "self_improvement";
|
|
281
|
+
productivity: "productivity";
|
|
282
|
+
reading: "reading";
|
|
283
|
+
online_courses: "online_courses";
|
|
284
|
+
philosophy: "philosophy";
|
|
285
|
+
psychology: "psychology";
|
|
286
|
+
therapy: "therapy";
|
|
287
|
+
sleep_optimization: "sleep_optimization";
|
|
288
|
+
gym: "gym";
|
|
289
|
+
yoga: "yoga";
|
|
290
|
+
photography: "photography";
|
|
291
|
+
writing: "writing";
|
|
292
|
+
graphic_design: "graphic_design";
|
|
293
|
+
filmmaking: "filmmaking";
|
|
294
|
+
digital_art: "digital_art";
|
|
295
|
+
content_creation: "content_creation";
|
|
296
|
+
blogging: "blogging";
|
|
297
|
+
vlogging: "vlogging";
|
|
298
|
+
podcasts: "podcasts";
|
|
299
|
+
animation: "animation";
|
|
300
|
+
music_production: "music_production";
|
|
301
|
+
volunteering: "volunteering";
|
|
302
|
+
ngo_work: "ngo_work";
|
|
303
|
+
environmental: "environmental";
|
|
304
|
+
women_empowerment: "women_empowerment";
|
|
305
|
+
community_service: "community_service";
|
|
306
|
+
education_access: "education_access";
|
|
307
|
+
}>>;
|
|
308
|
+
}, z.core.$strip>;
|
|
309
|
+
export type MyInterests = z.infer<typeof myInterestsSchema>;
|
|
310
|
+
/** `PUT /api/v1/profiles/me/interests`: the whole list, by onboarding's own rule (`interestsSchema`). */
|
|
311
|
+
export declare const putMyInterestsBodySchema: z.ZodObject<{
|
|
312
|
+
interests: z.ZodArray<z.ZodEnum<{
|
|
313
|
+
ai_ml: "ai_ml";
|
|
314
|
+
b2b_saas: "b2b_saas";
|
|
315
|
+
d2c: "d2c";
|
|
316
|
+
deeptech: "deeptech";
|
|
317
|
+
robotics: "robotics";
|
|
318
|
+
growth: "growth";
|
|
319
|
+
sales: "sales";
|
|
320
|
+
marketing: "marketing";
|
|
321
|
+
supply_chain: "supply_chain";
|
|
322
|
+
fundraising: "fundraising";
|
|
323
|
+
social_enterprise: "social_enterprise";
|
|
324
|
+
mentoring: "mentoring";
|
|
325
|
+
leadership: "leadership";
|
|
326
|
+
networking: "networking";
|
|
327
|
+
public_speaking: "public_speaking";
|
|
328
|
+
teaching: "teaching";
|
|
329
|
+
hiring_talent: "hiring_talent";
|
|
330
|
+
personal_branding: "personal_branding";
|
|
331
|
+
career_transition: "career_transition";
|
|
332
|
+
remote_work: "remote_work";
|
|
333
|
+
blockchain: "blockchain";
|
|
334
|
+
crypto_web3: "crypto_web3";
|
|
335
|
+
data_science: "data_science";
|
|
336
|
+
cybersecurity: "cybersecurity";
|
|
337
|
+
game_dev: "game_dev";
|
|
338
|
+
ux_design: "ux_design";
|
|
339
|
+
app_development: "app_development";
|
|
340
|
+
open_source: "open_source";
|
|
341
|
+
electronics: "electronics";
|
|
342
|
+
space_exploration: "space_exploration";
|
|
343
|
+
green_tech: "green_tech";
|
|
344
|
+
no_code: "no_code";
|
|
345
|
+
entrepreneurship: "entrepreneurship";
|
|
346
|
+
investing: "investing";
|
|
347
|
+
stock_trading: "stock_trading";
|
|
348
|
+
personal_finance: "personal_finance";
|
|
349
|
+
consulting: "consulting";
|
|
350
|
+
ecommerce: "ecommerce";
|
|
351
|
+
retail: "retail";
|
|
352
|
+
real_estate: "real_estate";
|
|
353
|
+
product_management: "product_management";
|
|
354
|
+
meditation: "meditation";
|
|
355
|
+
journaling: "journaling";
|
|
356
|
+
self_improvement: "self_improvement";
|
|
357
|
+
productivity: "productivity";
|
|
358
|
+
reading: "reading";
|
|
359
|
+
online_courses: "online_courses";
|
|
360
|
+
philosophy: "philosophy";
|
|
361
|
+
psychology: "psychology";
|
|
362
|
+
therapy: "therapy";
|
|
363
|
+
sleep_optimization: "sleep_optimization";
|
|
364
|
+
gym: "gym";
|
|
365
|
+
yoga: "yoga";
|
|
366
|
+
photography: "photography";
|
|
367
|
+
writing: "writing";
|
|
368
|
+
graphic_design: "graphic_design";
|
|
369
|
+
filmmaking: "filmmaking";
|
|
370
|
+
digital_art: "digital_art";
|
|
371
|
+
content_creation: "content_creation";
|
|
372
|
+
blogging: "blogging";
|
|
373
|
+
vlogging: "vlogging";
|
|
374
|
+
podcasts: "podcasts";
|
|
375
|
+
animation: "animation";
|
|
376
|
+
music_production: "music_production";
|
|
377
|
+
volunteering: "volunteering";
|
|
378
|
+
ngo_work: "ngo_work";
|
|
379
|
+
environmental: "environmental";
|
|
380
|
+
women_empowerment: "women_empowerment";
|
|
381
|
+
community_service: "community_service";
|
|
382
|
+
education_access: "education_access";
|
|
383
|
+
}>>;
|
|
384
|
+
}, z.core.$strip>;
|
|
385
|
+
export type PutMyInterestsBody = z.infer<typeof putMyInterestsBodySchema>;
|
|
386
|
+
//# sourceMappingURL=my-profile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"my-profile.d.ts","sourceRoot":"","sources":["../../../src/domains/profile/my-profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAWxB;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAG1B,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD,gFAAgF;AAChF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAoD,CAAC;AAClF,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAoD,CAAC;AACzF,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAIxE;;;GAGG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAgD,CAAC;AAC/E,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,yGAAyG;AACzG,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAA2C,CAAC;AACjF,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The member's own answers that NOBODY ELSE sees (0.16.0): their business's
|
|
3
|
+
* type and registration, and their interests. The Me tab reads and writes
|
|
4
|
+
* them on routes of their own, like the personal details, and they travel on
|
|
5
|
+
* no other response: not on `founderProfileSchema` (the app shell reads that on
|
|
6
|
+
* every page), not on a card, a member's page, a byline or Discover.
|
|
7
|
+
*
|
|
8
|
+
* GET /api/v1/profiles/me/business `myBusinessSchema`
|
|
9
|
+
* PUT /api/v1/profiles/me/business `putMyBusinessBodySchema`, answers `myBusinessSchema`
|
|
10
|
+
* GET /api/v1/profiles/me/interests `myInterestsSchema`
|
|
11
|
+
* PUT /api/v1/profiles/me/interests `putMyInterestsBodySchema`, answers `myInterestsSchema`
|
|
12
|
+
*
|
|
13
|
+
* In its own file because it joins two domains: the profile's venture and
|
|
14
|
+
* onboarding's vocabularies (business types, registrations, topics), and
|
|
15
|
+
* onboarding already imports the profile.
|
|
16
|
+
*
|
|
17
|
+
* @module domains/profile/my-profile
|
|
18
|
+
*/
|
|
19
|
+
import { z } from 'zod';
|
|
20
|
+
import { businessTypeSchema, interestsSchema, legalStructureSchema, topicSchema, } from '../onboarding/onboarding.js';
|
|
21
|
+
import { ventureSchema } from './founder-profile.js';
|
|
22
|
+
// ─── The business ────────────────────────────────────────────────────────────
|
|
23
|
+
/**
|
|
24
|
+
* The member's venture as only they see it: what everyone sees
|
|
25
|
+
* (`ventureSchema`) plus its business type and how it is registered, which are
|
|
26
|
+
* PRIVATE (the Me tab marks them so). Stored together on the profile's
|
|
27
|
+
* venture, so they live and go with it: no business, no type, no registration.
|
|
28
|
+
*
|
|
29
|
+
* ONE RULE PER FIELD: the very schemas onboarding finishes with.
|
|
30
|
+
*/
|
|
31
|
+
export const myVentureSchema = ventureSchema.extend({
|
|
32
|
+
businessType: businessTypeSchema.optional(),
|
|
33
|
+
legalStructure: legalStructureSchema.optional(),
|
|
34
|
+
});
|
|
35
|
+
/** `GET /api/v1/profiles/me/business`: absent `venture` = no business added. */
|
|
36
|
+
export const myBusinessSchema = z.object({ venture: myVentureSchema.optional() });
|
|
37
|
+
/**
|
|
38
|
+
* `PUT /api/v1/profiles/me/business`: the WHOLE business as the editor holds
|
|
39
|
+
* it, or `null` to remove it. A key left out of the venture is removed (a
|
|
40
|
+
* tagline, a website, the type, the registration): PUT, not a patch, because
|
|
41
|
+
* the editor always holds all of it.
|
|
42
|
+
*/
|
|
43
|
+
export const putMyBusinessBodySchema = z.object({ venture: myVentureSchema.nullable() });
|
|
44
|
+
// ─── The interests ───────────────────────────────────────────────────────────
|
|
45
|
+
/**
|
|
46
|
+
* `GET /api/v1/profiles/me/interests`: the topics the member wants to read
|
|
47
|
+
* about. A read shape, plain: a list stored under an older rule still reads.
|
|
48
|
+
*/
|
|
49
|
+
export const myInterestsSchema = z.object({ interests: z.array(topicSchema) });
|
|
50
|
+
/** `PUT /api/v1/profiles/me/interests`: the whole list, by onboarding's own rule (`interestsSchema`). */
|
|
51
|
+
export const putMyInterestsBodySchema = z.object({ interests: interestsSchema });
|
|
52
|
+
//# sourceMappingURL=my-profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"my-profile.js","sourceRoot":"","sources":["../../../src/domains/profile/my-profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,oBAAoB,EACpB,WAAW,GACZ,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,gFAAgF;AAEhF;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,aAAa,CAAC,MAAM,CAAC;IAClD,YAAY,EAAE,kBAAkB,CAAC,QAAQ,EAAE;IAC3C,cAAc,EAAE,oBAAoB,CAAC,QAAQ,EAAE;CAChD,CAAC,CAAC;AAGH,gFAAgF;AAChF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,eAAe,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AAGlF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,eAAe,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AAGzF,gFAAgF;AAEhF;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;AAG/E,yGAAyG;AACzG,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC,CAAC","sourcesContent":["/**\n * The member's own answers that NOBODY ELSE sees (0.16.0): their business's\n * type and registration, and their interests. The Me tab reads and writes\n * them on routes of their own, like the personal details, and they travel on\n * no other response: not on `founderProfileSchema` (the app shell reads that on\n * every page), not on a card, a member's page, a byline or Discover.\n *\n * GET /api/v1/profiles/me/business `myBusinessSchema`\n * PUT /api/v1/profiles/me/business `putMyBusinessBodySchema`, answers `myBusinessSchema`\n * GET /api/v1/profiles/me/interests `myInterestsSchema`\n * PUT /api/v1/profiles/me/interests `putMyInterestsBodySchema`, answers `myInterestsSchema`\n *\n * In its own file because it joins two domains: the profile's venture and\n * onboarding's vocabularies (business types, registrations, topics), and\n * onboarding already imports the profile.\n *\n * @module domains/profile/my-profile\n */\n\nimport { z } from 'zod';\nimport {\n businessTypeSchema,\n interestsSchema,\n legalStructureSchema,\n topicSchema,\n} from '../onboarding/onboarding.js';\nimport { ventureSchema } from './founder-profile.js';\n\n// ─── The business ────────────────────────────────────────────────────────────\n\n/**\n * The member's venture as only they see it: what everyone sees\n * (`ventureSchema`) plus its business type and how it is registered, which are\n * PRIVATE (the Me tab marks them so). Stored together on the profile's\n * venture, so they live and go with it: no business, no type, no registration.\n *\n * ONE RULE PER FIELD: the very schemas onboarding finishes with.\n */\nexport const myVentureSchema = ventureSchema.extend({\n businessType: businessTypeSchema.optional(),\n legalStructure: legalStructureSchema.optional(),\n});\nexport type MyVenture = z.infer<typeof myVentureSchema>;\n\n/** `GET /api/v1/profiles/me/business`: absent `venture` = no business added. */\nexport const myBusinessSchema = z.object({ venture: myVentureSchema.optional() });\nexport type MyBusiness = z.infer<typeof myBusinessSchema>;\n\n/**\n * `PUT /api/v1/profiles/me/business`: the WHOLE business as the editor holds\n * it, or `null` to remove it. A key left out of the venture is removed (a\n * tagline, a website, the type, the registration): PUT, not a patch, because\n * the editor always holds all of it.\n */\nexport const putMyBusinessBodySchema = z.object({ venture: myVentureSchema.nullable() });\nexport type PutMyBusinessBody = z.infer<typeof putMyBusinessBodySchema>;\n\n// ─── The interests ───────────────────────────────────────────────────────────\n\n/**\n * `GET /api/v1/profiles/me/interests`: the topics the member wants to read\n * about. A read shape, plain: a list stored under an older rule still reads.\n */\nexport const myInterestsSchema = z.object({ interests: z.array(topicSchema) });\nexport type MyInterests = z.infer<typeof myInterestsSchema>;\n\n/** `PUT /api/v1/profiles/me/interests`: the whole list, by onboarding's own rule (`interestsSchema`). */\nexport const putMyInterestsBodySchema = z.object({ interests: interestsSchema });\nexport type PutMyInterestsBody = z.infer<typeof putMyInterestsBodySchema>;\n"]}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* founder-schema — Waitlist: joining before the launch, and your place on it
|
|
3
|
+
*
|
|
4
|
+
* Founder Circle opens at one instant, `FC_LAUNCH_AT`, a server-only env on
|
|
5
|
+
* BOTH the backend and the web (the user, 2026-10-18: Tuesday 20 October 2026,
|
|
6
|
+
* 12:00 noon IST). Until then the app is "waiting": a signed-in person can join
|
|
7
|
+
* the waitlist, see their place, fill in their profile, sign out and delete
|
|
8
|
+
* their account, and nothing else (`NOT_LAUNCHED`). Unset means launched, so a
|
|
9
|
+
* deployment without it (dev, tests, local) never shows the waitlist.
|
|
10
|
+
*
|
|
11
|
+
* JOINING IS SIGNING IN (the user's option A). Each account holds at most one
|
|
12
|
+
* place; places count up in the order the server records joins and are never
|
|
13
|
+
* given again, not even when their holder deletes the account, and neither
|
|
14
|
+
* the same inbox nor the same sign-in takes a second one
|
|
15
|
+
* (`WAITLIST_PLACE_USED`). The first
|
|
16
|
+
* `FOUNDING_PLACES` places get the membership free, as "Founding member #N"
|
|
17
|
+
* (0.14.0). Staff never take a place (`WAITLIST_STAFF`). The waitlist closes
|
|
18
|
+
* at launch (`WAITLIST_CLOSED`); free places nobody took by then are gone.
|
|
19
|
+
*
|
|
20
|
+
* Routes:
|
|
21
|
+
* GET /api/v1/waitlist public -> waitlistStatusSchema
|
|
22
|
+
* GET /api/v1/waitlist/me signed in -> myWaitlistSchema
|
|
23
|
+
* POST /api/v1/waitlist/join signed in -> waitlistPlaceSchema (no body; a repeat answers the same place)
|
|
24
|
+
*
|
|
25
|
+
* @module founder-schema/domains/waitlist
|
|
26
|
+
*/
|
|
27
|
+
import { z } from 'zod';
|
|
28
|
+
export declare const waitlistPlaceSchema: z.ZodObject<{
|
|
29
|
+
place: z.ZodNumber;
|
|
30
|
+
joinedAt: z.ZodISODateTime;
|
|
31
|
+
founding: z.ZodBoolean;
|
|
32
|
+
}, z.core.$strip>;
|
|
33
|
+
export type WaitlistPlace = z.infer<typeof waitlistPlaceSchema>;
|
|
34
|
+
/**
|
|
35
|
+
* Why an account not on the list cannot join, said outright so a client never
|
|
36
|
+
* guesses it from `canJoin`, checked in this order: `closed` (the launch has
|
|
37
|
+
* passed), `staff` (any platform role), `place_used` (this email's inbox or
|
|
38
|
+
* this sign-in already had a place, a deleted account's included).
|
|
39
|
+
*/
|
|
40
|
+
export declare const WAITLIST_REFUSAL_VALUES: readonly ["closed", "staff", "place_used"];
|
|
41
|
+
export declare const waitlistRefusalSchema: z.ZodEnum<{
|
|
42
|
+
staff: "staff";
|
|
43
|
+
closed: "closed";
|
|
44
|
+
place_used: "place_used";
|
|
45
|
+
}>;
|
|
46
|
+
export type WaitlistRefusal = z.infer<typeof waitlistRefusalSchema>;
|
|
47
|
+
export declare const myWaitlistSchema: z.ZodObject<{
|
|
48
|
+
place: z.ZodNullable<z.ZodObject<{
|
|
49
|
+
place: z.ZodNumber;
|
|
50
|
+
joinedAt: z.ZodISODateTime;
|
|
51
|
+
founding: z.ZodBoolean;
|
|
52
|
+
}, z.core.$strip>>;
|
|
53
|
+
canJoin: z.ZodBoolean;
|
|
54
|
+
refusal: z.ZodNullable<z.ZodEnum<{
|
|
55
|
+
staff: "staff";
|
|
56
|
+
closed: "closed";
|
|
57
|
+
place_used: "place_used";
|
|
58
|
+
}>>;
|
|
59
|
+
}, z.core.$strip>;
|
|
60
|
+
export type MyWaitlist = z.infer<typeof myWaitlistSchema>;
|
|
61
|
+
export declare const waitlistStatusSchema: z.ZodObject<{
|
|
62
|
+
waiting: z.ZodBoolean;
|
|
63
|
+
launchAt: z.ZodNullable<z.ZodISODateTime>;
|
|
64
|
+
foundingPlaces: z.ZodNumber;
|
|
65
|
+
foundingPlacesLeft: z.ZodNumber;
|
|
66
|
+
}, z.core.$strip>;
|
|
67
|
+
export type WaitlistStatus = z.infer<typeof waitlistStatusSchema>;
|
|
68
|
+
//# sourceMappingURL=waitlist.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"waitlist.d.ts","sourceRoot":"","sources":["../../../src/domains/waitlist/waitlist.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,mBAAmB;;;;iBAM9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAIhE;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,4CAA6C,CAAC;AAClF,eAAO,MAAM,qBAAqB;;;;EAAkC,CAAC;AACrE,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,eAAO,MAAM,gBAAgB;;;;;;;;;;;;iBAO3B,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAI1D,eAAO,MAAM,oBAAoB;;;;;iBAS/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* founder-schema — Waitlist: joining before the launch, and your place on it
|
|
3
|
+
*
|
|
4
|
+
* Founder Circle opens at one instant, `FC_LAUNCH_AT`, a server-only env on
|
|
5
|
+
* BOTH the backend and the web (the user, 2026-10-18: Tuesday 20 October 2026,
|
|
6
|
+
* 12:00 noon IST). Until then the app is "waiting": a signed-in person can join
|
|
7
|
+
* the waitlist, see their place, fill in their profile, sign out and delete
|
|
8
|
+
* their account, and nothing else (`NOT_LAUNCHED`). Unset means launched, so a
|
|
9
|
+
* deployment without it (dev, tests, local) never shows the waitlist.
|
|
10
|
+
*
|
|
11
|
+
* JOINING IS SIGNING IN (the user's option A). Each account holds at most one
|
|
12
|
+
* place; places count up in the order the server records joins and are never
|
|
13
|
+
* given again, not even when their holder deletes the account, and neither
|
|
14
|
+
* the same inbox nor the same sign-in takes a second one
|
|
15
|
+
* (`WAITLIST_PLACE_USED`). The first
|
|
16
|
+
* `FOUNDING_PLACES` places get the membership free, as "Founding member #N"
|
|
17
|
+
* (0.14.0). Staff never take a place (`WAITLIST_STAFF`). The waitlist closes
|
|
18
|
+
* at launch (`WAITLIST_CLOSED`); free places nobody took by then are gone.
|
|
19
|
+
*
|
|
20
|
+
* Routes:
|
|
21
|
+
* GET /api/v1/waitlist public -> waitlistStatusSchema
|
|
22
|
+
* GET /api/v1/waitlist/me signed in -> myWaitlistSchema
|
|
23
|
+
* POST /api/v1/waitlist/join signed in -> waitlistPlaceSchema (no body; a repeat answers the same place)
|
|
24
|
+
*
|
|
25
|
+
* @module founder-schema/domains/waitlist
|
|
26
|
+
*/
|
|
27
|
+
import { z } from 'zod';
|
|
28
|
+
// ─── POST /waitlist/join, and inside GET /waitlist/me ────────────────────────
|
|
29
|
+
export const waitlistPlaceSchema = z.object({
|
|
30
|
+
/** 1 for the first person to join; never reused. */
|
|
31
|
+
place: z.number().int().positive(),
|
|
32
|
+
joinedAt: z.iso.datetime(),
|
|
33
|
+
/** `place <= FOUNDING_PLACES`: this place carries a free founding membership. */
|
|
34
|
+
founding: z.boolean(),
|
|
35
|
+
});
|
|
36
|
+
// ─── GET /waitlist/me ────────────────────────────────────────────────────────
|
|
37
|
+
/**
|
|
38
|
+
* Why an account not on the list cannot join, said outright so a client never
|
|
39
|
+
* guesses it from `canJoin`, checked in this order: `closed` (the launch has
|
|
40
|
+
* passed), `staff` (any platform role), `place_used` (this email's inbox or
|
|
41
|
+
* this sign-in already had a place, a deleted account's included).
|
|
42
|
+
*/
|
|
43
|
+
export const WAITLIST_REFUSAL_VALUES = ['closed', 'staff', 'place_used'];
|
|
44
|
+
export const waitlistRefusalSchema = z.enum(WAITLIST_REFUSAL_VALUES);
|
|
45
|
+
export const myWaitlistSchema = z.object({
|
|
46
|
+
/** Null until this account joins. */
|
|
47
|
+
place: waitlistPlaceSchema.nullable(),
|
|
48
|
+
/** True only while waiting, for an account not on the list that may join: show Join. */
|
|
49
|
+
canJoin: z.boolean(),
|
|
50
|
+
/** Null when on the list or free to join. */
|
|
51
|
+
refusal: waitlistRefusalSchema.nullable(),
|
|
52
|
+
});
|
|
53
|
+
// ─── GET /waitlist (public) ──────────────────────────────────────────────────
|
|
54
|
+
export const waitlistStatusSchema = z.object({
|
|
55
|
+
/** True until the launch instant; false when no launch is set or it has passed. */
|
|
56
|
+
waiting: z.boolean(),
|
|
57
|
+
/** The launch instant, or null when none is set. */
|
|
58
|
+
launchAt: z.iso.datetime().nullable(),
|
|
59
|
+
/** `FOUNDING_PLACES`, so the landing need not hard-code 100. */
|
|
60
|
+
foundingPlaces: z.number().int().positive(),
|
|
61
|
+
/** Free places not yet taken: `foundingPlaces` minus places given, never below 0. */
|
|
62
|
+
foundingPlacesLeft: z.number().int().nonnegative(),
|
|
63
|
+
});
|
|
64
|
+
//# sourceMappingURL=waitlist.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"waitlist.js","sourceRoot":"","sources":["../../../src/domains/waitlist/waitlist.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,gFAAgF;AAEhF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,oDAAoD;IACpD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAClC,QAAQ,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE;IAC1B,iFAAiF;IACjF,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE;CACtB,CAAC,CAAC;AAGH,gFAAgF;AAEhF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,YAAY,CAAU,CAAC;AAClF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;AAGrE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,qCAAqC;IACrC,KAAK,EAAE,mBAAmB,CAAC,QAAQ,EAAE;IACrC,wFAAwF;IACxF,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;IACpB,6CAA6C;IAC7C,OAAO,EAAE,qBAAqB,CAAC,QAAQ,EAAE;CAC1C,CAAC,CAAC;AAGH,gFAAgF;AAEhF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,mFAAmF;IACnF,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;IACpB,oDAAoD;IACpD,QAAQ,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IACrC,gEAAgE;IAChE,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAC3C,qFAAqF;IACrF,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;CACnD,CAAC,CAAC","sourcesContent":["/**\n * founder-schema — Waitlist: joining before the launch, and your place on it\n *\n * Founder Circle opens at one instant, `FC_LAUNCH_AT`, a server-only env on\n * BOTH the backend and the web (the user, 2026-10-18: Tuesday 20 October 2026,\n * 12:00 noon IST). Until then the app is \"waiting\": a signed-in person can join\n * the waitlist, see their place, fill in their profile, sign out and delete\n * their account, and nothing else (`NOT_LAUNCHED`). Unset means launched, so a\n * deployment without it (dev, tests, local) never shows the waitlist.\n *\n * JOINING IS SIGNING IN (the user's option A). Each account holds at most one\n * place; places count up in the order the server records joins and are never\n * given again, not even when their holder deletes the account, and neither\n * the same inbox nor the same sign-in takes a second one\n * (`WAITLIST_PLACE_USED`). The first\n * `FOUNDING_PLACES` places get the membership free, as \"Founding member #N\"\n * (0.14.0). Staff never take a place (`WAITLIST_STAFF`). The waitlist closes\n * at launch (`WAITLIST_CLOSED`); free places nobody took by then are gone.\n *\n * Routes:\n * GET /api/v1/waitlist public -> waitlistStatusSchema\n * GET /api/v1/waitlist/me signed in -> myWaitlistSchema\n * POST /api/v1/waitlist/join signed in -> waitlistPlaceSchema (no body; a repeat answers the same place)\n *\n * @module founder-schema/domains/waitlist\n */\n\nimport { z } from 'zod';\n\n// ─── POST /waitlist/join, and inside GET /waitlist/me ────────────────────────\n\nexport const waitlistPlaceSchema = z.object({\n /** 1 for the first person to join; never reused. */\n place: z.number().int().positive(),\n joinedAt: z.iso.datetime(),\n /** `place <= FOUNDING_PLACES`: this place carries a free founding membership. */\n founding: z.boolean(),\n});\nexport type WaitlistPlace = z.infer<typeof waitlistPlaceSchema>;\n\n// ─── GET /waitlist/me ────────────────────────────────────────────────────────\n\n/**\n * Why an account not on the list cannot join, said outright so a client never\n * guesses it from `canJoin`, checked in this order: `closed` (the launch has\n * passed), `staff` (any platform role), `place_used` (this email's inbox or\n * this sign-in already had a place, a deleted account's included).\n */\nexport const WAITLIST_REFUSAL_VALUES = ['closed', 'staff', 'place_used'] as const;\nexport const waitlistRefusalSchema = z.enum(WAITLIST_REFUSAL_VALUES);\nexport type WaitlistRefusal = z.infer<typeof waitlistRefusalSchema>;\n\nexport const myWaitlistSchema = z.object({\n /** Null until this account joins. */\n place: waitlistPlaceSchema.nullable(),\n /** True only while waiting, for an account not on the list that may join: show Join. */\n canJoin: z.boolean(),\n /** Null when on the list or free to join. */\n refusal: waitlistRefusalSchema.nullable(),\n});\nexport type MyWaitlist = z.infer<typeof myWaitlistSchema>;\n\n// ─── GET /waitlist (public) ──────────────────────────────────────────────────\n\nexport const waitlistStatusSchema = z.object({\n /** True until the launch instant; false when no launch is set or it has passed. */\n waiting: z.boolean(),\n /** The launch instant, or null when none is set. */\n launchAt: z.iso.datetime().nullable(),\n /** `FOUNDING_PLACES`, so the landing need not hard-code 100. */\n foundingPlaces: z.number().int().positive(),\n /** Free places not yet taken: `foundingPlaces` minus places given, never below 0. */\n foundingPlacesLeft: z.number().int().nonnegative(),\n});\nexport type WaitlistStatus = z.infer<typeof waitlistStatusSchema>;\n"]}
|