dating-schema 0.1.0 → 0.6.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/common.d.ts +0 -1
- package/dist/common.d.ts.map +1 -1
- package/dist/common.js +7 -14
- package/dist/common.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -4
- package/dist/index.js.map +1 -1
- package/dist/interactions.d.ts +65 -0
- package/dist/interactions.d.ts.map +1 -0
- package/dist/interactions.js +53 -0
- package/dist/interactions.js.map +1 -0
- package/dist/plan-limits.d.ts +73 -0
- package/dist/plan-limits.d.ts.map +1 -0
- package/dist/plan-limits.js +135 -0
- package/dist/plan-limits.js.map +1 -0
- package/dist/profile-fields/01-hero-identity.d.ts +3 -0
- package/dist/profile-fields/01-hero-identity.d.ts.map +1 -0
- package/dist/profile-fields/01-hero-identity.js +248 -0
- package/dist/profile-fields/01-hero-identity.js.map +1 -0
- package/dist/profile-fields/02-story-prompts.d.ts +3 -0
- package/dist/profile-fields/02-story-prompts.d.ts.map +1 -0
- package/dist/profile-fields/02-story-prompts.js +171 -0
- package/dist/profile-fields/02-story-prompts.js.map +1 -0
- package/dist/profile-fields/03-basics.d.ts +3 -0
- package/dist/profile-fields/03-basics.d.ts.map +1 -0
- package/dist/profile-fields/03-basics.js +501 -0
- package/dist/profile-fields/03-basics.js.map +1 -0
- package/dist/profile-fields/04-looking-for.d.ts +3 -0
- package/dist/profile-fields/04-looking-for.d.ts.map +1 -0
- package/dist/profile-fields/04-looking-for.js +111 -0
- package/dist/profile-fields/04-looking-for.js.map +1 -0
- package/dist/profile-fields/05-personality.d.ts +3 -0
- package/dist/profile-fields/05-personality.d.ts.map +1 -0
- package/dist/profile-fields/05-personality.js +263 -0
- package/dist/profile-fields/05-personality.js.map +1 -0
- package/dist/profile-fields/06-self-assessment.d.ts +3 -0
- package/dist/profile-fields/06-self-assessment.d.ts.map +1 -0
- package/dist/profile-fields/06-self-assessment.js +153 -0
- package/dist/profile-fields/06-self-assessment.js.map +1 -0
- package/dist/profile-fields/07-interests.d.ts +3 -0
- package/dist/profile-fields/07-interests.d.ts.map +1 -0
- package/dist/profile-fields/07-interests.js +272 -0
- package/dist/profile-fields/07-interests.js.map +1 -0
- package/dist/profile-fields/08-favourites.d.ts +3 -0
- package/dist/profile-fields/08-favourites.d.ts.map +1 -0
- package/dist/profile-fields/08-favourites.js +85 -0
- package/dist/profile-fields/08-favourites.js.map +1 -0
- package/dist/profile-fields/09-values.d.ts +3 -0
- package/dist/profile-fields/09-values.d.ts.map +1 -0
- package/dist/profile-fields/09-values.js +156 -0
- package/dist/profile-fields/09-values.js.map +1 -0
- package/dist/profile-fields/10-career.d.ts +3 -0
- package/dist/profile-fields/10-career.d.ts.map +1 -0
- package/dist/profile-fields/10-career.js +91 -0
- package/dist/profile-fields/10-career.js.map +1 -0
- package/dist/profile-fields/11-lifestyle.d.ts +3 -0
- package/dist/profile-fields/11-lifestyle.d.ts.map +1 -0
- package/dist/profile-fields/11-lifestyle.js +448 -0
- package/dist/profile-fields/11-lifestyle.js.map +1 -0
- package/dist/profile-fields/12-cognitive.d.ts +3 -0
- package/dist/profile-fields/12-cognitive.d.ts.map +1 -0
- package/dist/profile-fields/12-cognitive.js +236 -0
- package/dist/profile-fields/12-cognitive.js.map +1 -0
- package/dist/profile-fields/13-relationship-intimacy.d.ts +3 -0
- package/dist/profile-fields/13-relationship-intimacy.d.ts.map +1 -0
- package/dist/profile-fields/13-relationship-intimacy.js +282 -0
- package/dist/profile-fields/13-relationship-intimacy.js.map +1 -0
- package/dist/profile-fields/14-family-home.d.ts +3 -0
- package/dist/profile-fields/14-family-home.d.ts.map +1 -0
- package/dist/profile-fields/14-family-home.js +230 -0
- package/dist/profile-fields/14-family-home.js.map +1 -0
- package/dist/profile-fields/15-finance-legal.d.ts +3 -0
- package/dist/profile-fields/15-finance-legal.d.ts.map +1 -0
- package/dist/profile-fields/15-finance-legal.js +263 -0
- package/dist/profile-fields/15-finance-legal.js.map +1 -0
- package/dist/profile-fields/16-health-wellness.d.ts +3 -0
- package/dist/profile-fields/16-health-wellness.d.ts.map +1 -0
- package/dist/profile-fields/16-health-wellness.js +428 -0
- package/dist/profile-fields/16-health-wellness.js.map +1 -0
- package/dist/profile-fields/index.d.ts +21 -0
- package/dist/profile-fields/index.d.ts.map +1 -0
- package/dist/profile-fields/index.js +52 -0
- package/dist/profile-fields/index.js.map +1 -0
- package/dist/profile-fields/types.d.ts +115 -0
- package/dist/profile-fields/types.d.ts.map +1 -0
- package/dist/profile-fields/types.js +7 -0
- package/dist/profile-fields/types.js.map +1 -0
- package/dist/profile.d.ts +3906 -0
- package/dist/profile.d.ts.map +1 -0
- package/dist/profile.js +1981 -0
- package/dist/profile.js.map +1 -0
- package/dist/safety.d.ts +51 -0
- package/dist/safety.d.ts.map +1 -0
- package/dist/safety.js +37 -0
- package/dist/safety.js.map +1 -0
- package/dist/subscription.d.ts +43 -0
- package/dist/subscription.d.ts.map +1 -0
- package/dist/subscription.js +21 -0
- package/dist/subscription.js.map +1 -0
- package/package.json +48 -48
package/dist/common.d.ts
CHANGED
|
@@ -31,7 +31,6 @@ export type InterestedIn = z.infer<typeof interestedInSchema>;
|
|
|
31
31
|
/** Swipe / interaction action a user can take on another profile. */
|
|
32
32
|
export declare const swipeActionSchema: z.ZodEnum<{
|
|
33
33
|
like: "like";
|
|
34
|
-
superlike: "superlike";
|
|
35
34
|
pass: "pass";
|
|
36
35
|
}>;
|
|
37
36
|
export type SwipeAction = z.infer<typeof swipeActionSchema>;
|
package/dist/common.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../src/common.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB;;;GAGG;AACH,eAAO,MAAM,sBAAsB,GAAI,OAAO,OAAO,KAAG,OAGvD,CAAC;AAEF,yEAAyE;AACzE,eAAO,MAAM,qBAAqB,GAAI,kBAAe,4EAC8B,CAAC;AAIpF,gEAAgE;AAChE,eAAO,MAAM,YAAY;;;;;EAAgE,CAAC;AAC1F,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD,6CAA6C;AAC7C,eAAO,MAAM,kBAAkB;;;;EAAyC,CAAC;AACzE,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,qEAAqE;AACrE,eAAO,MAAM,iBAAiB
|
|
1
|
+
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../src/common.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB;;;GAGG;AACH,eAAO,MAAM,sBAAsB,GAAI,OAAO,OAAO,KAAG,OAGvD,CAAC;AAEF,yEAAyE;AACzE,eAAO,MAAM,qBAAqB,GAAI,kBAAe,4EAC8B,CAAC;AAIpF,gEAAgE;AAChE,eAAO,MAAM,YAAY;;;;;EAAgE,CAAC;AAC1F,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD,6CAA6C;AAC7C,eAAO,MAAM,kBAAkB;;;;EAAyC,CAAC;AACzE,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,qEAAqE;AACrE,eAAO,MAAM,iBAAiB;;;EAA2B,CAAC;AAC1D,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,qDAAqD;AACrD,eAAO,MAAM,mBAAmB;;;;;EAAgE,CAAC;AACjG,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,oDAAoD;AACpD,eAAO,MAAM,gBAAgB;;;;EAAgE,CAAC;AAC9F,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,4BAA4B;AAC5B,eAAO,MAAM,iBAAiB;;;;EAAmC,CAAC;AAClE,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,mCAAmC;AACnC,eAAO,MAAM,iBAAiB;;;;EAA6C,CAAC;AAC5E,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAI5D,mCAAmC;AACnC,eAAO,MAAM,cAAc;;;iBAKsD,CAAC;AAClF,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtD,qCAAqC;AACrC,eAAO,MAAM,WAAW;;;;;;iBAMtB,CAAC;AACH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEhD,4DAA4D;AAC5D,eAAO,MAAM,gBAAgB;;;iBAG3B,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC"}
|
package/dist/common.js
CHANGED
|
@@ -24,30 +24,23 @@ export const genderSchema = z.enum(['male', 'female', 'non_binary', 'prefer_not_
|
|
|
24
24
|
/** Who the user is interested in meeting. */
|
|
25
25
|
export const interestedInSchema = z.enum(['male', 'female', 'everyone']);
|
|
26
26
|
/** Swipe / interaction action a user can take on another profile. */
|
|
27
|
-
export const swipeActionSchema = z.enum(['like', '
|
|
27
|
+
export const swipeActionSchema = z.enum(['like', 'pass']);
|
|
28
28
|
/** Current marital / relationship history status. */
|
|
29
|
-
export const maritalStatusSchema = z.enum([
|
|
30
|
-
'never_married',
|
|
31
|
-
'divorced',
|
|
32
|
-
'widowed',
|
|
33
|
-
'separated',
|
|
34
|
-
]);
|
|
29
|
+
export const maritalStatusSchema = z.enum(['never_married', 'divorced', 'widowed', 'separated']);
|
|
35
30
|
/** What the user is looking for on the platform. */
|
|
36
|
-
export const lookingForSchema = z.enum([
|
|
37
|
-
'serious_relationship',
|
|
38
|
-
'friendship',
|
|
39
|
-
'open_to_all',
|
|
40
|
-
]);
|
|
31
|
+
export const lookingForSchema = z.enum(['serious_relationship', 'friendship', 'open_to_all']);
|
|
41
32
|
/** Message content type. */
|
|
42
33
|
export const messageTypeSchema = z.enum(['text', 'image', 'gif']);
|
|
43
34
|
/** Conversation / match status. */
|
|
44
35
|
export const matchStatusSchema = z.enum(['active', 'unmatched', 'blocked']);
|
|
45
36
|
// ─── Shared sub-schemas ──────────────────────────────────────────────────────
|
|
46
37
|
/** Age range preference filter. */
|
|
47
|
-
export const ageRangeSchema = z
|
|
38
|
+
export const ageRangeSchema = z
|
|
39
|
+
.object({
|
|
48
40
|
min: z.number().int().min(18).max(100),
|
|
49
41
|
max: z.number().int().min(18).max(100),
|
|
50
|
-
})
|
|
42
|
+
})
|
|
43
|
+
.refine((r) => r.min <= r.max, 'min age must be less than or equal to max age');
|
|
51
44
|
/** A single dating profile photo. */
|
|
52
45
|
export const photoSchema = z.object({
|
|
53
46
|
url: z.string().trim().min(1),
|
package/dist/common.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.js","sourceRoot":"","sources":["../src/common.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,gFAAgF;AAEhF;;;GAGG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,KAAc,EAAW,EAAE;IAChE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,SAAS,CAAC;IACvE,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,yEAAyE;AACzE,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,SAAS,GAAG,GAAG,EAAE,EAAE,CACvD,CAAC,CAAC,UAAU,CAAC,sBAAsB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;AAEpF,gFAAgF;AAEhF,gEAAgE;AAChE,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,mBAAmB,CAAC,CAAC,CAAC;AAG1F,6CAA6C;AAC7C,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC;AAGzE,qEAAqE;AACrE,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"common.js","sourceRoot":"","sources":["../src/common.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * dating-schema — Shared helpers and core enums\n *\n * These are the stable building blocks reused across all dating schemas.\n *\n * @module dating-schema/common\n */\n\nimport { z } from 'zod';\n\n// ─── String helpers ──────────────────────────────────────────────────────────\n\n/**\n * Converts empty / whitespace-only strings to `undefined`\n * so Zod `.optional()` treats them as \"not provided\".\n */\nexport const emptyStringToUndefined = (value: unknown): unknown => {\n if (typeof value === 'string' && value.trim() === '') return undefined;\n return value;\n};\n\n/** Optional trimmed string. Empty strings are coerced to `undefined`. */\nexport const optionalTrimmedString = (maxLength = 100) =>\n z.preprocess(emptyStringToUndefined, z.string().trim().max(maxLength).optional());\n\n// ─── Core enums ──────────────────────────────────────────────────────────────\n\n/** Biological / self-identified gender for a dating profile. */\nexport const genderSchema = z.enum(['male', 'female', 'non_binary', 'prefer_not_to_say']);\nexport type Gender = z.infer<typeof genderSchema>;\n\n/** Who the user is interested in meeting. */\nexport const interestedInSchema = z.enum(['male', 'female', 'everyone']);\nexport type InterestedIn = z.infer<typeof interestedInSchema>;\n\n/** Swipe / interaction action a user can take on another profile. */\nexport const swipeActionSchema = z.enum(['like', 'pass']);\nexport type SwipeAction = z.infer<typeof swipeActionSchema>;\n\n/** Current marital / relationship history status. */\nexport const maritalStatusSchema = z.enum(['never_married', 'divorced', 'widowed', 'separated']);\nexport type MaritalStatus = z.infer<typeof maritalStatusSchema>;\n\n/** What the user is looking for on the platform. */\nexport const lookingForSchema = z.enum(['serious_relationship', 'friendship', 'open_to_all']);\nexport type LookingFor = z.infer<typeof lookingForSchema>;\n\n/** Message content type. */\nexport const messageTypeSchema = z.enum(['text', 'image', 'gif']);\nexport type MessageType = z.infer<typeof messageTypeSchema>;\n\n/** Conversation / match status. */\nexport const matchStatusSchema = z.enum(['active', 'unmatched', 'blocked']);\nexport type MatchStatus = z.infer<typeof matchStatusSchema>;\n\n// ─── Shared sub-schemas ──────────────────────────────────────────────────────\n\n/** Age range preference filter. */\nexport const ageRangeSchema = z\n .object({\n min: z.number().int().min(18).max(100),\n max: z.number().int().min(18).max(100),\n })\n .refine((r) => r.min <= r.max, 'min age must be less than or equal to max age');\nexport type AgeRange = z.infer<typeof ageRangeSchema>;\n\n/** A single dating profile photo. */\nexport const photoSchema = z.object({\n url: z.string().trim().min(1),\n order: z.number().int().min(0),\n assetId: z.string().trim().optional(),\n mimeType: z.string().trim().optional(),\n sizeBytes: z.number().min(0).optional(),\n});\nexport type Photo = z.infer<typeof photoSchema>;\n\n/** Pagination query params shared across list endpoints. */\nexport const paginationSchema = z.object({\n page: z.coerce.number().int().min(1).default(1),\n limit: z.coerce.number().int().min(1).max(100).default(20),\n});\nexport type Pagination = z.infer<typeof paginationSchema>;\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -6,5 +6,10 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module dating-schema
|
|
8
8
|
*/
|
|
9
|
-
export {
|
|
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
|
+
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';
|
|
11
|
+
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 CreateProfileInput, createProfileSchema, type FullProfileData, fullProfileSchema, type UpdateProfileInput, updateProfileSchema, } from './profile.js';
|
|
13
|
+
export { type BlockBody, blockBodySchema, type ReportBody, type ReportReason, type ReportStatus, reportBodySchema, reportReasonSchema, reportStatusSchema, } from './safety.js';
|
|
14
|
+
export { type CreateSubscriptionBody, createSubscriptionBodySchema, type SubscriptionStatus, subscriptionStatusSchema, type Tenure, tenureSchema, } from './subscription.js';
|
|
10
15
|
//# sourceMappingURL=index.d.ts.map
|
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,sBAAsB,EACtB,
|
|
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;AAErB,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,KAAK,kBAAkB,EACvB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AAGtB,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
|
@@ -7,9 +7,19 @@
|
|
|
7
7
|
* @module dating-schema
|
|
8
8
|
*/
|
|
9
9
|
// ─── Common helpers and enums ────────────────────────────────────────────────
|
|
10
|
-
export {
|
|
11
|
-
// enums
|
|
12
|
-
genderSchema, interestedInSchema, swipeActionSchema, maritalStatusSchema, lookingForSchema, messageTypeSchema, matchStatusSchema,
|
|
10
|
+
export {
|
|
13
11
|
// sub-schemas
|
|
14
|
-
ageRangeSchema,
|
|
12
|
+
ageRangeSchema, emptyStringToUndefined,
|
|
13
|
+
// enums
|
|
14
|
+
genderSchema, interestedInSchema, lookingForSchema, maritalStatusSchema, matchStatusSchema, messageTypeSchema, optionalTrimmedString, paginationSchema, photoSchema, swipeActionSchema, } from './common.js';
|
|
15
|
+
// ─── Interaction schemas ─────────────────────────────────────────────────────
|
|
16
|
+
export { boostBodySchema, complimentBodySchema, imageLikeBodySchema, interactionListQuerySchema, interactionTypeSchema, rewindBodySchema, swipeBodySchema, swipeResponseSchema, } from './interactions.js';
|
|
17
|
+
// ─── Plan limits ─────────────────────────────────────────────────────────────
|
|
18
|
+
export { getMinPlanForFeature, getPlanLimit, getPlanLimits, hasRemainingQuota, isFeatureEnabled, PLAN_IDS, PLAN_LIMITS, } from './plan-limits.js';
|
|
19
|
+
// ─── Profile schemas ─────────────────────────────────────────────────────────
|
|
20
|
+
export { createProfileSchema, fullProfileSchema, updateProfileSchema, } from './profile.js';
|
|
21
|
+
// ─── Safety schemas ──────────────────────────────────────────────────────────
|
|
22
|
+
export { blockBodySchema, reportBodySchema, reportReasonSchema, reportStatusSchema, } from './safety.js';
|
|
23
|
+
// ─── Subscription schemas ────────────────────────────────────────────────────
|
|
24
|
+
export { createSubscriptionBodySchema, subscriptionStatusSchema, tenureSchema, } from './subscription.js';
|
|
15
25
|
//# sourceMappingURL=index.js.map
|
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,
|
|
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,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,EAKL,oBAAoB,EACpB,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAEhB,QAAQ,EACR,WAAW,GAIZ,MAAM,kBAAkB,CAAC;AAC1B,gFAAgF;AAChF,OAAO,EAEL,mBAAmB,EAEnB,iBAAiB,EAEjB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AAEtB,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';\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 FeatureKey,\n type FilterLevel,\n getMinPlanForFeature,\n getPlanLimit,\n getPlanLimits,\n hasRemainingQuota,\n isFeatureEnabled,\n type NumericFeatureKey,\n PLAN_IDS,\n PLAN_LIMITS,\n type PlanId,\n type PlanLimits,\n type WhoLikedYouLevel,\n} from './plan-limits.js';\n// ─── Profile schemas ─────────────────────────────────────────────────────────\nexport {\n type CreateProfileInput,\n createProfileSchema,\n type FullProfileData,\n fullProfileSchema,\n type UpdateProfileInput,\n updateProfileSchema,\n} from './profile.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"]}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dating-schema — Interaction API schemas
|
|
3
|
+
*
|
|
4
|
+
* Zod schemas for swipe, compliment, image-like, rewind, boost,
|
|
5
|
+
* and interaction list queries.
|
|
6
|
+
*
|
|
7
|
+
* @module dating-schema/interactions
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
/** Record a swipe (like or pass). */
|
|
11
|
+
export declare const swipeBodySchema: z.ZodObject<{
|
|
12
|
+
targetProfileId: z.ZodString;
|
|
13
|
+
action: z.ZodEnum<{
|
|
14
|
+
like: "like";
|
|
15
|
+
pass: "pass";
|
|
16
|
+
}>;
|
|
17
|
+
}, z.core.$strip>;
|
|
18
|
+
export type SwipeBody = z.infer<typeof swipeBodySchema>;
|
|
19
|
+
/** Swipe response — includes match info if mutual like. */
|
|
20
|
+
export declare const swipeResponseSchema: z.ZodObject<{
|
|
21
|
+
matched: z.ZodBoolean;
|
|
22
|
+
matchId: z.ZodOptional<z.ZodString>;
|
|
23
|
+
}, z.core.$strip>;
|
|
24
|
+
export type SwipeResponse = z.infer<typeof swipeResponseSchema>;
|
|
25
|
+
/** Undo last swipe. No body needed. */
|
|
26
|
+
export declare const rewindBodySchema: z.ZodObject<{}, z.core.$strip>;
|
|
27
|
+
export type RewindBody = z.infer<typeof rewindBodySchema>;
|
|
28
|
+
/** Send a compliment (auto-likes the profile). */
|
|
29
|
+
export declare const complimentBodySchema: z.ZodObject<{
|
|
30
|
+
targetProfileId: z.ZodString;
|
|
31
|
+
text: z.ZodString;
|
|
32
|
+
}, z.core.$strip>;
|
|
33
|
+
export type ComplimentBody = z.infer<typeof complimentBodySchema>;
|
|
34
|
+
/** Like/unlike a specific photo on a profile. */
|
|
35
|
+
export declare const imageLikeBodySchema: z.ZodObject<{
|
|
36
|
+
targetProfileId: z.ZodString;
|
|
37
|
+
photoIndex: z.ZodNumber;
|
|
38
|
+
}, z.core.$strip>;
|
|
39
|
+
export type ImageLikeBody = z.infer<typeof imageLikeBodySchema>;
|
|
40
|
+
/** Activate a profile boost. No body needed. */
|
|
41
|
+
export declare const boostBodySchema: z.ZodObject<{}, z.core.$strip>;
|
|
42
|
+
export type BoostBody = z.infer<typeof boostBodySchema>;
|
|
43
|
+
/** The type of interaction list to retrieve. */
|
|
44
|
+
export declare const interactionTypeSchema: z.ZodEnum<{
|
|
45
|
+
liked: "liked";
|
|
46
|
+
liked_me: "liked_me";
|
|
47
|
+
mutual: "mutual";
|
|
48
|
+
compliments_sent: "compliments_sent";
|
|
49
|
+
compliments_received: "compliments_received";
|
|
50
|
+
}>;
|
|
51
|
+
export type InteractionType = z.infer<typeof interactionTypeSchema>;
|
|
52
|
+
/** Query params for interaction list endpoints. */
|
|
53
|
+
export declare const interactionListQuerySchema: z.ZodObject<{
|
|
54
|
+
page: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
55
|
+
limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
56
|
+
type: z.ZodEnum<{
|
|
57
|
+
liked: "liked";
|
|
58
|
+
liked_me: "liked_me";
|
|
59
|
+
mutual: "mutual";
|
|
60
|
+
compliments_sent: "compliments_sent";
|
|
61
|
+
compliments_received: "compliments_received";
|
|
62
|
+
}>;
|
|
63
|
+
}, z.core.$strip>;
|
|
64
|
+
export type InteractionListQuery = z.infer<typeof interactionListQuerySchema>;
|
|
65
|
+
//# sourceMappingURL=interactions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactions.d.ts","sourceRoot":"","sources":["../src/interactions.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,qCAAqC;AACrC,eAAO,MAAM,eAAe;;;;;;iBAG1B,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD,2DAA2D;AAC3D,eAAO,MAAM,mBAAmB;;;iBAG9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAIhE,uCAAuC;AACvC,eAAO,MAAM,gBAAgB,gCAAe,CAAC;AAC7C,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAI1D,kDAAkD;AAClD,eAAO,MAAM,oBAAoB;;;iBAG/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAIlE,iDAAiD;AACjD,eAAO,MAAM,mBAAmB;;;iBAG9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAIhE,gDAAgD;AAChD,eAAO,MAAM,eAAe,gCAAe,CAAC;AAC5C,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAIxD,gDAAgD;AAChD,eAAO,MAAM,qBAAqB;;;;;;EAMhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,mDAAmD;AACnD,eAAO,MAAM,0BAA0B;;;;;;;;;;iBAErC,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dating-schema — Interaction API schemas
|
|
3
|
+
*
|
|
4
|
+
* Zod schemas for swipe, compliment, image-like, rewind, boost,
|
|
5
|
+
* and interaction list queries.
|
|
6
|
+
*
|
|
7
|
+
* @module dating-schema/interactions
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
import { paginationSchema, swipeActionSchema } from './common.js';
|
|
11
|
+
// ─── Swipe ───────────────────────────────────────────────────────────────────
|
|
12
|
+
/** Record a swipe (like or pass). */
|
|
13
|
+
export const swipeBodySchema = z.object({
|
|
14
|
+
targetProfileId: z.string().trim().min(1),
|
|
15
|
+
action: swipeActionSchema,
|
|
16
|
+
});
|
|
17
|
+
/** Swipe response — includes match info if mutual like. */
|
|
18
|
+
export const swipeResponseSchema = z.object({
|
|
19
|
+
matched: z.boolean(),
|
|
20
|
+
matchId: z.string().optional(),
|
|
21
|
+
});
|
|
22
|
+
// ─── Rewind ──────────────────────────────────────────────────────────────────
|
|
23
|
+
/** Undo last swipe. No body needed. */
|
|
24
|
+
export const rewindBodySchema = z.object({});
|
|
25
|
+
// ─── Compliment ──────────────────────────────────────────────────────────────
|
|
26
|
+
/** Send a compliment (auto-likes the profile). */
|
|
27
|
+
export const complimentBodySchema = z.object({
|
|
28
|
+
targetProfileId: z.string().trim().min(1),
|
|
29
|
+
text: z.string().trim().min(1).max(300),
|
|
30
|
+
});
|
|
31
|
+
// ─── Image Like ──────────────────────────────────────────────────────────────
|
|
32
|
+
/** Like/unlike a specific photo on a profile. */
|
|
33
|
+
export const imageLikeBodySchema = z.object({
|
|
34
|
+
targetProfileId: z.string().trim().min(1),
|
|
35
|
+
photoIndex: z.number().int().min(0).max(5),
|
|
36
|
+
});
|
|
37
|
+
// ─── Boost ───────────────────────────────────────────────────────────────────
|
|
38
|
+
/** Activate a profile boost. No body needed. */
|
|
39
|
+
export const boostBodySchema = z.object({});
|
|
40
|
+
// ─── Interaction List Queries ────────────────────────────────────────────────
|
|
41
|
+
/** The type of interaction list to retrieve. */
|
|
42
|
+
export const interactionTypeSchema = z.enum([
|
|
43
|
+
'liked',
|
|
44
|
+
'liked_me',
|
|
45
|
+
'mutual',
|
|
46
|
+
'compliments_sent',
|
|
47
|
+
'compliments_received',
|
|
48
|
+
]);
|
|
49
|
+
/** Query params for interaction list endpoints. */
|
|
50
|
+
export const interactionListQuerySchema = paginationSchema.extend({
|
|
51
|
+
type: interactionTypeSchema,
|
|
52
|
+
});
|
|
53
|
+
//# sourceMappingURL=interactions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactions.js","sourceRoot":"","sources":["../src/interactions.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAElE,gFAAgF;AAEhF,qCAAqC;AACrC,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACzC,MAAM,EAAE,iBAAiB;CAC1B,CAAC,CAAC;AAGH,2DAA2D;AAC3D,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;IACpB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC/B,CAAC,CAAC;AAGH,gFAAgF;AAEhF,uCAAuC;AACvC,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAG7C,gFAAgF;AAEhF,kDAAkD;AAClD,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACzC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;CACxC,CAAC,CAAC;AAGH,gFAAgF;AAEhF,iDAAiD;AACjD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACzC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;CAC3C,CAAC,CAAC;AAGH,gFAAgF;AAEhF,gDAAgD;AAChD,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAG5C,gFAAgF;AAEhF,gDAAgD;AAChD,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,IAAI,CAAC;IAC1C,OAAO;IACP,UAAU;IACV,QAAQ;IACR,kBAAkB;IAClB,sBAAsB;CACvB,CAAC,CAAC;AAGH,mDAAmD;AACnD,MAAM,CAAC,MAAM,0BAA0B,GAAG,gBAAgB,CAAC,MAAM,CAAC;IAChE,IAAI,EAAE,qBAAqB;CAC5B,CAAC,CAAC","sourcesContent":["/**\n * dating-schema — Interaction API schemas\n *\n * Zod schemas for swipe, compliment, image-like, rewind, boost,\n * and interaction list queries.\n *\n * @module dating-schema/interactions\n */\n\nimport { z } from 'zod';\nimport { paginationSchema, swipeActionSchema } from './common.js';\n\n// ─── Swipe ───────────────────────────────────────────────────────────────────\n\n/** Record a swipe (like or pass). */\nexport const swipeBodySchema = z.object({\n targetProfileId: z.string().trim().min(1),\n action: swipeActionSchema,\n});\nexport type SwipeBody = z.infer<typeof swipeBodySchema>;\n\n/** Swipe response — includes match info if mutual like. */\nexport const swipeResponseSchema = z.object({\n matched: z.boolean(),\n matchId: z.string().optional(),\n});\nexport type SwipeResponse = z.infer<typeof swipeResponseSchema>;\n\n// ─── Rewind ──────────────────────────────────────────────────────────────────\n\n/** Undo last swipe. No body needed. */\nexport const rewindBodySchema = z.object({});\nexport type RewindBody = z.infer<typeof rewindBodySchema>;\n\n// ─── Compliment ──────────────────────────────────────────────────────────────\n\n/** Send a compliment (auto-likes the profile). */\nexport const complimentBodySchema = z.object({\n targetProfileId: z.string().trim().min(1),\n text: z.string().trim().min(1).max(300),\n});\nexport type ComplimentBody = z.infer<typeof complimentBodySchema>;\n\n// ─── Image Like ──────────────────────────────────────────────────────────────\n\n/** Like/unlike a specific photo on a profile. */\nexport const imageLikeBodySchema = z.object({\n targetProfileId: z.string().trim().min(1),\n photoIndex: z.number().int().min(0).max(5),\n});\nexport type ImageLikeBody = z.infer<typeof imageLikeBodySchema>;\n\n// ─── Boost ───────────────────────────────────────────────────────────────────\n\n/** Activate a profile boost. No body needed. */\nexport const boostBodySchema = z.object({});\nexport type BoostBody = z.infer<typeof boostBodySchema>;\n\n// ─── Interaction List Queries ────────────────────────────────────────────────\n\n/** The type of interaction list to retrieve. */\nexport const interactionTypeSchema = z.enum([\n 'liked',\n 'liked_me',\n 'mutual',\n 'compliments_sent',\n 'compliments_received',\n]);\nexport type InteractionType = z.infer<typeof interactionTypeSchema>;\n\n/** Query params for interaction list endpoints. */\nexport const interactionListQuerySchema = paginationSchema.extend({\n type: interactionTypeSchema,\n});\nexport type InteractionListQuery = z.infer<typeof interactionListQuerySchema>;\n"]}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dating-schema — Plan limits configuration
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for feature gating by pricing plan.
|
|
5
|
+
* Both backend middleware and frontend UI read from this config.
|
|
6
|
+
*
|
|
7
|
+
* To add/remove a gated feature:
|
|
8
|
+
* 1. Add/remove the key in PlanLimits interface
|
|
9
|
+
* 2. Set values for each plan in PLAN_LIMITS
|
|
10
|
+
* 3. Backend: add enforcePlanLimit('featureKey') middleware to the route
|
|
11
|
+
* That's it — no scattered if-checks needed.
|
|
12
|
+
*
|
|
13
|
+
* @module dating-schema/plan-limits
|
|
14
|
+
*/
|
|
15
|
+
/** The 4 pricing plans. */
|
|
16
|
+
export type PlanId = 'spark' | 'gold' | 'diamond' | 'platinum';
|
|
17
|
+
/** Filter capability levels by plan. */
|
|
18
|
+
export type FilterLevel = 'basic' | 'advanced' | 'ai';
|
|
19
|
+
/** "Who liked you" visibility levels by plan. */
|
|
20
|
+
export type WhoLikedYouLevel = 'none' | 'blurred' | 'full' | 'realtime';
|
|
21
|
+
/** All numeric limit keys (daily/periodic counters enforced server-side). */
|
|
22
|
+
export type NumericFeatureKey = 'dailySwipes' | 'dailyCompliments' | 'dailyRewinds' | 'dailyProfileVisits' | 'maxChatThreads' | 'maxActiveIntents' | 'monthlyBoosts' | 'weeklyBoosts';
|
|
23
|
+
/** All boolean feature keys (on/off per plan). */
|
|
24
|
+
export type BooleanFeatureKey = 'readReceipts' | 'incognitoMode' | 'voiceMessages' | 'voiceCalls' | 'videoCalls' | 'showAds' | 'calendarSync' | 'priorityVisibility' | 'autoBoost';
|
|
25
|
+
/** All string-enum feature keys. */
|
|
26
|
+
export type EnumFeatureKey = 'filterLevel' | 'whoLikedYou';
|
|
27
|
+
/** Union of all feature keys that can be gated. */
|
|
28
|
+
export type FeatureKey = NumericFeatureKey | BooleanFeatureKey | EnumFeatureKey;
|
|
29
|
+
/** Complete plan limits definition. */
|
|
30
|
+
export interface PlanLimits {
|
|
31
|
+
dailySwipes: number;
|
|
32
|
+
dailyCompliments: number;
|
|
33
|
+
dailyRewinds: number;
|
|
34
|
+
dailyProfileVisits: number;
|
|
35
|
+
maxChatThreads: number;
|
|
36
|
+
maxActiveIntents: number;
|
|
37
|
+
monthlyBoosts: number;
|
|
38
|
+
weeklyBoosts: number;
|
|
39
|
+
filterLevel: FilterLevel;
|
|
40
|
+
whoLikedYou: WhoLikedYouLevel;
|
|
41
|
+
readReceipts: boolean;
|
|
42
|
+
incognitoMode: boolean;
|
|
43
|
+
voiceMessages: boolean;
|
|
44
|
+
voiceCalls: boolean;
|
|
45
|
+
videoCalls: boolean;
|
|
46
|
+
showAds: boolean;
|
|
47
|
+
calendarSync: boolean;
|
|
48
|
+
priorityVisibility: boolean;
|
|
49
|
+
autoBoost: boolean;
|
|
50
|
+
}
|
|
51
|
+
export declare const PLAN_LIMITS: Record<PlanId, PlanLimits>;
|
|
52
|
+
/** All valid plan IDs. */
|
|
53
|
+
export declare const PLAN_IDS: PlanId[];
|
|
54
|
+
/** Get the limits object for a plan. */
|
|
55
|
+
export declare function getPlanLimits(planId: PlanId): PlanLimits;
|
|
56
|
+
/** Get a specific limit value for a plan + feature. */
|
|
57
|
+
export declare function getPlanLimit<K extends FeatureKey>(planId: PlanId, feature: K): PlanLimits[K];
|
|
58
|
+
/**
|
|
59
|
+
* Check if a boolean feature is enabled for a plan.
|
|
60
|
+
* Returns `false` for non-boolean features.
|
|
61
|
+
*/
|
|
62
|
+
export declare function isFeatureEnabled(planId: PlanId, feature: BooleanFeatureKey): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Check if a numeric feature has remaining capacity.
|
|
65
|
+
* Returns `true` if the limit is Infinity or greater than current usage.
|
|
66
|
+
*/
|
|
67
|
+
export declare function hasRemainingQuota(planId: PlanId, feature: NumericFeatureKey, currentUsage: number): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Get the minimum plan required for a boolean feature.
|
|
70
|
+
* Returns undefined if no plan enables it.
|
|
71
|
+
*/
|
|
72
|
+
export declare function getMinPlanForFeature(feature: BooleanFeatureKey): PlanId | undefined;
|
|
73
|
+
//# sourceMappingURL=plan-limits.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan-limits.d.ts","sourceRoot":"","sources":["../src/plan-limits.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,2BAA2B;AAC3B,MAAM,MAAM,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC;AAE/D,wCAAwC;AACxC,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,UAAU,GAAG,IAAI,CAAC;AAEtD,iDAAiD;AACjD,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,UAAU,CAAC;AAExE,6EAA6E;AAC7E,MAAM,MAAM,iBAAiB,GACzB,aAAa,GACb,kBAAkB,GAClB,cAAc,GACd,oBAAoB,GACpB,gBAAgB,GAChB,kBAAkB,GAClB,eAAe,GACf,cAAc,CAAC;AAEnB,kDAAkD;AAClD,MAAM,MAAM,iBAAiB,GACzB,cAAc,GACd,eAAe,GACf,eAAe,GACf,YAAY,GACZ,YAAY,GACZ,SAAS,GACT,cAAc,GACd,oBAAoB,GACpB,WAAW,CAAC;AAEhB,oCAAoC;AACpC,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG,aAAa,CAAC;AAE3D,mDAAmD;AACnD,MAAM,MAAM,UAAU,GAAG,iBAAiB,GAAG,iBAAiB,GAAG,cAAc,CAAC;AAEhF,uCAAuC;AACvC,MAAM,WAAW,UAAU;IAEzB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IAGrB,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,gBAAgB,CAAC;IAG9B,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,OAAO,CAAC;IACtB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,SAAS,EAAE,OAAO,CAAC;CACpB;AAID,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAwFzC,CAAC;AAIX,0BAA0B;AAC1B,eAAO,MAAM,QAAQ,EAAE,MAAM,EAA6C,CAAC;AAE3E,wCAAwC;AACxC,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAExD;AAED,uDAAuD;AACvD,wBAAgB,YAAY,CAAC,CAAC,SAAS,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAE5F;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAEpF;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,iBAAiB,EAC1B,YAAY,EAAE,MAAM,GACnB,OAAO,CAGT;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,GAAG,SAAS,CAEnF"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dating-schema — Plan limits configuration
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for feature gating by pricing plan.
|
|
5
|
+
* Both backend middleware and frontend UI read from this config.
|
|
6
|
+
*
|
|
7
|
+
* To add/remove a gated feature:
|
|
8
|
+
* 1. Add/remove the key in PlanLimits interface
|
|
9
|
+
* 2. Set values for each plan in PLAN_LIMITS
|
|
10
|
+
* 3. Backend: add enforcePlanLimit('featureKey') middleware to the route
|
|
11
|
+
* That's it — no scattered if-checks needed.
|
|
12
|
+
*
|
|
13
|
+
* @module dating-schema/plan-limits
|
|
14
|
+
*/
|
|
15
|
+
// ─── Plan Limits Config ──────────────────────────────────────────────────────
|
|
16
|
+
export const PLAN_LIMITS = {
|
|
17
|
+
spark: {
|
|
18
|
+
dailySwipes: 20,
|
|
19
|
+
dailyCompliments: 1,
|
|
20
|
+
dailyRewinds: 0,
|
|
21
|
+
dailyProfileVisits: 10,
|
|
22
|
+
maxChatThreads: 3,
|
|
23
|
+
maxActiveIntents: 2,
|
|
24
|
+
monthlyBoosts: 0,
|
|
25
|
+
weeklyBoosts: 0,
|
|
26
|
+
filterLevel: 'basic',
|
|
27
|
+
whoLikedYou: 'none',
|
|
28
|
+
readReceipts: false,
|
|
29
|
+
incognitoMode: false,
|
|
30
|
+
voiceMessages: false,
|
|
31
|
+
voiceCalls: false,
|
|
32
|
+
videoCalls: false,
|
|
33
|
+
showAds: true,
|
|
34
|
+
calendarSync: false,
|
|
35
|
+
priorityVisibility: false,
|
|
36
|
+
autoBoost: false,
|
|
37
|
+
},
|
|
38
|
+
gold: {
|
|
39
|
+
dailySwipes: 100,
|
|
40
|
+
dailyCompliments: 10,
|
|
41
|
+
dailyRewinds: 5,
|
|
42
|
+
dailyProfileVisits: 50,
|
|
43
|
+
maxChatThreads: Infinity,
|
|
44
|
+
maxActiveIntents: 3,
|
|
45
|
+
monthlyBoosts: 1,
|
|
46
|
+
weeklyBoosts: 0,
|
|
47
|
+
filterLevel: 'advanced',
|
|
48
|
+
whoLikedYou: 'blurred',
|
|
49
|
+
readReceipts: false,
|
|
50
|
+
incognitoMode: false,
|
|
51
|
+
voiceMessages: true,
|
|
52
|
+
voiceCalls: false,
|
|
53
|
+
videoCalls: false,
|
|
54
|
+
showAds: false,
|
|
55
|
+
calendarSync: false,
|
|
56
|
+
priorityVisibility: false,
|
|
57
|
+
autoBoost: false,
|
|
58
|
+
},
|
|
59
|
+
diamond: {
|
|
60
|
+
dailySwipes: 300,
|
|
61
|
+
dailyCompliments: 25,
|
|
62
|
+
dailyRewinds: Infinity,
|
|
63
|
+
dailyProfileVisits: Infinity,
|
|
64
|
+
maxChatThreads: Infinity,
|
|
65
|
+
maxActiveIntents: 5,
|
|
66
|
+
monthlyBoosts: 0,
|
|
67
|
+
weeklyBoosts: 1,
|
|
68
|
+
filterLevel: 'ai',
|
|
69
|
+
whoLikedYou: 'full',
|
|
70
|
+
readReceipts: true,
|
|
71
|
+
incognitoMode: false,
|
|
72
|
+
voiceMessages: true,
|
|
73
|
+
voiceCalls: true,
|
|
74
|
+
videoCalls: true,
|
|
75
|
+
showAds: false,
|
|
76
|
+
calendarSync: false,
|
|
77
|
+
priorityVisibility: false,
|
|
78
|
+
autoBoost: false,
|
|
79
|
+
},
|
|
80
|
+
platinum: {
|
|
81
|
+
dailySwipes: Infinity,
|
|
82
|
+
dailyCompliments: 60,
|
|
83
|
+
dailyRewinds: Infinity,
|
|
84
|
+
dailyProfileVisits: Infinity,
|
|
85
|
+
maxChatThreads: Infinity,
|
|
86
|
+
maxActiveIntents: 7, // all intents
|
|
87
|
+
monthlyBoosts: 0,
|
|
88
|
+
weeklyBoosts: 0, // auto-boost instead
|
|
89
|
+
filterLevel: 'ai',
|
|
90
|
+
whoLikedYou: 'realtime',
|
|
91
|
+
readReceipts: true,
|
|
92
|
+
incognitoMode: true,
|
|
93
|
+
voiceMessages: true,
|
|
94
|
+
voiceCalls: true,
|
|
95
|
+
videoCalls: true,
|
|
96
|
+
showAds: false,
|
|
97
|
+
calendarSync: true,
|
|
98
|
+
priorityVisibility: true,
|
|
99
|
+
autoBoost: true,
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
103
|
+
/** All valid plan IDs. */
|
|
104
|
+
export const PLAN_IDS = ['spark', 'gold', 'diamond', 'platinum'];
|
|
105
|
+
/** Get the limits object for a plan. */
|
|
106
|
+
export function getPlanLimits(planId) {
|
|
107
|
+
return PLAN_LIMITS[planId];
|
|
108
|
+
}
|
|
109
|
+
/** Get a specific limit value for a plan + feature. */
|
|
110
|
+
export function getPlanLimit(planId, feature) {
|
|
111
|
+
return PLAN_LIMITS[planId][feature];
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Check if a boolean feature is enabled for a plan.
|
|
115
|
+
* Returns `false` for non-boolean features.
|
|
116
|
+
*/
|
|
117
|
+
export function isFeatureEnabled(planId, feature) {
|
|
118
|
+
return PLAN_LIMITS[planId][feature];
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Check if a numeric feature has remaining capacity.
|
|
122
|
+
* Returns `true` if the limit is Infinity or greater than current usage.
|
|
123
|
+
*/
|
|
124
|
+
export function hasRemainingQuota(planId, feature, currentUsage) {
|
|
125
|
+
const limit = PLAN_LIMITS[planId][feature];
|
|
126
|
+
return limit === Infinity || currentUsage < limit;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Get the minimum plan required for a boolean feature.
|
|
130
|
+
* Returns undefined if no plan enables it.
|
|
131
|
+
*/
|
|
132
|
+
export function getMinPlanForFeature(feature) {
|
|
133
|
+
return PLAN_IDS.find((id) => PLAN_LIMITS[id][feature] === true);
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=plan-limits.js.map
|
|
@@ -0,0 +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"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"01-hero-identity.d.ts","sourceRoot":"","sources":["../../src/profile-fields/01-hero-identity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,eAAO,MAAM,YAAY,EAAE,UAsP1B,CAAC"}
|