riverbankcms 0.14.0 → 0.16.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.
@@ -92,6 +92,7 @@ const unsafeAsFormSubmissionId = (id) => id;
92
92
  const unsafeAsPassId = (id) => id;
93
93
  const unsafeAsMembershipId = (id) => id;
94
94
  const unsafeAsCustomerId = (id) => id;
95
+ const unsafeAsOrderRetirementOperationId = (id) => id;
95
96
  const unsafeAsOrderId = (id) => id;
96
97
  const unsafeAsOrderItemId = (id) => id;
97
98
  const unsafeAsOrderRefundId = (id) => id;
@@ -203,6 +204,7 @@ const parseEventSeriesRegistrationId = (value) => parseUuidBrand(value, unsafeAs
203
204
  const parseParticipantId = (value) => parseUuidBrand(value, unsafeAsParticipantId);
204
205
  const parseParticipantParticipationId = (value) => parseUuidBrand(value, unsafeAsParticipantParticipationId);
205
206
  const parseOrderItemId = (value) => parseUuidBrand(value, unsafeAsOrderItemId);
207
+ const parseOrderRetirementOperationId = (value) => parseUuidBrand(value, unsafeAsOrderRetirementOperationId);
206
208
  const parseOrderId = (value) => parseUuidBrand(value, unsafeAsOrderId);
207
209
  const parseOrderRefundId = (value) => parseUuidBrand(value, unsafeAsOrderRefundId);
208
210
  const parseOrderPaymentReceiptId = (value) => parseUuidBrand(value, unsafeAsOrderPaymentReceiptId);
@@ -1474,21 +1476,16 @@ function resolveFlexibleBalancePaymentEligibility(input) {
1474
1476
  };
1475
1477
  }
1476
1478
  switch (input.status) {
1477
- case "payment_pending": return {
1478
- kind: "unavailable",
1479
- reason: "payment_pending"
1480
- };
1481
- case "cancelled_due_to_non_payment": return {
1482
- kind: "unavailable",
1483
- reason: "cancelled_due_to_non_payment"
1484
- };
1485
- case "refunded": return {
1479
+ case "payment_pending":
1480
+ case "cancelled_due_to_non_payment":
1481
+ case "refunded":
1482
+ case "waived": return {
1486
1483
  kind: "unavailable",
1487
- reason: "refunded"
1484
+ reason: input.status
1488
1485
  };
1489
- case "waived": return {
1486
+ case "closed_order_failed": return {
1490
1487
  kind: "unavailable",
1491
- reason: "waived"
1488
+ reason: "order_failed"
1492
1489
  };
1493
1490
  case "overdue": return {
1494
1491
  kind: "full_balance_only",
@@ -1681,6 +1678,126 @@ function assertNever$3(value) {
1681
1678
  throw new Error(`Unexpected value: ${String(value)}`);
1682
1679
  }
1683
1680
 
1681
+ //#endregion
1682
+ //#region ../core/src/booking-instalment-deposit.ts
1683
+ /**
1684
+ * A plan that starts with a deposit takes it by card when the customer books
1685
+ * and saves the card for the later payments, so the deposit must be at least
1686
+ * the card minimum for the site's currency. Plans without a deposit step
1687
+ * (equal instalments) charge their first instalment instead and are not
1688
+ * checked here.
1689
+ */
1690
+ function checkInstalmentPlanDeposit(plan, minimumCents) {
1691
+ if (!isDepositBearingBookingInstalmentPlan(plan)) return ok(undefined);
1692
+ return plan.depositAmountCents >= minimumCents ? ok(undefined) : err({
1693
+ kind: "instalment_deposit_below_minimum",
1694
+ minimumCents
1695
+ });
1696
+ }
1697
+ /** The deposit check for whichever instalment option a set of payment options offers. */
1698
+ function checkPaymentOptionsInstalmentDeposit(allowedOptions, minimumCents) {
1699
+ const failure = allowedOptions.map((option) => option.kind === "instalment_plan" ? checkInstalmentPlanDeposit(option.plan, minimumCents) : ok(undefined)).find((checked) => !checked.ok);
1700
+ return failure ?? ok(undefined);
1701
+ }
1702
+ /** The one message for a deposit below the minimum, shown in the editor and returned by the server. */
1703
+ function describeInstalmentDepositBelowMinimum(failure, currency) {
1704
+ const minimum = formatCurrencyAmount(failure.minimumCents, currency);
1705
+ return `Enter a deposit of at least ${minimum}. We take it when the customer books and save their card for the later payments.`;
1706
+ }
1707
+
1708
+ //#endregion
1709
+ //#region ../core/src/booking-live-payment-terms.ts
1710
+ /**
1711
+ * Whether an order still has payment terms being collected: an instalment plan
1712
+ * or a flexible-balance contract that hasn't been settled, closed or cancelled.
1713
+ *
1714
+ * Both tables are total over their status unions, so a new status is a compile
1715
+ * error here until someone decides whether it counts as live.
1716
+ */
1717
+ const LIVE_PLAN_STATUSES = {
1718
+ pending_initial_payment: true,
1719
+ active: true,
1720
+ payment_failed: true,
1721
+ reconciliation_required: true,
1722
+ completed: false,
1723
+ cancelled: false,
1724
+ cancelled_as_paid_early: false,
1725
+ refunded: false
1726
+ };
1727
+ const LIVE_CONTRACT_STATUSES = {
1728
+ active: true,
1729
+ payment_pending: true,
1730
+ overdue: true,
1731
+ completed: false,
1732
+ waived: false,
1733
+ refunded: false,
1734
+ cancelled_due_to_non_payment: false,
1735
+ closed_order_failed: false
1736
+ };
1737
+ function isLiveOrderInstalmentPlanStatus(status) {
1738
+ return LIVE_PLAN_STATUSES[status];
1739
+ }
1740
+ function isLiveFlexibleBalanceContractStatus(status) {
1741
+ return LIVE_CONTRACT_STATUSES[status];
1742
+ }
1743
+ function hasLivePaymentTerms(input) {
1744
+ return input.plan !== null && isLiveOrderInstalmentPlanStatus(input.plan.status) || input.contract !== null && isLiveFlexibleBalanceContractStatus(input.contract.status);
1745
+ }
1746
+ /** Partial refunds must also protect a cancelled contract that staff can reopen. */
1747
+ function paymentTermsBlockPartialRefund(input) {
1748
+ return hasLivePaymentTerms(input) || input.contract?.status === "cancelled_due_to_non_payment";
1749
+ }
1750
+ /**
1751
+ * Live statuses where a collection is already in flight: the first payment,
1752
+ * a card charge, or a Stripe reconciliation hasn't resolved yet. Nobody may
1753
+ * settle the balance by hand while one of these is running. Both tables are
1754
+ * total over the live statuses, so a new live status must be classified here.
1755
+ */
1756
+ const PLAN_COLLECTION_IN_FLIGHT = {
1757
+ pending_initial_payment: true,
1758
+ reconciliation_required: true,
1759
+ active: false,
1760
+ payment_failed: false
1761
+ };
1762
+ const CONTRACT_COLLECTION_IN_FLIGHT = {
1763
+ payment_pending: true,
1764
+ active: false,
1765
+ overdue: false
1766
+ };
1767
+ /**
1768
+ * Whether an instalment plan's remaining balance can take a payment now, by
1769
+ * hand or online: it's live and no collection is in flight.
1770
+ */
1771
+ function isSettleableOrderInstalmentPlanStatus(status) {
1772
+ return isLiveOrderInstalmentPlanStatus(status) && !PLAN_COLLECTION_IN_FLIGHT[status];
1773
+ }
1774
+ /**
1775
+ * Whether a flexible-balance contract's remaining balance can take a payment
1776
+ * now, by hand or online: it's live and no collection is in flight.
1777
+ */
1778
+ function isSettleableFlexibleBalanceContractStatus(status) {
1779
+ return isLiveFlexibleBalanceContractStatus(status) && !CONTRACT_COLLECTION_IN_FLIGHT[status];
1780
+ }
1781
+ function decideContractClosureForFailedOrder(status) {
1782
+ return isLiveFlexibleBalanceContractStatus(status) ? {
1783
+ kind: "close",
1784
+ from: status
1785
+ } : { kind: "keep" };
1786
+ }
1787
+
1788
+ //#endregion
1789
+ //#region ../core/src/booking-payment-options.ts
1790
+ /** Automatic instalments and a flexible balance cannot share one booking offer. */
1791
+ function validateBookingPaymentOptionKinds(kinds) {
1792
+ if (kinds.length === 0) return err("no_options");
1793
+ const uniqueKinds = new Set(kinds);
1794
+ if (uniqueKinds.size !== kinds.length) return err("duplicate_kind");
1795
+ if (uniqueKinds.has("instalment_plan") && uniqueKinds.has("flexible_balance")) {
1796
+ return err("incompatible_collection_options");
1797
+ }
1798
+ return ok(undefined);
1799
+ }
1800
+
1684
1801
  //#endregion
1685
1802
  //#region ../core/src/booking-time-zone.ts
1686
1803
  const TIME_ZONE_VALIDITY_CACHE_LIMIT = 100;
@@ -2600,6 +2717,11 @@ function syncStateOf(sync) {
2600
2717
 
2601
2718
  //#endregion
2602
2719
  //#region ../core/src/edit-lease.ts
2720
+ /**
2721
+ * How long a lease lasts without a heartbeat. The server grants for this long, and a
2722
+ * reload handover is only worth presenting within it (issue 1570).
2723
+ */
2724
+ const EDIT_LEASE_TTL_SECONDS = 60;
2603
2725
  function parseEditLeaseScope(input) {
2604
2726
  switch (input.nodeType) {
2605
2727
  case "page": {
@@ -7246,4 +7368,54 @@ function eventCatalogueChoices(catalogue) {
7246
7368
  }
7247
7369
 
7248
7370
  //#endregion
7249
- export { parseEventPageSurfaceSubject as $, footerNavigationLayouts as A, unsafeAsOriginalFilename as At, formatBookingDate as B, unsafeAsStoragePath as Bt, parseMailingListContentVersionId as C, unsafeAsDetectedMimeType as Ct, sameMailingListPlacementTargeting as D, unsafeAsFileChecksumSha256 as Dt, planMailingListChoicePresentation as E, unsafeAsEventSeriesId as Et, isPresent as F, unsafeAsSiteFontId as Ft, getBookingLocalDateKey as G, formatBookingTime as H, unsafeAsUserId as Ht, normalizeLocationAddressText as I, unsafeAsSiteId as It, parseUtcIsoDateTimeString as J, getLocalScheduleDate as K, toLocationCoordinates as L, unsafeAsSiteScopedStoragePath as Lt, parseMailingListPlacementTargeting as M, unsafeAsPositiveSeconds as Mt, isCanonicalRichTextDoc as N, unsafeAsProductId as Nt, DEFAULT_MAILING_LIST_SUCCESS_MESSAGE as O, unsafeAsMediaAssetId as Ot, assertAllowedPublicUrl as P, unsafeAsSafeDownloadFilename as Pt, parseBookingTimeZone as Q, selectCategoryView as R, unsafeAsStaffMemberId as Rt, parseMailingListBlockId as S, unsafeAsDemoCapability as St, parseMailingListRuntimeContext as T, unsafeAsEventOfferingId as Tt, formatLocalScheduleDate as U, err as Ut, formatBookingDateParts as V, unsafeAsUploadSessionId as Vt, formatLocalScheduleTime as W, ok as Wt, toScheduledBookingDateRange as X, toBookingTimeZone as Y, toScheduledBookingDateTime as Z, createSecret as _, parseUserId as _t, parseVerticalId as a, publicEventPricingType as at, stableJsonStringify as b, unsafeAsBookingSessionId as bt, DEFAULT_EVENT_TYPE_PRESETS as c, fromArray as ct, SURFACE_EVENT_PRESET_VALUES as d, assertNever as dt, formatBookingPriceDisplay as et, WHOLE_SERIES_EVENT_PRESET_VALUES as f, parseApiKeyId as ft, resolveWholeSeriesBookingPhase as g, parseSiteId as gt, orderedLiveRunSessions as h, parsePageId as ht, canonicalizeConfiguredBookingVerticalConfig as i, publicEventPricingDisplay as it, parseFooterCompositionV1 as j, unsafeAsPositiveByteCount as jt, parseMailingListProviderScope as k, unsafeAsOccurrenceId as kt, EVENT_PRESET_VALUES as l, mapNonEmptyArray as lt, CANCELLED_SESSION_STATUS as m, parseMediaAssetId as mt, NAVIGATION_LOCATIONS as n, isPublicEventPricingOptionDisplayable as nt, parseVerticalPresetId as o, resolveExactOrFreePriceDisplay as ot, publicReadFreshnessSeconds as p, parseEventSeriesId as pt, getLocalScheduleTime as q, areConfiguredBookingVerticalConfigsEqual as r, publicEventPricingCurrency as rt, resolveSiteVerticalBookingConfig as s, resolvePricingOptionsPriceDisplay as st, resolveEventCatalogue as t, formatEventPricing as tt, ORDINARY_EVENT_PRESET_VALUES as u, formatCurrencyAmount as ut, exposeSecret as v, unsafeAsAppointmentResourceId as vt, parseMailingListSignedSourceToken as w, unsafeAsEntitlementId as wt, buildMailingListSignupBlockSourceRef as x, unsafeAsDeclaredMimeType as xt, parseManagementKey as y, unsafeAsBookingRequirementId as yt, buildBookingUtcDateWindow as z, unsafeAsStorageBucketName as zt };
7371
+ //#region ../core/src/patch/index.ts
7372
+ function settableFrom(wireValue) {
7373
+ return wireValue === undefined ? { kind: "keep" } : {
7374
+ kind: "set",
7375
+ value: wireValue
7376
+ };
7377
+ }
7378
+ function clearableFrom(wireValue) {
7379
+ return wireValue === undefined ? { kind: "keep" } : wireValue === null ? { kind: "clear" } : {
7380
+ kind: "set",
7381
+ value: wireValue
7382
+ };
7383
+ }
7384
+ function applySettable(stored, change) {
7385
+ switch (change.kind) {
7386
+ case "keep": return stored;
7387
+ case "set": return change.value;
7388
+ default: return assertNever(change);
7389
+ }
7390
+ }
7391
+ function applyClearable(stored, change) {
7392
+ switch (change.kind) {
7393
+ case "keep": return stored;
7394
+ case "set": return change.value;
7395
+ case "clear": return null;
7396
+ default: return assertNever(change);
7397
+ }
7398
+ }
7399
+ /** A null deletes a key; protected keys are refused even when their value agrees. */
7400
+ function mergeBag(stored, patch, options) {
7401
+ const keys = options.protectedKeys.filter((key) => Object.prototype.hasOwnProperty.call(patch, key));
7402
+ if (keys.length > 0) return {
7403
+ ok: false,
7404
+ error: {
7405
+ kind: "protected-keys",
7406
+ keys
7407
+ }
7408
+ };
7409
+ const retained = Object.fromEntries(Object.entries(stored).filter(([key]) => !Object.prototype.hasOwnProperty.call(patch, key) || patch[key] !== null));
7410
+ const supplied = Object.fromEntries(Object.entries(patch).filter((entry) => entry[1] !== undefined && entry[1] !== null));
7411
+ return {
7412
+ ok: true,
7413
+ value: {
7414
+ ...retained,
7415
+ ...supplied
7416
+ }
7417
+ };
7418
+ }
7419
+
7420
+ //#endregion
7421
+ export { parseBookingTimeZone as $, unsafeAsEventSeriesId as $t, footerNavigationLayouts as A, parseCurrencyCode as At, buildBookingUtcDateWindow as B, parseRetiredCourseId as Bt, parseMailingListContentVersionId as C, isNonNegativeWholeCents as Ct, sameMailingListPlacementTargeting as D, unsafeAsNonNegativeCents as Dt, planMailingListChoicePresentation as E, toNonNegativeCents as Et, assertAllowedPublicUrl as F, parseDatedOfferingCapacityHoldId as Ft, formatLocalScheduleTime as G, unsafeAsBookingSessionId as Gt, formatBookingDateParts as H, parseUserId as Ht, isPresent as I, parseEventSeriesId as It, getLocalScheduleTime as J, unsafeAsDemoCapability as Jt, getBookingLocalDateKey as K, unsafeAsCheckoutLineId as Kt, normalizeLocationAddressText as L, parseMediaAssetId as Lt, parseMailingListPlacementTargeting as M, parseApiKeyId as Mt, isCanonicalRichTextDoc as N, parseCustomerId as Nt, DEFAULT_MAILING_LIST_SUCCESS_MESSAGE as O, unsafeAsPositiveCents as Ot, parsePublicContactDetails as P, parseDatedOfferingCapacityHoldAuditRef as Pt, toScheduledBookingDateTime as Q, unsafeAsEventOfferingId as Qt, toLocationCoordinates as R, parseMembershipId as Rt, parseMailingListBlockId as S, mapNonEmptyArray as St, parseMailingListRuntimeContext as T, toCents as Tt, formatBookingTime as U, unsafeAsAppointmentResourceId as Ut, formatBookingDate as V, parseSiteId as Vt, formatLocalScheduleDate as W, unsafeAsBookingRequirementId as Wt, toBookingTimeZone as X, unsafeAsEntitlementId as Xt, parseUtcIsoDateTimeString as Y, unsafeAsDetectedMimeType as Yt, toScheduledBookingDateRange as Z, unsafeAsEventInstanceId as Zt, createSecret as _, unsafeAsUserId as _n, publicEventPricingDisplay as _t, parseVerticalId as a, unsafeAsPositiveByteCount as an, clampConfiguredAmount as at, stableJsonStringify as b, resolvePricingOptionsPriceDisplay as bt, DEFAULT_EVENT_TYPE_PRESETS as c, unsafeAsProductId as cn, omitZeroAmountFutureRows as ct, SURFACE_EVENT_PRESET_VALUES as d, unsafeAsSiteId as dn, resolveFlexibleBalanceInitialPaymentCents as dt, unsafeAsFileChecksumSha256 as en, validateBookingPaymentOptionKinds as et, WHOLE_SERIES_EVENT_PRESET_VALUES as f, unsafeAsSiteScopedStoragePath as fn, parseEventPageSurfaceSubject as ft, resolveWholeSeriesBookingPhase as g, unsafeAsUploadSessionId as gn, publicEventPricingCurrency as gt, orderedLiveRunSessions as h, unsafeAsStoragePath as hn, isPublicEventPricingOptionDisplayable as ht, canonicalizeConfiguredBookingVerticalConfig as i, unsafeAsPassId as in, addIntervalPreservingMonthAnchor as it, parseFooterCompositionV1 as j, assertNever as jt, parseMailingListProviderScope as k, formatCurrencyAmount as kt, EVENT_PRESET_VALUES as l, unsafeAsSafeDownloadFilename as ln, splitAmountWithRemainderInFirst as lt, CANCELLED_SESSION_STATUS as m, unsafeAsStorageBucketName as mn, formatEventPricing as mt, NAVIGATION_LOCATIONS as n, unsafeAsOccurrenceId as nn, isSettleableFlexibleBalanceContractStatus as nt, parseVerticalPresetId as o, unsafeAsPositiveSeconds as on, getBookingInstalmentDepositRefundability as ot, publicReadFreshnessSeconds as p, unsafeAsStaffMemberId as pn, formatBookingPriceDisplay as pt, getLocalScheduleDate as q, unsafeAsDeclaredMimeType as qt, areConfiguredBookingVerticalConfigsEqual as r, unsafeAsOriginalFilename as rn, isSettleableOrderInstalmentPlanStatus as rt, resolveSiteVerticalBookingConfig as s, unsafeAsPricingOptionId as sn, getBookingInstalmentProtectedDepositAmountCents as st, resolveEventCatalogue as t, unsafeAsMediaAssetId as tn, isLiveOrderInstalmentPlanStatus as tt, ORDINARY_EVENT_PRESET_VALUES as u, unsafeAsSiteFontId as un, resolveFlexibleBalanceDueAt as ut, exposeSecret as v, err as vn, publicEventPricingType as vt, parseMailingListSignedSourceToken as w, parseNonNegativeCents as wt, buildMailingListSignupBlockSourceRef as x, fromArray as xt, parseManagementKey as y, ok as yn, resolveExactOrFreePriceDisplay as yt, selectCategoryView as z, parsePageId as zt };
package/dist/testing.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import "./sdk-event-upsert-CqCQwcwu.mjs";
3
- import "./src-CxEAuQpf.mjs";
4
- import { n as syncLocalMediaForPush, r as syncLocalMediaForPull, y as writeMediaManifest } from "./local-sync-C-FEofmj.mjs";
2
+ import "./sdk-event-upsert-TBJhbame.mjs";
3
+ import "./src-DxiCPcDa.mjs";
4
+ import { n as syncLocalMediaForPush, r as syncLocalMediaForPull, y as writeMediaManifest } from "./local-sync-2x8FP35G.mjs";
5
5
 
6
6
  export { syncLocalMediaForPull, syncLocalMediaForPush, writeMediaManifest };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "riverbankcms",
3
- "version": "0.14.0",
3
+ "version": "0.16.0",
4
4
  "description": "Riverbank CMS command-line tools for SDK site developers",
5
5
  "bin": {
6
6
  "riverbankcms": "dist/cli/index.mjs"
@@ -1,4 +0,0 @@
1
- #!/usr/bin/env node
2
- import { t as loadConfigFile } from "./load-config-D0Qfqh2m.mjs";
3
-
4
- export { loadConfigFile };