dating-schema 0.31.0 → 0.32.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/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/plan-limits.d.ts +38 -12
- package/dist/plan-limits.d.ts.map +1 -1
- package/dist/plan-limits.js +144 -35
- package/dist/plan-limits.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
export { type AgeRange, ageRangeSchema, emptyStringToUndefined, type Gender, genderSchema, type InterestedIn, interestedInSchema, type LookingFor, lookingForSchema, type MaritalStatus, type MatchStatus, type MessageType, maritalStatusSchema, matchStatusSchema, messageTypeSchema, optionalTrimmedString, type Pagination, type Photo, paginationSchema, photoSchema, type SwipeAction, swipeActionSchema, } from './common.js';
|
|
10
10
|
export { getFieldOptions } from './field-helpers.js';
|
|
11
11
|
export { type BoostBody, boostBodySchema, type ComplimentBody, complimentBodySchema, type ImageLikeBody, type InteractionListQuery, type InteractionType, imageLikeBodySchema, interactionListQuerySchema, interactionTypeSchema, type RewindBody, rewindBodySchema, type SwipeBody, type SwipeResponse, swipeBodySchema, swipeResponseSchema, } from './interactions.js';
|
|
12
|
-
export { type BooleanFeatureKey, type EnumFeatureKey, type FeatureKey, type FilterLevel, getMinPlanForFeature, getPlanLimit, getPlanLimits, hasRemainingQuota, isFeatureEnabled, type NumericFeatureKey, PLAN_IDS, PLAN_LIMITS, type PlanId, type PlanLimits, type WhoLikedYouLevel, } from './plan-limits.js';
|
|
12
|
+
export { type BooleanFeatureKey, type EnumFeatureKey, type ExploreAccessLevel, type FeatureKey, type FilterLevel, getMinPlanForFeature, getPlanLimit, getPlanLimits, hasRemainingQuota, isFeatureEnabled, isPaidPlan, type NumericFeatureKey, PAID_PLANS, PLAN_IDS, PLAN_LIMITS, type PlanId, type PlanLimits, PREMIUM_EXPLORE_CATEGORIES, PREMIUM_PLANS, type ScoreBreakdownLevel, TOP_PLANS, type WhoLikedYouLevel, } from './plan-limits.js';
|
|
13
13
|
export { type CreateProfileInput, createProfileSchema, type FullProfileData, fullProfileSchema, getCognitiveBandRank, type OnboardingFormData, onboardingFormSchema, type UpdateProfileInput, updateProfileSchema, } from './profile.js';
|
|
14
14
|
export { allFieldGroups, basics, career, cognitive, type FieldGroup, type FieldOption, familyHome, favourites, financeLegal, healthWellness, heroIdentity, interestCategories, interests, lifestyle, lookingFor, type MultiSelectField, type OptionCategory, type ProfileField, personality, relationshipIntimacy, type SelectField, selfAssessment, storyPrompts, values, } from './profile-fields/index.js';
|
|
15
15
|
export { type BlockBody, blockBodySchema, type ReportBody, type ReportReason, type ReportStatus, reportBodySchema, reportReasonSchema, reportStatusSchema, } from './safety.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EACL,KAAK,QAAQ,EAEb,cAAc,EACd,sBAAsB,EACtB,KAAK,MAAM,EAEX,YAAY,EACZ,KAAK,YAAY,EACjB,kBAAkB,EAClB,KAAK,UAAU,EACf,gBAAgB,EAChB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,KAAK,UAAU,EACf,KAAK,KAAK,EACV,gBAAgB,EAChB,WAAW,EACX,KAAK,WAAW,EAChB,iBAAiB,GAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,EACL,KAAK,SAAS,EACd,eAAe,EACf,KAAK,cAAc,EACnB,oBAAoB,EACpB,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,mBAAmB,EACnB,0BAA0B,EAC1B,qBAAqB,EACrB,KAAK,UAAU,EACf,gBAAgB,EAChB,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,eAAe,EACf,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,oBAAoB,EACpB,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,KAAK,iBAAiB,EACtB,QAAQ,EACR,WAAW,EACX,KAAK,MAAM,EACX,KAAK,UAAU,EACf,KAAK,gBAAgB,GACtB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,KAAK,kBAAkB,EACvB,mBAAmB,EACnB,KAAK,eAAe,EACpB,iBAAiB,EACjB,oBAAoB,EACpB,KAAK,kBAAkB,EACvB,oBAAoB,EACpB,KAAK,kBAAkB,EACvB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,cAAc,EACd,MAAM,EACN,MAAM,EACN,SAAS,EACT,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,UAAU,EACV,UAAU,EACV,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,kBAAkB,EAClB,SAAS,EACT,SAAS,EACT,UAAU,EACV,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,WAAW,EACX,oBAAoB,EACpB,KAAK,WAAW,EAChB,cAAc,EACd,YAAY,EACZ,MAAM,GACP,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EACL,KAAK,SAAS,EACd,eAAe,EACf,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,KAAK,sBAAsB,EAC3B,4BAA4B,EAC5B,KAAK,kBAAkB,EACvB,wBAAwB,EACxB,KAAK,MAAM,EACX,YAAY,GACb,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EACL,KAAK,QAAQ,EAEb,cAAc,EACd,sBAAsB,EACtB,KAAK,MAAM,EAEX,YAAY,EACZ,KAAK,YAAY,EACjB,kBAAkB,EAClB,KAAK,UAAU,EACf,gBAAgB,EAChB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,KAAK,UAAU,EACf,KAAK,KAAK,EACV,gBAAgB,EAChB,WAAW,EACX,KAAK,WAAW,EAChB,iBAAiB,GAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,EACL,KAAK,SAAS,EACd,eAAe,EACf,KAAK,cAAc,EACnB,oBAAoB,EACpB,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,mBAAmB,EACnB,0BAA0B,EAC1B,qBAAqB,EACrB,KAAK,UAAU,EACf,gBAAgB,EAChB,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,eAAe,EACf,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,oBAAoB,EACpB,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACV,KAAK,iBAAiB,EACtB,UAAU,EACV,QAAQ,EACR,WAAW,EACX,KAAK,MAAM,EACX,KAAK,UAAU,EACf,0BAA0B,EAC1B,aAAa,EACb,KAAK,mBAAmB,EACxB,SAAS,EACT,KAAK,gBAAgB,GACtB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,KAAK,kBAAkB,EACvB,mBAAmB,EACnB,KAAK,eAAe,EACpB,iBAAiB,EACjB,oBAAoB,EACpB,KAAK,kBAAkB,EACvB,oBAAoB,EACpB,KAAK,kBAAkB,EACvB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,cAAc,EACd,MAAM,EACN,MAAM,EACN,SAAS,EACT,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,UAAU,EACV,UAAU,EACV,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,kBAAkB,EAClB,SAAS,EACT,SAAS,EACT,UAAU,EACV,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,WAAW,EACX,oBAAoB,EACpB,KAAK,WAAW,EAChB,cAAc,EACd,YAAY,EACZ,MAAM,GACP,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EACL,KAAK,SAAS,EACd,eAAe,EACf,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,KAAK,sBAAsB,EAC3B,4BAA4B,EAC5B,KAAK,kBAAkB,EACvB,wBAAwB,EACxB,KAAK,MAAM,EACX,YAAY,GACb,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -16,7 +16,7 @@ export { getFieldOptions } from './field-helpers.js';
|
|
|
16
16
|
// ─── Interaction schemas ─────────────────────────────────────────────────────
|
|
17
17
|
export { boostBodySchema, complimentBodySchema, imageLikeBodySchema, interactionListQuerySchema, interactionTypeSchema, rewindBodySchema, swipeBodySchema, swipeResponseSchema, } from './interactions.js';
|
|
18
18
|
// ─── Plan limits ─────────────────────────────────────────────────────────────
|
|
19
|
-
export { getMinPlanForFeature, getPlanLimit, getPlanLimits, hasRemainingQuota, isFeatureEnabled, PLAN_IDS, PLAN_LIMITS, } from './plan-limits.js';
|
|
19
|
+
export { getMinPlanForFeature, getPlanLimit, getPlanLimits, hasRemainingQuota, isFeatureEnabled, isPaidPlan, PAID_PLANS, PLAN_IDS, PLAN_LIMITS, PREMIUM_EXPLORE_CATEGORIES, PREMIUM_PLANS, TOP_PLANS, } from './plan-limits.js';
|
|
20
20
|
// ─── Profile schemas ─────────────────────────────────────────────────────────
|
|
21
21
|
export { createProfileSchema, fullProfileSchema, getCognitiveBandRank, onboardingFormSchema, updateProfileSchema, } from './profile.js';
|
|
22
22
|
// ─── Profile field configs (option arrays with labels for UI rendering) ──────
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,gFAAgF;AAChF,OAAO;AAEL,cAAc;AACd,cAAc,EACd,sBAAsB;AAEtB,QAAQ;AACR,YAAY,EAEZ,kBAAkB,EAElB,gBAAgB,EAIhB,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EAGrB,gBAAgB,EAChB,WAAW,EAEX,iBAAiB,GAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,gFAAgF;AAChF,OAAO,EAEL,eAAe,EAEf,oBAAoB,EAIpB,mBAAmB,EACnB,0BAA0B,EAC1B,qBAAqB,EAErB,gBAAgB,EAGhB,eAAe,EACf,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAC3B,gFAAgF;AAChF,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,gFAAgF;AAChF,OAAO;AAEL,cAAc;AACd,cAAc,EACd,sBAAsB;AAEtB,QAAQ;AACR,YAAY,EAEZ,kBAAkB,EAElB,gBAAgB,EAIhB,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EAGrB,gBAAgB,EAChB,WAAW,EAEX,iBAAiB,GAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,gFAAgF;AAChF,OAAO,EAEL,eAAe,EAEf,oBAAoB,EAIpB,mBAAmB,EACnB,0BAA0B,EAC1B,qBAAqB,EAErB,gBAAgB,EAGhB,eAAe,EACf,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAC3B,gFAAgF;AAChF,OAAO,EAML,oBAAoB,EACpB,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EAEV,UAAU,EACV,QAAQ,EACR,WAAW,EAGX,0BAA0B,EAC1B,aAAa,EAEb,SAAS,GAEV,MAAM,kBAAkB,CAAC;AAC1B,gFAAgF;AAChF,OAAO,EAEL,mBAAmB,EAEnB,iBAAiB,EACjB,oBAAoB,EAEpB,oBAAoB,EAEpB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AACtB,gFAAgF;AAChF,OAAO,EACL,cAAc,EACd,MAAM,EACN,MAAM,EACN,SAAS,EAGT,UAAU,EACV,UAAU,EACV,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,kBAAkB,EAClB,SAAS,EACT,SAAS,EACT,UAAU,EAIV,WAAW,EACX,oBAAoB,EAEpB,cAAc,EACd,YAAY,EACZ,MAAM,GACP,MAAM,2BAA2B,CAAC;AAEnC,gFAAgF;AAChF,OAAO,EAEL,eAAe,EAIf,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAErB,gFAAgF;AAChF,OAAO,EAEL,4BAA4B,EAE5B,wBAAwB,EAExB,YAAY,GACb,MAAM,mBAAmB,CAAC","sourcesContent":["/**\n * dating-schema — Shared Zod schemas for the Dating feature\n *\n * Single source of truth consumed by both jansathi-frontend and reform-backend.\n * Guarantees identical validation logic and TypeScript types on both sides.\n *\n * @module dating-schema\n */\n\n// ─── Common helpers and enums ────────────────────────────────────────────────\nexport {\n type AgeRange,\n // sub-schemas\n ageRangeSchema,\n emptyStringToUndefined,\n type Gender,\n // enums\n genderSchema,\n type InterestedIn,\n interestedInSchema,\n type LookingFor,\n lookingForSchema,\n type MaritalStatus,\n type MatchStatus,\n type MessageType,\n maritalStatusSchema,\n matchStatusSchema,\n messageTypeSchema,\n optionalTrimmedString,\n type Pagination,\n type Photo,\n paginationSchema,\n photoSchema,\n type SwipeAction,\n swipeActionSchema,\n} from './common.js';\nexport { getFieldOptions } from './field-helpers.js';\n// ─── Interaction schemas ─────────────────────────────────────────────────────\nexport {\n type BoostBody,\n boostBodySchema,\n type ComplimentBody,\n complimentBodySchema,\n type ImageLikeBody,\n type InteractionListQuery,\n type InteractionType,\n imageLikeBodySchema,\n interactionListQuerySchema,\n interactionTypeSchema,\n type RewindBody,\n rewindBodySchema,\n type SwipeBody,\n type SwipeResponse,\n swipeBodySchema,\n swipeResponseSchema,\n} from './interactions.js';\n// ─── Plan limits ─────────────────────────────────────────────────────────────\nexport {\n type BooleanFeatureKey,\n type EnumFeatureKey,\n type ExploreAccessLevel,\n type FeatureKey,\n type FilterLevel,\n getMinPlanForFeature,\n getPlanLimit,\n getPlanLimits,\n hasRemainingQuota,\n isFeatureEnabled,\n isPaidPlan,\n type NumericFeatureKey,\n PAID_PLANS,\n PLAN_IDS,\n PLAN_LIMITS,\n type PlanId,\n type PlanLimits,\n PREMIUM_EXPLORE_CATEGORIES,\n PREMIUM_PLANS,\n type ScoreBreakdownLevel,\n TOP_PLANS,\n type WhoLikedYouLevel,\n} from './plan-limits.js';\n// ─── Profile schemas ─────────────────────────────────────────────────────────\nexport {\n type CreateProfileInput,\n createProfileSchema,\n type FullProfileData,\n fullProfileSchema,\n getCognitiveBandRank,\n type OnboardingFormData,\n onboardingFormSchema,\n type UpdateProfileInput,\n updateProfileSchema,\n} from './profile.js';\n// ─── Profile field configs (option arrays with labels for UI rendering) ──────\nexport {\n allFieldGroups,\n basics,\n career,\n cognitive,\n type FieldGroup,\n type FieldOption,\n familyHome,\n favourites,\n financeLegal,\n healthWellness,\n heroIdentity,\n interestCategories,\n interests,\n lifestyle,\n lookingFor,\n type MultiSelectField,\n type OptionCategory,\n type ProfileField,\n personality,\n relationshipIntimacy,\n type SelectField,\n selfAssessment,\n storyPrompts,\n values,\n} from './profile-fields/index.js';\n\n// ─── Safety schemas ──────────────────────────────────────────────────────────\nexport {\n type BlockBody,\n blockBodySchema,\n type ReportBody,\n type ReportReason,\n type ReportStatus,\n reportBodySchema,\n reportReasonSchema,\n reportStatusSchema,\n} from './safety.js';\n\n// ─── Subscription schemas ────────────────────────────────────────────────────\nexport {\n type CreateSubscriptionBody,\n createSubscriptionBodySchema,\n type SubscriptionStatus,\n subscriptionStatusSchema,\n type Tenure,\n tenureSchema,\n} from './subscription.js';\n"]}
|
package/dist/plan-limits.d.ts
CHANGED
|
@@ -7,23 +7,27 @@
|
|
|
7
7
|
* To add/remove a gated feature:
|
|
8
8
|
* 1. Add/remove the key in PlanLimits interface
|
|
9
9
|
* 2. Set values for each plan in PLAN_LIMITS
|
|
10
|
-
* 3. Backend: add
|
|
10
|
+
* 3. Backend: add enforceDatingPlanLimit('featureKey') middleware to the route
|
|
11
11
|
* That's it — no scattered if-checks needed.
|
|
12
12
|
*
|
|
13
13
|
* @module dating-schema/plan-limits
|
|
14
14
|
*/
|
|
15
|
-
/** The
|
|
16
|
-
export type PlanId = 'spark' | 'gold' | 'diamond' | 'platinum';
|
|
15
|
+
/** The 5 pricing plans. Black is the exclusive celebrity/HNI tier. */
|
|
16
|
+
export type PlanId = 'spark' | 'gold' | 'diamond' | 'platinum' | 'black';
|
|
17
17
|
/** Filter capability levels by plan. */
|
|
18
|
-
export type FilterLevel = 'basic' | 'advanced' | '
|
|
18
|
+
export type FilterLevel = 'basic' | 'advanced' | 'full';
|
|
19
19
|
/** "Who liked you" visibility levels by plan. */
|
|
20
20
|
export type WhoLikedYouLevel = 'none' | 'blurred' | 'full' | 'realtime';
|
|
21
|
+
/** Explore category access levels by plan. */
|
|
22
|
+
export type ExploreAccessLevel = 'basic' | 'premium';
|
|
23
|
+
/** Compatibility score breakdown visibility by plan. */
|
|
24
|
+
export type ScoreBreakdownLevel = 'none' | 'score' | 'breakdown';
|
|
21
25
|
/** All numeric limit keys (daily/periodic counters enforced server-side). */
|
|
22
|
-
export type NumericFeatureKey = 'dailySwipes' | 'dailyCompliments' | 'dailyRewinds' | 'dailyProfileVisits' | '
|
|
26
|
+
export type NumericFeatureKey = 'dailySwipes' | 'dailyCompliments' | 'dailyRewinds' | 'dailyProfileVisits' | 'monthlyNewChatThreads' | 'monthlyBoosts' | 'weeklyAutoBoost' | 'dailyVoiceCalls' | 'dailyVideoCalls' | 'voiceCallDurationMin' | 'videoCallDurationMin' | 'monthlyIntentChanges' | 'scoreVisibleProfiles';
|
|
23
27
|
/** All boolean feature keys (on/off per plan). */
|
|
24
|
-
export type BooleanFeatureKey = 'readReceipts' | 'incognitoMode' | 'voiceMessages' | 'voiceCalls' | 'videoCalls' | 'showAds' | '
|
|
28
|
+
export type BooleanFeatureKey = 'readReceipts' | 'incognitoMode' | 'voiceMessages' | 'voiceCalls' | 'videoCalls' | 'showAds' | 'priorityVisibility' | 'autoBoost' | 'seeProfileViewers' | 'messageBeforeMatch' | 'travelMode' | 'profileContentUnlock' | 'photoInsights' | 'exclusiveLeague';
|
|
25
29
|
/** All string-enum feature keys. */
|
|
26
|
-
export type EnumFeatureKey = 'filterLevel' | 'whoLikedYou';
|
|
30
|
+
export type EnumFeatureKey = 'filterLevel' | 'whoLikedYou' | 'exploreAccess' | 'scoreBreakdown';
|
|
27
31
|
/** Union of all feature keys that can be gated. */
|
|
28
32
|
export type FeatureKey = NumericFeatureKey | BooleanFeatureKey | EnumFeatureKey;
|
|
29
33
|
/** Complete plan limits definition. */
|
|
@@ -32,25 +36,47 @@ export interface PlanLimits {
|
|
|
32
36
|
dailyCompliments: number;
|
|
33
37
|
dailyRewinds: number;
|
|
34
38
|
dailyProfileVisits: number;
|
|
35
|
-
|
|
36
|
-
maxActiveIntents: number;
|
|
39
|
+
monthlyNewChatThreads: number;
|
|
37
40
|
monthlyBoosts: number;
|
|
38
|
-
|
|
41
|
+
weeklyAutoBoost: number;
|
|
42
|
+
dailyVoiceCalls: number;
|
|
43
|
+
dailyVideoCalls: number;
|
|
44
|
+
voiceCallDurationMin: number;
|
|
45
|
+
videoCallDurationMin: number;
|
|
46
|
+
monthlyIntentChanges: number;
|
|
47
|
+
scoreVisibleProfiles: number;
|
|
39
48
|
filterLevel: FilterLevel;
|
|
40
49
|
whoLikedYou: WhoLikedYouLevel;
|
|
50
|
+
exploreAccess: ExploreAccessLevel;
|
|
51
|
+
scoreBreakdown: ScoreBreakdownLevel;
|
|
41
52
|
readReceipts: boolean;
|
|
42
53
|
incognitoMode: boolean;
|
|
43
54
|
voiceMessages: boolean;
|
|
44
55
|
voiceCalls: boolean;
|
|
45
56
|
videoCalls: boolean;
|
|
46
57
|
showAds: boolean;
|
|
47
|
-
calendarSync: boolean;
|
|
48
58
|
priorityVisibility: boolean;
|
|
49
59
|
autoBoost: boolean;
|
|
60
|
+
seeProfileViewers: boolean;
|
|
61
|
+
messageBeforeMatch: boolean;
|
|
62
|
+
travelMode: boolean;
|
|
63
|
+
profileContentUnlock: boolean;
|
|
64
|
+
photoInsights: boolean;
|
|
65
|
+
exclusiveLeague: boolean;
|
|
50
66
|
}
|
|
51
67
|
export declare const PLAN_LIMITS: Record<PlanId, PlanLimits>;
|
|
52
|
-
/** All valid plan IDs. */
|
|
68
|
+
/** All valid plan IDs in tier order. */
|
|
53
69
|
export declare const PLAN_IDS: PlanId[];
|
|
70
|
+
/** Paid plans (Gold and above). */
|
|
71
|
+
export declare const PAID_PLANS: PlanId[];
|
|
72
|
+
/** Premium plans (Diamond and above). */
|
|
73
|
+
export declare const PREMIUM_PLANS: PlanId[];
|
|
74
|
+
/** Top-tier plans (Platinum and Black). */
|
|
75
|
+
export declare const TOP_PLANS: PlanId[];
|
|
76
|
+
/** Check if a plan is paid (not Spark). */
|
|
77
|
+
export declare function isPaidPlan(planId: PlanId): boolean;
|
|
78
|
+
/** Premium explore categories that require Gold+ to access. */
|
|
79
|
+
export declare const PREMIUM_EXPLORE_CATEGORIES: readonly ["high-iq", "elite-institute", "wealth-dating", "casual", "nri-dating", "senior-dating", "lgbtq", "second-innings"];
|
|
54
80
|
/** Get the limits object for a plan. */
|
|
55
81
|
export declare function getPlanLimits(planId: PlanId): PlanLimits;
|
|
56
82
|
/** Get a specific limit value for a plan + feature. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan-limits.d.ts","sourceRoot":"","sources":["../src/plan-limits.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,
|
|
1
|
+
{"version":3,"file":"plan-limits.d.ts","sourceRoot":"","sources":["../src/plan-limits.ts"],"names":[],"mappings":"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"}
|
package/dist/plan-limits.js
CHANGED
|
@@ -7,101 +7,210 @@
|
|
|
7
7
|
* To add/remove a gated feature:
|
|
8
8
|
* 1. Add/remove the key in PlanLimits interface
|
|
9
9
|
* 2. Set values for each plan in PLAN_LIMITS
|
|
10
|
-
* 3. Backend: add
|
|
10
|
+
* 3. Backend: add enforceDatingPlanLimit('featureKey') middleware to the route
|
|
11
11
|
* That's it — no scattered if-checks needed.
|
|
12
12
|
*
|
|
13
13
|
* @module dating-schema/plan-limits
|
|
14
14
|
*/
|
|
15
15
|
// ─── Plan Limits Config ──────────────────────────────────────────────────────
|
|
16
16
|
export const PLAN_LIMITS = {
|
|
17
|
+
// ── Spark (Free) — Enough to hook, heavily limited ──
|
|
17
18
|
spark: {
|
|
18
19
|
dailySwipes: 20,
|
|
19
20
|
dailyCompliments: 1,
|
|
20
21
|
dailyRewinds: 0,
|
|
21
22
|
dailyProfileVisits: 10,
|
|
22
|
-
|
|
23
|
-
maxActiveIntents: 2,
|
|
23
|
+
monthlyNewChatThreads: 5,
|
|
24
24
|
monthlyBoosts: 0,
|
|
25
|
-
|
|
25
|
+
weeklyAutoBoost: 0,
|
|
26
|
+
dailyVoiceCalls: 0,
|
|
27
|
+
dailyVideoCalls: 0,
|
|
28
|
+
voiceCallDurationMin: 0,
|
|
29
|
+
videoCallDurationMin: 0,
|
|
30
|
+
monthlyIntentChanges: 2,
|
|
31
|
+
scoreVisibleProfiles: 3,
|
|
26
32
|
filterLevel: 'basic',
|
|
27
33
|
whoLikedYou: 'none',
|
|
34
|
+
exploreAccess: 'basic',
|
|
35
|
+
scoreBreakdown: 'none',
|
|
28
36
|
readReceipts: false,
|
|
29
37
|
incognitoMode: false,
|
|
30
38
|
voiceMessages: false,
|
|
31
39
|
voiceCalls: false,
|
|
32
40
|
videoCalls: false,
|
|
33
41
|
showAds: true,
|
|
34
|
-
calendarSync: false,
|
|
35
42
|
priorityVisibility: false,
|
|
36
43
|
autoBoost: false,
|
|
44
|
+
seeProfileViewers: false,
|
|
45
|
+
messageBeforeMatch: false,
|
|
46
|
+
travelMode: false,
|
|
47
|
+
profileContentUnlock: false,
|
|
48
|
+
photoInsights: false,
|
|
49
|
+
exclusiveLeague: false,
|
|
37
50
|
},
|
|
51
|
+
// ── Gold — Good value, removes major pain points ──
|
|
38
52
|
gold: {
|
|
39
|
-
dailySwipes:
|
|
40
|
-
dailyCompliments:
|
|
41
|
-
dailyRewinds:
|
|
42
|
-
dailyProfileVisits:
|
|
43
|
-
|
|
44
|
-
maxActiveIntents: 3,
|
|
53
|
+
dailySwipes: 80,
|
|
54
|
+
dailyCompliments: 5,
|
|
55
|
+
dailyRewinds: 3,
|
|
56
|
+
dailyProfileVisits: 30,
|
|
57
|
+
monthlyNewChatThreads: 15,
|
|
45
58
|
monthlyBoosts: 1,
|
|
46
|
-
|
|
59
|
+
weeklyAutoBoost: 0,
|
|
60
|
+
dailyVoiceCalls: 2,
|
|
61
|
+
dailyVideoCalls: 1,
|
|
62
|
+
voiceCallDurationMin: 10,
|
|
63
|
+
videoCallDurationMin: 10,
|
|
64
|
+
monthlyIntentChanges: 4,
|
|
65
|
+
scoreVisibleProfiles: Infinity,
|
|
47
66
|
filterLevel: 'advanced',
|
|
48
67
|
whoLikedYou: 'blurred',
|
|
68
|
+
exploreAccess: 'premium',
|
|
69
|
+
scoreBreakdown: 'score',
|
|
49
70
|
readReceipts: false,
|
|
50
71
|
incognitoMode: false,
|
|
51
72
|
voiceMessages: true,
|
|
52
|
-
voiceCalls:
|
|
53
|
-
videoCalls:
|
|
73
|
+
voiceCalls: true,
|
|
74
|
+
videoCalls: true,
|
|
54
75
|
showAds: false,
|
|
55
|
-
calendarSync: false,
|
|
56
76
|
priorityVisibility: false,
|
|
57
77
|
autoBoost: false,
|
|
78
|
+
seeProfileViewers: true,
|
|
79
|
+
messageBeforeMatch: false,
|
|
80
|
+
travelMode: false,
|
|
81
|
+
profileContentUnlock: true,
|
|
82
|
+
photoInsights: false,
|
|
83
|
+
exclusiveLeague: false,
|
|
58
84
|
},
|
|
85
|
+
// ── Diamond (DECOY) — Generous but capped, pushes to Platinum ──
|
|
59
86
|
diamond: {
|
|
60
|
-
dailySwipes:
|
|
61
|
-
dailyCompliments:
|
|
62
|
-
dailyRewinds:
|
|
63
|
-
dailyProfileVisits:
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
87
|
+
dailySwipes: 200,
|
|
88
|
+
dailyCompliments: 15,
|
|
89
|
+
dailyRewinds: 10,
|
|
90
|
+
dailyProfileVisits: 100,
|
|
91
|
+
monthlyNewChatThreads: 50,
|
|
92
|
+
monthlyBoosts: 3,
|
|
93
|
+
weeklyAutoBoost: 0,
|
|
94
|
+
dailyVoiceCalls: 5,
|
|
95
|
+
dailyVideoCalls: 3,
|
|
96
|
+
voiceCallDurationMin: 20,
|
|
97
|
+
videoCallDurationMin: 15,
|
|
98
|
+
monthlyIntentChanges: 8,
|
|
99
|
+
scoreVisibleProfiles: Infinity,
|
|
100
|
+
filterLevel: 'full',
|
|
69
101
|
whoLikedYou: 'full',
|
|
102
|
+
exploreAccess: 'premium',
|
|
103
|
+
scoreBreakdown: 'score',
|
|
70
104
|
readReceipts: true,
|
|
71
105
|
incognitoMode: false,
|
|
72
106
|
voiceMessages: true,
|
|
73
107
|
voiceCalls: true,
|
|
74
108
|
videoCalls: true,
|
|
75
109
|
showAds: false,
|
|
76
|
-
|
|
77
|
-
priorityVisibility: false,
|
|
110
|
+
priorityVisibility: true,
|
|
78
111
|
autoBoost: false,
|
|
112
|
+
seeProfileViewers: true,
|
|
113
|
+
messageBeforeMatch: false,
|
|
114
|
+
travelMode: false,
|
|
115
|
+
profileContentUnlock: true,
|
|
116
|
+
photoInsights: true,
|
|
117
|
+
exclusiveLeague: false,
|
|
79
118
|
},
|
|
119
|
+
// ── Platinum — Unlimited everything, the aspirational tier ──
|
|
80
120
|
platinum: {
|
|
81
121
|
dailySwipes: Infinity,
|
|
82
|
-
dailyCompliments:
|
|
122
|
+
dailyCompliments: Infinity,
|
|
83
123
|
dailyRewinds: Infinity,
|
|
84
124
|
dailyProfileVisits: Infinity,
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
125
|
+
monthlyNewChatThreads: Infinity,
|
|
126
|
+
monthlyBoosts: 7,
|
|
127
|
+
weeklyAutoBoost: 1,
|
|
128
|
+
dailyVoiceCalls: Infinity,
|
|
129
|
+
dailyVideoCalls: Infinity,
|
|
130
|
+
voiceCallDurationMin: Infinity,
|
|
131
|
+
videoCallDurationMin: Infinity,
|
|
132
|
+
monthlyIntentChanges: Infinity,
|
|
133
|
+
scoreVisibleProfiles: Infinity,
|
|
134
|
+
filterLevel: 'full',
|
|
135
|
+
whoLikedYou: 'realtime',
|
|
136
|
+
exploreAccess: 'premium',
|
|
137
|
+
scoreBreakdown: 'breakdown',
|
|
138
|
+
readReceipts: true,
|
|
139
|
+
incognitoMode: true,
|
|
140
|
+
voiceMessages: true,
|
|
141
|
+
voiceCalls: true,
|
|
142
|
+
videoCalls: true,
|
|
143
|
+
showAds: false,
|
|
144
|
+
priorityVisibility: true,
|
|
145
|
+
autoBoost: true,
|
|
146
|
+
seeProfileViewers: true,
|
|
147
|
+
messageBeforeMatch: true,
|
|
148
|
+
travelMode: true,
|
|
149
|
+
profileContentUnlock: true,
|
|
150
|
+
photoInsights: true,
|
|
151
|
+
exclusiveLeague: false,
|
|
152
|
+
},
|
|
153
|
+
// ── Black — Exclusive league for celebrities & HNIs ──
|
|
154
|
+
// All Platinum features + exclusive league (only Black users see each other)
|
|
155
|
+
black: {
|
|
156
|
+
dailySwipes: Infinity,
|
|
157
|
+
dailyCompliments: Infinity,
|
|
158
|
+
dailyRewinds: Infinity,
|
|
159
|
+
dailyProfileVisits: Infinity,
|
|
160
|
+
monthlyNewChatThreads: Infinity,
|
|
161
|
+
monthlyBoosts: 7,
|
|
162
|
+
weeklyAutoBoost: 1,
|
|
163
|
+
dailyVoiceCalls: Infinity,
|
|
164
|
+
dailyVideoCalls: Infinity,
|
|
165
|
+
voiceCallDurationMin: Infinity,
|
|
166
|
+
videoCallDurationMin: Infinity,
|
|
167
|
+
monthlyIntentChanges: Infinity,
|
|
168
|
+
scoreVisibleProfiles: Infinity,
|
|
169
|
+
filterLevel: 'full',
|
|
90
170
|
whoLikedYou: 'realtime',
|
|
171
|
+
exploreAccess: 'premium',
|
|
172
|
+
scoreBreakdown: 'breakdown',
|
|
91
173
|
readReceipts: true,
|
|
92
174
|
incognitoMode: true,
|
|
93
175
|
voiceMessages: true,
|
|
94
176
|
voiceCalls: true,
|
|
95
177
|
videoCalls: true,
|
|
96
178
|
showAds: false,
|
|
97
|
-
calendarSync: true,
|
|
98
179
|
priorityVisibility: true,
|
|
99
180
|
autoBoost: true,
|
|
181
|
+
seeProfileViewers: true,
|
|
182
|
+
messageBeforeMatch: true,
|
|
183
|
+
travelMode: true,
|
|
184
|
+
profileContentUnlock: true,
|
|
185
|
+
photoInsights: true,
|
|
186
|
+
exclusiveLeague: true,
|
|
100
187
|
},
|
|
101
188
|
};
|
|
189
|
+
// ─── Plan Tier Helpers ──────────────────────────────────────────────────────
|
|
190
|
+
/** All valid plan IDs in tier order. */
|
|
191
|
+
export const PLAN_IDS = ['spark', 'gold', 'diamond', 'platinum', 'black'];
|
|
192
|
+
/** Paid plans (Gold and above). */
|
|
193
|
+
export const PAID_PLANS = ['gold', 'diamond', 'platinum', 'black'];
|
|
194
|
+
/** Premium plans (Diamond and above). */
|
|
195
|
+
export const PREMIUM_PLANS = ['diamond', 'platinum', 'black'];
|
|
196
|
+
/** Top-tier plans (Platinum and Black). */
|
|
197
|
+
export const TOP_PLANS = ['platinum', 'black'];
|
|
198
|
+
/** Check if a plan is paid (not Spark). */
|
|
199
|
+
export function isPaidPlan(planId) {
|
|
200
|
+
return planId !== 'spark';
|
|
201
|
+
}
|
|
202
|
+
/** Premium explore categories that require Gold+ to access. */
|
|
203
|
+
export const PREMIUM_EXPLORE_CATEGORIES = [
|
|
204
|
+
'high-iq',
|
|
205
|
+
'elite-institute',
|
|
206
|
+
'wealth-dating',
|
|
207
|
+
'casual',
|
|
208
|
+
'nri-dating',
|
|
209
|
+
'senior-dating',
|
|
210
|
+
'lgbtq',
|
|
211
|
+
'second-innings',
|
|
212
|
+
];
|
|
102
213
|
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
103
|
-
/** All valid plan IDs. */
|
|
104
|
-
export const PLAN_IDS = ['spark', 'gold', 'diamond', 'platinum'];
|
|
105
214
|
/** Get the limits object for a plan. */
|
|
106
215
|
export function getPlanLimits(planId) {
|
|
107
216
|
return PLAN_LIMITS[planId];
|
package/dist/plan-limits.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan-limits.js","sourceRoot":"","sources":["../src/plan-limits.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * dating-schema — Plan limits configuration\n *\n * Single source of truth for feature gating by pricing plan.\n * Both backend middleware and frontend UI read from this config.\n *\n * To add/remove a gated feature:\n * 1. Add/remove the key in PlanLimits interface\n * 2. Set values for each plan in PLAN_LIMITS\n * 3. Backend: add enforcePlanLimit('featureKey') middleware to the route\n * That's it — no scattered if-checks needed.\n *\n * @module dating-schema/plan-limits\n */\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/** The 4 pricing plans. */\nexport type PlanId = 'spark' | 'gold' | 'diamond' | 'platinum';\n\n/** Filter capability levels by plan. */\nexport type FilterLevel = 'basic' | 'advanced' | 'ai';\n\n/** \"Who liked you\" visibility levels by plan. */\nexport type WhoLikedYouLevel = 'none' | 'blurred' | 'full' | 'realtime';\n\n/** All numeric limit keys (daily/periodic counters enforced server-side). */\nexport type NumericFeatureKey =\n | 'dailySwipes'\n | 'dailyCompliments'\n | 'dailyRewinds'\n | 'dailyProfileVisits'\n | 'maxChatThreads'\n | 'maxActiveIntents'\n | 'monthlyBoosts'\n | 'weeklyBoosts';\n\n/** All boolean feature keys (on/off per plan). */\nexport type BooleanFeatureKey =\n | 'readReceipts'\n | 'incognitoMode'\n | 'voiceMessages'\n | 'voiceCalls'\n | 'videoCalls'\n | 'showAds'\n | 'calendarSync'\n | 'priorityVisibility'\n | 'autoBoost';\n\n/** All string-enum feature keys. */\nexport type EnumFeatureKey = 'filterLevel' | 'whoLikedYou';\n\n/** Union of all feature keys that can be gated. */\nexport type FeatureKey = NumericFeatureKey | BooleanFeatureKey | EnumFeatureKey;\n\n/** Complete plan limits definition. */\nexport interface PlanLimits {\n // ── Numeric limits (daily/periodic) ──\n dailySwipes: number;\n dailyCompliments: number;\n dailyRewinds: number;\n dailyProfileVisits: number;\n maxChatThreads: number;\n maxActiveIntents: number;\n monthlyBoosts: number;\n weeklyBoosts: number;\n\n // ── Enum limits ──\n filterLevel: FilterLevel;\n whoLikedYou: WhoLikedYouLevel;\n\n // ── Boolean flags ──\n readReceipts: boolean;\n incognitoMode: boolean;\n voiceMessages: boolean;\n voiceCalls: boolean;\n videoCalls: boolean;\n showAds: boolean;\n calendarSync: boolean;\n priorityVisibility: boolean;\n autoBoost: boolean;\n}\n\n// ─── Plan Limits Config ──────────────────────────────────────────────────────\n\nexport const PLAN_LIMITS: Record<PlanId, PlanLimits> = {\n spark: {\n dailySwipes: 20,\n dailyCompliments: 1,\n dailyRewinds: 0,\n dailyProfileVisits: 10,\n maxChatThreads: 3,\n maxActiveIntents: 2,\n monthlyBoosts: 0,\n weeklyBoosts: 0,\n filterLevel: 'basic',\n whoLikedYou: 'none',\n readReceipts: false,\n incognitoMode: false,\n voiceMessages: false,\n voiceCalls: false,\n videoCalls: false,\n showAds: true,\n calendarSync: false,\n priorityVisibility: false,\n autoBoost: false,\n },\n\n gold: {\n dailySwipes: 100,\n dailyCompliments: 10,\n dailyRewinds: 5,\n dailyProfileVisits: 50,\n maxChatThreads: Infinity,\n maxActiveIntents: 3,\n monthlyBoosts: 1,\n weeklyBoosts: 0,\n filterLevel: 'advanced',\n whoLikedYou: 'blurred',\n readReceipts: false,\n incognitoMode: false,\n voiceMessages: true,\n voiceCalls: false,\n videoCalls: false,\n showAds: false,\n calendarSync: false,\n priorityVisibility: false,\n autoBoost: false,\n },\n\n diamond: {\n dailySwipes: 300,\n dailyCompliments: 25,\n dailyRewinds: Infinity,\n dailyProfileVisits: Infinity,\n maxChatThreads: Infinity,\n maxActiveIntents: 5,\n monthlyBoosts: 0,\n weeklyBoosts: 1,\n filterLevel: 'ai',\n whoLikedYou: 'full',\n readReceipts: true,\n incognitoMode: false,\n voiceMessages: true,\n voiceCalls: true,\n videoCalls: true,\n showAds: false,\n calendarSync: false,\n priorityVisibility: false,\n autoBoost: false,\n },\n\n platinum: {\n dailySwipes: Infinity,\n dailyCompliments: 60,\n dailyRewinds: Infinity,\n dailyProfileVisits: Infinity,\n maxChatThreads: Infinity,\n maxActiveIntents: 7, // all intents\n monthlyBoosts: 0,\n weeklyBoosts: 0, // auto-boost instead\n filterLevel: 'ai',\n whoLikedYou: 'realtime',\n readReceipts: true,\n incognitoMode: true,\n voiceMessages: true,\n voiceCalls: true,\n videoCalls: true,\n showAds: false,\n calendarSync: true,\n priorityVisibility: true,\n autoBoost: true,\n },\n} as const;\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\n/** All valid plan IDs. */\nexport const PLAN_IDS: PlanId[] = ['spark', 'gold', 'diamond', 'platinum'];\n\n/** Get the limits object for a plan. */\nexport function getPlanLimits(planId: PlanId): PlanLimits {\n return PLAN_LIMITS[planId];\n}\n\n/** Get a specific limit value for a plan + feature. */\nexport function getPlanLimit<K extends FeatureKey>(planId: PlanId, feature: K): PlanLimits[K] {\n return PLAN_LIMITS[planId][feature];\n}\n\n/**\n * Check if a boolean feature is enabled for a plan.\n * Returns `false` for non-boolean features.\n */\nexport function isFeatureEnabled(planId: PlanId, feature: BooleanFeatureKey): boolean {\n return PLAN_LIMITS[planId][feature];\n}\n\n/**\n * Check if a numeric feature has remaining capacity.\n * Returns `true` if the limit is Infinity or greater than current usage.\n */\nexport function hasRemainingQuota(\n planId: PlanId,\n feature: NumericFeatureKey,\n currentUsage: number,\n): boolean {\n const limit = PLAN_LIMITS[planId][feature];\n return limit === Infinity || currentUsage < limit;\n}\n\n/**\n * Get the minimum plan required for a boolean feature.\n * Returns undefined if no plan enables it.\n */\nexport function getMinPlanForFeature(feature: BooleanFeatureKey): PlanId | undefined {\n return PLAN_IDS.find((id) => PLAN_LIMITS[id][feature] === true);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"plan-limits.js","sourceRoot":"","sources":["../src/plan-limits.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * dating-schema — Plan limits configuration\n *\n * Single source of truth for feature gating by pricing plan.\n * Both backend middleware and frontend UI read from this config.\n *\n * To add/remove a gated feature:\n * 1. Add/remove the key in PlanLimits interface\n * 2. Set values for each plan in PLAN_LIMITS\n * 3. Backend: add enforceDatingPlanLimit('featureKey') middleware to the route\n * That's it — no scattered if-checks needed.\n *\n * @module dating-schema/plan-limits\n */\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/** The 5 pricing plans. Black is the exclusive celebrity/HNI tier. */\nexport type PlanId = 'spark' | 'gold' | 'diamond' | 'platinum' | 'black';\n\n/** Filter capability levels by plan. */\nexport type FilterLevel = 'basic' | 'advanced' | 'full';\n\n/** \"Who liked you\" visibility levels by plan. */\nexport type WhoLikedYouLevel = 'none' | 'blurred' | 'full' | 'realtime';\n\n/** Explore category access levels by plan. */\nexport type ExploreAccessLevel = 'basic' | 'premium';\n\n/** Compatibility score breakdown visibility by plan. */\nexport type ScoreBreakdownLevel = 'none' | 'score' | 'breakdown';\n\n/** All numeric limit keys (daily/periodic counters enforced server-side). */\nexport type NumericFeatureKey =\n | 'dailySwipes'\n | 'dailyCompliments'\n | 'dailyRewinds'\n | 'dailyProfileVisits'\n | 'monthlyNewChatThreads'\n | 'monthlyBoosts'\n | 'weeklyAutoBoost'\n | 'dailyVoiceCalls'\n | 'dailyVideoCalls'\n | 'voiceCallDurationMin'\n | 'videoCallDurationMin'\n | 'monthlyIntentChanges'\n | 'scoreVisibleProfiles';\n\n/** All boolean feature keys (on/off per plan). */\nexport type BooleanFeatureKey =\n | 'readReceipts'\n | 'incognitoMode'\n | 'voiceMessages'\n | 'voiceCalls'\n | 'videoCalls'\n | 'showAds'\n | 'priorityVisibility'\n | 'autoBoost'\n | 'seeProfileViewers'\n | 'messageBeforeMatch'\n | 'travelMode'\n | 'profileContentUnlock'\n | 'photoInsights'\n | 'exclusiveLeague';\n\n/** All string-enum feature keys. */\nexport type EnumFeatureKey = 'filterLevel' | 'whoLikedYou' | 'exploreAccess' | 'scoreBreakdown';\n\n/** Union of all feature keys that can be gated. */\nexport type FeatureKey = NumericFeatureKey | BooleanFeatureKey | EnumFeatureKey;\n\n/** Complete plan limits definition. */\nexport interface PlanLimits {\n // ── Numeric limits (daily/periodic) ──\n dailySwipes: number;\n dailyCompliments: number;\n dailyRewinds: number;\n dailyProfileVisits: number;\n monthlyNewChatThreads: number;\n monthlyBoosts: number;\n weeklyAutoBoost: number;\n dailyVoiceCalls: number;\n dailyVideoCalls: number;\n voiceCallDurationMin: number;\n videoCallDurationMin: number;\n monthlyIntentChanges: number;\n scoreVisibleProfiles: number;\n\n // ── Enum limits ──\n filterLevel: FilterLevel;\n whoLikedYou: WhoLikedYouLevel;\n exploreAccess: ExploreAccessLevel;\n scoreBreakdown: ScoreBreakdownLevel;\n\n // ── Boolean flags ──\n readReceipts: boolean;\n incognitoMode: boolean;\n voiceMessages: boolean;\n voiceCalls: boolean;\n videoCalls: boolean;\n showAds: boolean;\n priorityVisibility: boolean;\n autoBoost: boolean;\n seeProfileViewers: boolean;\n messageBeforeMatch: boolean;\n travelMode: boolean;\n profileContentUnlock: boolean;\n photoInsights: boolean;\n exclusiveLeague: boolean;\n}\n\n// ─── Plan Limits Config ──────────────────────────────────────────────────────\n\nexport const PLAN_LIMITS: Record<PlanId, PlanLimits> = {\n // ── Spark (Free) — Enough to hook, heavily limited ──\n spark: {\n dailySwipes: 20,\n dailyCompliments: 1,\n dailyRewinds: 0,\n dailyProfileVisits: 10,\n monthlyNewChatThreads: 5,\n monthlyBoosts: 0,\n weeklyAutoBoost: 0,\n dailyVoiceCalls: 0,\n dailyVideoCalls: 0,\n voiceCallDurationMin: 0,\n videoCallDurationMin: 0,\n monthlyIntentChanges: 2,\n scoreVisibleProfiles: 3,\n filterLevel: 'basic',\n whoLikedYou: 'none',\n exploreAccess: 'basic',\n scoreBreakdown: 'none',\n readReceipts: false,\n incognitoMode: false,\n voiceMessages: false,\n voiceCalls: false,\n videoCalls: false,\n showAds: true,\n priorityVisibility: false,\n autoBoost: false,\n seeProfileViewers: false,\n messageBeforeMatch: false,\n travelMode: false,\n profileContentUnlock: false,\n photoInsights: false,\n exclusiveLeague: false,\n },\n\n // ── Gold — Good value, removes major pain points ──\n gold: {\n dailySwipes: 80,\n dailyCompliments: 5,\n dailyRewinds: 3,\n dailyProfileVisits: 30,\n monthlyNewChatThreads: 15,\n monthlyBoosts: 1,\n weeklyAutoBoost: 0,\n dailyVoiceCalls: 2,\n dailyVideoCalls: 1,\n voiceCallDurationMin: 10,\n videoCallDurationMin: 10,\n monthlyIntentChanges: 4,\n scoreVisibleProfiles: Infinity,\n filterLevel: 'advanced',\n whoLikedYou: 'blurred',\n exploreAccess: 'premium',\n scoreBreakdown: 'score',\n readReceipts: false,\n incognitoMode: false,\n voiceMessages: true,\n voiceCalls: true,\n videoCalls: true,\n showAds: false,\n priorityVisibility: false,\n autoBoost: false,\n seeProfileViewers: true,\n messageBeforeMatch: false,\n travelMode: false,\n profileContentUnlock: true,\n photoInsights: false,\n exclusiveLeague: false,\n },\n\n // ── Diamond (DECOY) — Generous but capped, pushes to Platinum ──\n diamond: {\n dailySwipes: 200,\n dailyCompliments: 15,\n dailyRewinds: 10,\n dailyProfileVisits: 100,\n monthlyNewChatThreads: 50,\n monthlyBoosts: 3,\n weeklyAutoBoost: 0,\n dailyVoiceCalls: 5,\n dailyVideoCalls: 3,\n voiceCallDurationMin: 20,\n videoCallDurationMin: 15,\n monthlyIntentChanges: 8,\n scoreVisibleProfiles: Infinity,\n filterLevel: 'full',\n whoLikedYou: 'full',\n exploreAccess: 'premium',\n scoreBreakdown: 'score',\n readReceipts: true,\n incognitoMode: false,\n voiceMessages: true,\n voiceCalls: true,\n videoCalls: true,\n showAds: false,\n priorityVisibility: true,\n autoBoost: false,\n seeProfileViewers: true,\n messageBeforeMatch: false,\n travelMode: false,\n profileContentUnlock: true,\n photoInsights: true,\n exclusiveLeague: false,\n },\n\n // ── Platinum — Unlimited everything, the aspirational tier ──\n platinum: {\n dailySwipes: Infinity,\n dailyCompliments: Infinity,\n dailyRewinds: Infinity,\n dailyProfileVisits: Infinity,\n monthlyNewChatThreads: Infinity,\n monthlyBoosts: 7,\n weeklyAutoBoost: 1,\n dailyVoiceCalls: Infinity,\n dailyVideoCalls: Infinity,\n voiceCallDurationMin: Infinity,\n videoCallDurationMin: Infinity,\n monthlyIntentChanges: Infinity,\n scoreVisibleProfiles: Infinity,\n filterLevel: 'full',\n whoLikedYou: 'realtime',\n exploreAccess: 'premium',\n scoreBreakdown: 'breakdown',\n readReceipts: true,\n incognitoMode: true,\n voiceMessages: true,\n voiceCalls: true,\n videoCalls: true,\n showAds: false,\n priorityVisibility: true,\n autoBoost: true,\n seeProfileViewers: true,\n messageBeforeMatch: true,\n travelMode: true,\n profileContentUnlock: true,\n photoInsights: true,\n exclusiveLeague: false,\n },\n\n // ── Black — Exclusive league for celebrities & HNIs ──\n // All Platinum features + exclusive league (only Black users see each other)\n black: {\n dailySwipes: Infinity,\n dailyCompliments: Infinity,\n dailyRewinds: Infinity,\n dailyProfileVisits: Infinity,\n monthlyNewChatThreads: Infinity,\n monthlyBoosts: 7,\n weeklyAutoBoost: 1,\n dailyVoiceCalls: Infinity,\n dailyVideoCalls: Infinity,\n voiceCallDurationMin: Infinity,\n videoCallDurationMin: Infinity,\n monthlyIntentChanges: Infinity,\n scoreVisibleProfiles: Infinity,\n filterLevel: 'full',\n whoLikedYou: 'realtime',\n exploreAccess: 'premium',\n scoreBreakdown: 'breakdown',\n readReceipts: true,\n incognitoMode: true,\n voiceMessages: true,\n voiceCalls: true,\n videoCalls: true,\n showAds: false,\n priorityVisibility: true,\n autoBoost: true,\n seeProfileViewers: true,\n messageBeforeMatch: true,\n travelMode: true,\n profileContentUnlock: true,\n photoInsights: true,\n exclusiveLeague: true,\n },\n} as const;\n\n// ─── Plan Tier Helpers ──────────────────────────────────────────────────────\n\n/** All valid plan IDs in tier order. */\nexport const PLAN_IDS: PlanId[] = ['spark', 'gold', 'diamond', 'platinum', 'black'];\n\n/** Paid plans (Gold and above). */\nexport const PAID_PLANS: PlanId[] = ['gold', 'diamond', 'platinum', 'black'];\n\n/** Premium plans (Diamond and above). */\nexport const PREMIUM_PLANS: PlanId[] = ['diamond', 'platinum', 'black'];\n\n/** Top-tier plans (Platinum and Black). */\nexport const TOP_PLANS: PlanId[] = ['platinum', 'black'];\n\n/** Check if a plan is paid (not Spark). */\nexport function isPaidPlan(planId: PlanId): boolean {\n return planId !== 'spark';\n}\n\n/** Premium explore categories that require Gold+ to access. */\nexport const PREMIUM_EXPLORE_CATEGORIES = [\n 'high-iq',\n 'elite-institute',\n 'wealth-dating',\n 'casual',\n 'nri-dating',\n 'senior-dating',\n 'lgbtq',\n 'second-innings',\n] as const;\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\n/** Get the limits object for a plan. */\nexport function getPlanLimits(planId: PlanId): PlanLimits {\n return PLAN_LIMITS[planId];\n}\n\n/** Get a specific limit value for a plan + feature. */\nexport function getPlanLimit<K extends FeatureKey>(planId: PlanId, feature: K): PlanLimits[K] {\n return PLAN_LIMITS[planId][feature];\n}\n\n/**\n * Check if a boolean feature is enabled for a plan.\n * Returns `false` for non-boolean features.\n */\nexport function isFeatureEnabled(planId: PlanId, feature: BooleanFeatureKey): boolean {\n return PLAN_LIMITS[planId][feature];\n}\n\n/**\n * Check if a numeric feature has remaining capacity.\n * Returns `true` if the limit is Infinity or greater than current usage.\n */\nexport function hasRemainingQuota(\n planId: PlanId,\n feature: NumericFeatureKey,\n currentUsage: number,\n): boolean {\n const limit = PLAN_LIMITS[planId][feature];\n return limit === Infinity || currentUsage < limit;\n}\n\n/**\n * Get the minimum plan required for a boolean feature.\n * Returns undefined if no plan enables it.\n */\nexport function getMinPlanForFeature(feature: BooleanFeatureKey): PlanId | undefined {\n return PLAN_IDS.find((id) => PLAN_LIMITS[id][feature] === true);\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dating-schema",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.32.0",
|
|
4
4
|
"description": "Shared Zod schemas for the Dating feature — single source of truth for API contracts, validation, and TypeScript types (frontend + backend).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|