dating-schema 0.42.0 → 0.43.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/badges.d.ts +33 -0
- package/dist/badges.d.ts.map +1 -0
- package/dist/badges.js +26 -0
- package/dist/badges.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/plan-limits.d.ts +1 -1
- package/dist/plan-limits.d.ts.map +1 -1
- package/dist/plan-limits.js +2 -4
- package/dist/plan-limits.js.map +1 -1
- package/package.json +1 -1
package/dist/badges.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dating-schema — Badge types and validation schemas
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for profile badge keys, display metadata,
|
|
5
|
+
* and moderator badge-update validation.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
/** All possible profile badge identifiers, ordered by display priority. */
|
|
9
|
+
export declare const badgeKeySchema: z.ZodEnum<{
|
|
10
|
+
blackCircle: "blackCircle";
|
|
11
|
+
verified: "verified";
|
|
12
|
+
eliteInstitute: "eliteInstitute";
|
|
13
|
+
highIq: "highIq";
|
|
14
|
+
}>;
|
|
15
|
+
export type BadgeKey = z.infer<typeof badgeKeySchema>;
|
|
16
|
+
export interface BadgeDisplayInfo {
|
|
17
|
+
key: BadgeKey;
|
|
18
|
+
label: string;
|
|
19
|
+
}
|
|
20
|
+
/** Ordered list of badge display metadata (priority order). */
|
|
21
|
+
export declare const BADGE_DISPLAY: readonly BadgeDisplayInfo[];
|
|
22
|
+
/** Request body for `PATCH /api/matchmaking/profiles/:userId/badges`. */
|
|
23
|
+
export declare const updateBadgesBodySchema: z.ZodObject<{
|
|
24
|
+
isVerified: z.ZodOptional<z.ZodBoolean>;
|
|
25
|
+
isEliteInstitute: z.ZodOptional<z.ZodBoolean>;
|
|
26
|
+
isHighIq: z.ZodOptional<z.ZodBoolean>;
|
|
27
|
+
blackCircleStatus: z.ZodOptional<z.ZodEnum<{
|
|
28
|
+
approved: "approved";
|
|
29
|
+
rejected: "rejected";
|
|
30
|
+
}>>;
|
|
31
|
+
}, z.core.$strip>;
|
|
32
|
+
export type UpdateBadgesBody = z.infer<typeof updateBadgesBodySchema>;
|
|
33
|
+
//# sourceMappingURL=badges.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"badges.d.ts","sourceRoot":"","sources":["../src/badges.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,2EAA2E;AAC3E,eAAO,MAAM,cAAc;;;;;EAAkE,CAAC;AAE9F,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAItD,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,QAAQ,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,+DAA+D;AAC/D,eAAO,MAAM,aAAa,EAAE,SAAS,gBAAgB,EAK3C,CAAC;AAIX,yEAAyE;AACzE,eAAO,MAAM,sBAAsB;;;;;;;;iBAKjC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
|
package/dist/badges.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dating-schema — Badge types and validation schemas
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for profile badge keys, display metadata,
|
|
5
|
+
* and moderator badge-update validation.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
// ─── Badge Key ──────────────────────────────────────────────────────────────
|
|
9
|
+
/** All possible profile badge identifiers, ordered by display priority. */
|
|
10
|
+
export const badgeKeySchema = z.enum(['blackCircle', 'verified', 'eliteInstitute', 'highIq']);
|
|
11
|
+
/** Ordered list of badge display metadata (priority order). */
|
|
12
|
+
export const BADGE_DISPLAY = [
|
|
13
|
+
{ key: 'blackCircle', label: 'Black Circle' },
|
|
14
|
+
{ key: 'verified', label: 'Verified' },
|
|
15
|
+
{ key: 'eliteInstitute', label: 'IIT/IIM' },
|
|
16
|
+
{ key: 'highIq', label: 'High IQ' },
|
|
17
|
+
];
|
|
18
|
+
// ─── Moderator Badge Update ─────────────────────────────────────────────────
|
|
19
|
+
/** Request body for `PATCH /api/matchmaking/profiles/:userId/badges`. */
|
|
20
|
+
export const updateBadgesBodySchema = z.object({
|
|
21
|
+
isVerified: z.boolean().optional(),
|
|
22
|
+
isEliteInstitute: z.boolean().optional(),
|
|
23
|
+
isHighIq: z.boolean().optional(),
|
|
24
|
+
blackCircleStatus: z.enum(['approved', 'rejected']).optional(),
|
|
25
|
+
});
|
|
26
|
+
//# sourceMappingURL=badges.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"badges.js","sourceRoot":"","sources":["../src/badges.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,+EAA+E;AAE/E,2EAA2E;AAC3E,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,UAAU,EAAE,gBAAgB,EAAE,QAAQ,CAAC,CAAC,CAAC;AAW9F,+DAA+D;AAC/D,MAAM,CAAC,MAAM,aAAa,GAAgC;IACxD,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,cAAc,EAAE;IAC7C,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE;IACtC,EAAE,GAAG,EAAE,gBAAgB,EAAE,KAAK,EAAE,SAAS,EAAE;IAC3C,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE;CAC3B,CAAC;AAEX,+EAA+E;AAE/E,yEAAyE;AACzE,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAClC,gBAAgB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACxC,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAChC,iBAAiB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,EAAE;CAC/D,CAAC,CAAC","sourcesContent":["/**\n * dating-schema — Badge types and validation schemas\n *\n * Single source of truth for profile badge keys, display metadata,\n * and moderator badge-update validation.\n */\n\nimport { z } from 'zod';\n\n// ─── Badge Key ──────────────────────────────────────────────────────────────\n\n/** All possible profile badge identifiers, ordered by display priority. */\nexport const badgeKeySchema = z.enum(['blackCircle', 'verified', 'eliteInstitute', 'highIq']);\n\nexport type BadgeKey = z.infer<typeof badgeKeySchema>;\n\n// ─── Badge Display Metadata ─────────────────────────────────────────────────\n\nexport interface BadgeDisplayInfo {\n key: BadgeKey;\n label: string;\n}\n\n/** Ordered list of badge display metadata (priority order). */\nexport const BADGE_DISPLAY: readonly BadgeDisplayInfo[] = [\n { key: 'blackCircle', label: 'Black Circle' },\n { key: 'verified', label: 'Verified' },\n { key: 'eliteInstitute', label: 'IIT/IIM' },\n { key: 'highIq', label: 'High IQ' },\n] as const;\n\n// ─── Moderator Badge Update ─────────────────────────────────────────────────\n\n/** Request body for `PATCH /api/matchmaking/profiles/:userId/badges`. */\nexport const updateBadgesBodySchema = z.object({\n isVerified: z.boolean().optional(),\n isEliteInstitute: z.boolean().optional(),\n isHighIq: z.boolean().optional(),\n blackCircleStatus: z.enum(['approved', 'rejected']).optional(),\n});\n\nexport type UpdateBadgesBody = z.infer<typeof updateBadgesBodySchema>;\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module dating-schema
|
|
8
8
|
*/
|
|
9
|
+
export { BADGE_DISPLAY, type BadgeDisplayInfo, type BadgeKey, badgeKeySchema, type UpdateBadgesBody, updateBadgesBodySchema, } from './badges.js';
|
|
9
10
|
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
11
|
export { getFieldMeta, getFieldOptions } from './field-helpers.js';
|
|
11
12
|
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';
|
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,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAEnE,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;AAC3B,OAAO,EACL,wBAAwB,EACxB,iBAAiB,EACjB,sBAAsB,EACtB,2BAA2B,EAC3B,0BAA0B,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,GACzB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,oBAAoB,EACpB,qBAAqB,EACrB,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACV,KAAK,iBAAiB,EACtB,UAAU,EACV,oBAAoB,EACpB,QAAQ,EACR,WAAW,EACX,KAAK,MAAM,EACX,KAAK,UAAU,EACf,0BAA0B,EAC1B,aAAa,EACb,kBAAkB,EAClB,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,iBAAiB,EACjB,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":"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"}
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module dating-schema
|
|
8
8
|
*/
|
|
9
|
+
// ─── Badge schemas ──────────────────────────────────────────────────────────
|
|
10
|
+
export { BADGE_DISPLAY, badgeKeySchema, updateBadgesBodySchema, } from './badges.js';
|
|
9
11
|
// ─── Common helpers and enums ────────────────────────────────────────────────
|
|
10
12
|
export {
|
|
11
13
|
// sub-schemas
|
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,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACnE,gFAAgF;AAChF,OAAO,EAEL,eAAe,EAEf,oBAAoB,EAIpB,mBAAmB,EACnB,0BAA0B,EAC1B,qBAAqB,EAErB,gBAAgB,EAGhB,eAAe,EACf,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,wBAAwB,EACxB,iBAAiB,EACjB,sBAAsB,EACtB,2BAA2B,EAC3B,0BAA0B,GAG3B,MAAM,wBAAwB,CAAC;AAChC,gFAAgF;AAChF,OAAO,EAQL,oBAAoB,EACpB,qBAAqB,EACrB,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EAEV,UAAU,EACV,oBAAoB,EACpB,QAAQ,EACR,WAAW,EAGX,0BAA0B,EAC1B,aAAa,EACb,kBAAkB,EAElB,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,EACpB,iBAAiB,EAEjB,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 { getFieldMeta, 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';\nexport {\n getOnboardingFieldConfig,\n ONBOARDING_FIELDS,\n ONBOARDING_STEP_GROUPS,\n ONBOARDING_TOTAL_MAIN_STEPS,\n ONBOARDING_TOTAL_SUB_STEPS,\n type OnboardingFieldConfig,\n type OnboardingStepGroup,\n} from './onboarding-config.js';\n// ─── Plan limits ─────────────────────────────────────────────────────────────\nexport {\n type BooleanFeatureKey,\n type EnumFeatureKey,\n type ExploreAccessLevel,\n type FeatureDisplayItem,\n type FeatureKey,\n type FeatureValue,\n type FilterLevel,\n getMinPlanForFeature,\n getPlanFeatureDisplay,\n getPlanLimit,\n getPlanLimits,\n hasRemainingQuota,\n isFeatureEnabled,\n isPaidPlan,\n type NumericFeatureKey,\n PAID_PLANS,\n PLAN_FEATURE_DISPLAY,\n PLAN_IDS,\n PLAN_LIMITS,\n type PlanId,\n type PlanLimits,\n PREMIUM_EXPLORE_CATEGORIES,\n PREMIUM_PLANS,\n renderFeatureValue,\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 religionCommunity,\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"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,+EAA+E;AAC/E,OAAO,EACL,aAAa,EAGb,cAAc,EAEd,sBAAsB,GACvB,MAAM,aAAa,CAAC;AAErB,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,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACnE,gFAAgF;AAChF,OAAO,EAEL,eAAe,EAEf,oBAAoB,EAIpB,mBAAmB,EACnB,0BAA0B,EAC1B,qBAAqB,EAErB,gBAAgB,EAGhB,eAAe,EACf,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,wBAAwB,EACxB,iBAAiB,EACjB,sBAAsB,EACtB,2BAA2B,EAC3B,0BAA0B,GAG3B,MAAM,wBAAwB,CAAC;AAChC,gFAAgF;AAChF,OAAO,EAQL,oBAAoB,EACpB,qBAAqB,EACrB,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EAEV,UAAU,EACV,oBAAoB,EACpB,QAAQ,EACR,WAAW,EAGX,0BAA0B,EAC1B,aAAa,EACb,kBAAkB,EAElB,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,EACpB,iBAAiB,EAEjB,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// ─── Badge schemas ──────────────────────────────────────────────────────────\nexport {\n BADGE_DISPLAY,\n type BadgeDisplayInfo,\n type BadgeKey,\n badgeKeySchema,\n type UpdateBadgesBody,\n updateBadgesBodySchema,\n} from './badges.js';\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 { getFieldMeta, 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';\nexport {\n getOnboardingFieldConfig,\n ONBOARDING_FIELDS,\n ONBOARDING_STEP_GROUPS,\n ONBOARDING_TOTAL_MAIN_STEPS,\n ONBOARDING_TOTAL_SUB_STEPS,\n type OnboardingFieldConfig,\n type OnboardingStepGroup,\n} from './onboarding-config.js';\n// ─── Plan limits ─────────────────────────────────────────────────────────────\nexport {\n type BooleanFeatureKey,\n type EnumFeatureKey,\n type ExploreAccessLevel,\n type FeatureDisplayItem,\n type FeatureKey,\n type FeatureValue,\n type FilterLevel,\n getMinPlanForFeature,\n getPlanFeatureDisplay,\n getPlanLimit,\n getPlanLimits,\n hasRemainingQuota,\n isFeatureEnabled,\n isPaidPlan,\n type NumericFeatureKey,\n PAID_PLANS,\n PLAN_FEATURE_DISPLAY,\n PLAN_IDS,\n PLAN_LIMITS,\n type PlanId,\n type PlanLimits,\n PREMIUM_EXPLORE_CATEGORIES,\n PREMIUM_PLANS,\n renderFeatureValue,\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 religionCommunity,\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
|
@@ -101,7 +101,7 @@ export interface FeatureDisplayItem {
|
|
|
101
101
|
plans: Record<PlanId, FeatureValue | boolean>;
|
|
102
102
|
}
|
|
103
103
|
/** Render a plan feature value to a single display string */
|
|
104
|
-
export declare function renderFeatureValue(value: FeatureValue | boolean, label: string): string;
|
|
104
|
+
export declare function renderFeatureValue(value: FeatureValue | boolean | undefined, label: string): string;
|
|
105
105
|
/**
|
|
106
106
|
* Master feature list for plan comparison UI.
|
|
107
107
|
* Now in plan-features-data.ts for cleaner separation.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan-limits.d.ts","sourceRoot":"","sources":["../src/plan-limits.ts"],"names":[],"mappings":"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
|
|
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
|
@@ -174,9 +174,7 @@ export const PREMIUM_EXPLORE_CATEGORIES = [
|
|
|
174
174
|
];
|
|
175
175
|
/** Render a plan feature value to a single display string */
|
|
176
176
|
export function renderFeatureValue(value, label) {
|
|
177
|
-
if (value === true)
|
|
178
|
-
return label;
|
|
179
|
-
if (value === false)
|
|
177
|
+
if (value == null || value === true || value === false)
|
|
180
178
|
return label;
|
|
181
179
|
const parts = [value.qty, value.text];
|
|
182
180
|
if (value.unit)
|
|
@@ -201,7 +199,7 @@ export function getPlanFeatureDisplay(planId) {
|
|
|
201
199
|
if (!f.available)
|
|
202
200
|
continue;
|
|
203
201
|
const val = f.plans[planId];
|
|
204
|
-
if (val === false) {
|
|
202
|
+
if (val == null || val === false) {
|
|
205
203
|
locked.push({ key: f.key, label: f.label, helpText: f.helpText });
|
|
206
204
|
}
|
|
207
205
|
else if (val === true) {
|
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 * 4-tier system: Lite (free) → Basic (decoy) → Premium (target) → Black (elite)\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\nimport { PLAN_FEATURE_DISPLAY_DATA as PLAN_FEATURE_DISPLAY_ITEMS } from './plan-features-data.js';\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/** The 4 pricing plans. Black is the exclusive celebrity/HNI tier. */\nexport type PlanId = 'lite' | 'basic' | 'premium' | '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 | 'dailyLikes'\n | 'dailyCompliments'\n | 'dailyRewinds'\n | 'dailyProfileVisits'\n | 'monthlyNewChatThreads'\n | 'monthlyBoosts'\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 | 'seeProfileViewers'\n | 'messageBeforeMatch'\n | 'travelMode'\n | 'profileContentUnlock'\n | 'photoInsights'\n | 'viewContactNumber'\n | 'exclusiveLeague'\n | 'seePublicBlackProfiles';\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 dailyLikes: number;\n dailyCompliments: number;\n dailyRewinds: number;\n dailyProfileVisits: number;\n monthlyNewChatThreads: number;\n monthlyBoosts: number;\n\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 seeProfileViewers: boolean;\n messageBeforeMatch: boolean;\n travelMode: boolean;\n profileContentUnlock: boolean;\n photoInsights: boolean;\n viewContactNumber: boolean;\n exclusiveLeague: boolean;\n seePublicBlackProfiles: boolean;\n}\n\n// ─── Plan Limits Config ──────────────────────────────────────────────────────\n\nexport const PLAN_LIMITS: Record<PlanId, PlanLimits> = {\n // ── Lite (Free) — Hook users, limited enough to upgrade ──\n lite: {\n dailyLikes: 10,\n dailyCompliments: 1,\n dailyRewinds: 0,\n dailyProfileVisits: 20,\n monthlyNewChatThreads: Infinity, // no chat cap — matches can always chat\n monthlyBoosts: 0,\n\n dailyVoiceCalls: 0,\n dailyVideoCalls: 0,\n voiceCallDurationMin: 0,\n videoCallDurationMin: 0,\n monthlyIntentChanges: 2,\n scoreVisibleProfiles: 3,\n\n filterLevel: 'basic',\n whoLikedYou: 'none',\n exploreAccess: 'basic',\n scoreBreakdown: 'none',\n\n readReceipts: false,\n incognitoMode: false,\n voiceMessages: false,\n voiceCalls: false,\n videoCalls: false,\n showAds: true,\n seeProfileViewers: false,\n messageBeforeMatch: false,\n travelMode: false,\n profileContentUnlock: false,\n photoInsights: false,\n viewContactNumber: false,\n exclusiveLeague: false,\n seePublicBlackProfiles: false,\n },\n\n // ── Basic (DECOY) — Good enough to taste, limited enough to push Premium ──\n basic: {\n dailyLikes: 50,\n dailyCompliments: 5,\n dailyRewinds: Infinity,\n dailyProfileVisits: Infinity,\n monthlyNewChatThreads: Infinity,\n monthlyBoosts: 3,\n\n dailyVoiceCalls: 3, // hidden feature — not yet rolled out\n dailyVideoCalls: 2, // hidden feature — not yet rolled out\n voiceCallDurationMin: 15, // hidden feature — not yet rolled out\n videoCallDurationMin: 10, // hidden feature — not yet rolled out\n monthlyIntentChanges: 8,\n scoreVisibleProfiles: Infinity,\n\n filterLevel: 'advanced',\n whoLikedYou: 'blurred',\n exploreAccess: 'basic', // NO premium explore — key decoy differentiator\n scoreBreakdown: 'score',\n\n readReceipts: false, // key decoy limitation — only Premium gets this\n incognitoMode: false,\n voiceMessages: true, // hidden feature — not yet rolled out\n voiceCalls: true, // hidden feature — not yet rolled out\n videoCalls: true, // hidden feature — not yet rolled out\n showAds: false, // ad-free\n seeProfileViewers: false,\n messageBeforeMatch: false,\n travelMode: false,\n profileContentUnlock: true,\n photoInsights: false,\n viewContactNumber: false,\n exclusiveLeague: false,\n seePublicBlackProfiles: false,\n },\n\n // ── Premium — The aspirational tier, almost everything unlocked ──\n premium: {\n dailyLikes: 300,\n dailyCompliments: 10,\n dailyRewinds: Infinity,\n dailyProfileVisits: Infinity,\n monthlyNewChatThreads: Infinity,\n monthlyBoosts: 5,\n\n dailyVoiceCalls: Infinity, // hidden feature — not yet rolled out\n dailyVideoCalls: Infinity, // hidden feature — not yet rolled out\n voiceCallDurationMin: Infinity, // hidden feature — not yet rolled out\n videoCallDurationMin: Infinity, // hidden feature — not yet rolled out\n monthlyIntentChanges: Infinity,\n scoreVisibleProfiles: Infinity,\n\n filterLevel: 'full',\n whoLikedYou: 'realtime',\n exploreAccess: 'premium',\n scoreBreakdown: 'breakdown',\n\n readReceipts: true,\n incognitoMode: true,\n voiceMessages: true, // hidden feature — not yet rolled out\n voiceCalls: true, // hidden feature — not yet rolled out\n videoCalls: true, // hidden feature — not yet rolled out\n showAds: false,\n seeProfileViewers: true,\n messageBeforeMatch: true,\n travelMode: true,\n profileContentUnlock: true,\n photoInsights: true,\n viewContactNumber: true,\n exclusiveLeague: false,\n seePublicBlackProfiles: true,\n },\n\n // ── Black — Exclusive league for celebrities & HNIs ──\n black: {\n dailyLikes: Infinity,\n dailyCompliments: Infinity,\n dailyRewinds: Infinity,\n dailyProfileVisits: Infinity,\n monthlyNewChatThreads: Infinity,\n monthlyBoosts: 10,\n\n dailyVoiceCalls: Infinity,\n dailyVideoCalls: Infinity,\n voiceCallDurationMin: Infinity,\n videoCallDurationMin: Infinity,\n monthlyIntentChanges: Infinity,\n scoreVisibleProfiles: Infinity,\n\n filterLevel: 'full',\n whoLikedYou: 'realtime',\n exploreAccess: 'premium',\n scoreBreakdown: 'breakdown',\n\n readReceipts: true,\n incognitoMode: true,\n voiceMessages: true,\n voiceCalls: true,\n videoCalls: true,\n showAds: false,\n seeProfileViewers: true,\n messageBeforeMatch: true,\n travelMode: true,\n profileContentUnlock: true,\n photoInsights: true,\n viewContactNumber: true,\n exclusiveLeague: true,\n seePublicBlackProfiles: true,\n },\n} as const;\n\n// ─── Plan Tier Helpers ──────────────────────────────────────────────────────\n\n/** All valid plan IDs in tier order. */\nexport const PLAN_IDS: PlanId[] = ['lite', 'basic', 'premium', 'black'];\n\n/** Paid plans (Basic and above). */\nexport const PAID_PLANS: PlanId[] = ['basic', 'premium', 'black'];\n\n/** Premium plans (Premium and above). */\nexport const PREMIUM_PLANS: PlanId[] = ['premium', 'black'];\n\n/** Top-tier plans (Black only). */\nexport const TOP_PLANS: PlanId[] = ['black'];\n\n/** Check if a plan is paid (not Lite). */\nexport function isPaidPlan(planId: PlanId): boolean {\n return planId !== 'lite';\n}\n\n/** Premium explore categories that require Premium+ to access. */\nexport const PREMIUM_EXPLORE_CATEGORIES = [\n 'high-iq',\n 'elite-institute',\n 'nri-dating',\n 'senior-dating',\n 'lgbtq',\n 'second-innings',\n] as const;\n\n// ─── Feature Display Config (UI source of truth) ────────────────────────────\n\n/** How a feature appears in UI — per-plan value can be a string (quantity), true (check), or false (locked). */\n/** Structured value for numeric/descriptive plan features */\nexport interface FeatureValue {\n /** Quantity — e.g. \"10\", \"Unlimited\", \"3\", \"All 147\", \"Blurred preview\" */\n qty: string;\n /** Feature noun — e.g. \"compliments\", \"swipes\", \"filters\", \"of likes\" */\n text: string;\n /** Time/frequency unit — e.g. \"per day\", \"per month\". Omit if not applicable. */\n unit?: string;\n}\n\nexport interface FeatureDisplayItem {\n /** Unique key matching a FeatureKey or custom display key */\n key: string;\n /** Short, clear label shown when feature is locked */\n label: string;\n /** Tooltip help text explaining what this feature does */\n helpText: string;\n /** Whether this feature is live. If false, hidden from UI entirely (not yet rolled out). */\n available: boolean;\n /** Per-plan display value: FeatureValue = structured text, true = checkmark, false = locked */\n plans: Record<PlanId, FeatureValue | boolean>;\n}\n\n/** Render a plan feature value to a single display string */\nexport function renderFeatureValue(value: FeatureValue | boolean, label: string): string {\n if (value === true) return label;\n if (value === false) return label;\n const parts = [value.qty, value.text];\n if (value.unit) parts.push(value.unit);\n return parts.join(' ');\n}\n\n/**\n * Master feature list for plan comparison UI.\n * Now in plan-features-data.ts for cleaner separation.\n */\nexport { PLAN_FEATURE_DISPLAY_DATA as PLAN_FEATURE_DISPLAY } from './plan-features-data.js';\n\n/**\n * Get features for a plan, split into included (with values) and locked.\n * Included features come first, locked features last.\n * Only includes features where `available: true` (hides unreleased features).\n */\nexport function getPlanFeatureDisplay(planId: PlanId): {\n included: { key: string; label: string; helpText: string; value: string | true }[];\n locked: { key: string; label: string; helpText: string }[];\n} {\n const included: { key: string; label: string; helpText: string; value: string | true }[] = [];\n const locked: { key: string; label: string; helpText: string }[] = [];\n\n for (const f of PLAN_FEATURE_DISPLAY_ITEMS) {\n // Skip features not yet rolled out\n if (!f.available) continue;\n\n const val = f.plans[planId];\n if (val === false) {\n locked.push({ key: f.key, label: f.label, helpText: f.helpText });\n } else if (val === true) {\n included.push({ key: f.key, label: f.label, helpText: f.helpText, value: true });\n } else {\n included.push({\n key: f.key,\n label: f.label,\n helpText: f.helpText,\n value: renderFeatureValue(val, f.label),\n });\n }\n }\n\n return { included, locked };\n}\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"]}
|
|
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 * 4-tier system: Lite (free) → Basic (decoy) → Premium (target) → Black (elite)\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\nimport { PLAN_FEATURE_DISPLAY_DATA as PLAN_FEATURE_DISPLAY_ITEMS } from './plan-features-data.js';\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/** The 4 pricing plans. Black is the exclusive celebrity/HNI tier. */\nexport type PlanId = 'lite' | 'basic' | 'premium' | '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 | 'dailyLikes'\n | 'dailyCompliments'\n | 'dailyRewinds'\n | 'dailyProfileVisits'\n | 'monthlyNewChatThreads'\n | 'monthlyBoosts'\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 | 'seeProfileViewers'\n | 'messageBeforeMatch'\n | 'travelMode'\n | 'profileContentUnlock'\n | 'photoInsights'\n | 'viewContactNumber'\n | 'exclusiveLeague'\n | 'seePublicBlackProfiles';\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 dailyLikes: number;\n dailyCompliments: number;\n dailyRewinds: number;\n dailyProfileVisits: number;\n monthlyNewChatThreads: number;\n monthlyBoosts: number;\n\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 seeProfileViewers: boolean;\n messageBeforeMatch: boolean;\n travelMode: boolean;\n profileContentUnlock: boolean;\n photoInsights: boolean;\n viewContactNumber: boolean;\n exclusiveLeague: boolean;\n seePublicBlackProfiles: boolean;\n}\n\n// ─── Plan Limits Config ──────────────────────────────────────────────────────\n\nexport const PLAN_LIMITS: Record<PlanId, PlanLimits> = {\n // ── Lite (Free) — Hook users, limited enough to upgrade ──\n lite: {\n dailyLikes: 10,\n dailyCompliments: 1,\n dailyRewinds: 0,\n dailyProfileVisits: 20,\n monthlyNewChatThreads: Infinity, // no chat cap — matches can always chat\n monthlyBoosts: 0,\n\n dailyVoiceCalls: 0,\n dailyVideoCalls: 0,\n voiceCallDurationMin: 0,\n videoCallDurationMin: 0,\n monthlyIntentChanges: 2,\n scoreVisibleProfiles: 3,\n\n filterLevel: 'basic',\n whoLikedYou: 'none',\n exploreAccess: 'basic',\n scoreBreakdown: 'none',\n\n readReceipts: false,\n incognitoMode: false,\n voiceMessages: false,\n voiceCalls: false,\n videoCalls: false,\n showAds: true,\n seeProfileViewers: false,\n messageBeforeMatch: false,\n travelMode: false,\n profileContentUnlock: false,\n photoInsights: false,\n viewContactNumber: false,\n exclusiveLeague: false,\n seePublicBlackProfiles: false,\n },\n\n // ── Basic (DECOY) — Good enough to taste, limited enough to push Premium ──\n basic: {\n dailyLikes: 50,\n dailyCompliments: 5,\n dailyRewinds: Infinity,\n dailyProfileVisits: Infinity,\n monthlyNewChatThreads: Infinity,\n monthlyBoosts: 3,\n\n dailyVoiceCalls: 3, // hidden feature — not yet rolled out\n dailyVideoCalls: 2, // hidden feature — not yet rolled out\n voiceCallDurationMin: 15, // hidden feature — not yet rolled out\n videoCallDurationMin: 10, // hidden feature — not yet rolled out\n monthlyIntentChanges: 8,\n scoreVisibleProfiles: Infinity,\n\n filterLevel: 'advanced',\n whoLikedYou: 'blurred',\n exploreAccess: 'basic', // NO premium explore — key decoy differentiator\n scoreBreakdown: 'score',\n\n readReceipts: false, // key decoy limitation — only Premium gets this\n incognitoMode: false,\n voiceMessages: true, // hidden feature — not yet rolled out\n voiceCalls: true, // hidden feature — not yet rolled out\n videoCalls: true, // hidden feature — not yet rolled out\n showAds: false, // ad-free\n seeProfileViewers: false,\n messageBeforeMatch: false,\n travelMode: false,\n profileContentUnlock: true,\n photoInsights: false,\n viewContactNumber: false,\n exclusiveLeague: false,\n seePublicBlackProfiles: false,\n },\n\n // ── Premium — The aspirational tier, almost everything unlocked ──\n premium: {\n dailyLikes: 300,\n dailyCompliments: 10,\n dailyRewinds: Infinity,\n dailyProfileVisits: Infinity,\n monthlyNewChatThreads: Infinity,\n monthlyBoosts: 5,\n\n dailyVoiceCalls: Infinity, // hidden feature — not yet rolled out\n dailyVideoCalls: Infinity, // hidden feature — not yet rolled out\n voiceCallDurationMin: Infinity, // hidden feature — not yet rolled out\n videoCallDurationMin: Infinity, // hidden feature — not yet rolled out\n monthlyIntentChanges: Infinity,\n scoreVisibleProfiles: Infinity,\n\n filterLevel: 'full',\n whoLikedYou: 'realtime',\n exploreAccess: 'premium',\n scoreBreakdown: 'breakdown',\n\n readReceipts: true,\n incognitoMode: true,\n voiceMessages: true, // hidden feature — not yet rolled out\n voiceCalls: true, // hidden feature — not yet rolled out\n videoCalls: true, // hidden feature — not yet rolled out\n showAds: false,\n seeProfileViewers: true,\n messageBeforeMatch: true,\n travelMode: true,\n profileContentUnlock: true,\n photoInsights: true,\n viewContactNumber: true,\n exclusiveLeague: false,\n seePublicBlackProfiles: true,\n },\n\n // ── Black — Exclusive league for celebrities & HNIs ──\n black: {\n dailyLikes: Infinity,\n dailyCompliments: Infinity,\n dailyRewinds: Infinity,\n dailyProfileVisits: Infinity,\n monthlyNewChatThreads: Infinity,\n monthlyBoosts: 10,\n\n dailyVoiceCalls: Infinity,\n dailyVideoCalls: Infinity,\n voiceCallDurationMin: Infinity,\n videoCallDurationMin: Infinity,\n monthlyIntentChanges: Infinity,\n scoreVisibleProfiles: Infinity,\n\n filterLevel: 'full',\n whoLikedYou: 'realtime',\n exploreAccess: 'premium',\n scoreBreakdown: 'breakdown',\n\n readReceipts: true,\n incognitoMode: true,\n voiceMessages: true,\n voiceCalls: true,\n videoCalls: true,\n showAds: false,\n seeProfileViewers: true,\n messageBeforeMatch: true,\n travelMode: true,\n profileContentUnlock: true,\n photoInsights: true,\n viewContactNumber: true,\n exclusiveLeague: true,\n seePublicBlackProfiles: true,\n },\n} as const;\n\n// ─── Plan Tier Helpers ──────────────────────────────────────────────────────\n\n/** All valid plan IDs in tier order. */\nexport const PLAN_IDS: PlanId[] = ['lite', 'basic', 'premium', 'black'];\n\n/** Paid plans (Basic and above). */\nexport const PAID_PLANS: PlanId[] = ['basic', 'premium', 'black'];\n\n/** Premium plans (Premium and above). */\nexport const PREMIUM_PLANS: PlanId[] = ['premium', 'black'];\n\n/** Top-tier plans (Black only). */\nexport const TOP_PLANS: PlanId[] = ['black'];\n\n/** Check if a plan is paid (not Lite). */\nexport function isPaidPlan(planId: PlanId): boolean {\n return planId !== 'lite';\n}\n\n/** Premium explore categories that require Premium+ to access. */\nexport const PREMIUM_EXPLORE_CATEGORIES = [\n 'high-iq',\n 'elite-institute',\n 'nri-dating',\n 'senior-dating',\n 'lgbtq',\n 'second-innings',\n] as const;\n\n// ─── Feature Display Config (UI source of truth) ────────────────────────────\n\n/** How a feature appears in UI — per-plan value can be a string (quantity), true (check), or false (locked). */\n/** Structured value for numeric/descriptive plan features */\nexport interface FeatureValue {\n /** Quantity — e.g. \"10\", \"Unlimited\", \"3\", \"All 147\", \"Blurred preview\" */\n qty: string;\n /** Feature noun — e.g. \"compliments\", \"swipes\", \"filters\", \"of likes\" */\n text: string;\n /** Time/frequency unit — e.g. \"per day\", \"per month\". Omit if not applicable. */\n unit?: string;\n}\n\nexport interface FeatureDisplayItem {\n /** Unique key matching a FeatureKey or custom display key */\n key: string;\n /** Short, clear label shown when feature is locked */\n label: string;\n /** Tooltip help text explaining what this feature does */\n helpText: string;\n /** Whether this feature is live. If false, hidden from UI entirely (not yet rolled out). */\n available: boolean;\n /** Per-plan display value: FeatureValue = structured text, true = checkmark, false = locked */\n plans: Record<PlanId, FeatureValue | boolean>;\n}\n\n/** Render a plan feature value to a single display string */\nexport function renderFeatureValue(value: FeatureValue | boolean | undefined, label: string): string {\n if (value == null || value === true || value === false) return label;\n const parts = [value.qty, value.text];\n if (value.unit) parts.push(value.unit);\n return parts.join(' ');\n}\n\n/**\n * Master feature list for plan comparison UI.\n * Now in plan-features-data.ts for cleaner separation.\n */\nexport { PLAN_FEATURE_DISPLAY_DATA as PLAN_FEATURE_DISPLAY } from './plan-features-data.js';\n\n/**\n * Get features for a plan, split into included (with values) and locked.\n * Included features come first, locked features last.\n * Only includes features where `available: true` (hides unreleased features).\n */\nexport function getPlanFeatureDisplay(planId: PlanId): {\n included: { key: string; label: string; helpText: string; value: string | true }[];\n locked: { key: string; label: string; helpText: string }[];\n} {\n const included: { key: string; label: string; helpText: string; value: string | true }[] = [];\n const locked: { key: string; label: string; helpText: string }[] = [];\n\n for (const f of PLAN_FEATURE_DISPLAY_ITEMS) {\n // Skip features not yet rolled out\n if (!f.available) continue;\n\n const val = f.plans[planId];\n if (val == null || val === false) {\n locked.push({ key: f.key, label: f.label, helpText: f.helpText });\n } else if (val === true) {\n included.push({ key: f.key, label: f.label, helpText: f.helpText, value: true });\n } else {\n included.push({\n key: f.key,\n label: f.label,\n helpText: f.helpText,\n value: renderFeatureValue(val, f.label),\n });\n }\n }\n\n return { included, locked };\n}\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.43.1",
|
|
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",
|