@odla-ai/chapter 0.50.0 → 0.51.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -239,6 +239,7 @@ __export(src_exports, {
239
239
  resolveSignupControl: () => resolveSignupControl,
240
240
  resolveTiers: () => resolveTiers,
241
241
  roleFromClaim: () => roleFromClaim,
242
+ seatPurchaseDeadline: () => seatPurchaseDeadline,
242
243
  sendTemplated: () => sendTemplated,
243
244
  sharedPersonInput: () => sharedPersonInput,
244
245
  sharedRecordFromCrm: () => sharedRecordFromCrm,
@@ -3472,6 +3473,11 @@ function createChapterIntegration(chapter, options = {}) {
3472
3473
  }
3473
3474
 
3474
3475
  // src/membership-policy.ts
3476
+ function seatPurchaseDeadline(offering, member) {
3477
+ if (offering.seatPurchaseWindowCalendarMonths === void 0) return Number(member.termEndsAt);
3478
+ if (Number.isSafeInteger(member.seatPurchaseEndsAt)) return Number(member.seatPurchaseEndsAt);
3479
+ return addMembershipCalendarMonths(Number(member.initialTermStartedAt ?? member.termStartedAt), offering.seatPurchaseWindowCalendarMonths);
3480
+ }
3475
3481
  var fail2 = (field2) => {
3476
3482
  throw new TypeError(`invalid membership policy: ${field2}`);
3477
3483
  };
@@ -3528,7 +3534,7 @@ function membershipOfferingVersion(value) {
3528
3534
  autoRenew: true,
3529
3535
  paymentGraceDays: integer2(input.paymentGraceDays, 0, 60),
3530
3536
  seatPriceCents: integer2(input.seatPriceCents, 1, Number.MAX_SAFE_INTEGER),
3531
- seatPurchaseWindowCalendarMonths: integer2(input.seatPurchaseWindowCalendarMonths, 1, 120),
3537
+ ...input.seatPurchaseWindowCalendarMonths === void 0 || input.seatPurchaseWindowCalendarMonths === null ? {} : { seatPurchaseWindowCalendarMonths: integer2(input.seatPurchaseWindowCalendarMonths, 1, 120) },
3532
3538
  requiredDisclosures: ids(input.requiredDisclosures)
3533
3539
  };
3534
3540
  }
@@ -3922,7 +3928,7 @@ async function confirmMembershipPayment(db, input, now) {
3922
3928
  initialTermEndsAt: endsAt,
3923
3929
  termStartedAt: paidAt,
3924
3930
  termEndsAt: endsAt,
3925
- seatPurchaseEndsAt: addMembershipCalendarMonths(Number(paidAt), offering.seatPurchaseWindowCalendarMonths),
3931
+ seatPurchaseEndsAt: seatPurchaseDeadline(offering, { initialTermStartedAt: paidAt, termEndsAt: endsAt }),
3926
3932
  autoRenew: true,
3927
3933
  refundedCents: 0,
3928
3934
  revision: 1,
@@ -4350,7 +4356,11 @@ async function reconcileMembershipRenewal(db, input, now) {
4350
4356
  membershipUpdate("networkMembership", id10, {
4351
4357
  status: status2,
4352
4358
  graceEndsAt,
4353
- ...paid ? { termStartedAt: start, termEndsAt: end } : {},
4359
+ ...paid ? {
4360
+ termStartedAt: start,
4361
+ termEndsAt: end,
4362
+ ...membershipOfferingVersion(member.offeringSnapshot).seatPurchaseWindowCalendarMonths === void 0 ? { seatPurchaseEndsAt: end } : {}
4363
+ } : {},
4354
4364
  revision: Number(member.revision) + 1,
4355
4365
  updatedAt: now
4356
4366
  }),
@@ -4652,10 +4662,11 @@ async function reserveNamedMembershipSeat(db, input, now) {
4652
4662
  const id10 = (await membershipOfferIdForRequest({ ...input, requestId: "named_seat" })).replace(/^offer_/, "seat_");
4653
4663
  let seat = await membershipLoad(db, "networkSeat", id10);
4654
4664
  if (!seat) {
4655
- if (!["paid_pending_approval", "active", "cancel_at_term_end"].includes(String(member.status)) || Number(member.refundedCents) !== 0 || now < Number(member.initialTermStartedAt) || now >= Number(member.termEndsAt) || now > Number(member.seatPurchaseEndsAt) || !Number.isSafeInteger(member.seatPurchaseEndsAt) || member.namedSeatId !== void 0) {
4665
+ const offering = membershipOfferingVersion(member.offeringSnapshot), claimId = await recipientKey(input, email);
4666
+ const purchaseEndsAt = seatPurchaseDeadline(offering, member);
4667
+ if (!["paid_pending_approval", "active", "cancel_at_term_end"].includes(String(member.status)) || Number(member.refundedCents) !== 0 || now < Number(member.initialTermStartedAt) || now >= Number(member.termEndsAt) || now > purchaseEndsAt || !Number.isSafeInteger(purchaseEndsAt) || member.namedSeatId !== void 0) {
4656
4668
  membershipFail("named_seat_purchase_unavailable");
4657
4669
  }
4658
- const offering = membershipOfferingVersion(member.offeringSnapshot), claimId = await recipientKey(input, email);
4659
4670
  const attrs = {
4660
4671
  id: id10,
4661
4672
  ...membershipScope(input),
@@ -4674,7 +4685,7 @@ async function reserveNamedMembershipSeat(db, input, now) {
4674
4685
  status: "payment_pending",
4675
4686
  preparedAt: now,
4676
4687
  termEndsAt: member.termEndsAt,
4677
- seatPurchaseEndsAt: member.seatPurchaseEndsAt,
4688
+ seatPurchaseEndsAt: purchaseEndsAt,
4678
4689
  offeringSnapshot: offering,
4679
4690
  revision: 1,
4680
4691
  createdAt: now,
@@ -4891,7 +4902,7 @@ async function confirmNamedMembershipSeatPayment(db, input, now) {
4891
4902
  }
4892
4903
  if (seat.purchasedAt === void 0) {
4893
4904
  if (!["payment_processing", "payment_canceling"].includes(String(seat.status))) membershipFail("named_seat_payment_not_expected");
4894
- const eligible = seat.status !== "payment_canceling" && ["paid_pending_approval", "active", "cancel_at_term_end"].includes(String(member.status)) && Number(member.refundedCents) === 0 && paidAt <= Number(member.seatPurchaseEndsAt) && now < Number(member.termEndsAt);
4905
+ const eligible = seat.status !== "payment_canceling" && ["paid_pending_approval", "active", "cancel_at_term_end"].includes(String(member.status)) && Number(member.refundedCents) === 0 && paidAt <= seatPurchaseDeadline(membershipOfferingVersion(member.offeringSnapshot), member) && now < Number(member.termEndsAt);
4895
4906
  const status2 = eligible ? "renewal_pending" : "refund_pending", effectId = `${seat.id}:${eligible ? "attach-renewal" : "refund"}`;
4896
4907
  try {
4897
4908
  await db.transact([
@@ -5243,15 +5254,16 @@ async function readNamedSeatOffer(db, input, now) {
5243
5254
  const offering = membershipOfferingVersion(member.offeringSnapshot);
5244
5255
  const seat = member.namedSeatId ? await membershipLoad(db, "networkSeat", String(member.namedSeatId)) : void 0;
5245
5256
  if (seat) requireMembershipScope(seat, input);
5257
+ const purchaseEndsAt = seatPurchaseDeadline(offering, member);
5246
5258
  const offer = {
5247
5259
  membershipId: id10,
5248
5260
  amountCents: offering.seatPriceCents,
5249
5261
  currency: offering.currency,
5250
5262
  interval: offering.interval,
5251
5263
  termEndsAt: Number(member.termEndsAt),
5252
- purchaseEndsAt: Number(member.seatPurchaseEndsAt),
5264
+ purchaseEndsAt,
5253
5265
  autoRenew: member.autoRenew === true,
5254
- eligible: ["paid_pending_approval", "active", "cancel_at_term_end"].includes(String(member.status)) && member.refundedCents === 0 && now >= Number(member.initialTermStartedAt) && now < Number(member.termEndsAt) && now <= Number(member.seatPurchaseEndsAt) && (!seat || ["payment_pending", "payment_processing"].includes(String(seat.status))),
5266
+ eligible: ["paid_pending_approval", "active", "cancel_at_term_end"].includes(String(member.status)) && member.refundedCents === 0 && now >= Number(member.initialTermStartedAt) && now < Number(member.termEndsAt) && now <= purchaseEndsAt && (!seat || ["payment_pending", "payment_processing"].includes(String(seat.status))),
5255
5267
  ...seat ? { seat: {
5256
5268
  seatId: String(seat.id),
5257
5269
  status: String(seat.status),
@@ -5259,7 +5271,7 @@ async function readNamedSeatOffer(db, input, now) {
5259
5271
  recipientEmail: String(seat.recipientEmailNormalized)
5260
5272
  } } : {}
5261
5273
  };
5262
- return { ...offer, digest: await namedSeatOfferDigest(offer) };
5274
+ return { ...offer, digest: await namedSeatOfferDigest(offer), purchaseWindowed: offering.seatPurchaseWindowCalendarMonths !== void 0 };
5263
5275
  }
5264
5276
 
5265
5277
  // src/membership-seat-invitation.ts
@@ -5744,7 +5756,7 @@ async function requestNamedSeatReservation(options) {
5744
5756
  async function requestNamedSeatOffer(options) {
5745
5757
  const result = await requestAuthority(options, "seat-offer", { applicationId: options.applicationId, skuId: options.skuId });
5746
5758
  const offer = result.seat;
5747
- if (!offer || offer.membershipId !== await networkMembershipId(options) || !Number.isSafeInteger(offer.amountCents) || offer.amountCents <= 0 || !/^[a-z]{3}$/.test(offer.currency) || !["month", "year"].includes(offer.interval) || typeof offer.eligible !== "boolean" || typeof offer.autoRenew !== "boolean" || !Number.isSafeInteger(offer.termEndsAt) || !Number.isSafeInteger(offer.purchaseEndsAt) || offer.digest !== await namedSeatOfferDigest(offer)) throw new Error("invalid named seat offer");
5759
+ if (!offer || offer.membershipId !== await networkMembershipId(options) || !Number.isSafeInteger(offer.amountCents) || offer.amountCents <= 0 || !/^[a-z]{3}$/.test(offer.currency) || !["month", "year"].includes(offer.interval) || typeof offer.eligible !== "boolean" || typeof offer.autoRenew !== "boolean" || !Number.isSafeInteger(offer.termEndsAt) || !Number.isSafeInteger(offer.purchaseEndsAt) || offer.purchaseWindowed !== void 0 && typeof offer.purchaseWindowed !== "boolean" || offer.digest !== await namedSeatOfferDigest(offer)) throw new Error("invalid named seat offer");
5748
5760
  return offer;
5749
5761
  }
5750
5762
  async function requestNamedSeatInvitation(options) {