founder-schema 0.16.0 → 0.18.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 +263 -19
- package/dist/access/access.d.ts +1 -1
- package/dist/access/access.d.ts.map +1 -1
- package/dist/access/access.js +4 -1
- package/dist/access/access.js.map +1 -1
- package/dist/access/permissions.d.ts +27 -29
- package/dist/access/permissions.d.ts.map +1 -1
- package/dist/access/permissions.js +39 -3
- package/dist/access/permissions.js.map +1 -1
- package/dist/core/common.d.ts +117 -23
- package/dist/core/common.d.ts.map +1 -1
- package/dist/core/common.js +104 -21
- package/dist/core/common.js.map +1 -1
- package/dist/core/errors.d.ts +7 -5
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +17 -11
- package/dist/core/errors.js.map +1 -1
- package/dist/core/limits.d.ts +55 -17
- package/dist/core/limits.d.ts.map +1 -1
- package/dist/core/limits.js +59 -22
- package/dist/core/limits.js.map +1 -1
- package/dist/core/money.d.ts +33 -0
- package/dist/core/money.d.ts.map +1 -0
- package/dist/core/money.js +36 -0
- package/dist/core/money.js.map +1 -0
- package/dist/core/responses.d.ts +14 -4
- package/dist/core/responses.d.ts.map +1 -1
- package/dist/core/responses.js.map +1 -1
- package/dist/core/validation.d.ts +32 -2
- package/dist/core/validation.d.ts.map +1 -1
- package/dist/core/validation.js +32 -2
- package/dist/core/validation.js.map +1 -1
- package/dist/domains/billing/billing.d.ts +61 -8
- package/dist/domains/billing/billing.d.ts.map +1 -1
- package/dist/domains/billing/billing.js +58 -22
- package/dist/domains/billing/billing.js.map +1 -1
- package/dist/domains/billing/gst.d.ts.map +1 -1
- package/dist/domains/billing/gst.js +4 -3
- package/dist/domains/billing/gst.js.map +1 -1
- package/dist/domains/chat/chat.d.ts +0 -21
- package/dist/domains/chat/chat.d.ts.map +1 -1
- package/dist/domains/chat/chat.js +0 -20
- package/dist/domains/chat/chat.js.map +1 -1
- package/dist/domains/communities/communities.d.ts +30 -12
- package/dist/domains/communities/communities.d.ts.map +1 -1
- package/dist/domains/communities/communities.js +43 -15
- package/dist/domains/communities/communities.js.map +1 -1
- package/dist/domains/contributions/contributions.d.ts +1 -1
- package/dist/domains/contributions/contributions.js +1 -1
- package/dist/domains/contributions/contributions.js.map +1 -1
- package/dist/domains/dashboard/dashboard.d.ts +3 -1
- package/dist/domains/dashboard/dashboard.d.ts.map +1 -1
- package/dist/domains/dashboard/dashboard.js +23 -7
- package/dist/domains/dashboard/dashboard.js.map +1 -1
- package/dist/domains/discover/discover.d.ts +8 -8
- package/dist/domains/feed/feed.d.ts +55 -153
- package/dist/domains/feed/feed.d.ts.map +1 -1
- package/dist/domains/feed/feed.js +53 -58
- package/dist/domains/feed/feed.js.map +1 -1
- package/dist/domains/location/india.d.ts +215 -0
- package/dist/domains/location/india.d.ts.map +1 -0
- package/dist/domains/location/india.js +1203 -0
- package/dist/domains/location/india.js.map +1 -0
- package/dist/domains/members/members.d.ts +2 -2
- package/dist/domains/membership/membership.d.ts +26 -0
- package/dist/domains/membership/membership.d.ts.map +1 -1
- package/dist/domains/membership/membership.js +55 -1
- package/dist/domains/membership/membership.js.map +1 -1
- package/dist/domains/moderation/moderation.d.ts +2 -2
- package/dist/domains/moderation/moderation.js +3 -3
- package/dist/domains/moderation/moderation.js.map +1 -1
- package/dist/domains/notifications/notifications.d.ts +1 -10
- package/dist/domains/notifications/notifications.d.ts.map +1 -1
- package/dist/domains/notifications/notifications.js +2 -3
- package/dist/domains/notifications/notifications.js.map +1 -1
- package/dist/domains/onboarding/onboarding-answers.d.ts +112 -0
- package/dist/domains/onboarding/onboarding-answers.d.ts.map +1 -0
- package/dist/domains/onboarding/onboarding-answers.js +164 -0
- package/dist/domains/onboarding/onboarding-answers.js.map +1 -0
- package/dist/domains/onboarding/onboarding.d.ts +398 -62
- package/dist/domains/onboarding/onboarding.d.ts.map +1 -1
- package/dist/domains/onboarding/onboarding.js +229 -68
- package/dist/domains/onboarding/onboarding.js.map +1 -1
- package/dist/domains/products/products.d.ts +43 -8
- package/dist/domains/products/products.d.ts.map +1 -1
- package/dist/domains/products/products.js +57 -11
- package/dist/domains/products/products.js.map +1 -1
- package/dist/domains/profile/founder-profile.d.ts +120 -68
- package/dist/domains/profile/founder-profile.d.ts.map +1 -1
- package/dist/domains/profile/founder-profile.js +80 -29
- package/dist/domains/profile/founder-profile.js.map +1 -1
- package/dist/domains/profile/my-profile.d.ts +3 -3
- package/dist/domains/reviews/reviews.d.ts +1 -1
- package/dist/domains/reviews/reviews.d.ts.map +1 -1
- package/dist/domains/reviews/reviews.js +2 -2
- package/dist/domains/reviews/reviews.js.map +1 -1
- package/dist/domains/support/support.d.ts +22 -3
- package/dist/domains/support/support.d.ts.map +1 -1
- package/dist/domains/support/support.js +19 -5
- package/dist/domains/support/support.js.map +1 -1
- 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/domains/uploads/uploads.d.ts +7 -22
- package/dist/domains/uploads/uploads.d.ts.map +1 -1
- package/dist/domains/uploads/uploads.js +7 -21
- package/dist/domains/uploads/uploads.js.map +1 -1
- package/dist/env.d.ts +26 -13
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +58 -23
- package/dist/env.js.map +1 -1
- package/dist/index.d.ts +18 -15
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -14
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"india.js","sourceRoot":"","sources":["../../../src/domains/location/india.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * founder-schema — Where a founder is based: India's states, union territories\n * and cities (0.17.0, moved here from the web client, where the location step's\n * lists lived in the screen).\n *\n * Founder Circle is in India for now (the user, 2026-10-18: the country is\n * shown locked to India and a state and city are chosen from lists). The RULE\n * is `indiaLocationSchema` below; this file is its data, read by every side:\n *\n * states all 28 states and 8 union territories, by their current names: a\n * CLOSED list, so a state is one of these or refused (`stateUnknown`)\n * cities per state, the larger cities first, the rest A to Z. A HELP, NOT A\n * RULE: the profile stores the city as text and Discover matches\n * text, so the list spares members the typing and the spelling\n * variants, and the picker also takes a town it does not hold\n * aliases older or other names a member may search by (\"Bangalore\" finds\n * Bengaluru), and the district names the location lookup answers\n * with (\"Bengaluru Urban\"), so the server's suggestion and a member's\n * search land on the list's own spelling\n *\n * Written for this product from public knowledge of India's cities; no\n * third-party dataset is copied in.\n *\n * @module founder-schema/domains/location/india\n */\n\nimport { z } from 'zod';\nimport { CITY_MAX } from '../../core/limits.js';\nimport { VALIDATION_MESSAGE } from '../../core/validation.js';\nimport type { GST_STATES } from '../billing/gst.js';\n\n/**\n * A state or union territory, by the ONE list of their names: GST's\n * (`GST_STATES`, billing), which already held all 36. This module adds each\n * one's cities and other names; it never spells a state on its own, and a\n * test holds the two sets equal.\n */\nexport type IndiaStateName = (typeof GST_STATES)[number]['name'];\n\nexport interface IndiaState {\n name: IndiaStateName;\n /** Other names the state is searched or answered by. */\n aliases?: readonly string[];\n cities: readonly string[];\n}\n\n/** The one country a location may be in, for now. */\nexport const INDIA = 'India' as const;\n\n/** India's international dialing code: what a phone number is shown with (the stored number has none). */\nexport const INDIA_DIALING_CODE = '+91' as const;\n\nexport const INDIA_STATES: readonly IndiaState[] = [\n {\n name: 'Andhra Pradesh',\n cities: [\n 'Visakhapatnam',\n 'Vijayawada',\n 'Guntur',\n 'Nellore',\n 'Kurnool',\n 'Rajamahendravaram',\n 'Tirupati',\n 'Kakinada',\n 'Kadapa',\n 'Anantapur',\n 'Amaravati',\n 'Adoni',\n 'Bhimavaram',\n 'Chilakaluripet',\n 'Chittoor',\n 'Dharmavaram',\n 'Eluru',\n 'Gudivada',\n 'Guntakal',\n 'Hindupur',\n 'Machilipatnam',\n 'Madanapalle',\n 'Nandyal',\n 'Narasaraopet',\n 'Ongole',\n 'Proddatur',\n 'Puttaparthi',\n 'Srikakulam',\n 'Tadepalligudem',\n 'Tenali',\n 'Vizianagaram',\n ],\n },\n {\n name: 'Arunachal Pradesh',\n cities: [\n 'Itanagar',\n 'Naharlagun',\n 'Pasighat',\n 'Aalo',\n 'Bomdila',\n 'Changlang',\n 'Daporijo',\n 'Khonsa',\n 'Namsai',\n 'Roing',\n 'Seppa',\n 'Tawang',\n 'Tezu',\n 'Ziro',\n ],\n },\n {\n name: 'Assam',\n cities: [\n 'Guwahati',\n 'Dibrugarh',\n 'Silchar',\n 'Jorhat',\n 'Tezpur',\n 'Nagaon',\n 'Tinsukia',\n 'Barpeta',\n 'Bongaigaon',\n 'Dhubri',\n 'Diphu',\n 'Goalpara',\n 'Golaghat',\n 'Haflong',\n 'Hailakandi',\n 'Karimganj',\n 'Kokrajhar',\n 'Mangaldoi',\n 'Nalbari',\n 'North Lakhimpur',\n 'Sivasagar',\n ],\n },\n {\n name: 'Bihar',\n cities: [\n 'Patna',\n 'Gaya Ji',\n 'Bhagalpur',\n 'Muzaffarpur',\n 'Darbhanga',\n 'Purnia',\n 'Arrah',\n 'Aurangabad',\n 'Begusarai',\n 'Bettiah',\n 'Bihar Sharif',\n 'Bodh Gaya',\n 'Buxar',\n 'Chapra',\n 'Dehri',\n 'Hajipur',\n 'Jamalpur',\n 'Jehanabad',\n 'Katihar',\n 'Kishanganj',\n 'Motihari',\n 'Munger',\n 'Nawada',\n 'Saharsa',\n 'Sasaram',\n 'Sitamarhi',\n 'Siwan',\n ],\n },\n {\n name: 'Chhattisgarh',\n cities: [\n 'Raipur',\n 'Bhilai',\n 'Bilaspur',\n 'Korba',\n 'Durg',\n 'Ambikapur',\n 'Bhatapara',\n 'Chirmiri',\n 'Dhamtari',\n 'Jagdalpur',\n 'Janjgir',\n 'Kanker',\n 'Mahasamund',\n 'Nava Raipur',\n 'Raigarh',\n 'Rajnandgaon',\n ],\n },\n {\n name: 'Goa',\n cities: [\n 'Panaji',\n 'Margao',\n 'Vasco da Gama',\n 'Mapusa',\n 'Ponda',\n 'Bicholim',\n 'Canacona',\n 'Curchorem',\n 'Pernem',\n 'Porvorim',\n 'Quepem',\n 'Sanguem',\n 'Valpoi',\n ],\n },\n {\n name: 'Gujarat',\n cities: [\n 'Ahmedabad',\n 'Surat',\n 'Vadodara',\n 'Rajkot',\n 'Gandhinagar',\n 'Bhavnagar',\n 'Jamnagar',\n 'Junagadh',\n 'Amreli',\n 'Anand',\n 'Ankleshwar',\n 'Bharuch',\n 'Bhuj',\n 'Botad',\n 'Dahod',\n 'Deesa',\n 'Gandhidham',\n 'Godhra',\n 'Himmatnagar',\n 'Kalol',\n 'Mehsana',\n 'Morbi',\n 'Nadiad',\n 'Navsari',\n 'Palanpur',\n 'Patan',\n 'Porbandar',\n 'Surendranagar',\n 'Valsad',\n 'Vapi',\n 'Veraval',\n ],\n },\n {\n name: 'Haryana',\n cities: [\n 'Gurugram',\n 'Faridabad',\n 'Panipat',\n 'Ambala',\n 'Karnal',\n 'Rohtak',\n 'Hisar',\n 'Sonipat',\n 'Panchkula',\n 'Bahadurgarh',\n 'Bhiwani',\n 'Charkhi Dadri',\n 'Fatehabad',\n 'Hansi',\n 'Jhajjar',\n 'Jind',\n 'Kaithal',\n 'Kurukshetra',\n 'Manesar',\n 'Narnaul',\n 'Nuh',\n 'Palwal',\n 'Rewari',\n 'Sirsa',\n 'Yamunanagar',\n ],\n },\n {\n name: 'Himachal Pradesh',\n cities: [\n 'Shimla',\n 'Dharamshala',\n 'Solan',\n 'Mandi',\n 'Baddi',\n 'Bilaspur',\n 'Chamba',\n 'Hamirpur',\n 'Kangra',\n 'Keylong',\n 'Kullu',\n 'Manali',\n 'Nahan',\n 'Palampur',\n 'Paonta Sahib',\n 'Reckong Peo',\n 'Sundernagar',\n 'Una',\n ],\n },\n {\n name: 'Jharkhand',\n cities: [\n 'Ranchi',\n 'Jamshedpur',\n 'Dhanbad',\n 'Bokaro',\n 'Deoghar',\n 'Hazaribagh',\n 'Adityapur',\n 'Chaibasa',\n 'Chatra',\n 'Dumka',\n 'Garhwa',\n 'Giridih',\n 'Godda',\n 'Gumla',\n 'Jamtara',\n 'Khunti',\n 'Koderma',\n 'Latehar',\n 'Lohardaga',\n 'Medininagar',\n 'Pakur',\n 'Phusro',\n 'Ramgarh',\n 'Sahibganj',\n 'Saraikela',\n 'Simdega',\n ],\n },\n {\n name: 'Karnataka',\n cities: [\n 'Bengaluru',\n 'Mysuru',\n 'Mangaluru',\n 'Hubballi',\n 'Dharwad',\n 'Belagavi',\n 'Kalaburagi',\n 'Davanagere',\n 'Bagalkot',\n 'Ballari',\n 'Bidar',\n 'Chamarajanagar',\n 'Chikkaballapur',\n 'Chikkamagaluru',\n 'Chitradurga',\n 'Gadag',\n 'Hassan',\n 'Haveri',\n 'Hosapete',\n 'Karwar',\n 'Kolar',\n 'Koppal',\n 'Madikeri',\n 'Mandya',\n 'Manipal',\n 'Raichur',\n 'Ramanagara',\n 'Shivamogga',\n 'Tumakuru',\n 'Udupi',\n 'Vijayapura',\n 'Yadgir',\n ],\n },\n {\n name: 'Kerala',\n cities: [\n 'Thiruvananthapuram',\n 'Kochi',\n 'Kozhikode',\n 'Thrissur',\n 'Kollam',\n 'Kannur',\n 'Alappuzha',\n 'Palakkad',\n 'Kottayam',\n 'Malappuram',\n 'Aluva',\n 'Changanassery',\n 'Guruvayur',\n 'Kalpetta',\n 'Kanhangad',\n 'Kasaragod',\n 'Kayamkulam',\n 'Manjeri',\n 'Munnar',\n 'Pathanamthitta',\n 'Perinthalmanna',\n 'Ponnani',\n 'Thalassery',\n 'Thodupuzha',\n 'Tirur',\n 'Vatakara',\n ],\n },\n {\n name: 'Madhya Pradesh',\n cities: [\n 'Indore',\n 'Bhopal',\n 'Jabalpur',\n 'Gwalior',\n 'Ujjain',\n 'Sagar',\n 'Dewas',\n 'Satna',\n 'Ratlam',\n 'Rewa',\n 'Agar',\n 'Anuppur',\n 'Ashoknagar',\n 'Balaghat',\n 'Barwani',\n 'Betul',\n 'Bhind',\n 'Burhanpur',\n 'Chhatarpur',\n 'Chhindwara',\n 'Damoh',\n 'Datia',\n 'Dhar',\n 'Dindori',\n 'Guna',\n 'Itarsi',\n 'Jhabua',\n 'Katni',\n 'Khandwa',\n 'Khargone',\n 'Mandla',\n 'Mandsaur',\n 'Morena',\n 'Narmadapuram',\n 'Neemuch',\n 'Panna',\n 'Pithampur',\n 'Rajgarh',\n 'Sehore',\n 'Seoni',\n 'Shahdol',\n 'Shajapur',\n 'Shivpuri',\n 'Sidhi',\n 'Singrauli',\n 'Tikamgarh',\n 'Umaria',\n 'Vidisha',\n ],\n },\n {\n name: 'Maharashtra',\n cities: [\n 'Mumbai',\n 'Pune',\n 'Nagpur',\n 'Thane',\n 'Navi Mumbai',\n 'Nashik',\n 'Chhatrapati Sambhajinagar',\n 'Solapur',\n 'Kolhapur',\n 'Pimpri-Chinchwad',\n 'Ahilyanagar',\n 'Akola',\n 'Alibag',\n 'Amravati',\n 'Baramati',\n 'Beed',\n 'Bhandara',\n 'Bhiwandi',\n 'Buldhana',\n 'Chandrapur',\n 'Dharashiv',\n 'Dhule',\n 'Gadchiroli',\n 'Gondia',\n 'Hingoli',\n 'Ichalkaranji',\n 'Jalgaon',\n 'Jalna',\n 'Kalyan',\n 'Latur',\n 'Lonavala',\n 'Malegaon',\n 'Mira-Bhayandar',\n 'Nanded',\n 'Nandurbar',\n 'Palghar',\n 'Panvel',\n 'Parbhani',\n 'Ratnagiri',\n 'Sangli',\n 'Satara',\n 'Ulhasnagar',\n 'Vasai-Virar',\n 'Wardha',\n 'Washim',\n 'Yavatmal',\n ],\n },\n {\n name: 'Manipur',\n cities: [\n 'Imphal',\n 'Thoubal',\n 'Bishnupur',\n 'Chandel',\n 'Churachandpur',\n 'Jiribam',\n 'Kakching',\n 'Moreh',\n 'Senapati',\n 'Tamenglong',\n 'Ukhrul',\n ],\n },\n {\n name: 'Meghalaya',\n cities: [\n 'Shillong',\n 'Tura',\n 'Jowai',\n 'Baghmara',\n 'Mairang',\n 'Nongpoh',\n 'Nongstoin',\n 'Resubelpara',\n 'Sohra',\n 'Williamnagar',\n ],\n },\n {\n name: 'Mizoram',\n cities: [\n 'Aizawl',\n 'Lunglei',\n 'Champhai',\n 'Hnahthial',\n 'Khawzawl',\n 'Kolasib',\n 'Lawngtlai',\n 'Mamit',\n 'Saitual',\n 'Serchhip',\n 'Siaha',\n ],\n },\n {\n name: 'Nagaland',\n cities: [\n 'Kohima',\n 'Dimapur',\n 'Mokokchung',\n 'Chumoukedima',\n 'Kiphire',\n 'Longleng',\n 'Mon',\n 'Niuland',\n 'Noklak',\n 'Peren',\n 'Phek',\n 'Shamator',\n 'Tseminyu',\n 'Tuensang',\n 'Wokha',\n 'Zunheboto',\n ],\n },\n {\n name: 'Odisha',\n aliases: ['Orissa'],\n cities: [\n 'Bhubaneswar',\n 'Cuttack',\n 'Rourkela',\n 'Berhampur',\n 'Sambalpur',\n 'Puri',\n 'Balasore',\n 'Angul',\n 'Balangir',\n 'Bargarh',\n 'Baripada',\n 'Bhadrak',\n 'Bhawanipatna',\n 'Dhenkanal',\n 'Jagatsinghpur',\n 'Jajpur',\n 'Jeypore',\n 'Jharsuguda',\n 'Kendrapara',\n 'Keonjhar',\n 'Khordha',\n 'Koraput',\n 'Malkangiri',\n 'Nabarangpur',\n 'Nayagarh',\n 'Paradip',\n 'Phulbani',\n 'Rayagada',\n 'Sundargarh',\n 'Talcher',\n ],\n },\n {\n name: 'Punjab',\n cities: [\n 'Ludhiana',\n 'Amritsar',\n 'Jalandhar',\n 'Patiala',\n 'Mohali',\n 'Bathinda',\n 'Abohar',\n 'Barnala',\n 'Batala',\n 'Faridkot',\n 'Fazilka',\n 'Firozpur',\n 'Gurdaspur',\n 'Hoshiarpur',\n 'Kapurthala',\n 'Khanna',\n 'Malerkotla',\n 'Mansa',\n 'Moga',\n 'Muktsar',\n 'Nawanshahr',\n 'Pathankot',\n 'Phagwara',\n 'Rajpura',\n 'Rupnagar',\n 'Sangrur',\n 'Tarn Taran',\n 'Zirakpur',\n ],\n },\n {\n name: 'Rajasthan',\n cities: [\n 'Jaipur',\n 'Jodhpur',\n 'Kota',\n 'Udaipur',\n 'Bikaner',\n 'Ajmer',\n 'Alwar',\n 'Bhilwara',\n 'Banswara',\n 'Baran',\n 'Barmer',\n 'Beawar',\n 'Bharatpur',\n 'Bhiwadi',\n 'Bundi',\n 'Chittorgarh',\n 'Churu',\n 'Dausa',\n 'Dhaulpur',\n 'Dungarpur',\n 'Gangapur City',\n 'Hanumangarh',\n 'Jaisalmer',\n 'Jalore',\n 'Jhalawar',\n 'Jhunjhunu',\n 'Karauli',\n 'Kishangarh',\n 'Mount Abu',\n 'Nagaur',\n 'Neemrana',\n 'Pali',\n 'Pratapgarh',\n 'Rajsamand',\n 'Sawai Madhopur',\n 'Sikar',\n 'Sirohi',\n 'Sri Ganganagar',\n 'Tonk',\n ],\n },\n {\n name: 'Sikkim',\n cities: [\n 'Gangtok',\n 'Namchi',\n 'Gyalshing',\n 'Jorethang',\n 'Mangan',\n 'Pakyong',\n 'Rangpo',\n 'Ravangla',\n 'Singtam',\n 'Soreng',\n ],\n },\n {\n name: 'Tamil Nadu',\n cities: [\n 'Chennai',\n 'Coimbatore',\n 'Madurai',\n 'Tiruchirappalli',\n 'Salem',\n 'Tiruppur',\n 'Erode',\n 'Tirunelveli',\n 'Vellore',\n 'Hosur',\n 'Ambur',\n 'Ariyalur',\n 'Chengalpattu',\n 'Cuddalore',\n 'Dharmapuri',\n 'Dindigul',\n 'Gudiyatham',\n 'Kallakurichi',\n 'Kanchipuram',\n 'Kanyakumari',\n 'Karaikudi',\n 'Karur',\n 'Krishnagiri',\n 'Kumbakonam',\n 'Mayiladuthurai',\n 'Nagapattinam',\n 'Nagercoil',\n 'Namakkal',\n 'Ooty',\n 'Perambalur',\n 'Pollachi',\n 'Pudukkottai',\n 'Rajapalayam',\n 'Ramanathapuram',\n 'Ranipet',\n 'Sivaganga',\n 'Sivakasi',\n 'Tenkasi',\n 'Thanjavur',\n 'Theni',\n 'Thoothukudi',\n 'Tirupattur',\n 'Tiruvallur',\n 'Tiruvannamalai',\n 'Tiruvarur',\n 'Viluppuram',\n 'Virudhunagar',\n ],\n },\n {\n name: 'Telangana',\n cities: [\n 'Hyderabad',\n 'Warangal',\n 'Nizamabad',\n 'Karimnagar',\n 'Khammam',\n 'Secunderabad',\n 'Adilabad',\n 'Bhongir',\n 'Jagtial',\n 'Kamareddy',\n 'Kothagudem',\n 'Mahbubnagar',\n 'Mancherial',\n 'Medak',\n 'Miryalaguda',\n 'Nalgonda',\n 'Nirmal',\n 'Ramagundam',\n 'Sangareddy',\n 'Siddipet',\n 'Suryapet',\n 'Vikarabad',\n 'Wanaparthy',\n 'Zahirabad',\n ],\n },\n {\n name: 'Tripura',\n cities: [\n 'Agartala',\n 'Dharmanagar',\n 'Udaipur',\n 'Ambassa',\n 'Belonia',\n 'Bishalgarh',\n 'Kailashahar',\n 'Kamalpur',\n 'Khowai',\n 'Sabroom',\n 'Sonamura',\n 'Teliamura',\n ],\n },\n {\n name: 'Uttar Pradesh',\n cities: [\n 'Lucknow',\n 'Kanpur',\n 'Noida',\n 'Ghaziabad',\n 'Agra',\n 'Varanasi',\n 'Prayagraj',\n 'Meerut',\n 'Greater Noida',\n 'Bareilly',\n 'Aligarh',\n 'Moradabad',\n 'Gorakhpur',\n 'Amroha',\n 'Ayodhya',\n 'Azamgarh',\n 'Bahraich',\n 'Ballia',\n 'Banda',\n 'Barabanki',\n 'Basti',\n 'Bulandshahr',\n 'Chandausi',\n 'Deoria',\n 'Etah',\n 'Etawah',\n 'Farrukhabad',\n 'Fatehpur',\n 'Firozabad',\n 'Gonda',\n 'Hapur',\n 'Hardoi',\n 'Hathras',\n 'Jaunpur',\n 'Jhansi',\n 'Kasganj',\n 'Lakhimpur',\n 'Lalitpur',\n 'Mainpuri',\n 'Mathura',\n 'Mau',\n 'Mirzapur',\n 'Modinagar',\n 'Muzaffarnagar',\n 'Orai',\n 'Pilibhit',\n 'Raebareli',\n 'Rampur',\n 'Saharanpur',\n 'Sambhal',\n 'Shahjahanpur',\n 'Sitapur',\n 'Sultanpur',\n 'Unnao',\n 'Vrindavan',\n ],\n },\n {\n name: 'Uttarakhand',\n aliases: ['Uttaranchal'],\n cities: [\n 'Dehradun',\n 'Haridwar',\n 'Roorkee',\n 'Haldwani',\n 'Rudrapur',\n 'Kashipur',\n 'Rishikesh',\n 'Almora',\n 'Bageshwar',\n 'Champawat',\n 'Gopeshwar',\n 'Khatima',\n 'Kotdwar',\n 'Mussoorie',\n 'Nainital',\n 'Pauri',\n 'Pithoragarh',\n 'Ramnagar',\n 'Rudraprayag',\n 'Sitarganj',\n 'Srinagar',\n 'Tehri',\n 'Uttarkashi',\n ],\n },\n {\n name: 'West Bengal',\n cities: [\n 'Kolkata',\n 'Howrah',\n 'Siliguri',\n 'Durgapur',\n 'Asansol',\n 'Bardhaman',\n 'Bidhannagar',\n 'New Town',\n 'Kharagpur',\n 'Haldia',\n 'Alipurduar',\n 'Baharampur',\n 'Balurghat',\n 'Bally',\n 'Bankura',\n 'Barasat',\n 'Barrackpore',\n 'Bolpur',\n 'Chandannagar',\n 'Chinsurah',\n 'Contai',\n 'Cooch Behar',\n 'Darjeeling',\n 'Digha',\n 'Habra',\n 'Jalpaiguri',\n 'Kalimpong',\n 'Kalyani',\n 'Krishnanagar',\n 'Malda',\n 'Medinipur',\n 'Purulia',\n 'Raiganj',\n 'Serampore',\n 'Shantipur',\n 'Tamluk',\n ],\n },\n {\n name: 'Andaman and Nicobar Islands',\n aliases: ['Andaman & Nicobar Islands', 'Andaman and Nicobar'],\n cities: [\n 'Sri Vijaya Puram',\n 'Campbell Bay',\n 'Car Nicobar',\n 'Diglipur',\n 'Mayabunder',\n 'Rangat',\n 'Shaheed Dweep',\n 'Swaraj Dweep',\n ],\n },\n { name: 'Chandigarh', cities: ['Chandigarh'] },\n {\n name: 'Dadra and Nagar Haveli and Daman and Diu',\n aliases: [\n 'The Dadra and Nagar Haveli and Daman and Diu',\n 'Dadra and Nagar Haveli',\n 'Daman and Diu',\n ],\n cities: ['Silvassa', 'Daman', 'Diu'],\n },\n {\n name: 'Delhi',\n aliases: ['NCT of Delhi', 'National Capital Territory of Delhi'],\n cities: ['Delhi', 'New Delhi'],\n },\n {\n name: 'Jammu and Kashmir',\n aliases: ['Jammu & Kashmir', 'J&K'],\n cities: [\n 'Srinagar',\n 'Jammu',\n 'Anantnag',\n 'Bandipora',\n 'Baramulla',\n 'Budgam',\n 'Doda',\n 'Ganderbal',\n 'Kathua',\n 'Katra',\n 'Kishtwar',\n 'Kulgam',\n 'Kupwara',\n 'Poonch',\n 'Pulwama',\n 'Rajouri',\n 'Ramban',\n 'Reasi',\n 'Samba',\n 'Shopian',\n 'Sopore',\n 'Udhampur',\n ],\n },\n { name: 'Ladakh', cities: ['Leh', 'Kargil'] },\n {\n name: 'Lakshadweep',\n cities: ['Kavaratti', 'Agatti', 'Amini', 'Andrott', 'Kadmat', 'Kalpeni', 'Minicoy'],\n },\n {\n name: 'Puducherry',\n aliases: ['Pondicherry'],\n cities: ['Puducherry', 'Karaikal', 'Mahe', 'Yanam'],\n },\n];\n\n/**\n * Other names a city is searched by, keyed by the list's name: the older name,\n * the district name the location lookup answers with, or both. A search for\n * any of them shows the city as the list writes it.\n */\nexport const CITY_ALIASES: Readonly<Record<string, readonly string[]>> = {\n Bengaluru: ['Bangalore', 'Bengaluru Urban', 'Bangalore Urban'],\n Mumbai: ['Bombay', 'Mumbai Suburban', 'Mumbai City'],\n Chennai: ['Madras'],\n Kolkata: ['Calcutta'],\n Gurugram: ['Gurgaon'],\n Noida: ['Gautam Buddha Nagar'],\n Pune: ['Poona'],\n Vadodara: ['Baroda'],\n Visakhapatnam: ['Vizag', 'Vishakhapatnam'],\n Mysuru: ['Mysore'],\n Mangaluru: ['Mangalore', 'Dakshina Kannada'],\n Hubballi: ['Hubli'],\n Belagavi: ['Belgaum'],\n Kalaburagi: ['Gulbarga'],\n Vijayapura: ['Bijapur'],\n Shivamogga: ['Shimoga'],\n Tumakuru: ['Tumkur'],\n Ballari: ['Bellary'],\n Davanagere: ['Davangere'],\n Chikkamagaluru: ['Chikmagalur'],\n Hosapete: ['Hospet', 'Vijayanagara'],\n Thiruvananthapuram: ['Trivandrum'],\n Kochi: ['Cochin', 'Ernakulam'],\n Kozhikode: ['Calicut'],\n Thrissur: ['Trichur'],\n Alappuzha: ['Alleppey'],\n Kollam: ['Quilon'],\n Kannur: ['Cannanore'],\n Palakkad: ['Palghat'],\n Prayagraj: ['Allahabad'],\n Ayodhya: ['Faizabad'],\n Varanasi: ['Banaras', 'Benares', 'Kashi'],\n Tiruchirappalli: ['Trichy'],\n Thoothukudi: ['Tuticorin'],\n Ooty: ['Udhagamandalam', 'The Nilgiris'],\n Kanchipuram: ['Kanchi'],\n Puducherry: ['Pondicherry'],\n 'Chhatrapati Sambhajinagar': ['Aurangabad'],\n Ahilyanagar: ['Ahmednagar'],\n Dharashiv: ['Osmanabad'],\n Nashik: ['Nasik'],\n 'Pimpri-Chinchwad': ['Pimpri', 'Chinchwad', 'PCMC'],\n 'Vasai-Virar': ['Vasai', 'Virar'],\n Narmadapuram: ['Hoshangabad'],\n Medininagar: ['Daltonganj'],\n Bokaro: ['Bokaro Steel City'],\n Rajamahendravaram: ['Rajahmundry', 'Rajahmahendravaram'],\n Anantapur: ['Anantapuramu'],\n Kadapa: ['Cuddapah'],\n Berhampur: ['Brahmapur'],\n Balasore: ['Baleswar'],\n Keonjhar: ['Kendujhar'],\n Bidhannagar: ['Salt Lake'],\n Malda: ['English Bazar'],\n Baharampur: ['Berhampore'],\n Bardhaman: ['Burdwan', 'Purba Bardhaman'],\n Sohra: ['Cherrapunji'],\n 'Sri Vijaya Puram': ['Port Blair', 'South Andaman'],\n Mohali: ['SAS Nagar', 'Sahibzada Ajit Singh Nagar'],\n Kurukshetra: ['Thanesar'],\n Gyalshing: ['Geyzing'],\n Siaha: ['Saiha'],\n Aalo: ['Along'],\n 'Gaya Ji': ['Gaya'],\n Karimganj: ['Sribhumi'],\n // District names the location lookup answers with, for the city people name.\n Guwahati: ['Kamrup Metropolitan'],\n Vijayawada: ['NTR'],\n Hyderabad: ['Rangareddy', 'Ranga Reddy', 'Medchal Malkajgiri'],\n Panaji: ['Panjim', 'North Goa'],\n Margao: ['Madgaon', 'South Goa'],\n Shillong: ['East Khasi Hills'],\n Itanagar: ['Papum Pare'],\n Agartala: ['West Tripura'],\n Imphal: ['Imphal West', 'Imphal East'],\n Jamshedpur: ['East Singhbhum', 'Purbi Singhbhum'],\n Rudrapur: ['Udham Singh Nagar'],\n Asansol: ['Paschim Bardhaman'],\n Delhi: [\n 'Central Delhi',\n 'East Delhi',\n 'North Delhi',\n 'North East Delhi',\n 'North West Delhi',\n 'Shahdara',\n 'South Delhi',\n 'South East Delhi',\n 'South West Delhi',\n 'West Delhi',\n ],\n // Spellings people also use.\n Chapra: ['Chhapra'],\n Dhaulpur: ['Dholpur'],\n Mangaldoi: ['Mangaldai'],\n Rupnagar: ['Ropar'],\n 'Shaheed Dweep': ['Neil Island'],\n 'Swaraj Dweep': ['Havelock'],\n};\n\nconst key = (text: string) =>\n text\n .toLowerCase()\n .replace(/[.\\s&]+/g, ' ')\n .replace(/\\band\\b/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n\n/**\n * The state a name means, by its own name or an alias, ignoring case, dots,\n * \"&\" and \"and\" (\"JAMMU AND KASHMIR\", \"Jammu & Kashmir\"). `undefined` when it\n * is not an Indian state or union territory this list knows.\n */\nexport function findIndiaState(name: string | null | undefined): IndiaState | undefined {\n if (!name) return undefined;\n const wanted = key(name);\n if (!wanted) return undefined;\n return INDIA_STATES.find(\n (state) => key(state.name) === wanted || state.aliases?.some((a) => key(a) === wanted),\n );\n}\n\n/**\n * The names the state picker lists, in its order (states A to Z, then union\n * territories A to Z): the closed list a written state is checked against.\n */\nexport const INDIA_STATE_NAMES = INDIA_STATES.map((state) => state.name) as unknown as readonly [\n IndiaStateName,\n ...IndiaStateName[],\n];\n\n/** The state pickers' other names, by the list's name: \"Orissa\" finds Odisha. */\nexport const STATE_ALIASES: Readonly<Record<string, readonly string[]>> = Object.fromEntries(\n INDIA_STATES.filter((state) => state.aliases).map((state) => [state.name, state.aliases ?? []]),\n);\n\n/**\n * A city as the list writes it, when `name` is one of the state's cities or\n * another name of one (\"Bengaluru Urban\", the location lookup's district, is\n * Bengaluru). Anything else comes back as it was given: never guessed.\n */\nexport function listedCityName(state: IndiaState | undefined, name: string): string {\n if (!state) return name;\n const wanted = key(name);\n const city = state.cities.find(\n (c) => key(c) === wanted || CITY_ALIASES[c]?.some((alias) => key(alias) === wanted),\n );\n return city ?? name;\n}\n\n/**\n * A city as the list writes it from its name ALONE (0.18.0), for where no\n * state comes with it (Discover's `?city=` from a shared link): the list's\n * spelling when the name, or another name of a city, matches exactly ONE\n * spelling in the list (\"Bangalore\" is Bengaluru; \"BILASPUR\", a city of two\n * states, is \"Bilaspur\" either way), and the name unchanged when it matches\n * none or two different spellings (never guessed between them). `states` is\n * the list, India's unless a test hands it another.\n */\nexport function canonicalCityName(\n name: string,\n states: readonly Pick<IndiaState, 'cities'>[] = INDIA_STATES,\n): string {\n const wanted = key(name);\n if (!wanted) return name;\n const found = new Set<string>();\n for (const state of states) {\n for (const c of state.cities) {\n if (key(c) === wanted || CITY_ALIASES[c]?.some((alias) => key(alias) === wanted))\n found.add(c);\n }\n }\n const [only] = found;\n return found.size === 1 && only ? only : name;\n}\n\n/**\n * A place as the list writes it, from however it arrived: a member's older\n * draft (\"karnataka\"), the location lookup (\"Bengaluru Urban\" in \"KARNATAKA\"),\n * or another client. The state becomes the list's name when the list knows it\n * (else stays as given, trimmed, for the rule to refuse); the city becomes the\n * list's spelling when it is one of that state's cities or another name of\n * one, and is never guessed otherwise; the country is India.\n *\n * The SERVER applies it to every location it stores, so Discover's exact match\n * finds \"Bengaluru\" however a client spelled it; a client applies it when it\n * restores or suggests a place, so the member sees the spelling they will get.\n */\nexport function canonicalIndiaLocation(place: { city: string; state?: string | null }): {\n city: string;\n state: string;\n country: typeof INDIA;\n} {\n const listed = findIndiaState(place.state);\n return {\n city: listedCityName(listed, place.city.trim()),\n state: listed?.name ?? (place.state ?? '').trim(),\n country: INDIA,\n };\n}\n\n// ─── The rule ────────────────────────────────────────────────────────────────\n\n/**\n * A location as it is WRITTEN (0.17.0): onboarding's finish, the Me tab's\n * personal details, and the server's own suggestion. India only, one of its\n * states and union territories, and a city of any name within it.\n *\n * Until 0.17.0 the schema took any country and any state text while the web\n * locked the country to India and chose the state from this list, so another\n * client could store what no screen can show. The read side keeps\n * `locationSchema`: a location stored before this rule is still read as it is.\n *\n * The STATE is required: every Indian city has one, and the picker lists a\n * state's cities only once it is chosen. It is read the way people and the\n * location lookup write it (\"KARNATAKA\", \"Orissa\", \"Jammu & Kashmir\" are the\n * list's Karnataka, Odisha, Jammu and Kashmir: `findIndiaState`), so any client\n * may send another spelling and the list's name is what is kept. Left empty it\n * is `stateRequired`; one the list does not know is `stateUnknown`.\n */\nexport const indiaLocationSchema = z.object({\n city: z.string().trim().min(1).max(CITY_MAX),\n // A typed string in, the list's name out: never a preprocess (0.18.0: its\n // input read as `unknown`, so a caller typing the body by `z.input` could\n // send anything and still compile).\n // Missing, blank and unknown all reach the CHOICE (`invalid_value`, as a\n // picker's refusal always was): a form words an unchosen state \"Choose your\n // state\", not \"fill this in\" (0.18.0, ram's suite: a length check, then a\n // missing key, each changed that). Typed in: a string, or left out.\n state: z\n .string({ error: VALIDATION_MESSAGE.stateUnknown })\n .default('')\n .transform((given) => findIndiaState(given)?.name ?? given.trim())\n .pipe(\n z.enum(INDIA_STATE_NAMES, {\n error: (issue) =>\n issue.input === '' ? VALIDATION_MESSAGE.stateRequired : VALIDATION_MESSAGE.stateUnknown,\n }),\n ),\n country: z.literal(INDIA),\n});\nexport type IndiaLocation = z.infer<typeof indiaLocationSchema>;\n\n/**\n * The city these coordinates look like, for the member to CONFIRM, or `null`\n * when the lookup could not place them confidently (or they are outside India,\n * whose area data is all there is). A suggestion, never a write: only what the\n * member then submits becomes their location.\n *\n * In the WRITE shape (0.17.0): the server names the state and city the way\n * this list does (`findIndiaState`, `listedCityName`: the lookup's \"Bengaluru\n * Urban\" is Bengaluru), so what it suggests is what the member could have\n * picked, and saving it unchanged can never be refused.\n */\nexport const suggestedLocationSchema = indiaLocationSchema.nullable();\nexport type SuggestedLocation = z.infer<typeof suggestedLocationSchema>;\n"]}
|
|
@@ -49,8 +49,8 @@ export type MemberParams = z.infer<typeof memberParamsSchema>;
|
|
|
49
49
|
*/
|
|
50
50
|
export declare const memberDirectoryQuerySchema: z.ZodObject<{
|
|
51
51
|
limit: z.ZodPreprocess<z.ZodDefault<z.ZodCoercedNumber<unknown>>, unknown>;
|
|
52
|
-
cursor: z.ZodOptional<z.ZodString>;
|
|
53
|
-
q: z.
|
|
52
|
+
cursor: z.ZodPreprocess<z.ZodOptional<z.ZodString>, unknown>;
|
|
53
|
+
q: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>>;
|
|
54
54
|
status: z.ZodPreprocess<z.ZodOptional<z.ZodEnum<{
|
|
55
55
|
active: "active";
|
|
56
56
|
suspended: "suspended";
|
|
@@ -82,6 +82,29 @@ export declare const PLAN_SPECS: Readonly<Record<PlanTier, {
|
|
|
82
82
|
prices: Readonly<Record<PlanPeriod, number>>;
|
|
83
83
|
limits: PlanLimits;
|
|
84
84
|
}>>;
|
|
85
|
+
/**
|
|
86
|
+
* A calendar month or year later on India's calendar (`count` of them), the
|
|
87
|
+
* day clamped to the month's last: 31 January plus a month is 28 or 29
|
|
88
|
+
* February. India has one offset all year, so its calendar is UTC's, shifted.
|
|
89
|
+
*/
|
|
90
|
+
export declare function addPlanPeriod(from: Date, period: PlanPeriod, count?: number): Date;
|
|
91
|
+
/** What an upgrade costs for each whole calendar year of Premium left: the yearly difference. */
|
|
92
|
+
export declare const UPGRADE_PER_YEAR: number;
|
|
93
|
+
/** ...for each whole calendar month after the years: the monthly difference (a 31-day month and February alike). */
|
|
94
|
+
export declare const UPGRADE_PER_MONTH: number;
|
|
95
|
+
/** The days left over are charged as this many to a month. */
|
|
96
|
+
export declare const UPGRADE_DAYS_PER_MONTH = 30;
|
|
97
|
+
/** ...so each day left over costs this, never more than `UPGRADE_PER_MONTH` for them all. */
|
|
98
|
+
export declare const UPGRADE_PER_DAY: number;
|
|
99
|
+
/**
|
|
100
|
+
* What an upgrade of `convertedMs` of Premium, from `now`, costs in paise (the
|
|
101
|
+
* user: "ask for the rest of the money, the difference"). Each whole calendar
|
|
102
|
+
* year left costs `UPGRADE_PER_YEAR`; each whole calendar month after that,
|
|
103
|
+
* `UPGRADE_PER_MONTH`; the days left over `UPGRADE_PER_DAY` each, but never
|
|
104
|
+
* more than one month's. The part below a year never costs more than a year's.
|
|
105
|
+
* A part day counts as a day; rounded up to the rupee.
|
|
106
|
+
*/
|
|
107
|
+
export declare function upgradePrice(convertedMs: number, now: Date): number;
|
|
85
108
|
/**
|
|
86
109
|
* Free founding memberships (0.14.0): the first 100 people to join the launch
|
|
87
110
|
* waitlist get their membership free, numbered #1 to #100 by their place
|
|
@@ -154,6 +177,9 @@ export declare const planBlockSchema: z.ZodObject<{
|
|
|
154
177
|
endsAt: z.ZodISODateTime;
|
|
155
178
|
}, z.core.$strip>;
|
|
156
179
|
export type PlanBlock = z.infer<typeof planBlockSchema>;
|
|
180
|
+
/** Why someone takes part: their membership, or a staff role (staff are members). */
|
|
181
|
+
export declare const TAKES_PART_THROUGH_VALUES: readonly ["membership", "staff"];
|
|
182
|
+
export type TakesPartThrough = (typeof TAKES_PART_THROUGH_VALUES)[number];
|
|
157
183
|
export declare const meMembershipSchema: z.ZodObject<{
|
|
158
184
|
standing: z.ZodEnum<{
|
|
159
185
|
viewer: "viewer";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"membership.d.ts","sourceRoot":"","sources":["../../../src/domains/membership/membership.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"membership.d.ts","sourceRoot":"","sources":["../../../src/domains/membership/membership.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
*/
|
|
23
23
|
import { z } from 'zod';
|
|
24
24
|
import { standingSchema } from '../../access/standing.js';
|
|
25
|
+
import { DAY_MS, INDIA_UTC_OFFSET_MS } from '../../core/limits.js';
|
|
25
26
|
import { billingDetailsSchema } from '../billing/gst.js';
|
|
26
27
|
/**
|
|
27
28
|
* How someone came to hold a membership. ⚠ Stored: append only.
|
|
@@ -83,6 +84,57 @@ export const PLAN_SPECS = {
|
|
|
83
84
|
limits: { productsLive: null, newPeoplePerMonth: 50 },
|
|
84
85
|
},
|
|
85
86
|
};
|
|
87
|
+
// ─── Plan time on India's calendar, and an upgrade's price (0.18.0) ──────────
|
|
88
|
+
//
|
|
89
|
+
// Moved here from the backend's plan timeline so the price a member is charged
|
|
90
|
+
// and the rule the Terms of Service state are ONE function: the Terms said
|
|
91
|
+
// "Rs 20 a day for the rest" for a week after the server stopped charging it
|
|
92
|
+
// (2026-10-13).
|
|
93
|
+
/**
|
|
94
|
+
* A calendar month or year later on India's calendar (`count` of them), the
|
|
95
|
+
* day clamped to the month's last: 31 January plus a month is 28 or 29
|
|
96
|
+
* February. India has one offset all year, so its calendar is UTC's, shifted.
|
|
97
|
+
*/
|
|
98
|
+
export function addPlanPeriod(from, period, count = 1) {
|
|
99
|
+
const months = period === 'year' ? 12 * count : count;
|
|
100
|
+
const local = new Date(from.getTime() + INDIA_UTC_OFFSET_MS);
|
|
101
|
+
const m = local.getUTCMonth() + months;
|
|
102
|
+
const targetYear = local.getUTCFullYear() + Math.floor(m / 12);
|
|
103
|
+
const targetMonth = ((m % 12) + 12) % 12;
|
|
104
|
+
const lastDay = new Date(Date.UTC(targetYear, targetMonth + 1, 0)).getUTCDate();
|
|
105
|
+
const shifted = Date.UTC(targetYear, targetMonth, Math.min(local.getUTCDate(), lastDay), local.getUTCHours(), local.getUTCMinutes(), local.getUTCSeconds(), local.getUTCMilliseconds());
|
|
106
|
+
return new Date(shifted - INDIA_UTC_OFFSET_MS);
|
|
107
|
+
}
|
|
108
|
+
/** What an upgrade costs for each whole calendar year of Premium left: the yearly difference. */
|
|
109
|
+
export const UPGRADE_PER_YEAR = PLAN_SPECS.business.prices.year - PLAN_SPECS.premium.prices.year;
|
|
110
|
+
/** ...for each whole calendar month after the years: the monthly difference (a 31-day month and February alike). */
|
|
111
|
+
export const UPGRADE_PER_MONTH = PLAN_SPECS.business.prices.month - PLAN_SPECS.premium.prices.month;
|
|
112
|
+
/** The days left over are charged as this many to a month. */
|
|
113
|
+
export const UPGRADE_DAYS_PER_MONTH = 30;
|
|
114
|
+
/** ...so each day left over costs this, never more than `UPGRADE_PER_MONTH` for them all. */
|
|
115
|
+
export const UPGRADE_PER_DAY = UPGRADE_PER_MONTH / UPGRADE_DAYS_PER_MONTH;
|
|
116
|
+
/**
|
|
117
|
+
* What an upgrade of `convertedMs` of Premium, from `now`, costs in paise (the
|
|
118
|
+
* user: "ask for the rest of the money, the difference"). Each whole calendar
|
|
119
|
+
* year left costs `UPGRADE_PER_YEAR`; each whole calendar month after that,
|
|
120
|
+
* `UPGRADE_PER_MONTH`; the days left over `UPGRADE_PER_DAY` each, but never
|
|
121
|
+
* more than one month's. The part below a year never costs more than a year's.
|
|
122
|
+
* A part day counts as a day; rounded up to the rupee.
|
|
123
|
+
*/
|
|
124
|
+
export function upgradePrice(convertedMs, now) {
|
|
125
|
+
const end = now.getTime() + Math.max(convertedMs, 1);
|
|
126
|
+
let years = 0;
|
|
127
|
+
while (addPlanPeriod(now, 'year', years + 1).getTime() <= end)
|
|
128
|
+
years += 1;
|
|
129
|
+
const afterYears = addPlanPeriod(now, 'year', years);
|
|
130
|
+
let months = 0;
|
|
131
|
+
while (addPlanPeriod(afterYears, 'month', months + 1).getTime() <= end)
|
|
132
|
+
months += 1;
|
|
133
|
+
const restDays = Math.ceil((end - addPlanPeriod(afterYears, 'month', months).getTime()) / DAY_MS);
|
|
134
|
+
const belowAYear = months * UPGRADE_PER_MONTH + Math.min(restDays * UPGRADE_PER_DAY, UPGRADE_PER_MONTH);
|
|
135
|
+
const paise = years * UPGRADE_PER_YEAR + Math.min(belowAYear, UPGRADE_PER_YEAR);
|
|
136
|
+
return Math.ceil(paise / 100) * 100;
|
|
137
|
+
}
|
|
86
138
|
/**
|
|
87
139
|
* Free founding memberships (0.14.0): the first 100 people to join the launch
|
|
88
140
|
* waitlist get their membership free, numbered #1 to #100 by their place
|
|
@@ -130,12 +182,14 @@ export const planBlockSchema = z.object({
|
|
|
130
182
|
startsAt: z.iso.datetime(),
|
|
131
183
|
endsAt: z.iso.datetime(),
|
|
132
184
|
});
|
|
185
|
+
/** Why someone takes part: their membership, or a staff role (staff are members). */
|
|
186
|
+
export const TAKES_PART_THROUGH_VALUES = ['membership', 'staff'];
|
|
133
187
|
export const meMembershipSchema = z.object({
|
|
134
188
|
standing: standingSchema,
|
|
135
189
|
/** Null for a viewer, and for staff who hold none (they take part through their role). */
|
|
136
190
|
membership: membershipSchema.nullable(),
|
|
137
191
|
/** Why they take part: their membership, or a staff role (staff are members). Null for a viewer. */
|
|
138
|
-
through: z.enum(
|
|
192
|
+
through: z.enum(TAKES_PART_THROUGH_VALUES).nullable(),
|
|
139
193
|
plan: z.object({
|
|
140
194
|
/** The tier in force now; null with no plan. */
|
|
141
195
|
tier: planTierSchema.nullable(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"membership.js","sourceRoot":"","sources":["../../../src/domains/membership/membership.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * founder-schema: membership and plans, as a member holds them (0.12.0)\n *\n * GET /api/v1/plans planCatalogSchema (anyone: prices and what each includes)\n * GET /api/v1/me/membership meMembershipSchema (signed in: what I hold, what I have used)\n *\n * THE USER'S RULING (2026-10-11): looking is free; taking part needs a\n * MEMBERSHIP, Rs 99 once, for life (the first 100 free with a coupon). On top,\n * two PLANS: Premium (5 live products, 15 new people a month to message) and\n * Business (unlimited products, 50 new people). Prices and plan contents come\n * from the server, so a change needs no client release.\n *\n * A PLAN IS TIME, PREPAID, IN TWO BLOCKS: Business time first, then Premium\n * time. Buying more APPENDS; buying Premium while on Business waits its turn;\n * buying Business while on Premium is an upgrade that turns the Premium time\n * left into Business for the difference (`domains/billing`). `blocks` says it\n * as it stands, from now on.\n *\n * Money is integer PAISE everywhere in this package: never a float of rupees.\n *\n * @module founder-schema/domains/membership\n */\n\nimport { z } from 'zod';\nimport { standingSchema } from '../../access/standing.js';\nimport { billingDetailsSchema } from '../billing/gst.js';\n\n/**\n * How someone came to hold a membership. ⚠ Stored: append only.\n *\n * founding free for life, numbered \"Founding member #N\": one of the first\n * `FOUNDING_PLACES` people to join the launch WAITLIST (0.14.0,\n * the user's rule of 2026-10-16). Before that, the founding\n * coupon (`FIRST100`), which no longer exists on main.\n * coupon another free-membership coupon\n * paid Rs 99, captured\n * granted staff gave it (a partner, a press account), with a reason on record\n */\nexport const MEMBERSHIP_KIND_VALUES = ['founding', 'coupon', 'paid', 'granted'] as const;\nexport const membershipKindSchema = z.enum(MEMBERSHIP_KIND_VALUES);\nexport type MembershipKind = z.infer<typeof membershipKindSchema>;\n\n/** ⚠ Stored: append only. Highest last is NOT implied: compare with `PLAN_TIER_RANK`. */\nexport const PLAN_TIER_VALUES = ['premium', 'business'] as const;\nexport const planTierSchema = z.enum(PLAN_TIER_VALUES);\nexport type PlanTier = z.infer<typeof planTierSchema>;\n\n/** Which tier outranks which: Business above Premium. */\nexport const PLAN_TIER_RANK: Readonly<Record<PlanTier, number>> = { premium: 1, business: 2 };\n\n/** One payment buys a calendar month or a calendar year. ⚠ Stored: append only. */\nexport const PLAN_PERIOD_VALUES = ['month', 'year'] as const;\nexport const planPeriodSchema = z.enum(PLAN_PERIOD_VALUES);\nexport type PlanPeriod = z.infer<typeof planPeriodSchema>;\n\n/** Integer paise, never negative. Rs 399 is 39900. */\nexport const paiseSchema = z.number().int().nonnegative();\nexport type Paise = z.infer<typeof paiseSchema>;\n\n/**\n * What a standing or a plan allows that is COUNTED (the ability says whether;\n * these say how many).\n *\n * productsLive products live at once; null is unlimited (the server\n * still holds a safety ceiling, `PRODUCTS_LIVE_SAFETY_MAX`)\n * newPeoplePerMonth conversations a month with people you do not know\n */\nexport const planLimitsSchema = z.object({\n productsLive: z.number().int().nonnegative().nullable(),\n newPeoplePerMonth: z.number().int().nonnegative(),\n});\nexport type PlanLimits = z.infer<typeof planLimitsSchema>;\n\n// ─── The price list ──────────────────────────────────────────────────────────\n//\n// THE ONE PLACE a price or a plan's limit is written (0.12.0). The backend\n// prices and counts from these (`modules/plans/catalog.ts`), `GET /plans`\n// serves them, and the web's Terms of Service are written FROM them, so the\n// Terms can never state a price the server does not charge. A change here is\n// a schema release, then the backend, then the web. Integer PAISE, GST\n// included. hary's India-first prices (the user: \"you decide, India first\").\n\n/** The membership: once, for life. */\nexport const MEMBERSHIP_PRICE_PAISE = 9_900;\n\n/** What a member with no plan may: 1 live product, no conversations with people they do not know. */\nexport const MEMBER_LIMIT_VALUES: PlanLimits = { productsLive: 1, newPeoplePerMonth: 0 };\n\n/** Each plan's name, prices and limits. Exhaustive by type. */\nexport const PLAN_SPECS: Readonly<\n Record<\n PlanTier,\n { name: string; prices: Readonly<Record<PlanPeriod, number>>; limits: PlanLimits }\n >\n> = {\n premium: {\n name: 'Premium',\n prices: { month: 39_900, year: 399_900 },\n limits: { productsLive: 5, newPeoplePerMonth: 15 },\n },\n business: {\n name: 'Business',\n prices: { month: 99_900, year: 999_900 },\n limits: { productsLive: null, newPeoplePerMonth: 50 },\n },\n};\n\n/**\n * Free founding memberships (0.14.0): the first 100 people to join the launch\n * waitlist get their membership free, numbered #1 to #100 by their place\n * (the user, 2026-10-16). Everyone else pays `MEMBERSHIP_PRICE_PAISE` once.\n * No code gives a founding place any more.\n */\nexport const FOUNDING_PLACES = 100;\n\n// ─── GET /plans ──────────────────────────────────────────────────────────────\n\nexport const planOfferSchema = z.object({\n tier: planTierSchema,\n /** \"Premium\", \"Business\": the server's word, so a rename needs no client release. */\n name: z.string(),\n /** GST included. */\n prices: z.object({ month: paiseSchema, year: paiseSchema }),\n limits: planLimitsSchema,\n});\nexport type PlanOffer = z.infer<typeof planOfferSchema>;\n\nexport const planCatalogSchema = z.object({\n currency: z.literal('INR'),\n membership: z.object({\n /** Once, for life, GST included. */\n price: paiseSchema,\n limits: planLimitsSchema,\n }),\n /** Lowest first. */\n plans: z.array(planOfferSchema),\n /** Every purchase is refunded in full within this many days of paying. */\n refundWindowDays: z.number().int().positive(),\n /**\n * Whether a payment can be taken here now. False when the gateway is not\n * configured: a free coupon still works, a paid purchase answers\n * `PAYMENTS_UNAVAILABLE`.\n */\n paymentsEnabled: z.boolean(),\n});\nexport type PlanCatalog = z.infer<typeof planCatalogSchema>;\n\n// ─── GET /me/membership ──────────────────────────────────────────────────────\n\nexport const membershipSchema = z.object({\n kind: membershipKindSchema,\n since: z.iso.datetime(),\n /** \"Founding member #N\": set only for `founding`. */\n foundingNumber: z.number().int().positive().nullable(),\n});\nexport type Membership = z.infer<typeof membershipSchema>;\n\n/** A stretch of one tier. Blocks never overlap and follow each other with no gap. */\nexport const planBlockSchema = z.object({\n tier: planTierSchema,\n startsAt: z.iso.datetime(),\n endsAt: z.iso.datetime(),\n});\nexport type PlanBlock = z.infer<typeof planBlockSchema>;\n\nexport const meMembershipSchema = z.object({\n standing: standingSchema,\n /** Null for a viewer, and for staff who hold none (they take part through their role). */\n membership: membershipSchema.nullable(),\n /** Why they take part: their membership, or a staff role (staff are members). Null for a viewer. */\n through: z.enum(['membership', 'staff']).nullable(),\n plan: z.object({\n /** The tier in force now; null with no plan. */\n tier: planTierSchema.nullable(),\n /** From now on, Business first, then Premium. Empty with no plan. */\n blocks: z.array(planBlockSchema),\n }),\n limits: planLimitsSchema,\n products: z.object({\n /** Products they own that are live now. */\n live: z.number().int().nonnegative(),\n /** Products they own, paused ones included. */\n owned: z.number().int().nonnegative(),\n /**\n * What adding another counts against (0.13.0): live ones and the ones\n * they paused themselves, not those a plan's end paused. \"Add a product\"\n * stops when this reaches `limits.productsLive`: pausing never makes room.\n */\n counted: z.number().int().nonnegative(),\n }),\n messages: z.object({\n /** New people they started a conversation with this month (India time). */\n used: z.number().int().nonnegative(),\n /** When this month's count starts again. */\n resetsAt: z.iso.datetime(),\n }),\n /** The billing details they last used, to prefill the next checkout; null before the first. */\n billing: billingDetailsSchema.nullable(),\n});\nexport type MeMembership = z.infer<typeof meMembershipSchema>;\n"]}
|
|
1
|
+
{"version":3,"file":"membership.js","sourceRoot":"","sources":["../../../src/domains/membership/membership.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * founder-schema: membership and plans, as a member holds them (0.12.0)\n *\n * GET /api/v1/plans planCatalogSchema (anyone: prices and what each includes)\n * GET /api/v1/me/membership meMembershipSchema (signed in: what I hold, what I have used)\n *\n * THE USER'S RULING (2026-10-11): looking is free; taking part needs a\n * MEMBERSHIP, Rs 99 once, for life (the first 100 free with a coupon). On top,\n * two PLANS: Premium (5 live products, 15 new people a month to message) and\n * Business (unlimited products, 50 new people). Prices and plan contents come\n * from the server, so a change needs no client release.\n *\n * A PLAN IS TIME, PREPAID, IN TWO BLOCKS: Business time first, then Premium\n * time. Buying more APPENDS; buying Premium while on Business waits its turn;\n * buying Business while on Premium is an upgrade that turns the Premium time\n * left into Business for the difference (`domains/billing`). `blocks` says it\n * as it stands, from now on.\n *\n * Money is integer PAISE everywhere in this package: never a float of rupees.\n *\n * @module founder-schema/domains/membership\n */\n\nimport { z } from 'zod';\nimport { standingSchema } from '../../access/standing.js';\nimport { DAY_MS, INDIA_UTC_OFFSET_MS } from '../../core/limits.js';\nimport { billingDetailsSchema } from '../billing/gst.js';\n\n/**\n * How someone came to hold a membership. ⚠ Stored: append only.\n *\n * founding free for life, numbered \"Founding member #N\": one of the first\n * `FOUNDING_PLACES` people to join the launch WAITLIST (0.14.0,\n * the user's rule of 2026-10-16). Before that, the founding\n * coupon (`FIRST100`), which no longer exists on main.\n * coupon another free-membership coupon\n * paid Rs 99, captured\n * granted staff gave it (a partner, a press account), with a reason on record\n */\nexport const MEMBERSHIP_KIND_VALUES = ['founding', 'coupon', 'paid', 'granted'] as const;\nexport const membershipKindSchema = z.enum(MEMBERSHIP_KIND_VALUES);\nexport type MembershipKind = z.infer<typeof membershipKindSchema>;\n\n/** ⚠ Stored: append only. Highest last is NOT implied: compare with `PLAN_TIER_RANK`. */\nexport const PLAN_TIER_VALUES = ['premium', 'business'] as const;\nexport const planTierSchema = z.enum(PLAN_TIER_VALUES);\nexport type PlanTier = z.infer<typeof planTierSchema>;\n\n/** Which tier outranks which: Business above Premium. */\nexport const PLAN_TIER_RANK: Readonly<Record<PlanTier, number>> = { premium: 1, business: 2 };\n\n/** One payment buys a calendar month or a calendar year. ⚠ Stored: append only. */\nexport const PLAN_PERIOD_VALUES = ['month', 'year'] as const;\nexport const planPeriodSchema = z.enum(PLAN_PERIOD_VALUES);\nexport type PlanPeriod = z.infer<typeof planPeriodSchema>;\n\n/** Integer paise, never negative. Rs 399 is 39900. */\nexport const paiseSchema = z.number().int().nonnegative();\nexport type Paise = z.infer<typeof paiseSchema>;\n\n/**\n * What a standing or a plan allows that is COUNTED (the ability says whether;\n * these say how many).\n *\n * productsLive products live at once; null is unlimited (the server\n * still holds a safety ceiling, `PRODUCTS_LIVE_SAFETY_MAX`)\n * newPeoplePerMonth conversations a month with people you do not know\n */\nexport const planLimitsSchema = z.object({\n productsLive: z.number().int().nonnegative().nullable(),\n newPeoplePerMonth: z.number().int().nonnegative(),\n});\nexport type PlanLimits = z.infer<typeof planLimitsSchema>;\n\n// ─── The price list ──────────────────────────────────────────────────────────\n//\n// THE ONE PLACE a price or a plan's limit is written (0.12.0). The backend\n// prices and counts from these (`modules/plans/catalog.ts`), `GET /plans`\n// serves them, and the web's Terms of Service are written FROM them, so the\n// Terms can never state a price the server does not charge. A change here is\n// a schema release, then the backend, then the web. Integer PAISE, GST\n// included. hary's India-first prices (the user: \"you decide, India first\").\n\n/** The membership: once, for life. */\nexport const MEMBERSHIP_PRICE_PAISE = 9_900;\n\n/** What a member with no plan may: 1 live product, no conversations with people they do not know. */\nexport const MEMBER_LIMIT_VALUES: PlanLimits = { productsLive: 1, newPeoplePerMonth: 0 };\n\n/** Each plan's name, prices and limits. Exhaustive by type. */\nexport const PLAN_SPECS: Readonly<\n Record<\n PlanTier,\n { name: string; prices: Readonly<Record<PlanPeriod, number>>; limits: PlanLimits }\n >\n> = {\n premium: {\n name: 'Premium',\n prices: { month: 39_900, year: 399_900 },\n limits: { productsLive: 5, newPeoplePerMonth: 15 },\n },\n business: {\n name: 'Business',\n prices: { month: 99_900, year: 999_900 },\n limits: { productsLive: null, newPeoplePerMonth: 50 },\n },\n};\n\n// ─── Plan time on India's calendar, and an upgrade's price (0.18.0) ──────────\n//\n// Moved here from the backend's plan timeline so the price a member is charged\n// and the rule the Terms of Service state are ONE function: the Terms said\n// \"Rs 20 a day for the rest\" for a week after the server stopped charging it\n// (2026-10-13).\n\n/**\n * A calendar month or year later on India's calendar (`count` of them), the\n * day clamped to the month's last: 31 January plus a month is 28 or 29\n * February. India has one offset all year, so its calendar is UTC's, shifted.\n */\nexport function addPlanPeriod(from: Date, period: PlanPeriod, count = 1): Date {\n const months = period === 'year' ? 12 * count : count;\n const local = new Date(from.getTime() + INDIA_UTC_OFFSET_MS);\n const m = local.getUTCMonth() + months;\n const targetYear = local.getUTCFullYear() + Math.floor(m / 12);\n const targetMonth = ((m % 12) + 12) % 12;\n const lastDay = new Date(Date.UTC(targetYear, targetMonth + 1, 0)).getUTCDate();\n const shifted = Date.UTC(\n targetYear,\n targetMonth,\n Math.min(local.getUTCDate(), lastDay),\n local.getUTCHours(),\n local.getUTCMinutes(),\n local.getUTCSeconds(),\n local.getUTCMilliseconds(),\n );\n return new Date(shifted - INDIA_UTC_OFFSET_MS);\n}\n\n/** What an upgrade costs for each whole calendar year of Premium left: the yearly difference. */\nexport const UPGRADE_PER_YEAR = PLAN_SPECS.business.prices.year - PLAN_SPECS.premium.prices.year;\n/** ...for each whole calendar month after the years: the monthly difference (a 31-day month and February alike). */\nexport const UPGRADE_PER_MONTH = PLAN_SPECS.business.prices.month - PLAN_SPECS.premium.prices.month;\n/** The days left over are charged as this many to a month. */\nexport const UPGRADE_DAYS_PER_MONTH = 30;\n/** ...so each day left over costs this, never more than `UPGRADE_PER_MONTH` for them all. */\nexport const UPGRADE_PER_DAY = UPGRADE_PER_MONTH / UPGRADE_DAYS_PER_MONTH;\n\n/**\n * What an upgrade of `convertedMs` of Premium, from `now`, costs in paise (the\n * user: \"ask for the rest of the money, the difference\"). Each whole calendar\n * year left costs `UPGRADE_PER_YEAR`; each whole calendar month after that,\n * `UPGRADE_PER_MONTH`; the days left over `UPGRADE_PER_DAY` each, but never\n * more than one month's. The part below a year never costs more than a year's.\n * A part day counts as a day; rounded up to the rupee.\n */\nexport function upgradePrice(convertedMs: number, now: Date): number {\n const end = now.getTime() + Math.max(convertedMs, 1);\n let years = 0;\n while (addPlanPeriod(now, 'year', years + 1).getTime() <= end) years += 1;\n const afterYears = addPlanPeriod(now, 'year', years);\n let months = 0;\n while (addPlanPeriod(afterYears, 'month', months + 1).getTime() <= end) months += 1;\n const restDays = Math.ceil((end - addPlanPeriod(afterYears, 'month', months).getTime()) / DAY_MS);\n const belowAYear =\n months * UPGRADE_PER_MONTH + Math.min(restDays * UPGRADE_PER_DAY, UPGRADE_PER_MONTH);\n const paise = years * UPGRADE_PER_YEAR + Math.min(belowAYear, UPGRADE_PER_YEAR);\n return Math.ceil(paise / 100) * 100;\n}\n\n/**\n * Free founding memberships (0.14.0): the first 100 people to join the launch\n * waitlist get their membership free, numbered #1 to #100 by their place\n * (the user, 2026-10-16). Everyone else pays `MEMBERSHIP_PRICE_PAISE` once.\n * No code gives a founding place any more.\n */\nexport const FOUNDING_PLACES = 100;\n\n// ─── GET /plans ──────────────────────────────────────────────────────────────\n\nexport const planOfferSchema = z.object({\n tier: planTierSchema,\n /** \"Premium\", \"Business\": the server's word, so a rename needs no client release. */\n name: z.string(),\n /** GST included. */\n prices: z.object({ month: paiseSchema, year: paiseSchema }),\n limits: planLimitsSchema,\n});\nexport type PlanOffer = z.infer<typeof planOfferSchema>;\n\nexport const planCatalogSchema = z.object({\n currency: z.literal('INR'),\n membership: z.object({\n /** Once, for life, GST included. */\n price: paiseSchema,\n limits: planLimitsSchema,\n }),\n /** Lowest first. */\n plans: z.array(planOfferSchema),\n /** Every purchase is refunded in full within this many days of paying. */\n refundWindowDays: z.number().int().positive(),\n /**\n * Whether a payment can be taken here now. False when the gateway is not\n * configured: a free coupon still works, a paid purchase answers\n * `PAYMENTS_UNAVAILABLE`.\n */\n paymentsEnabled: z.boolean(),\n});\nexport type PlanCatalog = z.infer<typeof planCatalogSchema>;\n\n// ─── GET /me/membership ──────────────────────────────────────────────────────\n\nexport const membershipSchema = z.object({\n kind: membershipKindSchema,\n since: z.iso.datetime(),\n /** \"Founding member #N\": set only for `founding`. */\n foundingNumber: z.number().int().positive().nullable(),\n});\nexport type Membership = z.infer<typeof membershipSchema>;\n\n/** A stretch of one tier. Blocks never overlap and follow each other with no gap. */\nexport const planBlockSchema = z.object({\n tier: planTierSchema,\n startsAt: z.iso.datetime(),\n endsAt: z.iso.datetime(),\n});\nexport type PlanBlock = z.infer<typeof planBlockSchema>;\n\n/** Why someone takes part: their membership, or a staff role (staff are members). */\nexport const TAKES_PART_THROUGH_VALUES = ['membership', 'staff'] as const;\nexport type TakesPartThrough = (typeof TAKES_PART_THROUGH_VALUES)[number];\n\nexport const meMembershipSchema = z.object({\n standing: standingSchema,\n /** Null for a viewer, and for staff who hold none (they take part through their role). */\n membership: membershipSchema.nullable(),\n /** Why they take part: their membership, or a staff role (staff are members). Null for a viewer. */\n through: z.enum(TAKES_PART_THROUGH_VALUES).nullable(),\n plan: z.object({\n /** The tier in force now; null with no plan. */\n tier: planTierSchema.nullable(),\n /** From now on, Business first, then Premium. Empty with no plan. */\n blocks: z.array(planBlockSchema),\n }),\n limits: planLimitsSchema,\n products: z.object({\n /** Products they own that are live now. */\n live: z.number().int().nonnegative(),\n /** Products they own, paused ones included. */\n owned: z.number().int().nonnegative(),\n /**\n * What adding another counts against (0.13.0): live ones and the ones\n * they paused themselves, not those a plan's end paused. \"Add a product\"\n * stops when this reaches `limits.productsLive`: pausing never makes room.\n */\n counted: z.number().int().nonnegative(),\n }),\n messages: z.object({\n /** New people they started a conversation with this month (India time). */\n used: z.number().int().nonnegative(),\n /** When this month's count starts again. */\n resetsAt: z.iso.datetime(),\n }),\n /** The billing details they last used, to prefill the next checkout; null before the first. */\n billing: billingDetailsSchema.nullable(),\n});\nexport type MeMembership = z.infer<typeof meMembershipSchema>;\n"]}
|
|
@@ -201,7 +201,7 @@ export type ModerationPage = z.infer<typeof moderationPageSchema>;
|
|
|
201
201
|
/** `GET /moderation/content`. Visible when not said. */
|
|
202
202
|
export declare const moderationContentQuerySchema: z.ZodObject<{
|
|
203
203
|
limit: z.ZodPreprocess<z.ZodDefault<z.ZodCoercedNumber<unknown>>, unknown>;
|
|
204
|
-
cursor: z.ZodOptional<z.ZodString>;
|
|
204
|
+
cursor: z.ZodPreprocess<z.ZodOptional<z.ZodString>, unknown>;
|
|
205
205
|
state: z.ZodPreprocess<z.ZodDefault<z.ZodEnum<{
|
|
206
206
|
hidden: "hidden";
|
|
207
207
|
visible: "visible";
|
|
@@ -230,7 +230,7 @@ export declare const moderationDecisionBodySchema: z.ZodObject<{
|
|
|
230
230
|
restore: "restore";
|
|
231
231
|
remove: "remove";
|
|
232
232
|
}>;
|
|
233
|
-
note: z.
|
|
233
|
+
note: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>>;
|
|
234
234
|
}, z.core.$strip>;
|
|
235
235
|
export type ModerationDecisionBody = z.infer<typeof moderationDecisionBodySchema>;
|
|
236
236
|
//# sourceMappingURL=moderation.d.ts.map
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
*/
|
|
41
41
|
import { z } from 'zod';
|
|
42
42
|
import { emptyStringToUndefined, objectIdSchema, optionalTrimmedString, paginationQuerySchema, } from '../../core/common.js';
|
|
43
|
-
import { MODERATION_NOTE_MAX } from '../../core/limits.js';
|
|
43
|
+
import { MODERATION_EXCERPT_MAX, MODERATION_NOTE_MAX } from '../../core/limits.js';
|
|
44
44
|
import { paginatedSchema } from '../../core/responses.js';
|
|
45
45
|
import { reportReasonSchema, reportTargetKindSchema } from '../feed/feed.js';
|
|
46
46
|
/**
|
|
@@ -81,14 +81,14 @@ export const moderationItemSchema = z.object({
|
|
|
81
81
|
* Its first words AS THEY ARE NOW, cut to `MODERATION_EXCERPT_MAX`: a poll's
|
|
82
82
|
* question, a product's name and tagline, a review's stars and text.
|
|
83
83
|
*/
|
|
84
|
-
excerpt: z.string(),
|
|
84
|
+
excerpt: z.string().max(MODERATION_EXCERPT_MAX),
|
|
85
85
|
/**
|
|
86
86
|
* The words as they were when first reported, when the author has edited
|
|
87
87
|
* them since (0.8.0): both are shown, so an edit can neither hide what was
|
|
88
88
|
* reported nor slip new words past a moderator judging the old ones.
|
|
89
89
|
* Absent when unedited since the report.
|
|
90
90
|
*/
|
|
91
|
-
asReported: z.string().optional(),
|
|
91
|
+
asReported: z.string().max(MODERATION_EXCERPT_MAX).optional(),
|
|
92
92
|
/** Who wrote it; for a product, its owner. */
|
|
93
93
|
author: z.object({
|
|
94
94
|
id: objectIdSchema,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"moderation.js","sourceRoot":"","sources":["../../../src/domains/moderation/moderation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * founder-schema: moderation\n *\n * GET /api/v1/moderation/queue ?limit&cursor\n * what members reported and nobody has decided on, oldest report first\n * GET /api/v1/moderation/content ?state&limit&cursor\n * by state, newest first: visible is posts and polls by when posted;\n * hidden and removed also hold comments (so a hidden comment can be\n * found and put back), by when hidden or removed\n * A decision that changes nothing (hiding what is already hidden, removing\n * what its author deleted) leaves the reports open and writes nothing: for\n * those, dismiss.\n * POST /api/v1/moderation/:contentKind/:contentId/decision { action, note? }\n * decide on one post, poll, comment, product or review; answers the\n * item as it now is\n *\n * PRODUCTS AND REVIEWS (0.6.0) are reported and decided here too. A product is\n * hidden or restored, never removed by staff (it is its team's work; hiding\n * takes it out of Discover and off every page but its team's). A review is\n * hidden, restored or removed like a comment. The hidden and removed lists\n * hold them too, so a hidden product can be found and put back.\n *\n * ONE ITEM PER THING, NOT PER REPORT. Five members reporting one post is one\n * row with five reports, so a moderator decides once. The queue's order is\n * the oldest open report first: whoever has waited longest is seen first, and\n * a pile-on cannot jump the line.\n *\n * THE DECISIONS\n * dismiss it stays up; its open reports close as dismissed\n * hide out of every feed and thread, kept, restorable; reports actioned\n * restore a hidden item goes back up\n * remove deleted as its author deleting it would (counts move), not\n * restorable from here; reports actioned\n * Every decision on someone else's content is written to the audit log, with\n * the note when there is one.\n *\n * A report's `note` was written by a member: untrusted text, shown as text.\n *\n * @module founder-schema/domains/moderation\n */\n\nimport { z } from 'zod';\nimport {\n emptyStringToUndefined,\n objectIdSchema,\n optionalTrimmedString,\n paginationQuerySchema,\n} from '../../core/common.js';\nimport { MODERATION_NOTE_MAX } from '../../core/limits.js';\nimport { paginatedSchema } from '../../core/responses.js';\nimport { type ReportTargetKind, reportReasonSchema, reportTargetKindSchema } from '../feed/feed.js';\n\n/**\n * Where something is read in the app: a post or poll, or a product page (for a\n * product, and for a review of it).\n */\nexport const MODERATION_CONTEXT_KIND_VALUES = ['post', 'poll', 'product'] as const;\nexport const moderationContextKindSchema = z.enum(MODERATION_CONTEXT_KIND_VALUES);\nexport type ModerationContextKind = z.infer<typeof moderationContextKindSchema>;\n\n/** Where a post, poll, comment, product or review stands. */\nexport const MODERATION_STATE_VALUES = ['visible', 'hidden', 'removed'] as const;\nexport const moderationStateSchema = z.enum(MODERATION_STATE_VALUES);\nexport type ModerationState = z.infer<typeof moderationStateSchema>;\n\nexport const MODERATION_ACTION_VALUES = ['dismiss', 'hide', 'restore', 'remove'] as const;\nexport const moderationActionSchema = z.enum(MODERATION_ACTION_VALUES);\nexport type ModerationAction = z.infer<typeof moderationActionSchema>;\n\n/**\n * Which decisions apply to which kind of thing: everything, except that a\n * product is never removed by staff (it is its team's work; hiding it takes it\n * out of Discover and off every page but its team's). The decision dialog\n * offers these, and the server refuses anything else with\n * `MODERATION_ACTION_INVALID`. Exhaustive by type.\n */\nexport const MODERATION_ACTIONS_BY_TARGET_KIND = {\n post: MODERATION_ACTION_VALUES,\n poll: MODERATION_ACTION_VALUES,\n comment: MODERATION_ACTION_VALUES,\n review: MODERATION_ACTION_VALUES,\n product: ['dismiss', 'hide', 'restore'],\n} as const satisfies Record<ReportTargetKind, readonly ModerationAction[]>;\n\nconst count = z.number().int().min(0);\n\n/** One post, poll, comment, product or review as moderation sees it. */\nexport const moderationItemSchema = z.object({\n target: z.object({ kind: reportTargetKindSchema, id: objectIdSchema }),\n /**\n * Where it is read in the app: the post or poll itself, or the one a comment\n * is on; the product page for a product or a review.\n */\n content: z.object({ kind: moderationContextKindSchema, id: objectIdSchema }),\n /**\n * Its first words AS THEY ARE NOW, cut to `MODERATION_EXCERPT_MAX`: a poll's\n * question, a product's name and tagline, a review's stars and text.\n */\n excerpt: z.string(),\n /**\n * The words as they were when first reported, when the author has edited\n * them since (0.8.0): both are shown, so an edit can neither hide what was\n * reported nor slip new words past a moderator judging the old ones.\n * Absent when unedited since the report.\n */\n asReported: z.string().optional(),\n /** Who wrote it; for a product, its owner. */\n author: z.object({\n id: objectIdSchema,\n displayName: z.string(),\n avatarUrl: z.url().nullable(),\n }),\n createdAt: z.iso.datetime(),\n state: moderationStateSchema,\n reports: z.object({\n /** Reports nobody has decided on. */\n open: count,\n /** Every report ever filed about it. */\n total: count,\n /** Why it was reported, among the open ones, most-given first. */\n reasons: z.array(z.object({ reason: reportReasonSchema, count })),\n /** The reporters' notes, among the open ones, newest first (a few, not all). */\n notes: z.array(z.string()),\n /** When the oldest open report was filed. Null when none is open. */\n oldestOpenAt: z.iso.datetime().nullable(),\n }),\n /** What the asking staff member may do to it now. */\n viewer: z.object({\n canDismiss: z.boolean(),\n canHide: z.boolean(),\n canRestore: z.boolean(),\n canRemove: z.boolean(),\n }),\n});\nexport type ModerationItem = z.infer<typeof moderationItemSchema>;\n\nexport const moderationPageSchema = paginatedSchema(moderationItemSchema);\nexport type ModerationPage = z.infer<typeof moderationPageSchema>;\n\n/** `GET /moderation/content`. Visible when not said. */\nexport const moderationContentQuerySchema = paginationQuerySchema.extend({\n state: z.preprocess(emptyStringToUndefined, moderationStateSchema.default('visible')),\n});\nexport type ModerationContentQuery = z.infer<typeof moderationContentQuerySchema>;\nexport type ModerationContentQueryInput = z.input<typeof moderationContentQuerySchema>;\n\n/** `POST /moderation/:contentKind/:contentId/decision`: what is decided on. */\nexport const moderationTargetParamsSchema = z.object({\n contentKind: reportTargetKindSchema,\n contentId: objectIdSchema,\n});\nexport type ModerationTargetParams = z.infer<typeof moderationTargetParamsSchema>;\n\n/** `POST /moderation/:contentKind/:contentId/decision`. */\nexport const moderationDecisionBodySchema = z.object({\n action: moderationActionSchema,\n /** Why, for the audit log. Optional: an obvious spam removal needs no essay. */\n note: optionalTrimmedString(MODERATION_NOTE_MAX),\n});\nexport type ModerationDecisionBody = z.infer<typeof moderationDecisionBodySchema>;\n"]}
|
|
1
|
+
{"version":3,"file":"moderation.js","sourceRoot":"","sources":["../../../src/domains/moderation/moderation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * founder-schema: moderation\n *\n * GET /api/v1/moderation/queue ?limit&cursor\n * what members reported and nobody has decided on, oldest report first\n * GET /api/v1/moderation/content ?state&limit&cursor\n * by state, newest first: visible is posts and polls by when posted;\n * hidden and removed also hold comments (so a hidden comment can be\n * found and put back), by when hidden or removed\n * A decision that changes nothing (hiding what is already hidden, removing\n * what its author deleted) leaves the reports open and writes nothing: for\n * those, dismiss.\n * POST /api/v1/moderation/:contentKind/:contentId/decision { action, note? }\n * decide on one post, poll, comment, product or review; answers the\n * item as it now is\n *\n * PRODUCTS AND REVIEWS (0.6.0) are reported and decided here too. A product is\n * hidden or restored, never removed by staff (it is its team's work; hiding\n * takes it out of Discover and off every page but its team's). A review is\n * hidden, restored or removed like a comment. The hidden and removed lists\n * hold them too, so a hidden product can be found and put back.\n *\n * ONE ITEM PER THING, NOT PER REPORT. Five members reporting one post is one\n * row with five reports, so a moderator decides once. The queue's order is\n * the oldest open report first: whoever has waited longest is seen first, and\n * a pile-on cannot jump the line.\n *\n * THE DECISIONS\n * dismiss it stays up; its open reports close as dismissed\n * hide out of every feed and thread, kept, restorable; reports actioned\n * restore a hidden item goes back up\n * remove deleted as its author deleting it would (counts move), not\n * restorable from here; reports actioned\n * Every decision on someone else's content is written to the audit log, with\n * the note when there is one.\n *\n * A report's `note` was written by a member: untrusted text, shown as text.\n *\n * @module founder-schema/domains/moderation\n */\n\nimport { z } from 'zod';\nimport {\n emptyStringToUndefined,\n objectIdSchema,\n optionalTrimmedString,\n paginationQuerySchema,\n} from '../../core/common.js';\nimport { MODERATION_EXCERPT_MAX, MODERATION_NOTE_MAX } from '../../core/limits.js';\nimport { paginatedSchema } from '../../core/responses.js';\nimport { type ReportTargetKind, reportReasonSchema, reportTargetKindSchema } from '../feed/feed.js';\n\n/**\n * Where something is read in the app: a post or poll, or a product page (for a\n * product, and for a review of it).\n */\nexport const MODERATION_CONTEXT_KIND_VALUES = ['post', 'poll', 'product'] as const;\nexport const moderationContextKindSchema = z.enum(MODERATION_CONTEXT_KIND_VALUES);\nexport type ModerationContextKind = z.infer<typeof moderationContextKindSchema>;\n\n/** Where a post, poll, comment, product or review stands. */\nexport const MODERATION_STATE_VALUES = ['visible', 'hidden', 'removed'] as const;\nexport const moderationStateSchema = z.enum(MODERATION_STATE_VALUES);\nexport type ModerationState = z.infer<typeof moderationStateSchema>;\n\nexport const MODERATION_ACTION_VALUES = ['dismiss', 'hide', 'restore', 'remove'] as const;\nexport const moderationActionSchema = z.enum(MODERATION_ACTION_VALUES);\nexport type ModerationAction = z.infer<typeof moderationActionSchema>;\n\n/**\n * Which decisions apply to which kind of thing: everything, except that a\n * product is never removed by staff (it is its team's work; hiding it takes it\n * out of Discover and off every page but its team's). The decision dialog\n * offers these, and the server refuses anything else with\n * `MODERATION_ACTION_INVALID`. Exhaustive by type.\n */\nexport const MODERATION_ACTIONS_BY_TARGET_KIND = {\n post: MODERATION_ACTION_VALUES,\n poll: MODERATION_ACTION_VALUES,\n comment: MODERATION_ACTION_VALUES,\n review: MODERATION_ACTION_VALUES,\n product: ['dismiss', 'hide', 'restore'],\n} as const satisfies Record<ReportTargetKind, readonly ModerationAction[]>;\n\nconst count = z.number().int().min(0);\n\n/** One post, poll, comment, product or review as moderation sees it. */\nexport const moderationItemSchema = z.object({\n target: z.object({ kind: reportTargetKindSchema, id: objectIdSchema }),\n /**\n * Where it is read in the app: the post or poll itself, or the one a comment\n * is on; the product page for a product or a review.\n */\n content: z.object({ kind: moderationContextKindSchema, id: objectIdSchema }),\n /**\n * Its first words AS THEY ARE NOW, cut to `MODERATION_EXCERPT_MAX`: a poll's\n * question, a product's name and tagline, a review's stars and text.\n */\n excerpt: z.string().max(MODERATION_EXCERPT_MAX),\n /**\n * The words as they were when first reported, when the author has edited\n * them since (0.8.0): both are shown, so an edit can neither hide what was\n * reported nor slip new words past a moderator judging the old ones.\n * Absent when unedited since the report.\n */\n asReported: z.string().max(MODERATION_EXCERPT_MAX).optional(),\n /** Who wrote it; for a product, its owner. */\n author: z.object({\n id: objectIdSchema,\n displayName: z.string(),\n avatarUrl: z.url().nullable(),\n }),\n createdAt: z.iso.datetime(),\n state: moderationStateSchema,\n reports: z.object({\n /** Reports nobody has decided on. */\n open: count,\n /** Every report ever filed about it. */\n total: count,\n /** Why it was reported, among the open ones, most-given first. */\n reasons: z.array(z.object({ reason: reportReasonSchema, count })),\n /** The reporters' notes, among the open ones, newest first (a few, not all). */\n notes: z.array(z.string()),\n /** When the oldest open report was filed. Null when none is open. */\n oldestOpenAt: z.iso.datetime().nullable(),\n }),\n /** What the asking staff member may do to it now. */\n viewer: z.object({\n canDismiss: z.boolean(),\n canHide: z.boolean(),\n canRestore: z.boolean(),\n canRemove: z.boolean(),\n }),\n});\nexport type ModerationItem = z.infer<typeof moderationItemSchema>;\n\nexport const moderationPageSchema = paginatedSchema(moderationItemSchema);\nexport type ModerationPage = z.infer<typeof moderationPageSchema>;\n\n/** `GET /moderation/content`. Visible when not said. */\nexport const moderationContentQuerySchema = paginationQuerySchema.extend({\n state: z.preprocess(emptyStringToUndefined, moderationStateSchema.default('visible')),\n});\nexport type ModerationContentQuery = z.infer<typeof moderationContentQuerySchema>;\nexport type ModerationContentQueryInput = z.input<typeof moderationContentQuerySchema>;\n\n/** `POST /moderation/:contentKind/:contentId/decision`: what is decided on. */\nexport const moderationTargetParamsSchema = z.object({\n contentKind: reportTargetKindSchema,\n contentId: objectIdSchema,\n});\nexport type ModerationTargetParams = z.infer<typeof moderationTargetParamsSchema>;\n\n/** `POST /moderation/:contentKind/:contentId/decision`. */\nexport const moderationDecisionBodySchema = z.object({\n action: moderationActionSchema,\n /** Why, for the audit log. Optional: an obvious spam removal needs no essay. */\n note: optionalTrimmedString(MODERATION_NOTE_MAX),\n});\nexport type ModerationDecisionBody = z.infer<typeof moderationDecisionBodySchema>;\n"]}
|
|
@@ -81,16 +81,7 @@ export declare const notificationKindSchema: z.ZodEnum<{
|
|
|
81
81
|
export type NotificationKind = z.infer<typeof notificationKindSchema>;
|
|
82
82
|
/** The switches a member has, each covering one or more kinds. */
|
|
83
83
|
export declare const NOTIFICATION_PREFERENCE_VALUES: readonly ["comments", "replies", "productActivity", "recognition", "reactions", "reposts", "communities"];
|
|
84
|
-
export
|
|
85
|
-
communities: "communities";
|
|
86
|
-
comments: "comments";
|
|
87
|
-
replies: "replies";
|
|
88
|
-
productActivity: "productActivity";
|
|
89
|
-
recognition: "recognition";
|
|
90
|
-
reactions: "reactions";
|
|
91
|
-
reposts: "reposts";
|
|
92
|
-
}>;
|
|
93
|
-
export type NotificationPreference = z.infer<typeof notificationPreferenceSchema>;
|
|
84
|
+
export type NotificationPreference = (typeof NOTIFICATION_PREFERENCE_VALUES)[number];
|
|
94
85
|
/**
|
|
95
86
|
* Which switch silences which kind. Null: always delivered. Exhaustive by
|
|
96
87
|
* type, so a kind added without a decision here does not compile.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../../../src/domains/notifications/notifications.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../../../src/domains/notifications/notifications.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAaxB;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,wBAAwB,+YAoB3B,CAAC;AACX,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;EAAmC,CAAC;AACvE,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,kEAAkE;AAClE,eAAO,MAAM,8BAA8B,2GAQjC,CAAC;AACX,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,8BAA8B,CAAC,CAAC,MAAM,CAAC,CAAC;AAErF;;;GAGG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;CAoBqC,CAAC;AAE7E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAyD7B,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAsC,CAAC;AAC1E,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,iBAAiB;AACjB,eAAO,MAAM,6BAA6B;;iBAExC,CAAC;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAEpF,eAAO,MAAM,wBAAwB;;iBAA+C,CAAC;AACrF,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,+CAA+C;AAC/C,eAAO,MAAM,6BAA6B;;;;;;;;iBAWxC,CAAC;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAEpF,kFAAkF;AAClF,eAAO,MAAM,uCAAuC;;;;;;;;iBAQlD,CAAC;AACH,MAAM,MAAM,iCAAiC,GAAG,CAAC,CAAC,KAAK,CACrD,OAAO,uCAAuC,CAC/C,CAAC"}
|
|
@@ -32,7 +32,7 @@ import { z } from 'zod';
|
|
|
32
32
|
import { objectIdSchema } from '../../core/common.js';
|
|
33
33
|
import { NOTIFICATION_EXCERPT_MAX } from '../../core/limits.js';
|
|
34
34
|
import { paginatedSchema } from '../../core/responses.js';
|
|
35
|
-
import { communityChipSchema } from '../communities/communities.js';
|
|
35
|
+
import { communityChipSchema, communitySuggestionDecisionSchema, } from '../communities/communities.js';
|
|
36
36
|
import { contentKindSchema, reactionTypeSchema } from '../feed/feed.js';
|
|
37
37
|
import { planTierSchema } from '../membership/membership.js';
|
|
38
38
|
import { productChipSchema, productInvitableRoleSchema } from '../products/products.js';
|
|
@@ -96,7 +96,6 @@ export const NOTIFICATION_PREFERENCE_VALUES = [
|
|
|
96
96
|
'reposts',
|
|
97
97
|
'communities',
|
|
98
98
|
];
|
|
99
|
-
export const notificationPreferenceSchema = z.enum(NOTIFICATION_PREFERENCE_VALUES);
|
|
100
99
|
/**
|
|
101
100
|
* Which switch silences which kind. Null: always delivered. Exhaustive by
|
|
102
101
|
* type, so a kind added without a decision here does not compile.
|
|
@@ -184,7 +183,7 @@ export const notificationSchema = z.object({
|
|
|
184
183
|
.object({
|
|
185
184
|
id: objectIdSchema,
|
|
186
185
|
name: z.string(),
|
|
187
|
-
status:
|
|
186
|
+
status: communitySuggestionDecisionSchema,
|
|
188
187
|
/** Why it was declined. */
|
|
189
188
|
reason: z.string().optional(),
|
|
190
189
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notifications.js","sourceRoot":"","sources":["../../../src/domains/notifications/notifications.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * founder-schema — Notifications: the bell\n *\n * The design the user approved on 2026-10-05 (\"Founder Circle Schema Review\"):\n *\n * - ONE ROW PER RECIPIENT, written when the event happens.\n * - REPEATS MERGE: a second comment on your post updates the same row\n * (\"2 new comments, latest from Asha\"), it never adds one. `count` is how\n * many events it holds and `actor` the latest. A member repeating the same\n * act (reacting, taking it back, reacting again) does not ring it again.\n * - THE ACTOR IS LOOKED UP WHEN READ, never copied in: a renamed member shows\n * their new name, and a deleted one shows as null (\"A former member\").\n * - PREFERENCES ARE CHECKED before writing (Jansathi stores them and never\n * reads them). A team invitation is always delivered: it needs an answer.\n * - KEPT `NOTIFICATION_RETENTION_DAYS`, then deleted.\n * - Nobody is notified of their own action.\n *\n * In-app only. Push stays chat's (async-service) until a channel is designed:\n * a client polls the unread count (on focus, and every minute while visible).\n *\n * Routes (all signed in):\n * GET /api/v1/notifications paginationQuerySchema -> notificationPageSchema\n * GET /api/v1/notifications/unread-count -> notificationUnreadCountSchema\n * POST /api/v1/notifications/read mark every one read -> notificationUnreadCountSchema\n * PUT /api/v1/notifications/:notificationId/read -> notificationSchema\n * GET /api/v1/notifications/preferences -> notificationPreferencesSchema\n * PUT /api/v1/notifications/preferences updateNotificationPreferencesBodySchema -> notificationPreferencesSchema\n *\n * @module founder-schema/domains/notifications\n */\n\nimport { z } from 'zod';\nimport { objectIdSchema } from '../../core/common.js';\nimport { NOTIFICATION_EXCERPT_MAX } from '../../core/limits.js';\nimport { paginatedSchema } from '../../core/responses.js';\nimport { communityChipSchema } from '../communities/communities.js';\nimport { contentKindSchema, reactionTypeSchema } from '../feed/feed.js';\nimport { planTierSchema } from '../membership/membership.js';\nimport { productChipSchema, productInvitableRoleSchema } from '../products/products.js';\nimport { memberBylineSchema } from '../profile/founder-profile.js';\n\n/**\n * What happened. ⚠ Stored per row: append only.\n *\n * comment_on_post someone commented on your post or poll\n * reply_to_comment someone replied to your comment\n * product_invite a team invited you (always delivered)\n * product_invite_accepted someone accepted your team's invitation\n * product_review someone reviewed a product you are on the team of\n * review_reply a product's team answered your review\n * feedback_helpful a team marked your feedback as having helped\n * tester_confirmed a team confirmed you tested their product\n * post_reaction someone reacted to your post or poll (0.8.0)\n * comment_reaction someone reacted to your comment (0.8.0)\n * repost someone reposted your post or poll (0.8.0)\n * community_join_request someone asked to join a community you moderate (0.9.0)\n * community_request_approved your request to join was approved (always delivered)\n * community_invite a community invited you (always delivered)\n * community_announcement a community you are in pinned an announcement for everyone\n * community_suggestion_decided your community suggestion was approved or declined (always delivered)\n * plan_ending your plan ends in 7 days, then in 1 day (0.12.0, always delivered)\n * plan_ended your plan ended; `paused` products were paused (0.12.0, always delivered)\n * payment_refunded staff refunded one of your payments (0.12.0, always delivered)\n *\n * The three 0.8.0 kinds merge per target like the others. A reaction counts\n * once: changing it to another type is not a new event, and taking it back\n * does not take the event back.\n */\nexport const NOTIFICATION_KIND_VALUES = [\n 'comment_on_post',\n 'reply_to_comment',\n 'product_invite',\n 'product_invite_accepted',\n 'product_review',\n 'review_reply',\n 'feedback_helpful',\n 'tester_confirmed',\n 'post_reaction',\n 'comment_reaction',\n 'repost',\n 'community_join_request',\n 'community_request_approved',\n 'community_invite',\n 'community_announcement',\n 'community_suggestion_decided',\n 'plan_ending',\n 'plan_ended',\n 'payment_refunded',\n] as const;\nexport const notificationKindSchema = z.enum(NOTIFICATION_KIND_VALUES);\nexport type NotificationKind = z.infer<typeof notificationKindSchema>;\n\n/** The switches a member has, each covering one or more kinds. */\nexport const NOTIFICATION_PREFERENCE_VALUES = [\n 'comments',\n 'replies',\n 'productActivity',\n 'recognition',\n 'reactions',\n 'reposts',\n 'communities',\n] as const;\nexport const notificationPreferenceSchema = z.enum(NOTIFICATION_PREFERENCE_VALUES);\nexport type NotificationPreference = z.infer<typeof notificationPreferenceSchema>;\n\n/**\n * Which switch silences which kind. Null: always delivered. Exhaustive by\n * type, so a kind added without a decision here does not compile.\n */\nexport const NOTIFICATION_PREFERENCE_OF = {\n comment_on_post: 'comments',\n reply_to_comment: 'replies',\n product_invite: null,\n product_invite_accepted: 'productActivity',\n product_review: 'productActivity',\n review_reply: 'productActivity',\n feedback_helpful: 'recognition',\n tester_confirmed: 'recognition',\n post_reaction: 'reactions',\n comment_reaction: 'reactions',\n repost: 'reposts',\n community_join_request: 'communities',\n community_request_approved: null,\n community_invite: null,\n community_announcement: 'communities',\n community_suggestion_decided: null,\n plan_ending: null,\n plan_ended: null,\n payment_refunded: null,\n} as const satisfies Record<NotificationKind, NotificationPreference | null>;\n\n/**\n * One row of the bell. Which of the optional targets are present depends on\n * `kind`:\n *\n * comment_on_post content, commentId\n * reply_to_comment content, commentId (the reply)\n * product_invite product, role\n * product_invite_accepted product\n * product_review product, reviewId\n * review_reply product, reviewId\n * feedback_helpful product, content, commentId\n * tester_confirmed product\n * post_reaction content, reaction\n * comment_reaction content, commentId, reaction, excerpt (your comment)\n * repost content (yours, the one reposted), repostId (the latest repost, to read their words)\n * community_join_request community\n * community_request_approved community\n * community_invite community\n * community_announcement community, content (the pinned post or poll)\n * community_suggestion_decided suggestion, community (once approved)\n * plan_ending plan (the tier, and when it ends)\n * plan_ended plan (the tier that ended), paused (how many products)\n * payment_refunded payment\n *\n * Any row about something inside a community also carries `community`\n * (0.9.0), whatever its kind. When the recipient leaves the community, is\n * removed or is banned, its rows about that community lose their content,\n * comment, excerpt and repost: what they could read there, they no longer can.\n *\n * A target that no longer exists (a deleted post, product or review) is\n * absent rather than pointing at a 404; the row still says what happened.\n */\nexport const notificationSchema = z.object({\n id: objectIdSchema,\n kind: notificationKindSchema,\n /** The latest person to do it, live; null for a deleted account. */\n actor: memberBylineSchema.nullable(),\n /**\n * How many EVENTS this row merges, at least 1: three comments by one person\n * are 3. Word it as events (\"3 new comments, latest from Asha\"), never as\n * people (\"Asha and 2 others\"), which this count does not know.\n */\n count: z.number().int().positive(),\n content: z.object({ kind: contentKindSchema, id: objectIdSchema }).optional(),\n commentId: objectIdSchema.optional(),\n product: productChipSchema.optional(),\n reviewId: objectIdSchema.optional(),\n /**\n * For `repost` (0.8.0): the latest repost itself, so the row opens the\n * reposter's words above your post. Gone once that repost is.\n */\n repostId: objectIdSchema.optional(),\n /**\n * The community the row is about, or that its content is in (0.9.0). Absent\n * once that community is deleted, or the recipient may no longer see it.\n */\n community: communityChipSchema.optional(),\n /** For `community_suggestion_decided` (0.9.0): which suggestion, and how it went. */\n suggestion: z\n .object({\n id: objectIdSchema,\n name: z.string(),\n status: z.enum(['approved', 'declined']),\n /** Why it was declined. */\n reason: z.string().optional(),\n })\n .optional(),\n /** For `plan_ending` and `plan_ended` (0.12.0): which tier, and when it ends or ended. */\n plan: z.object({ tier: planTierSchema, endsAt: z.iso.datetime() }).optional(),\n /** For `plan_ended` (0.12.0): products paused because the plan's live places went. */\n paused: z.number().int().nonnegative().optional(),\n /** For `payment_refunded` (0.12.0): which purchase, by its title. */\n payment: z.object({ id: objectIdSchema, title: z.string() }).optional(),\n /** For `product_invite`: the role offered. */\n role: productInvitableRoleSchema.optional(),\n /** For the reaction kinds: the latest reaction, as it is now (0.8.0). */\n reaction: reactionTypeSchema.optional(),\n /**\n * The first words of what was written, for the comment and review kinds\n * (the latest one, on a merged row), cut to `NOTIFICATION_EXCERPT_MAX`. Gone\n * when that comment or review is deleted or hidden, and when its writer's\n * account is.\n */\n excerpt: z.string().max(NOTIFICATION_EXCERPT_MAX).optional(),\n /** Null until opened (or until \"mark all read\"). A merged repeat makes it unread again. */\n readAt: z.iso.datetime().nullable(),\n /** When it last happened: the list's order. */\n lastAt: z.iso.datetime(),\n createdAt: z.iso.datetime(),\n});\nexport type Notification = z.infer<typeof notificationSchema>;\n\nexport const notificationPageSchema = paginatedSchema(notificationSchema);\nexport type NotificationPage = z.infer<typeof notificationPageSchema>;\n\n/** The badge. */\nexport const notificationUnreadCountSchema = z.object({\n unread: z.number().int().nonnegative(),\n});\nexport type NotificationUnreadCount = z.infer<typeof notificationUnreadCountSchema>;\n\nexport const notificationParamsSchema = z.object({ notificationId: objectIdSchema });\nexport type NotificationParams = z.infer<typeof notificationParamsSchema>;\n\n/** Every switch, as stored (on by default). */\nexport const notificationPreferencesSchema = z.object({\n comments: z.boolean(),\n replies: z.boolean(),\n productActivity: z.boolean(),\n recognition: z.boolean(),\n /** Reactions to your posts, polls and comments (0.8.0). */\n reactions: z.boolean(),\n /** Reposts of your posts and polls (0.8.0). */\n reposts: z.boolean(),\n /** Announcements in your communities, and join requests to communities you moderate (0.9.0). */\n communities: z.boolean(),\n});\nexport type NotificationPreferences = z.infer<typeof notificationPreferencesSchema>;\n\n/** Only the switches that changed; no defaults (a patch states what was sent). */\nexport const updateNotificationPreferencesBodySchema = z.object({\n comments: z.boolean().optional(),\n replies: z.boolean().optional(),\n productActivity: z.boolean().optional(),\n recognition: z.boolean().optional(),\n reactions: z.boolean().optional(),\n reposts: z.boolean().optional(),\n communities: z.boolean().optional(),\n});\nexport type UpdateNotificationPreferencesBody = z.infer<\n typeof updateNotificationPreferencesBodySchema\n>;\n"]}
|
|
1
|
+
{"version":3,"file":"notifications.js","sourceRoot":"","sources":["../../../src/domains/notifications/notifications.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * founder-schema — Notifications: the bell\n *\n * The design the user approved on 2026-10-05 (\"Founder Circle Schema Review\"):\n *\n * - ONE ROW PER RECIPIENT, written when the event happens.\n * - REPEATS MERGE: a second comment on your post updates the same row\n * (\"2 new comments, latest from Asha\"), it never adds one. `count` is how\n * many events it holds and `actor` the latest. A member repeating the same\n * act (reacting, taking it back, reacting again) does not ring it again.\n * - THE ACTOR IS LOOKED UP WHEN READ, never copied in: a renamed member shows\n * their new name, and a deleted one shows as null (\"A former member\").\n * - PREFERENCES ARE CHECKED before writing (Jansathi stores them and never\n * reads them). A team invitation is always delivered: it needs an answer.\n * - KEPT `NOTIFICATION_RETENTION_DAYS`, then deleted.\n * - Nobody is notified of their own action.\n *\n * In-app only. Push stays chat's (async-service) until a channel is designed:\n * a client polls the unread count (on focus, and every minute while visible).\n *\n * Routes (all signed in):\n * GET /api/v1/notifications paginationQuerySchema -> notificationPageSchema\n * GET /api/v1/notifications/unread-count -> notificationUnreadCountSchema\n * POST /api/v1/notifications/read mark every one read -> notificationUnreadCountSchema\n * PUT /api/v1/notifications/:notificationId/read -> notificationSchema\n * GET /api/v1/notifications/preferences -> notificationPreferencesSchema\n * PUT /api/v1/notifications/preferences updateNotificationPreferencesBodySchema -> notificationPreferencesSchema\n *\n * @module founder-schema/domains/notifications\n */\n\nimport { z } from 'zod';\nimport { objectIdSchema } from '../../core/common.js';\nimport { NOTIFICATION_EXCERPT_MAX } from '../../core/limits.js';\nimport { paginatedSchema } from '../../core/responses.js';\nimport {\n communityChipSchema,\n communitySuggestionDecisionSchema,\n} from '../communities/communities.js';\nimport { contentKindSchema, reactionTypeSchema } from '../feed/feed.js';\nimport { planTierSchema } from '../membership/membership.js';\nimport { productChipSchema, productInvitableRoleSchema } from '../products/products.js';\nimport { memberBylineSchema } from '../profile/founder-profile.js';\n\n/**\n * What happened. ⚠ Stored per row: append only.\n *\n * comment_on_post someone commented on your post or poll\n * reply_to_comment someone replied to your comment\n * product_invite a team invited you (always delivered)\n * product_invite_accepted someone accepted your team's invitation\n * product_review someone reviewed a product you are on the team of\n * review_reply a product's team answered your review\n * feedback_helpful a team marked your feedback as having helped\n * tester_confirmed a team confirmed you tested their product\n * post_reaction someone reacted to your post or poll (0.8.0)\n * comment_reaction someone reacted to your comment (0.8.0)\n * repost someone reposted your post or poll (0.8.0)\n * community_join_request someone asked to join a community you moderate (0.9.0)\n * community_request_approved your request to join was approved (always delivered)\n * community_invite a community invited you (always delivered)\n * community_announcement a community you are in pinned an announcement for everyone\n * community_suggestion_decided your community suggestion was approved or declined (always delivered)\n * plan_ending your plan ends in 7 days, then in 1 day (0.12.0, always delivered)\n * plan_ended your plan ended; `paused` products were paused (0.12.0, always delivered)\n * payment_refunded staff refunded one of your payments (0.12.0, always delivered)\n *\n * The three 0.8.0 kinds merge per target like the others. A reaction counts\n * once: changing it to another type is not a new event, and taking it back\n * does not take the event back.\n */\nexport const NOTIFICATION_KIND_VALUES = [\n 'comment_on_post',\n 'reply_to_comment',\n 'product_invite',\n 'product_invite_accepted',\n 'product_review',\n 'review_reply',\n 'feedback_helpful',\n 'tester_confirmed',\n 'post_reaction',\n 'comment_reaction',\n 'repost',\n 'community_join_request',\n 'community_request_approved',\n 'community_invite',\n 'community_announcement',\n 'community_suggestion_decided',\n 'plan_ending',\n 'plan_ended',\n 'payment_refunded',\n] as const;\nexport const notificationKindSchema = z.enum(NOTIFICATION_KIND_VALUES);\nexport type NotificationKind = z.infer<typeof notificationKindSchema>;\n\n/** The switches a member has, each covering one or more kinds. */\nexport const NOTIFICATION_PREFERENCE_VALUES = [\n 'comments',\n 'replies',\n 'productActivity',\n 'recognition',\n 'reactions',\n 'reposts',\n 'communities',\n] as const;\nexport type NotificationPreference = (typeof NOTIFICATION_PREFERENCE_VALUES)[number];\n\n/**\n * Which switch silences which kind. Null: always delivered. Exhaustive by\n * type, so a kind added without a decision here does not compile.\n */\nexport const NOTIFICATION_PREFERENCE_OF = {\n comment_on_post: 'comments',\n reply_to_comment: 'replies',\n product_invite: null,\n product_invite_accepted: 'productActivity',\n product_review: 'productActivity',\n review_reply: 'productActivity',\n feedback_helpful: 'recognition',\n tester_confirmed: 'recognition',\n post_reaction: 'reactions',\n comment_reaction: 'reactions',\n repost: 'reposts',\n community_join_request: 'communities',\n community_request_approved: null,\n community_invite: null,\n community_announcement: 'communities',\n community_suggestion_decided: null,\n plan_ending: null,\n plan_ended: null,\n payment_refunded: null,\n} as const satisfies Record<NotificationKind, NotificationPreference | null>;\n\n/**\n * One row of the bell. Which of the optional targets are present depends on\n * `kind`:\n *\n * comment_on_post content, commentId\n * reply_to_comment content, commentId (the reply)\n * product_invite product, role\n * product_invite_accepted product\n * product_review product, reviewId\n * review_reply product, reviewId\n * feedback_helpful product, content, commentId\n * tester_confirmed product\n * post_reaction content, reaction\n * comment_reaction content, commentId, reaction, excerpt (your comment)\n * repost content (yours, the one reposted), repostId (the latest repost, to read their words)\n * community_join_request community\n * community_request_approved community\n * community_invite community\n * community_announcement community, content (the pinned post or poll)\n * community_suggestion_decided suggestion, community (once approved)\n * plan_ending plan (the tier, and when it ends)\n * plan_ended plan (the tier that ended), paused (how many products)\n * payment_refunded payment\n *\n * Any row about something inside a community also carries `community`\n * (0.9.0), whatever its kind. When the recipient leaves the community, is\n * removed or is banned, its rows about that community lose their content,\n * comment, excerpt and repost: what they could read there, they no longer can.\n *\n * A target that no longer exists (a deleted post, product or review) is\n * absent rather than pointing at a 404; the row still says what happened.\n */\nexport const notificationSchema = z.object({\n id: objectIdSchema,\n kind: notificationKindSchema,\n /** The latest person to do it, live; null for a deleted account. */\n actor: memberBylineSchema.nullable(),\n /**\n * How many EVENTS this row merges, at least 1: three comments by one person\n * are 3. Word it as events (\"3 new comments, latest from Asha\"), never as\n * people (\"Asha and 2 others\"), which this count does not know.\n */\n count: z.number().int().positive(),\n content: z.object({ kind: contentKindSchema, id: objectIdSchema }).optional(),\n commentId: objectIdSchema.optional(),\n product: productChipSchema.optional(),\n reviewId: objectIdSchema.optional(),\n /**\n * For `repost` (0.8.0): the latest repost itself, so the row opens the\n * reposter's words above your post. Gone once that repost is.\n */\n repostId: objectIdSchema.optional(),\n /**\n * The community the row is about, or that its content is in (0.9.0). Absent\n * once that community is deleted, or the recipient may no longer see it.\n */\n community: communityChipSchema.optional(),\n /** For `community_suggestion_decided` (0.9.0): which suggestion, and how it went. */\n suggestion: z\n .object({\n id: objectIdSchema,\n name: z.string(),\n status: communitySuggestionDecisionSchema,\n /** Why it was declined. */\n reason: z.string().optional(),\n })\n .optional(),\n /** For `plan_ending` and `plan_ended` (0.12.0): which tier, and when it ends or ended. */\n plan: z.object({ tier: planTierSchema, endsAt: z.iso.datetime() }).optional(),\n /** For `plan_ended` (0.12.0): products paused because the plan's live places went. */\n paused: z.number().int().nonnegative().optional(),\n /** For `payment_refunded` (0.12.0): which purchase, by its title. */\n payment: z.object({ id: objectIdSchema, title: z.string() }).optional(),\n /** For `product_invite`: the role offered. */\n role: productInvitableRoleSchema.optional(),\n /** For the reaction kinds: the latest reaction, as it is now (0.8.0). */\n reaction: reactionTypeSchema.optional(),\n /**\n * The first words of what was written, for the comment and review kinds\n * (the latest one, on a merged row), cut to `NOTIFICATION_EXCERPT_MAX`. Gone\n * when that comment or review is deleted or hidden, and when its writer's\n * account is.\n */\n excerpt: z.string().max(NOTIFICATION_EXCERPT_MAX).optional(),\n /** Null until opened (or until \"mark all read\"). A merged repeat makes it unread again. */\n readAt: z.iso.datetime().nullable(),\n /** When it last happened: the list's order. */\n lastAt: z.iso.datetime(),\n createdAt: z.iso.datetime(),\n});\nexport type Notification = z.infer<typeof notificationSchema>;\n\nexport const notificationPageSchema = paginatedSchema(notificationSchema);\nexport type NotificationPage = z.infer<typeof notificationPageSchema>;\n\n/** The badge. */\nexport const notificationUnreadCountSchema = z.object({\n unread: z.number().int().nonnegative(),\n});\nexport type NotificationUnreadCount = z.infer<typeof notificationUnreadCountSchema>;\n\nexport const notificationParamsSchema = z.object({ notificationId: objectIdSchema });\nexport type NotificationParams = z.infer<typeof notificationParamsSchema>;\n\n/** Every switch, as stored (on by default). */\nexport const notificationPreferencesSchema = z.object({\n comments: z.boolean(),\n replies: z.boolean(),\n productActivity: z.boolean(),\n recognition: z.boolean(),\n /** Reactions to your posts, polls and comments (0.8.0). */\n reactions: z.boolean(),\n /** Reposts of your posts and polls (0.8.0). */\n reposts: z.boolean(),\n /** Announcements in your communities, and join requests to communities you moderate (0.9.0). */\n communities: z.boolean(),\n});\nexport type NotificationPreferences = z.infer<typeof notificationPreferencesSchema>;\n\n/** Only the switches that changed; no defaults (a patch states what was sent). */\nexport const updateNotificationPreferencesBodySchema = z.object({\n comments: z.boolean().optional(),\n replies: z.boolean().optional(),\n productActivity: z.boolean().optional(),\n recognition: z.boolean().optional(),\n reactions: z.boolean().optional(),\n reposts: z.boolean().optional(),\n communities: z.boolean().optional(),\n});\nexport type UpdateNotificationPreferencesBody = z.infer<\n typeof updateNotificationPreferencesBodySchema\n>;\n"]}
|