founder-schema 0.19.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -0
- package/dist/access/permissions.d.ts +3 -3
- package/dist/access/permissions.d.ts.map +1 -1
- package/dist/access/permissions.js.map +1 -1
- package/dist/core/common.d.ts +42 -15
- package/dist/core/common.d.ts.map +1 -1
- package/dist/core/common.js +58 -15
- package/dist/core/common.js.map +1 -1
- package/dist/core/deletion.d.ts +40 -0
- package/dist/core/deletion.d.ts.map +1 -0
- package/dist/core/deletion.js +39 -0
- package/dist/core/deletion.js.map +1 -0
- package/dist/domains/audit/audit.d.ts +36 -12
- package/dist/domains/audit/audit.d.ts.map +1 -1
- package/dist/domains/audit/audit.js +9 -10
- package/dist/domains/audit/audit.js.map +1 -1
- package/dist/domains/billing/billing.d.ts +29 -13
- package/dist/domains/billing/billing.d.ts.map +1 -1
- package/dist/domains/billing/billing.js +2 -3
- package/dist/domains/billing/billing.js.map +1 -1
- package/dist/domains/chat/chat.d.ts +19 -5
- package/dist/domains/chat/chat.d.ts.map +1 -1
- package/dist/domains/chat/chat.js +10 -10
- package/dist/domains/chat/chat.js.map +1 -1
- package/dist/domains/communities/communities.d.ts +95 -57
- package/dist/domains/communities/communities.d.ts.map +1 -1
- package/dist/domains/contributions/contributions.d.ts +28 -12
- package/dist/domains/contributions/contributions.d.ts.map +1 -1
- package/dist/domains/contributions/contributions.js +3 -0
- package/dist/domains/contributions/contributions.js.map +1 -1
- package/dist/domains/discover/discover.d.ts +2 -2
- package/dist/domains/feed/feed.d.ts +111 -63
- package/dist/domains/feed/feed.d.ts.map +1 -1
- package/dist/domains/feed/feed.js +3 -0
- package/dist/domains/feed/feed.js.map +1 -1
- package/dist/domains/location/areas.d.ts +7 -0
- package/dist/domains/location/areas.d.ts.map +1 -1
- package/dist/domains/location/areas.js +3 -0
- package/dist/domains/location/areas.js.map +1 -1
- package/dist/domains/media/media.d.ts +22 -0
- package/dist/domains/media/media.d.ts.map +1 -1
- package/dist/domains/media/media.js +20 -0
- package/dist/domains/media/media.js.map +1 -1
- package/dist/domains/members/members.d.ts +27 -9
- package/dist/domains/members/members.d.ts.map +1 -1
- package/dist/domains/members/members.js +9 -10
- package/dist/domains/members/members.js.map +1 -1
- package/dist/domains/membership/membership.d.ts +42 -1
- package/dist/domains/membership/membership.d.ts.map +1 -1
- package/dist/domains/membership/membership.js +42 -1
- package/dist/domains/membership/membership.js.map +1 -1
- package/dist/domains/moderation/moderation.d.ts +8 -2
- package/dist/domains/moderation/moderation.d.ts.map +1 -1
- package/dist/domains/moderation/moderation.js +3 -6
- package/dist/domains/moderation/moderation.js.map +1 -1
- package/dist/domains/notifications/notifications.d.ts +10 -6
- package/dist/domains/notifications/notifications.d.ts.map +1 -1
- package/dist/domains/onboarding/onboarding-answers.js +1 -1
- package/dist/domains/onboarding/onboarding-answers.js.map +1 -1
- package/dist/domains/onboarding/onboarding.d.ts +11 -10
- package/dist/domains/onboarding/onboarding.d.ts.map +1 -1
- package/dist/domains/onboarding/onboarding.js +16 -9
- package/dist/domains/onboarding/onboarding.js.map +1 -1
- package/dist/domains/people/person.d.ts +54 -0
- package/dist/domains/people/person.d.ts.map +1 -0
- package/dist/domains/people/person.js +73 -0
- package/dist/domains/people/person.js.map +1 -0
- package/dist/domains/products/products.d.ts +62 -33
- package/dist/domains/products/products.d.ts.map +1 -1
- package/dist/domains/products/products.js +3 -0
- package/dist/domains/products/products.js.map +1 -1
- package/dist/domains/profile/founder-profile.d.ts +36 -19
- package/dist/domains/profile/founder-profile.d.ts.map +1 -1
- package/dist/domains/profile/founder-profile.js +43 -21
- package/dist/domains/profile/founder-profile.js.map +1 -1
- package/dist/domains/reviews/reviews.d.ts +25 -15
- package/dist/domains/reviews/reviews.d.ts.map +1 -1
- package/dist/domains/support/support.d.ts +47 -10
- package/dist/domains/support/support.d.ts.map +1 -1
- package/dist/domains/support/support.js +4 -2
- package/dist/domains/support/support.js.map +1 -1
- package/dist/domains/team/team.d.ts +9 -3
- package/dist/domains/team/team.d.ts.map +1 -1
- package/dist/domains/team/team.js +3 -6
- package/dist/domains/team/team.js.map +1 -1
- package/dist/index.d.ts +11 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -9
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
- package/dist/account.d.ts +0 -40
- package/dist/account.d.ts.map +0 -1
- package/dist/account.js +0 -39
- package/dist/account.js.map +0 -1
- package/dist/chat.d.ts +0 -187
- package/dist/chat.d.ts.map +0 -1
- package/dist/chat.js +0 -189
- package/dist/chat.js.map +0 -1
- package/dist/common.d.ts +0 -304
- package/dist/common.d.ts.map +0 -1
- package/dist/common.js +0 -340
- package/dist/common.js.map +0 -1
- package/dist/discover.d.ts +0 -245
- package/dist/discover.d.ts.map +0 -1
- package/dist/discover.js +0 -68
- package/dist/discover.js.map +0 -1
- package/dist/errors.d.ts +0 -85
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js +0 -89
- package/dist/errors.js.map +0 -1
- package/dist/feed.d.ts +0 -1658
- package/dist/feed.d.ts.map +0 -1
- package/dist/feed.js +0 -623
- package/dist/feed.js.map +0 -1
- package/dist/founder-profile.d.ts +0 -387
- package/dist/founder-profile.d.ts.map +0 -1
- package/dist/founder-profile.js +0 -180
- package/dist/founder-profile.js.map +0 -1
- package/dist/limits.d.ts +0 -76
- package/dist/limits.d.ts.map +0 -1
- package/dist/limits.js +0 -84
- package/dist/limits.js.map +0 -1
- package/dist/onboarding.d.ts +0 -1018
- package/dist/onboarding.d.ts.map +0 -1
- package/dist/onboarding.js +0 -717
- package/dist/onboarding.js.map +0 -1
- package/dist/responses/common.d.ts +0 -167
- package/dist/responses/common.d.ts.map +0 -1
- package/dist/responses/common.js +0 -67
- package/dist/responses/common.js.map +0 -1
- package/dist/responses/index.d.ts +0 -7
- package/dist/responses/index.d.ts.map +0 -1
- package/dist/responses/index.js +0 -7
- package/dist/responses/index.js.map +0 -1
- package/dist/uploads.d.ts +0 -113
- package/dist/uploads.d.ts.map +0 -1
- package/dist/uploads.js +0 -106
- package/dist/uploads.js.map +0 -1
- package/dist/validation.d.ts +0 -136
- package/dist/validation.d.ts.map +0 -1
- package/dist/validation.js +0 -142
- package/dist/validation.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"billing.js","sourceRoot":"","sources":["../../../src/domains/billing/billing.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * founder-schema: buying, paying, invoices, refunds and coupons (0.12.0)\n *\n * POST /api/v1/billing/quote quoteBodySchema -> quoteSchema\n * POST /api/v1/billing/orders createOrderBodySchema -> createOrderResponseSchema\n * GET /api/v1/billing/orders/:orderId orderStateSchema (polled while \"processing\")\n * POST /api/v1/billing/orders/:orderId/confirm confirmOrderBodySchema -> orderStateSchema\n * GET /api/v1/billing/payments paymentPageSchema (mine)\n * GET /api/v1/billing/payments/:orderId paymentDetailSchema (mine, with the invoice)\n *\n * Staff (by the ability: support reads; managers refund and run coupons):\n * GET /api/v1/staff/payments staffPaymentsQuerySchema -> staffPaymentPageSchema\n * GET /api/v1/staff/payments/:orderId staffPaymentDetailSchema\n * POST /api/v1/staff/payments/:orderId/refund refundPaymentBodySchema -> staffPaymentDetailSchema\n * GET /api/v1/staff/coupons couponListSchema\n * POST /api/v1/staff/coupons createCouponBodySchema -> couponSchema\n * PATCH /api/v1/staff/coupons/:couponId updateCouponBodySchema -> couponSchema\n * PUT /api/v1/members/:memberId/membership setMembershipBodySchema -> memberDetailSchema\n *\n * THE ONE RULE: THE SERVER PRICES, THE CLIENT CHOOSES. A request names what it\n * wants (an item) and maybe a coupon CODE; it never names an amount. Every\n * amount here is the server's, in integer paise, GST included.\n *\n * TWO PATHS IN, ONE GRANT. A payment reaches the server from the browser the\n * moment checkout returns (`confirm`) and from the gateway's webhook. Either\n * grants; the second is a no-op. So a member who closes the tab is still\n * granted, and `confirm` failing never means \"not paid\": the web says\n * \"processing\" and polls the order.\n *\n * GST: the company is registered, every captured payment gets a tax invoice,\n * every refund a credit note. Where the buyer is decides the tax: in the\n * supplier's state CGST + SGST, elsewhere IGST. So checkout asks for the state.\n *\n * @module founder-schema/domains/billing\n */\n\nimport { z } from 'zod';\nimport {\n eachOnce,\n emptyStringToUndefined,\n objectIdSchema,\n paginationQuerySchema,\n} from '../../core/common.js';\nimport {\n BILLING_REASON_MAX,\n BILLING_REASON_MIN,\n COUPON_CODE_MAX,\n COUPON_CODE_MIN,\n COUPON_LABEL_MAX,\n COUPON_LABEL_MIN,\n COUPON_PERCENT_MAX,\n COUPON_PERCENT_MIN,\n COUPON_USES_MAX,\n INVOICE_NUMBER_MAX,\n RAZORPAY_ID_MAX,\n RAZORPAY_SIGNATURE_MAX,\n} from '../../core/limits.js';\nimport { paginatedSchema } from '../../core/responses.js';\nimport { VALIDATION_MESSAGE } from '../../core/validation.js';\nimport { paiseSchema, planPeriodSchema, planTierSchema } from '../membership/membership.js';\nimport { billingDetailsSchema, gstStateCodeSchema } from './gst.js';\n\nexport {\n type BillingDetails,\n billingDetailsSchema,\n GST_RATE_PERCENT,\n GST_STATE_CODE_VALUES,\n GST_STATES,\n type GstStateCode,\n gstinChecksumValid,\n gstinSchema,\n gstStateCodeSchema,\n gstStateName,\n} from './gst.js';\n\n// ─── What can be bought ──────────────────────────────────────────────────────\n\n/** ⚠ Stored on every order: append only. */\nexport const PURCHASE_KIND_VALUES = ['membership', 'plan', 'upgrade'] as const;\nexport type PurchaseKind = (typeof PURCHASE_KIND_VALUES)[number];\n\n/**\n * The thing asked for.\n *\n * membership Rs 99, once\n * plan a month or a year of Premium or Business, appended\n * upgrade the Premium time left, turned into Business, for the difference\n */\nexport const purchaseItemSchema = z.discriminatedUnion('kind', [\n z.object({ kind: z.literal('membership') }),\n z.object({ kind: z.literal('plan'), tier: planTierSchema, period: planPeriodSchema }),\n z.object({ kind: z.literal('upgrade') }),\n]);\nexport type PurchaseItem = z.infer<typeof purchaseItemSchema>;\n\n/** A coupon code as typed: letters, digits, hyphens; compared upper-case. */\nexport const couponCodeSchema = z\n .string()\n .trim()\n .min(COUPON_CODE_MIN)\n .max(COUPON_CODE_MAX)\n .regex(/^[A-Za-z0-9-]+$/, VALIDATION_MESSAGE.couponCodeInvalid)\n .transform((v) => v.toUpperCase());\n\n// ─── Quote ───────────────────────────────────────────────────────────────────\n\n/**\n * The tax inside a total. `taxable + cgst + sgst + igst = total`; either\n * CGST + SGST (buyer in the supplier's state) or IGST, never both.\n */\nexport const taxSplitSchema = z.object({\n ratePercent: z.number().int().positive(),\n taxable: paiseSchema,\n cgst: paiseSchema,\n sgst: paiseSchema,\n igst: paiseSchema,\n total: paiseSchema,\n});\nexport type TaxSplit = z.infer<typeof taxSplitSchema>;\n\n/** `POST /billing/quote`. The state is optional: without it, no tax split. */\nexport const quoteBodySchema = z.object({\n item: purchaseItemSchema,\n couponCode: couponCodeSchema.optional(),\n stateCode: gstStateCodeSchema.optional(),\n});\nexport type QuoteBody = z.infer<typeof quoteBodySchema>;\n\n/** What a plan or an upgrade would do to the plan, priced now. */\nexport const planEffectSchema = z.object({\n tier: planTierSchema,\n /** When this purchase's time starts (later than now when it waits its turn). */\n startsAt: z.iso.datetime(),\n endsAt: z.iso.datetime(),\n /** For an upgrade: the days of Premium turned into Business. */\n upgradedDays: z.number().int().positive().nullable(),\n});\nexport type PlanEffect = z.infer<typeof planEffectSchema>;\n\n/** A coupon as a purchase carries it: its code and staff's name for it. */\nexport const appliedCouponSchema = z.object({ code: z.string(), label: z.string() });\nexport type AppliedCoupon = z.infer<typeof appliedCouponSchema>;\n\n/**\n * Why a captured payment was NOT applied (`grantFailed`), and so refunded\n * (0.18.0: the one list; the backend wrote two of these as loose strings and\n * the contract said `string`). Stored on the order: append only.\n *\n * AMOUNT_MISMATCH the gateway captured another amount than the price\n * ACCOUNT_DELETED paid after the account was deleted\n * COUPON_ALREADY_USED the code went to another of their orders, paid first\n * MEMBERSHIP_REQUIRED a plan, but the membership is gone (refunded, withdrawn)\n * ALREADY_MEMBER a membership, but they are a member already\n * PLAN_CHANGED an upgrade priced on a plan that has since changed\n * PLAN_NOTHING_TO_UPGRADE an upgrade with no Premium time left\n * PLAN_TERM_LIMIT past `PLAN_AHEAD_MAX_YEARS` of plan time\n * PLAN_UPGRADE_INSTEAD Business bought while on Premium (that is an upgrade)\n * GRANT_REFUSED any other refusal of the grant: still recorded and\n * refunded, never left captured for nothing (the\n * server logs which one, to add it here)\n */\nexport const GRANT_FAILURE_VALUES = [\n 'AMOUNT_MISMATCH',\n 'ACCOUNT_DELETED',\n 'COUPON_ALREADY_USED',\n 'MEMBERSHIP_REQUIRED',\n 'ALREADY_MEMBER',\n 'PLAN_CHANGED',\n 'PLAN_NOTHING_TO_UPGRADE',\n 'PLAN_TERM_LIMIT',\n 'PLAN_UPGRADE_INSTEAD',\n 'GRANT_REFUSED',\n] as const;\nexport const grantFailureSchema = z.enum(GRANT_FAILURE_VALUES);\nexport type GrantFailure = z.infer<typeof grantFailureSchema>;\n\nexport const quoteSchema = z.object({\n item: purchaseItemSchema,\n /** \"Membership\", \"Premium, 1 month\", \"Upgrade to Business\": the server's words. */\n title: z.string(),\n listPrice: paiseSchema,\n discount: paiseSchema,\n /** What would be charged. Zero for a free-membership coupon: no checkout at all. */\n total: paiseSchema,\n coupon: appliedCouponSchema.nullable(),\n /** Null for a membership. */\n plan: planEffectSchema.nullable(),\n /** Null without a state. */\n tax: taxSplitSchema.nullable(),\n refundWindowDays: z.number().int().positive(),\n});\nexport type Quote = z.infer<typeof quoteSchema>;\n\n// ─── Orders ──────────────────────────────────────────────────────────────────\n\n/**\n * Where an order stands. ⚠ Stored: append only.\n *\n * created checkout open, nothing paid yet\n * paid captured and granted; has an invoice\n * granted_free a free coupon: granted with no payment and no invoice\n * expired not paid within `ORDER_TTL_MINUTES`\n * refund_pending staff refunded it; the gateway is returning the money\n * refunded the money is back; has a credit note\n * refund_failed the gateway could not return it; staff act from its dashboard\n */\nexport const ORDER_STATUS_VALUES = [\n 'created',\n 'paid',\n 'granted_free',\n 'expired',\n 'refund_pending',\n 'refunded',\n 'refund_failed',\n] as const;\nexport const orderStatusSchema = z.enum(ORDER_STATUS_VALUES);\nexport type OrderStatus = z.infer<typeof orderStatusSchema>;\n\n/**\n * `POST /billing/orders`. Billing details are required for anything paid (the\n * invoice needs a place of supply): the server refuses a paid order without\n * them (`billing.stateCode`, VALIDATION_ERROR). A free coupon issues no\n * invoice, so it needs none (0.12.0).\n */\nexport const createOrderBodySchema = z.object({\n item: purchaseItemSchema,\n couponCode: couponCodeSchema.optional(),\n billing: billingDetailsSchema.optional(),\n});\nexport type CreateOrderBody = z.infer<typeof createOrderBodySchema>;\n\n/**\n * Either done (a free coupon granted at once) or a checkout to open. The\n * checkout fields are Razorpay Checkout's own options; identity (name, email,\n * phone) is the server's, never typed by the caller.\n */\nexport const createOrderResponseSchema = z.discriminatedUnion('status', [\n z.object({ status: z.literal('granted'), orderId: objectIdSchema }),\n z.object({\n status: z.literal('checkout'),\n orderId: objectIdSchema,\n expiresAt: z.iso.datetime(),\n checkout: z.object({\n keyId: z.string().min(1),\n razorpayOrderId: z.string().min(1),\n amount: paiseSchema,\n currency: z.literal('INR'),\n /** The merchant name on the dialog. */\n name: z.string(),\n /** What is being bought, under the name. */\n description: z.string(),\n prefill: z.object({\n name: z.string(),\n email: z.string(),\n contact: z.string().optional(),\n }),\n }),\n }),\n]);\nexport type CreateOrderResponse = z.infer<typeof createOrderResponseSchema>;\n\nexport const orderParamsSchema = z.object({ orderId: objectIdSchema });\nexport type OrderParams = z.infer<typeof orderParamsSchema>;\n\n/** What Razorpay Checkout's `handler` hands back, as it names it. */\nexport const confirmOrderBodySchema = z.object({\n razorpayOrderId: z.string().min(1).max(RAZORPAY_ID_MAX),\n razorpayPaymentId: z.string().min(1).max(RAZORPAY_ID_MAX),\n razorpaySignature: z.string().min(1).max(RAZORPAY_SIGNATURE_MAX),\n});\nexport type ConfirmOrderBody = z.infer<typeof confirmOrderBodySchema>;\n\n/** An order as its buyer polls it. */\nexport const orderStateSchema = z.object({\n orderId: objectIdSchema,\n item: purchaseItemSchema,\n status: orderStatusSchema,\n /**\n * The money was taken but what it bought could not be applied (bought\n * twice in two tabs, the plan changed while paying): it is refunded in\n * full, by itself. The client says so instead of \"done\".\n */\n notApplied: z.boolean(),\n});\nexport type OrderState = z.infer<typeof orderStateSchema>;\n\n// ─── Payments, invoices, credit notes ────────────────────────────────────────\n\n/** A party on an invoice. The supplier always has a GSTIN on a real invoice; a buyer, only on B2B. */\nexport const invoicePartySchema = z.object({\n name: z.string(),\n address: z.string().nullable(),\n gstin: z.string().nullable(),\n stateCode: gstStateCodeSchema,\n stateName: z.string(),\n});\nexport type InvoiceParty = z.infer<typeof invoicePartySchema>;\n\n/** B2B with the buyer's GSTIN, B2C without (0.18.0: the values, for the backend's model). */\nexport const INVOICE_KIND_VALUES = ['b2b', 'b2c'] as const;\nexport const invoiceKindSchema = z.enum(INVOICE_KIND_VALUES);\nexport type InvoiceKind = z.infer<typeof invoiceKindSchema>;\n\n/** A tax invoice, frozen when the payment was captured. */\nexport const invoiceSchema = z.object({\n /** e.g. `FC/26-27/000123`: sequential within a financial year, at most `INVOICE_NUMBER_MAX`. */\n number: z.string().max(INVOICE_NUMBER_MAX),\n issuedAt: z.iso.datetime(),\n /**\n * Issued where the supplier's GSTIN is not configured (dev, Razorpay test\n * mode): marked \"TEST: not a tax invoice\". Never true in production.\n */\n test: z.boolean(),\n supplier: invoicePartySchema,\n buyer: invoicePartySchema,\n kind: invoiceKindSchema,\n /** The service's accounting code (SAC). */\n sac: z.string(),\n description: z.string(),\n tax: taxSplitSchema,\n /** Always false: these services are never under reverse charge. */\n reverseCharge: z.literal(false),\n razorpayPaymentId: z.string(),\n});\nexport type Invoice = z.infer<typeof invoiceSchema>;\n\n/** A refund's credit note, against its invoice. */\nexport const creditNoteSchema = z.object({\n /** e.g. `FCCN/26-27/00012`: the invoice series + `CN`, sequential within a financial year. */\n number: z.string().max(INVOICE_NUMBER_MAX),\n issuedAt: z.iso.datetime(),\n invoiceNumber: z.string().max(INVOICE_NUMBER_MAX),\n tax: taxSplitSchema,\n});\nexport type CreditNote = z.infer<typeof creditNoteSchema>;\n\n/** One purchase in a member's history. Only settled orders are listed, never an abandoned checkout. */\nexport const paymentSummarySchema = z.object({\n id: objectIdSchema,\n item: purchaseItemSchema,\n title: z.string(),\n total: paiseSchema,\n status: orderStatusSchema,\n /** When it was captured, or granted for a free coupon. */\n paidAt: z.iso.datetime(),\n invoiceNumber: z.string().nullable(),\n /** Until when a refund may be asked for; null once refunded or for a free coupon. */\n refundableUntil: z.iso.datetime().nullable(),\n});\nexport type PaymentSummary = z.infer<typeof paymentSummarySchema>;\n\nexport const paymentPageSchema = paginatedSchema(paymentSummarySchema);\nexport type PaymentPage = z.infer<typeof paymentPageSchema>;\n\nexport const paymentDetailSchema = paymentSummarySchema.extend({\n listPrice: paiseSchema,\n discount: paiseSchema,\n coupon: appliedCouponSchema.nullable(),\n invoice: invoiceSchema.nullable(),\n creditNote: creditNoteSchema.nullable(),\n refundedAt: z.iso.datetime().nullable(),\n});\nexport type PaymentDetail = z.infer<typeof paymentDetailSchema>;\n\n// ─── Staff: payments and refunds ─────────────────────────────────────────────\n\n/** Who paid, as they are now, so staff can find them. Email only for a role that may read it. */\nexport const payerSchema = z.object({\n id: objectIdSchema,\n displayName: z.string(),\n email: z.string().nullable(),\n});\nexport type Payer = z.infer<typeof payerSchema>;\n\nexport const staffPaymentsQuerySchema = paginationQuerySchema.extend({\n status: orderStatusSchema.optional(),\n memberId: objectIdSchema.optional(),\n /** Only the ones a person must act on (`needsAction` below). */\n needsAction: z.preprocess(emptyStringToUndefined, z.stringbool().default(false)),\n});\nexport type StaffPaymentsQuery = z.infer<typeof staffPaymentsQuerySchema>;\nexport type StaffPaymentsQueryInput = z.input<typeof staffPaymentsQuerySchema>;\n\nexport const staffPaymentSummarySchema = paymentSummarySchema.extend({\n payer: payerSchema,\n /**\n * A person must act (0.12.0): taken but not applied and not yet refunded\n * (the automatic refund did not go through), a refund that failed at the\n * gateway, or an open chargeback.\n */\n needsAction: z.boolean(),\n});\nexport type StaffPaymentSummary = z.infer<typeof staffPaymentSummarySchema>;\nexport const staffPaymentPageSchema = paginatedSchema(staffPaymentSummarySchema);\nexport type StaffPaymentPage = z.infer<typeof staffPaymentPageSchema>;\n\nexport const staffPaymentDetailSchema = paymentDetailSchema.extend({\n payer: payerSchema,\n razorpay: z.object({\n orderId: z.string().nullable(),\n paymentId: z.string().nullable(),\n refundId: z.string().nullable(),\n }),\n /** Why staff refunded it, on record. */\n refundReason: z.string().nullable(),\n /**\n * The money was taken but what it bought could not be applied when it was\n * captured (they were a member already, the Premium time to upgrade had\n * run out, past the 3-year cap): refund it. Null when it applied. One of\n * `GRANT_FAILURE_VALUES` (0.18.0; a plain string before).\n */\n grantFailed: grantFailureSchema.nullable(),\n /** A chargeback was opened on it (cleared when it is won or closed). */\n disputedAt: z.iso.datetime().nullable(),\n /**\n * What refunds made outside Founder Circle (the Razorpay dashboard) have\n * already given back of this payment. A Refund here gives back the rest:\n * `total` less this. 0 when there were none.\n */\n refundedOutside: paiseSchema,\n /**\n * Payments captured on this order other than the one that settled it (a\n * late authorisation, a second Checkout attempt): each is refunded by\n * itself; `refunded: false` means that refund has not gone through yet and\n * the payment needs a person.\n */\n strayPayments: z.array(\n z.object({\n paymentId: z.string(),\n amount: paiseSchema,\n refunded: z.boolean(),\n at: z.iso.datetime(),\n }),\n ),\n /**\n * When the payer asked for a refund (0.13.0): their first \"Payments and\n * refunds\" ticket opened inside the refund window. An ask in time keeps the\n * payment refundable after the window ends. Null when they did not ask in\n * time, or it is not a paid payment.\n */\n refundAskedAt: z.iso.datetime().nullable(),\n viewer: z.object({\n /**\n * Paid, within the window (or asked for within it), not their own, and\n * the asker may refund.\n */\n canRefund: z.boolean(),\n }),\n});\nexport type StaffPaymentDetail = z.infer<typeof staffPaymentDetailSchema>;\n\nconst reasonSchema = z.string().trim().min(BILLING_REASON_MIN).max(BILLING_REASON_MAX);\n\n/** `POST /staff/payments/:orderId/refund`. The reason is on the audit record. */\nexport const refundPaymentBodySchema = z.object({ reason: reasonSchema });\nexport type RefundPaymentBody = z.infer<typeof refundPaymentBodySchema>;\n\n/**\n * `PUT /members/:memberId/membership`: grant (a partner, a press account) or\n * revoke (a fake or duplicate account holding a founding place). A paid one\n * is never revoked: refund its payment.\n */\nexport const setMembershipBodySchema = z.object({\n granted: z.boolean(),\n reason: reasonSchema,\n});\nexport type SetMembershipBody = z.infer<typeof setMembershipBodySchema>;\n\n// ─── Staff: coupons ──────────────────────────────────────────────────────────\n\n/** What a coupon is good for. A percent coupon names what it applies to. */\nexport const COUPON_TARGET_VALUES = ['membership', 'premium', 'business'] as const;\nexport const couponTargetSchema = z.enum(COUPON_TARGET_VALUES);\nexport type CouponTarget = z.infer<typeof couponTargetSchema>;\n\n/**\n * ⚠ Stored: append only.\n *\n * free_membership the membership at Rs 0; `founding` numbers its holders\n * (\"Founding member #N\"). ⚠ A NEW founding coupon is refused\n * (0.14.0, COUPON_FOUNDING_RETIRED): founding places come\n * from the launch waitlist alone. The field stays, because\n * stored coupons carry it.\n * percent_off a share off the listed price of what it applies to\n */\nexport const COUPON_KIND_VALUES = ['free_membership', 'percent_off'] as const;\nexport type CouponKind = (typeof COUPON_KIND_VALUES)[number];\n\nexport const couponBenefitSchema = z.discriminatedUnion('kind', [\n z.object({ kind: z.literal('free_membership'), founding: z.boolean() }),\n z.object({\n kind: z.literal('percent_off'),\n percent: z.number().int().min(COUPON_PERCENT_MIN).max(COUPON_PERCENT_MAX),\n appliesTo: z\n .array(couponTargetSchema)\n .min(1)\n .max(COUPON_TARGET_VALUES.length)\n .refine(eachOnce, {\n error: VALIDATION_MESSAGE.couponTargetsDuplicate,\n }),\n }),\n]);\nexport type CouponBenefit = z.infer<typeof couponBenefitSchema>;\n\nexport const couponSchema = z.object({\n id: objectIdSchema,\n code: z.string(),\n label: z.string(),\n benefit: couponBenefitSchema,\n /** Redemptions allowed in all; null is no cap. */\n max: z.number().int().positive().nullable(),\n /** Redemptions in force (a revoked founding place frees one). */\n used: z.number().int().nonnegative(),\n active: z.boolean(),\n validFrom: z.iso.datetime().nullable(),\n validUntil: z.iso.datetime().nullable(),\n createdAt: z.iso.datetime(),\n});\nexport type Coupon = z.infer<typeof couponSchema>;\n\n/** Never paged: coupons are few. Newest first. */\nexport const couponListSchema = z.object({ items: z.array(couponSchema) });\nexport type CouponList = z.infer<typeof couponListSchema>;\n\nexport const couponParamsSchema = z.object({ couponId: objectIdSchema });\nexport type CouponParams = z.infer<typeof couponParamsSchema>;\n\nconst windowValid = (body: { validFrom?: string | null; validUntil?: string | null }) =>\n !body.validFrom || !body.validUntil || Date.parse(body.validFrom) < Date.parse(body.validUntil);\n\nexport const createCouponBodySchema = z\n .object({\n code: couponCodeSchema,\n label: z.string().trim().min(COUPON_LABEL_MIN).max(COUPON_LABEL_MAX),\n benefit: couponBenefitSchema,\n max: z.number().int().positive().max(COUPON_USES_MAX).nullable(),\n validFrom: z.iso.datetime().nullable().optional(),\n validUntil: z.iso.datetime().nullable().optional(),\n })\n .refine(windowValid, { path: ['validUntil'], error: VALIDATION_MESSAGE.couponWindowInvalid });\nexport type CreateCouponBody = z.infer<typeof createCouponBodySchema>;\n\n/**\n * What may change on a live coupon. The code and the benefit never change: a\n * redemption is a record of what a code gave when it was used.\n */\nexport const updateCouponBodySchema = z\n .object({\n label: z.string().trim().min(COUPON_LABEL_MIN).max(COUPON_LABEL_MAX).optional(),\n active: z.boolean().optional(),\n max: z.number().int().positive().max(COUPON_USES_MAX).nullable().optional(),\n validFrom: z.iso.datetime().nullable().optional(),\n validUntil: z.iso.datetime().nullable().optional(),\n })\n .refine(windowValid, { path: ['validUntil'], error: VALIDATION_MESSAGE.couponWindowInvalid });\nexport type UpdateCouponBody = z.infer<typeof updateCouponBodySchema>;\n"]}
|
|
1
|
+
{"version":3,"file":"billing.js","sourceRoot":"","sources":["../../../src/domains/billing/billing.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * founder-schema: buying, paying, invoices, refunds and coupons (0.12.0)\n *\n * POST /api/v1/billing/quote quoteBodySchema -> quoteSchema\n * POST /api/v1/billing/orders createOrderBodySchema -> createOrderResponseSchema\n * GET /api/v1/billing/orders/:orderId orderStateSchema (polled while \"processing\")\n * POST /api/v1/billing/orders/:orderId/confirm confirmOrderBodySchema -> orderStateSchema\n * GET /api/v1/billing/payments paymentPageSchema (mine)\n * GET /api/v1/billing/payments/:orderId paymentDetailSchema (mine, with the invoice)\n *\n * Staff (by the ability: support reads; managers refund and run coupons):\n * GET /api/v1/staff/payments staffPaymentsQuerySchema -> staffPaymentPageSchema\n * GET /api/v1/staff/payments/:orderId staffPaymentDetailSchema\n * POST /api/v1/staff/payments/:orderId/refund refundPaymentBodySchema -> staffPaymentDetailSchema\n * GET /api/v1/staff/coupons couponListSchema\n * POST /api/v1/staff/coupons createCouponBodySchema -> couponSchema\n * PATCH /api/v1/staff/coupons/:couponId updateCouponBodySchema -> couponSchema\n * PUT /api/v1/members/:memberId/membership setMembershipBodySchema -> memberDetailSchema\n *\n * THE ONE RULE: THE SERVER PRICES, THE CLIENT CHOOSES. A request names what it\n * wants (an item) and maybe a coupon CODE; it never names an amount. Every\n * amount here is the server's, in integer paise, GST included.\n *\n * TWO PATHS IN, ONE GRANT. A payment reaches the server from the browser the\n * moment checkout returns (`confirm`) and from the gateway's webhook. Either\n * grants; the second is a no-op. So a member who closes the tab is still\n * granted, and `confirm` failing never means \"not paid\": the web says\n * \"processing\" and polls the order.\n *\n * GST: the company is registered, every captured payment gets a tax invoice,\n * every refund a credit note. Where the buyer is decides the tax: in the\n * supplier's state CGST + SGST, elsewhere IGST. So checkout asks for the state.\n *\n * @module founder-schema/domains/billing\n */\n\nimport { z } from 'zod';\nimport {\n eachOnce,\n emptyStringToUndefined,\n objectIdSchema,\n paginationQuerySchema,\n} from '../../core/common.js';\nimport {\n BILLING_REASON_MAX,\n BILLING_REASON_MIN,\n COUPON_CODE_MAX,\n COUPON_CODE_MIN,\n COUPON_LABEL_MAX,\n COUPON_LABEL_MIN,\n COUPON_PERCENT_MAX,\n COUPON_PERCENT_MIN,\n COUPON_USES_MAX,\n INVOICE_NUMBER_MAX,\n RAZORPAY_ID_MAX,\n RAZORPAY_SIGNATURE_MAX,\n} from '../../core/limits.js';\nimport { paginatedSchema } from '../../core/responses.js';\nimport { VALIDATION_MESSAGE } from '../../core/validation.js';\nimport { paiseSchema, planPeriodSchema, planTierSchema } from '../membership/membership.js';\nimport { personSchema } from '../people/person.js';\nimport { billingDetailsSchema, gstStateCodeSchema } from './gst.js';\n\nexport {\n type BillingDetails,\n billingDetailsSchema,\n GST_RATE_PERCENT,\n GST_STATE_CODE_VALUES,\n GST_STATES,\n type GstStateCode,\n gstinChecksumValid,\n gstinSchema,\n gstStateCodeSchema,\n gstStateName,\n} from './gst.js';\n\n// ─── What can be bought ──────────────────────────────────────────────────────\n\n/** ⚠ Stored on every order: append only. */\nexport const PURCHASE_KIND_VALUES = ['membership', 'plan', 'upgrade'] as const;\nexport type PurchaseKind = (typeof PURCHASE_KIND_VALUES)[number];\n\n/**\n * The thing asked for.\n *\n * membership Rs 99, once\n * plan a month or a year of Premium or Business, appended\n * upgrade the Premium time left, turned into Business, for the difference\n */\nexport const purchaseItemSchema = z.discriminatedUnion('kind', [\n z.object({ kind: z.literal('membership') }),\n z.object({ kind: z.literal('plan'), tier: planTierSchema, period: planPeriodSchema }),\n z.object({ kind: z.literal('upgrade') }),\n]);\nexport type PurchaseItem = z.infer<typeof purchaseItemSchema>;\n\n/** A coupon code as typed: letters, digits, hyphens; compared upper-case. */\nexport const couponCodeSchema = z\n .string()\n .trim()\n .min(COUPON_CODE_MIN)\n .max(COUPON_CODE_MAX)\n .regex(/^[A-Za-z0-9-]+$/, VALIDATION_MESSAGE.couponCodeInvalid)\n .transform((v) => v.toUpperCase());\n\n// ─── Quote ───────────────────────────────────────────────────────────────────\n\n/**\n * The tax inside a total. `taxable + cgst + sgst + igst = total`; either\n * CGST + SGST (buyer in the supplier's state) or IGST, never both.\n */\nexport const taxSplitSchema = z.object({\n ratePercent: z.number().int().positive(),\n taxable: paiseSchema,\n cgst: paiseSchema,\n sgst: paiseSchema,\n igst: paiseSchema,\n total: paiseSchema,\n});\nexport type TaxSplit = z.infer<typeof taxSplitSchema>;\n\n/** `POST /billing/quote`. The state is optional: without it, no tax split. */\nexport const quoteBodySchema = z.object({\n item: purchaseItemSchema,\n couponCode: couponCodeSchema.optional(),\n stateCode: gstStateCodeSchema.optional(),\n});\nexport type QuoteBody = z.infer<typeof quoteBodySchema>;\n\n/** What a plan or an upgrade would do to the plan, priced now. */\nexport const planEffectSchema = z.object({\n tier: planTierSchema,\n /** When this purchase's time starts (later than now when it waits its turn). */\n startsAt: z.iso.datetime(),\n endsAt: z.iso.datetime(),\n /** For an upgrade: the days of Premium turned into Business. */\n upgradedDays: z.number().int().positive().nullable(),\n});\nexport type PlanEffect = z.infer<typeof planEffectSchema>;\n\n/** A coupon as a purchase carries it: its code and staff's name for it. */\nexport const appliedCouponSchema = z.object({ code: z.string(), label: z.string() });\nexport type AppliedCoupon = z.infer<typeof appliedCouponSchema>;\n\n/**\n * Why a captured payment was NOT applied (`grantFailed`), and so refunded\n * (0.18.0: the one list; the backend wrote two of these as loose strings and\n * the contract said `string`). Stored on the order: append only.\n *\n * AMOUNT_MISMATCH the gateway captured another amount than the price\n * ACCOUNT_DELETED paid after the account was deleted\n * COUPON_ALREADY_USED the code went to another of their orders, paid first\n * MEMBERSHIP_REQUIRED a plan, but the membership is gone (refunded, withdrawn)\n * ALREADY_MEMBER a membership, but they are a member already\n * PLAN_CHANGED an upgrade priced on a plan that has since changed\n * PLAN_NOTHING_TO_UPGRADE an upgrade with no Premium time left\n * PLAN_TERM_LIMIT past `PLAN_AHEAD_MAX_YEARS` of plan time\n * PLAN_UPGRADE_INSTEAD Business bought while on Premium (that is an upgrade)\n * GRANT_REFUSED any other refusal of the grant: still recorded and\n * refunded, never left captured for nothing (the\n * server logs which one, to add it here)\n */\nexport const GRANT_FAILURE_VALUES = [\n 'AMOUNT_MISMATCH',\n 'ACCOUNT_DELETED',\n 'COUPON_ALREADY_USED',\n 'MEMBERSHIP_REQUIRED',\n 'ALREADY_MEMBER',\n 'PLAN_CHANGED',\n 'PLAN_NOTHING_TO_UPGRADE',\n 'PLAN_TERM_LIMIT',\n 'PLAN_UPGRADE_INSTEAD',\n 'GRANT_REFUSED',\n] as const;\nexport const grantFailureSchema = z.enum(GRANT_FAILURE_VALUES);\nexport type GrantFailure = z.infer<typeof grantFailureSchema>;\n\nexport const quoteSchema = z.object({\n item: purchaseItemSchema,\n /** \"Membership\", \"Premium, 1 month\", \"Upgrade to Business\": the server's words. */\n title: z.string(),\n listPrice: paiseSchema,\n discount: paiseSchema,\n /** What would be charged. Zero for a free-membership coupon: no checkout at all. */\n total: paiseSchema,\n coupon: appliedCouponSchema.nullable(),\n /** Null for a membership. */\n plan: planEffectSchema.nullable(),\n /** Null without a state. */\n tax: taxSplitSchema.nullable(),\n refundWindowDays: z.number().int().positive(),\n});\nexport type Quote = z.infer<typeof quoteSchema>;\n\n// ─── Orders ──────────────────────────────────────────────────────────────────\n\n/**\n * Where an order stands. ⚠ Stored: append only.\n *\n * created checkout open, nothing paid yet\n * paid captured and granted; has an invoice\n * granted_free a free coupon: granted with no payment and no invoice\n * expired not paid within `ORDER_TTL_MINUTES`\n * refund_pending staff refunded it; the gateway is returning the money\n * refunded the money is back; has a credit note\n * refund_failed the gateway could not return it; staff act from its dashboard\n */\nexport const ORDER_STATUS_VALUES = [\n 'created',\n 'paid',\n 'granted_free',\n 'expired',\n 'refund_pending',\n 'refunded',\n 'refund_failed',\n] as const;\nexport const orderStatusSchema = z.enum(ORDER_STATUS_VALUES);\nexport type OrderStatus = z.infer<typeof orderStatusSchema>;\n\n/**\n * `POST /billing/orders`. Billing details are required for anything paid (the\n * invoice needs a place of supply): the server refuses a paid order without\n * them (`billing.stateCode`, VALIDATION_ERROR). A free coupon issues no\n * invoice, so it needs none (0.12.0).\n */\nexport const createOrderBodySchema = z.object({\n item: purchaseItemSchema,\n couponCode: couponCodeSchema.optional(),\n billing: billingDetailsSchema.optional(),\n});\nexport type CreateOrderBody = z.infer<typeof createOrderBodySchema>;\n\n/**\n * Either done (a free coupon granted at once) or a checkout to open. The\n * checkout fields are Razorpay Checkout's own options; identity (name, email,\n * phone) is the server's, never typed by the caller.\n */\nexport const createOrderResponseSchema = z.discriminatedUnion('status', [\n z.object({ status: z.literal('granted'), orderId: objectIdSchema }),\n z.object({\n status: z.literal('checkout'),\n orderId: objectIdSchema,\n expiresAt: z.iso.datetime(),\n checkout: z.object({\n keyId: z.string().min(1),\n razorpayOrderId: z.string().min(1),\n amount: paiseSchema,\n currency: z.literal('INR'),\n /** The merchant name on the dialog. */\n name: z.string(),\n /** What is being bought, under the name. */\n description: z.string(),\n prefill: z.object({\n name: z.string(),\n email: z.string(),\n contact: z.string().optional(),\n }),\n }),\n }),\n]);\nexport type CreateOrderResponse = z.infer<typeof createOrderResponseSchema>;\n\nexport const orderParamsSchema = z.object({ orderId: objectIdSchema });\nexport type OrderParams = z.infer<typeof orderParamsSchema>;\n\n/** What Razorpay Checkout's `handler` hands back, as it names it. */\nexport const confirmOrderBodySchema = z.object({\n razorpayOrderId: z.string().min(1).max(RAZORPAY_ID_MAX),\n razorpayPaymentId: z.string().min(1).max(RAZORPAY_ID_MAX),\n razorpaySignature: z.string().min(1).max(RAZORPAY_SIGNATURE_MAX),\n});\nexport type ConfirmOrderBody = z.infer<typeof confirmOrderBodySchema>;\n\n/** An order as its buyer polls it. */\nexport const orderStateSchema = z.object({\n orderId: objectIdSchema,\n item: purchaseItemSchema,\n status: orderStatusSchema,\n /**\n * The money was taken but what it bought could not be applied (bought\n * twice in two tabs, the plan changed while paying): it is refunded in\n * full, by itself. The client says so instead of \"done\".\n */\n notApplied: z.boolean(),\n});\nexport type OrderState = z.infer<typeof orderStateSchema>;\n\n// ─── Payments, invoices, credit notes ────────────────────────────────────────\n\n/** A party on an invoice. The supplier always has a GSTIN on a real invoice; a buyer, only on B2B. */\nexport const invoicePartySchema = z.object({\n name: z.string(),\n address: z.string().nullable(),\n gstin: z.string().nullable(),\n stateCode: gstStateCodeSchema,\n stateName: z.string(),\n});\nexport type InvoiceParty = z.infer<typeof invoicePartySchema>;\n\n/** B2B with the buyer's GSTIN, B2C without (0.18.0: the values, for the backend's model). */\nexport const INVOICE_KIND_VALUES = ['b2b', 'b2c'] as const;\nexport const invoiceKindSchema = z.enum(INVOICE_KIND_VALUES);\nexport type InvoiceKind = z.infer<typeof invoiceKindSchema>;\n\n/** A tax invoice, frozen when the payment was captured. */\nexport const invoiceSchema = z.object({\n /** e.g. `FC/26-27/000123`: sequential within a financial year, at most `INVOICE_NUMBER_MAX`. */\n number: z.string().max(INVOICE_NUMBER_MAX),\n issuedAt: z.iso.datetime(),\n /**\n * Issued where the supplier's GSTIN is not configured (dev, Razorpay test\n * mode): marked \"TEST: not a tax invoice\". Never true in production.\n */\n test: z.boolean(),\n supplier: invoicePartySchema,\n buyer: invoicePartySchema,\n kind: invoiceKindSchema,\n /** The service's accounting code (SAC). */\n sac: z.string(),\n description: z.string(),\n tax: taxSplitSchema,\n /** Always false: these services are never under reverse charge. */\n reverseCharge: z.literal(false),\n razorpayPaymentId: z.string(),\n});\nexport type Invoice = z.infer<typeof invoiceSchema>;\n\n/** A refund's credit note, against its invoice. */\nexport const creditNoteSchema = z.object({\n /** e.g. `FCCN/26-27/00012`: the invoice series + `CN`, sequential within a financial year. */\n number: z.string().max(INVOICE_NUMBER_MAX),\n issuedAt: z.iso.datetime(),\n invoiceNumber: z.string().max(INVOICE_NUMBER_MAX),\n tax: taxSplitSchema,\n});\nexport type CreditNote = z.infer<typeof creditNoteSchema>;\n\n/** One purchase in a member's history. Only settled orders are listed, never an abandoned checkout. */\nexport const paymentSummarySchema = z.object({\n id: objectIdSchema,\n item: purchaseItemSchema,\n title: z.string(),\n total: paiseSchema,\n status: orderStatusSchema,\n /** When it was captured, or granted for a free coupon. */\n paidAt: z.iso.datetime(),\n invoiceNumber: z.string().nullable(),\n /** Until when a refund may be asked for; null once refunded or for a free coupon. */\n refundableUntil: z.iso.datetime().nullable(),\n});\nexport type PaymentSummary = z.infer<typeof paymentSummarySchema>;\n\nexport const paymentPageSchema = paginatedSchema(paymentSummarySchema);\nexport type PaymentPage = z.infer<typeof paymentPageSchema>;\n\nexport const paymentDetailSchema = paymentSummarySchema.extend({\n listPrice: paiseSchema,\n discount: paiseSchema,\n coupon: appliedCouponSchema.nullable(),\n invoice: invoiceSchema.nullable(),\n creditNote: creditNoteSchema.nullable(),\n refundedAt: z.iso.datetime().nullable(),\n});\nexport type PaymentDetail = z.infer<typeof paymentDetailSchema>;\n\n// ─── Staff: payments and refunds ─────────────────────────────────────────────\n\n/** Who paid, as they are now, so staff can find them. Email only for a role that may read it. */\nexport const payerSchema = personSchema.extend({\n email: z.string().nullable(),\n});\nexport type Payer = z.infer<typeof payerSchema>;\n\nexport const staffPaymentsQuerySchema = paginationQuerySchema.extend({\n status: orderStatusSchema.optional(),\n memberId: objectIdSchema.optional(),\n /** Only the ones a person must act on (`needsAction` below). */\n needsAction: z.preprocess(emptyStringToUndefined, z.stringbool().default(false)),\n});\nexport type StaffPaymentsQuery = z.infer<typeof staffPaymentsQuerySchema>;\nexport type StaffPaymentsQueryInput = z.input<typeof staffPaymentsQuerySchema>;\n\nexport const staffPaymentSummarySchema = paymentSummarySchema.extend({\n payer: payerSchema,\n /**\n * A person must act (0.12.0): taken but not applied and not yet refunded\n * (the automatic refund did not go through), a refund that failed at the\n * gateway, or an open chargeback.\n */\n needsAction: z.boolean(),\n});\nexport type StaffPaymentSummary = z.infer<typeof staffPaymentSummarySchema>;\nexport const staffPaymentPageSchema = paginatedSchema(staffPaymentSummarySchema);\nexport type StaffPaymentPage = z.infer<typeof staffPaymentPageSchema>;\n\nexport const staffPaymentDetailSchema = paymentDetailSchema.extend({\n payer: payerSchema,\n razorpay: z.object({\n orderId: z.string().nullable(),\n paymentId: z.string().nullable(),\n refundId: z.string().nullable(),\n }),\n /** Why staff refunded it, on record. */\n refundReason: z.string().nullable(),\n /**\n * The money was taken but what it bought could not be applied when it was\n * captured (they were a member already, the Premium time to upgrade had\n * run out, past the 3-year cap): refund it. Null when it applied. One of\n * `GRANT_FAILURE_VALUES` (0.18.0; a plain string before).\n */\n grantFailed: grantFailureSchema.nullable(),\n /** A chargeback was opened on it (cleared when it is won or closed). */\n disputedAt: z.iso.datetime().nullable(),\n /**\n * What refunds made outside Founder Circle (the Razorpay dashboard) have\n * already given back of this payment. A Refund here gives back the rest:\n * `total` less this. 0 when there were none.\n */\n refundedOutside: paiseSchema,\n /**\n * Payments captured on this order other than the one that settled it (a\n * late authorisation, a second Checkout attempt): each is refunded by\n * itself; `refunded: false` means that refund has not gone through yet and\n * the payment needs a person.\n */\n strayPayments: z.array(\n z.object({\n paymentId: z.string(),\n amount: paiseSchema,\n refunded: z.boolean(),\n at: z.iso.datetime(),\n }),\n ),\n /**\n * When the payer asked for a refund (0.13.0): their first \"Payments and\n * refunds\" ticket opened inside the refund window. An ask in time keeps the\n * payment refundable after the window ends. Null when they did not ask in\n * time, or it is not a paid payment.\n */\n refundAskedAt: z.iso.datetime().nullable(),\n viewer: z.object({\n /**\n * Paid, within the window (or asked for within it), not their own, and\n * the asker may refund.\n */\n canRefund: z.boolean(),\n }),\n});\nexport type StaffPaymentDetail = z.infer<typeof staffPaymentDetailSchema>;\n\nconst reasonSchema = z.string().trim().min(BILLING_REASON_MIN).max(BILLING_REASON_MAX);\n\n/** `POST /staff/payments/:orderId/refund`. The reason is on the audit record. */\nexport const refundPaymentBodySchema = z.object({ reason: reasonSchema });\nexport type RefundPaymentBody = z.infer<typeof refundPaymentBodySchema>;\n\n/**\n * `PUT /members/:memberId/membership`: grant (a partner, a press account) or\n * revoke (a fake or duplicate account holding a founding place). A paid one\n * is never revoked: refund its payment.\n */\nexport const setMembershipBodySchema = z.object({\n granted: z.boolean(),\n reason: reasonSchema,\n});\nexport type SetMembershipBody = z.infer<typeof setMembershipBodySchema>;\n\n// ─── Staff: coupons ──────────────────────────────────────────────────────────\n\n/** What a coupon is good for. A percent coupon names what it applies to. */\nexport const COUPON_TARGET_VALUES = ['membership', 'premium', 'business'] as const;\nexport const couponTargetSchema = z.enum(COUPON_TARGET_VALUES);\nexport type CouponTarget = z.infer<typeof couponTargetSchema>;\n\n/**\n * ⚠ Stored: append only.\n *\n * free_membership the membership at Rs 0; `founding` numbers its holders\n * (\"Founding member #N\"). ⚠ A NEW founding coupon is refused\n * (0.14.0, COUPON_FOUNDING_RETIRED): founding places come\n * from the launch waitlist alone. The field stays, because\n * stored coupons carry it.\n * percent_off a share off the listed price of what it applies to\n */\nexport const COUPON_KIND_VALUES = ['free_membership', 'percent_off'] as const;\nexport type CouponKind = (typeof COUPON_KIND_VALUES)[number];\n\nexport const couponBenefitSchema = z.discriminatedUnion('kind', [\n z.object({ kind: z.literal('free_membership'), founding: z.boolean() }),\n z.object({\n kind: z.literal('percent_off'),\n percent: z.number().int().min(COUPON_PERCENT_MIN).max(COUPON_PERCENT_MAX),\n appliesTo: z\n .array(couponTargetSchema)\n .min(1)\n .max(COUPON_TARGET_VALUES.length)\n .refine(eachOnce, {\n error: VALIDATION_MESSAGE.couponTargetsDuplicate,\n }),\n }),\n]);\nexport type CouponBenefit = z.infer<typeof couponBenefitSchema>;\n\nexport const couponSchema = z.object({\n id: objectIdSchema,\n code: z.string(),\n label: z.string(),\n benefit: couponBenefitSchema,\n /** Redemptions allowed in all; null is no cap. */\n max: z.number().int().positive().nullable(),\n /** Redemptions in force (a revoked founding place frees one). */\n used: z.number().int().nonnegative(),\n active: z.boolean(),\n validFrom: z.iso.datetime().nullable(),\n validUntil: z.iso.datetime().nullable(),\n createdAt: z.iso.datetime(),\n});\nexport type Coupon = z.infer<typeof couponSchema>;\n\n/** Never paged: coupons are few. Newest first. */\nexport const couponListSchema = z.object({ items: z.array(couponSchema) });\nexport type CouponList = z.infer<typeof couponListSchema>;\n\nexport const couponParamsSchema = z.object({ couponId: objectIdSchema });\nexport type CouponParams = z.infer<typeof couponParamsSchema>;\n\nconst windowValid = (body: { validFrom?: string | null; validUntil?: string | null }) =>\n !body.validFrom || !body.validUntil || Date.parse(body.validFrom) < Date.parse(body.validUntil);\n\nexport const createCouponBodySchema = z\n .object({\n code: couponCodeSchema,\n label: z.string().trim().min(COUPON_LABEL_MIN).max(COUPON_LABEL_MAX),\n benefit: couponBenefitSchema,\n max: z.number().int().positive().max(COUPON_USES_MAX).nullable(),\n validFrom: z.iso.datetime().nullable().optional(),\n validUntil: z.iso.datetime().nullable().optional(),\n })\n .refine(windowValid, { path: ['validUntil'], error: VALIDATION_MESSAGE.couponWindowInvalid });\nexport type CreateCouponBody = z.infer<typeof createCouponBodySchema>;\n\n/**\n * What may change on a live coupon. The code and the benefit never change: a\n * redemption is a record of what a code gave when it was used.\n */\nexport const updateCouponBodySchema = z\n .object({\n label: z.string().trim().min(COUPON_LABEL_MIN).max(COUPON_LABEL_MAX).optional(),\n active: z.boolean().optional(),\n max: z.number().int().positive().max(COUPON_USES_MAX).nullable().optional(),\n validFrom: z.iso.datetime().nullable().optional(),\n validUntil: z.iso.datetime().nullable().optional(),\n })\n .refine(windowValid, { path: ['validUntil'], error: VALIDATION_MESSAGE.couponWindowInvalid });\nexport type UpdateCouponBody = z.infer<typeof updateCouponBodySchema>;\n"]}
|
|
@@ -229,22 +229,36 @@ export declare const chatParticipantsBodySchema: z.ZodObject<{
|
|
|
229
229
|
userIds: z.ZodArray<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
|
|
230
230
|
}, z.core.$strip>;
|
|
231
231
|
export type ChatParticipantsBody = z.infer<typeof chatParticipantsBodySchema>;
|
|
232
|
-
/** The
|
|
232
|
+
/** The person, as every surface shows them (0.20.0, `personSchema`), and nothing more. */
|
|
233
233
|
export declare const chatParticipantSchema: z.ZodObject<{
|
|
234
|
+
userId: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
235
|
+
username: z.ZodNullable<z.ZodString>;
|
|
234
236
|
displayName: z.ZodString;
|
|
235
|
-
|
|
237
|
+
firstName: z.ZodString;
|
|
236
238
|
avatarUrl: z.ZodNullable<z.ZodURL>;
|
|
239
|
+
former: z.ZodBoolean;
|
|
237
240
|
}, z.core.$strip>;
|
|
238
241
|
export type ChatParticipant = z.infer<typeof chatParticipantSchema>;
|
|
242
|
+
/** A direct-contact lock row: being opened, or open. The backend's storage's own values, from here like every other list (0.20.0). */
|
|
243
|
+
export declare const DIRECT_CONTACT_STATUS_VALUES: readonly ["opening", "open"];
|
|
244
|
+
export declare const directContactStatusSchema: z.ZodEnum<{
|
|
245
|
+
open: "open";
|
|
246
|
+
opening: "opening";
|
|
247
|
+
}>;
|
|
248
|
+
export type DirectContactStatus = z.infer<typeof directContactStatusSchema>;
|
|
239
249
|
/**
|
|
240
|
-
* Keyed by user id.
|
|
241
|
-
*
|
|
250
|
+
* Keyed by user id. Every id asked for is answered (0.20.0): a deleted account
|
|
251
|
+
* as a former person (`former: true`, no name or picture), an id that names
|
|
252
|
+
* nobody the same way, so the client never has to guess.
|
|
242
253
|
*/
|
|
243
254
|
export declare const chatParticipantsResponseSchema: z.ZodObject<{
|
|
244
255
|
participants: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
256
|
+
userId: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
257
|
+
username: z.ZodNullable<z.ZodString>;
|
|
245
258
|
displayName: z.ZodString;
|
|
246
|
-
|
|
259
|
+
firstName: z.ZodString;
|
|
247
260
|
avatarUrl: z.ZodNullable<z.ZodURL>;
|
|
261
|
+
former: z.ZodBoolean;
|
|
248
262
|
}, z.core.$strip>>;
|
|
249
263
|
}, z.core.$strip>;
|
|
250
264
|
export type ChatParticipantsResponse = z.infer<typeof chatParticipantsResponseSchema>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../../src/domains/chat/chat.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../../src/domains/chat/chat.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,8 +21,9 @@
|
|
|
21
21
|
* @module founder-schema/domains/chat
|
|
22
22
|
*/
|
|
23
23
|
import { z } from 'zod';
|
|
24
|
-
import { objectIdSchema
|
|
24
|
+
import { objectIdSchema } from '../../core/common.js';
|
|
25
25
|
import { CHAT_PARTICIPANTS_MAX } from '../../core/limits.js';
|
|
26
|
+
import { personSchema } from '../people/person.js';
|
|
26
27
|
/**
|
|
27
28
|
* The product this package speaks for.
|
|
28
29
|
*
|
|
@@ -214,16 +215,15 @@ export const messagingSettingsSchema = z.object({ from: messageFromSchema });
|
|
|
214
215
|
export const chatParticipantsBodySchema = z.object({
|
|
215
216
|
userIds: z.array(objectIdSchema).min(1).max(CHAT_PARTICIPANTS_MAX),
|
|
216
217
|
});
|
|
217
|
-
/** The
|
|
218
|
-
export const chatParticipantSchema =
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
avatarUrl: z.url().nullable(),
|
|
223
|
-
});
|
|
218
|
+
/** The person, as every surface shows them (0.20.0, `personSchema`), and nothing more. */
|
|
219
|
+
export const chatParticipantSchema = personSchema;
|
|
220
|
+
/** A direct-contact lock row: being opened, or open. The backend's storage's own values, from here like every other list (0.20.0). */
|
|
221
|
+
export const DIRECT_CONTACT_STATUS_VALUES = ['opening', 'open'];
|
|
222
|
+
export const directContactStatusSchema = z.enum(DIRECT_CONTACT_STATUS_VALUES);
|
|
224
223
|
/**
|
|
225
|
-
* Keyed by user id.
|
|
226
|
-
*
|
|
224
|
+
* Keyed by user id. Every id asked for is answered (0.20.0): a deleted account
|
|
225
|
+
* as a former person (`former: true`, no name or picture), an id that names
|
|
226
|
+
* nobody the same way, so the client never has to guess.
|
|
227
227
|
*/
|
|
228
228
|
export const chatParticipantsResponseSchema = z.object({
|
|
229
229
|
participants: z.record(z.string(), chatParticipantSchema),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.js","sourceRoot":"","sources":["../../../src/domains/chat/chat.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * founder-schema — Chat: config, auth token, opening a conversation, participants\n *\n * Founder Circle does not run a chat server. It uses the shared one, which\n * serves several products, and that is the whole reason this file is careful:\n * when one server serves many tenants, the failure mode is SILENT. A push once\n * returned success having sent nothing, because the caller held the wrong\n * product's key and nothing in the exchange said which product it was for.\n *\n * So the rule these shapes exist to hold: TENANCY COMES FROM THE CREDENTIAL,\n * never from a request body. The token says which product it is for, the chat\n * server resolves the product from the token and from nothing else, and a\n * Founder Circle token cannot address another product's conversation even when\n * handed a valid-looking id.\n *\n * ⚠️ TEXT ONLY. There is deliberately no `callsEnabled` flag here, and its\n * absence is the feature: the user ruled chat is text only, there is no call\n * code to branch on, and the browser is told to deny camera and microphone\n * outright. A boolean that can never be true is an invitation to turn it on.\n *\n * @module founder-schema/domains/chat\n */\n\nimport { z } from 'zod';\nimport { objectIdSchema, usernameSchema } from '../../core/common.js';\nimport { CHAT_PARTICIPANTS_MAX } from '../../core/limits.js';\n\n/**\n * The product this package speaks for.\n *\n * Typed as a LITERAL on purpose. If the shared chat server ever hands back a\n * config or a token minted for a different product, parsing fails loudly here\n * rather than the client quietly talking to the wrong tenant. That is exactly\n * the class of bug this file exists to prevent, so it should be impossible to\n * carry past the first parse.\n */\nexport const CHAT_PRODUCT_ID = 'founder-circle' as const;\nexport const chatProductIdSchema = z.literal(CHAT_PRODUCT_ID);\nexport type ChatProductId = z.infer<typeof chatProductIdSchema>;\n\n// ─── Config ──────────────────────────────────────────────────────────────────\n\n/**\n * What the client needs before it can open a socket.\n *\n * ⚠️ `enabled` IS MANDATORY AND IS NOT DERIVED FROM `url`. \"Messaging is not\n * switched on yet\" is a first-class state, not a failure: a 404 is the expected\n * answer today, and the client collapses a disabled flag, a null url, a non-2xx\n * and a thrown fetch to the same quiet \"not on yet\" rather than an error. If\n * `enabled` were inferred from a missing url, \"off\" and \"broken\" would be the\n * same wire shape and the inbox could not tell a member which one it was.\n *\n * ⚠️ `userId` is required and is the field nothing works without. The client\n * needs to know WHO THE VIEWER IS to decide which side a bubble sits on, to\n * filter the viewer out of presence and typing, to pick the other participant\n * for a row's name and avatar, and to tell its own optimistic message from one\n * echoed back. Without it every conversation renders as though the viewer were\n * nobody. It was missing from the first sketch of this endpoint.\n */\nexport const chatConfigSchema = z.object({\n enabled: z.boolean(),\n /** Null whenever chat is not switched on. Never a placeholder string. */\n url: z.url().nullable(),\n /** The VIEWER's id, as the chat server knows them. */\n userId: z.string(),\n /** Which product this config is for. See `chatProductIdSchema`. */\n productId: chatProductIdSchema,\n});\nexport type ChatConfig = z.infer<typeof chatConfigSchema>;\n\n// ─── Auth token ──────────────────────────────────────────────────────────────\n\n/**\n * How long before expiry the client re-mints, in seconds.\n *\n * Exported because it is a contract detail and not an implementation one: a\n * token handed over with two seconds left is a socket that authenticates and is\n * closed again immediately, so the minting side needs to know the consuming\n * side will not use the last minute of a token's life.\n */\nexport const CHAT_TOKEN_REFRESH_MARGIN_SECONDS = 60;\n\n/**\n * How often the live socket re-authenticates, in seconds.\n *\n * Auth is an EVENT on the open socket rather than a handshake parameter, so\n * re-authenticating does not drop the connection.\n *\n * ⚠️ THIS MUST STAY BELOW THE REAL TOKEN LIFETIME, by more than the refresh\n * margin. It assumes a 15 minute token. A re-auth interval longer than the\n * lifetime is a socket that dies every quarter of an hour with no explanation,\n * and the symptom appears far from the cause. If the issued lifetime changes,\n * this number moves with it or the two silently disagree.\n */\nexport const CHAT_SOCKET_REAUTH_SECONDS = 10 * 60;\n\n/**\n * A short-lived token for the shared chat server.\n *\n * ⚠️ BOTH TIME FIELDS ARE KEPT, and they are not redundant, because two\n * different parties read them with two different clocks:\n *\n * `expiresAt` an absolute instant, for the SERVER. The chat server holds the\n * authoritative clock and must reject an expired token on its\n * own, whatever any client believes.\n * `expiresIn` a duration in seconds, for the CLIENT. Scheduling a refresh\n * from `receivedAt + expiresIn` uses only the client's own\n * elapsed time, so a device whose absolute clock is wrong still\n * refreshes correctly. Scheduling from `expiresAt` instead means\n * a browser an hour fast treats every fresh token as already\n * expired and re-mints forever.\n *\n * Dropping either one breaks the party that reads it. This is the same reason\n * OAuth carries `expires_in` on the wire while the token itself carries `exp`.\n *\n * ⚠️ AND THE CLIENT IS NOT THE ENFORCER. Its margin is an optimisation to avoid\n * a pointless round trip. A wrong clock, a tab asleep for an hour, or a modified\n * client all defeat anything the client does, so the chat server rejects an\n * expired token on its own.\n */\nexport const chatAuthTokenSchema = z.object({\n token: z.string().min(1),\n /** ISO 8601. Parsed with `Date.parse`, never an epoch number. */\n expiresAt: z.iso.datetime(),\n /** Seconds from issue. See the note above on why both exist. */\n expiresIn: z.number().int().positive(),\n /** The product this token is scoped to. A mismatch must fail loudly. */\n productId: chatProductIdSchema,\n});\nexport type ChatAuthToken = z.infer<typeof chatAuthTokenSchema>;\n\n// ─── Opening a conversation ──────────────────────────────────────────────────\n\n/**\n * `POST /api/v1/chat/open`: start (or find) the direct conversation with\n * another member.\n *\n * Our backend decides who may talk to whom, because only it knows this\n * product's rules, and it does the whole exchange with the chat server itself:\n * it mints the viewer's token and an invitation naming both participants, and\n * redeems them server to server. No credential reaches the browser.\n */\nexport const openChatBodySchema = z.object({\n /** The OTHER participant. The viewer is taken from the credential, never the body. */\n userId: objectIdSchema,\n /**\n * Agreement to use one of this month's allowance (0.12.0), when they do\n * not know the other person. Without it such an open is refused with\n * `MESSAGE_ALLOWANCE_UNCONFIRMED` and nothing is spent: an allowance is\n * never used by accident. Ignored for someone they know.\n */\n useAllowance: z.boolean().optional(),\n});\nexport type OpenChatBody = z.infer<typeof openChatBodySchema>;\n\n/**\n * How a conversation came to be allowed (0.12.0): they know each other, it\n * used the opener's allowance, or the opener was acting as a staff role,\n * which reaches anyone. ⚠ Stored: append only.\n */\nexport const CHAT_OPENED_VIA_VALUES = ['contact', 'allowance', 'staff'] as const;\nexport const chatOpenedViaSchema = z.enum(CHAT_OPENED_VIA_VALUES);\nexport type ChatOpenedVia = z.infer<typeof chatOpenedViaSchema>;\n\n/**\n * The conversation to navigate to. `201` with `wasCreated: true` the first\n * time, `200` and `false` on every later open of the same pair.\n */\nexport const openChatResponseSchema = z.object({\n conversationId: z.string().min(1),\n wasCreated: z.boolean(),\n /** 0.12.0. Every later open of the same pair is `contact`: they have a conversation now. */\n via: chatOpenedViaSchema,\n});\nexport type OpenChatResponse = z.infer<typeof openChatResponseSchema>;\n\n// ─── Who may start a conversation with whom (0.12.0) ─────────────────────────\n\n/**\n * Whether opening a conversation with someone would work, and what it would\n * cost, so the button can say so BEFORE it is tapped\n * (`GET /api/v1/chat/reach/:userId`):\n *\n * contact they know each other: free\n * allowance uses one of `left` new people this month: confirm first\n * allowance_exhausted none left this month (`resetsAt`)\n * plan_required they do not know each other and the asker has no plan\n * membership_required the asker cannot chat at all (a viewer)\n * not_accepted the other person takes conversations only from people\n * they know, or cannot chat (one answer for both)\n * staff the asker acts as a staff role, which starts a\n * conversation with anyone who can chat: free, past\n * their \"people I know only\" (the user, 2026-10-12)\n */\nexport const CHAT_REACH_VALUES = [\n 'contact',\n 'allowance',\n 'allowance_exhausted',\n 'plan_required',\n 'membership_required',\n 'not_accepted',\n 'staff',\n] as const;\nexport const chatReachKindSchema = z.enum(CHAT_REACH_VALUES);\nexport type ChatReachKind = z.infer<typeof chatReachKindSchema>;\n\nexport const chatReachSchema = z.object({\n reach: chatReachKindSchema,\n /** For `allowance`: how many new people are left this month, this one included. */\n left: z.number().int().nonnegative().nullable(),\n /** For `allowance` and `allowance_exhausted`: when the month's count starts again. */\n resetsAt: z.iso.datetime().nullable(),\n});\nexport type ChatReach = z.infer<typeof chatReachSchema>;\n\nexport const chatReachParamsSchema = z.object({ userId: objectIdSchema });\nexport type ChatReachParams = z.infer<typeof chatReachParamsSchema>;\n\n/**\n * Who may start a conversation with me (0.12.0). People I know always may.\n * ⚠ Stored: append only.\n *\n * contacts only people I know\n * contacts_and_plans also Premium and Business members (the default)\n */\nexport const MESSAGE_FROM_VALUES = ['contacts', 'contacts_and_plans'] as const;\nexport const messageFromSchema = z.enum(MESSAGE_FROM_VALUES);\nexport type MessageFrom = z.infer<typeof messageFromSchema>;\n\n/** `GET` and `PUT /api/v1/me/messaging`. */\nexport const messagingSettingsSchema = z.object({ from: messageFromSchema });\nexport type MessagingSettings = z.infer<typeof messagingSettingsSchema>;\n\n// ─── Participants ────────────────────────────────────────────────────────────\n\n/**\n * `POST /api/v1/chat/participants`: names and avatars for the people in the\n * viewer's conversations.\n *\n * The chat server knows ids and nothing about who anybody is, because it serves\n * several products and identity belongs to each; so the conversation list asks\n * here, once per screen. Bounded by `CHAT_PARTICIPANTS_MAX`, so it cannot page\n * through the directory.\n */\nexport const chatParticipantsBodySchema = z.object({\n userIds: z.array(objectIdSchema).min(1).max(CHAT_PARTICIPANTS_MAX),\n});\nexport type ChatParticipantsBody = z.infer<typeof chatParticipantsBodySchema>;\n\n/** The public card fields any member already sees, and nothing more. */\nexport const chatParticipantSchema = z.object({\n displayName: z.string(),\n username: usernameSchema,\n /** Null when the member has no photo. Ours, or from the login provider. */\n avatarUrl: z.url().nullable(),\n});\nexport type ChatParticipant = z.infer<typeof chatParticipantSchema>;\n\n/**\n * Keyed by user id. ⚠ An id with no active, onboarded profile is ABSENT, not\n * an error: the client renders it as a former member rather than guessing.\n */\nexport const chatParticipantsResponseSchema = z.object({\n participants: z.record(z.string(), chatParticipantSchema),\n});\nexport type ChatParticipantsResponse = z.infer<typeof chatParticipantsResponseSchema>;\n"]}
|
|
1
|
+
{"version":3,"file":"chat.js","sourceRoot":"","sources":["../../../src/domains/chat/chat.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * founder-schema — Chat: config, auth token, opening a conversation, participants\n *\n * Founder Circle does not run a chat server. It uses the shared one, which\n * serves several products, and that is the whole reason this file is careful:\n * when one server serves many tenants, the failure mode is SILENT. A push once\n * returned success having sent nothing, because the caller held the wrong\n * product's key and nothing in the exchange said which product it was for.\n *\n * So the rule these shapes exist to hold: TENANCY COMES FROM THE CREDENTIAL,\n * never from a request body. The token says which product it is for, the chat\n * server resolves the product from the token and from nothing else, and a\n * Founder Circle token cannot address another product's conversation even when\n * handed a valid-looking id.\n *\n * ⚠️ TEXT ONLY. There is deliberately no `callsEnabled` flag here, and its\n * absence is the feature: the user ruled chat is text only, there is no call\n * code to branch on, and the browser is told to deny camera and microphone\n * outright. A boolean that can never be true is an invitation to turn it on.\n *\n * @module founder-schema/domains/chat\n */\n\nimport { z } from 'zod';\nimport { objectIdSchema } from '../../core/common.js';\nimport { CHAT_PARTICIPANTS_MAX } from '../../core/limits.js';\nimport { personSchema } from '../people/person.js';\n\n/**\n * The product this package speaks for.\n *\n * Typed as a LITERAL on purpose. If the shared chat server ever hands back a\n * config or a token minted for a different product, parsing fails loudly here\n * rather than the client quietly talking to the wrong tenant. That is exactly\n * the class of bug this file exists to prevent, so it should be impossible to\n * carry past the first parse.\n */\nexport const CHAT_PRODUCT_ID = 'founder-circle' as const;\nexport const chatProductIdSchema = z.literal(CHAT_PRODUCT_ID);\nexport type ChatProductId = z.infer<typeof chatProductIdSchema>;\n\n// ─── Config ──────────────────────────────────────────────────────────────────\n\n/**\n * What the client needs before it can open a socket.\n *\n * ⚠️ `enabled` IS MANDATORY AND IS NOT DERIVED FROM `url`. \"Messaging is not\n * switched on yet\" is a first-class state, not a failure: a 404 is the expected\n * answer today, and the client collapses a disabled flag, a null url, a non-2xx\n * and a thrown fetch to the same quiet \"not on yet\" rather than an error. If\n * `enabled` were inferred from a missing url, \"off\" and \"broken\" would be the\n * same wire shape and the inbox could not tell a member which one it was.\n *\n * ⚠️ `userId` is required and is the field nothing works without. The client\n * needs to know WHO THE VIEWER IS to decide which side a bubble sits on, to\n * filter the viewer out of presence and typing, to pick the other participant\n * for a row's name and avatar, and to tell its own optimistic message from one\n * echoed back. Without it every conversation renders as though the viewer were\n * nobody. It was missing from the first sketch of this endpoint.\n */\nexport const chatConfigSchema = z.object({\n enabled: z.boolean(),\n /** Null whenever chat is not switched on. Never a placeholder string. */\n url: z.url().nullable(),\n /** The VIEWER's id, as the chat server knows them. */\n userId: z.string(),\n /** Which product this config is for. See `chatProductIdSchema`. */\n productId: chatProductIdSchema,\n});\nexport type ChatConfig = z.infer<typeof chatConfigSchema>;\n\n// ─── Auth token ──────────────────────────────────────────────────────────────\n\n/**\n * How long before expiry the client re-mints, in seconds.\n *\n * Exported because it is a contract detail and not an implementation one: a\n * token handed over with two seconds left is a socket that authenticates and is\n * closed again immediately, so the minting side needs to know the consuming\n * side will not use the last minute of a token's life.\n */\nexport const CHAT_TOKEN_REFRESH_MARGIN_SECONDS = 60;\n\n/**\n * How often the live socket re-authenticates, in seconds.\n *\n * Auth is an EVENT on the open socket rather than a handshake parameter, so\n * re-authenticating does not drop the connection.\n *\n * ⚠️ THIS MUST STAY BELOW THE REAL TOKEN LIFETIME, by more than the refresh\n * margin. It assumes a 15 minute token. A re-auth interval longer than the\n * lifetime is a socket that dies every quarter of an hour with no explanation,\n * and the symptom appears far from the cause. If the issued lifetime changes,\n * this number moves with it or the two silently disagree.\n */\nexport const CHAT_SOCKET_REAUTH_SECONDS = 10 * 60;\n\n/**\n * A short-lived token for the shared chat server.\n *\n * ⚠️ BOTH TIME FIELDS ARE KEPT, and they are not redundant, because two\n * different parties read them with two different clocks:\n *\n * `expiresAt` an absolute instant, for the SERVER. The chat server holds the\n * authoritative clock and must reject an expired token on its\n * own, whatever any client believes.\n * `expiresIn` a duration in seconds, for the CLIENT. Scheduling a refresh\n * from `receivedAt + expiresIn` uses only the client's own\n * elapsed time, so a device whose absolute clock is wrong still\n * refreshes correctly. Scheduling from `expiresAt` instead means\n * a browser an hour fast treats every fresh token as already\n * expired and re-mints forever.\n *\n * Dropping either one breaks the party that reads it. This is the same reason\n * OAuth carries `expires_in` on the wire while the token itself carries `exp`.\n *\n * ⚠️ AND THE CLIENT IS NOT THE ENFORCER. Its margin is an optimisation to avoid\n * a pointless round trip. A wrong clock, a tab asleep for an hour, or a modified\n * client all defeat anything the client does, so the chat server rejects an\n * expired token on its own.\n */\nexport const chatAuthTokenSchema = z.object({\n token: z.string().min(1),\n /** ISO 8601. Parsed with `Date.parse`, never an epoch number. */\n expiresAt: z.iso.datetime(),\n /** Seconds from issue. See the note above on why both exist. */\n expiresIn: z.number().int().positive(),\n /** The product this token is scoped to. A mismatch must fail loudly. */\n productId: chatProductIdSchema,\n});\nexport type ChatAuthToken = z.infer<typeof chatAuthTokenSchema>;\n\n// ─── Opening a conversation ──────────────────────────────────────────────────\n\n/**\n * `POST /api/v1/chat/open`: start (or find) the direct conversation with\n * another member.\n *\n * Our backend decides who may talk to whom, because only it knows this\n * product's rules, and it does the whole exchange with the chat server itself:\n * it mints the viewer's token and an invitation naming both participants, and\n * redeems them server to server. No credential reaches the browser.\n */\nexport const openChatBodySchema = z.object({\n /** The OTHER participant. The viewer is taken from the credential, never the body. */\n userId: objectIdSchema,\n /**\n * Agreement to use one of this month's allowance (0.12.0), when they do\n * not know the other person. Without it such an open is refused with\n * `MESSAGE_ALLOWANCE_UNCONFIRMED` and nothing is spent: an allowance is\n * never used by accident. Ignored for someone they know.\n */\n useAllowance: z.boolean().optional(),\n});\nexport type OpenChatBody = z.infer<typeof openChatBodySchema>;\n\n/**\n * How a conversation came to be allowed (0.12.0): they know each other, it\n * used the opener's allowance, or the opener was acting as a staff role,\n * which reaches anyone. ⚠ Stored: append only.\n */\nexport const CHAT_OPENED_VIA_VALUES = ['contact', 'allowance', 'staff'] as const;\nexport const chatOpenedViaSchema = z.enum(CHAT_OPENED_VIA_VALUES);\nexport type ChatOpenedVia = z.infer<typeof chatOpenedViaSchema>;\n\n/**\n * The conversation to navigate to. `201` with `wasCreated: true` the first\n * time, `200` and `false` on every later open of the same pair.\n */\nexport const openChatResponseSchema = z.object({\n conversationId: z.string().min(1),\n wasCreated: z.boolean(),\n /** 0.12.0. Every later open of the same pair is `contact`: they have a conversation now. */\n via: chatOpenedViaSchema,\n});\nexport type OpenChatResponse = z.infer<typeof openChatResponseSchema>;\n\n// ─── Who may start a conversation with whom (0.12.0) ─────────────────────────\n\n/**\n * Whether opening a conversation with someone would work, and what it would\n * cost, so the button can say so BEFORE it is tapped\n * (`GET /api/v1/chat/reach/:userId`):\n *\n * contact they know each other: free\n * allowance uses one of `left` new people this month: confirm first\n * allowance_exhausted none left this month (`resetsAt`)\n * plan_required they do not know each other and the asker has no plan\n * membership_required the asker cannot chat at all (a viewer)\n * not_accepted the other person takes conversations only from people\n * they know, or cannot chat (one answer for both)\n * staff the asker acts as a staff role, which starts a\n * conversation with anyone who can chat: free, past\n * their \"people I know only\" (the user, 2026-10-12)\n */\nexport const CHAT_REACH_VALUES = [\n 'contact',\n 'allowance',\n 'allowance_exhausted',\n 'plan_required',\n 'membership_required',\n 'not_accepted',\n 'staff',\n] as const;\nexport const chatReachKindSchema = z.enum(CHAT_REACH_VALUES);\nexport type ChatReachKind = z.infer<typeof chatReachKindSchema>;\n\nexport const chatReachSchema = z.object({\n reach: chatReachKindSchema,\n /** For `allowance`: how many new people are left this month, this one included. */\n left: z.number().int().nonnegative().nullable(),\n /** For `allowance` and `allowance_exhausted`: when the month's count starts again. */\n resetsAt: z.iso.datetime().nullable(),\n});\nexport type ChatReach = z.infer<typeof chatReachSchema>;\n\nexport const chatReachParamsSchema = z.object({ userId: objectIdSchema });\nexport type ChatReachParams = z.infer<typeof chatReachParamsSchema>;\n\n/**\n * Who may start a conversation with me (0.12.0). People I know always may.\n * ⚠ Stored: append only.\n *\n * contacts only people I know\n * contacts_and_plans also Premium and Business members (the default)\n */\nexport const MESSAGE_FROM_VALUES = ['contacts', 'contacts_and_plans'] as const;\nexport const messageFromSchema = z.enum(MESSAGE_FROM_VALUES);\nexport type MessageFrom = z.infer<typeof messageFromSchema>;\n\n/** `GET` and `PUT /api/v1/me/messaging`. */\nexport const messagingSettingsSchema = z.object({ from: messageFromSchema });\nexport type MessagingSettings = z.infer<typeof messagingSettingsSchema>;\n\n// ─── Participants ────────────────────────────────────────────────────────────\n\n/**\n * `POST /api/v1/chat/participants`: names and avatars for the people in the\n * viewer's conversations.\n *\n * The chat server knows ids and nothing about who anybody is, because it serves\n * several products and identity belongs to each; so the conversation list asks\n * here, once per screen. Bounded by `CHAT_PARTICIPANTS_MAX`, so it cannot page\n * through the directory.\n */\nexport const chatParticipantsBodySchema = z.object({\n userIds: z.array(objectIdSchema).min(1).max(CHAT_PARTICIPANTS_MAX),\n});\nexport type ChatParticipantsBody = z.infer<typeof chatParticipantsBodySchema>;\n\n/** The person, as every surface shows them (0.20.0, `personSchema`), and nothing more. */\nexport const chatParticipantSchema = personSchema;\nexport type ChatParticipant = z.infer<typeof chatParticipantSchema>;\n\n/** A direct-contact lock row: being opened, or open. The backend's storage's own values, from here like every other list (0.20.0). */\nexport const DIRECT_CONTACT_STATUS_VALUES = ['opening', 'open'] as const;\nexport const directContactStatusSchema = z.enum(DIRECT_CONTACT_STATUS_VALUES);\nexport type DirectContactStatus = z.infer<typeof directContactStatusSchema>;\n\n/**\n * Keyed by user id. Every id asked for is answered (0.20.0): a deleted account\n * as a former person (`former: true`, no name or picture), an id that names\n * nobody the same way, so the client never has to guess.\n */\nexport const chatParticipantsResponseSchema = z.object({\n participants: z.record(z.string(), chatParticipantSchema),\n});\nexport type ChatParticipantsResponse = z.infer<typeof chatParticipantsResponseSchema>;\n"]}
|