@fire-spark/core 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -399,7 +399,10 @@ type ReorderOrderOptions = CreateOrderOptions & {
399
399
  type OrderDraft = Order$2;
400
400
  type ApplyRedeemInput = {
401
401
  reward_id: string;
402
- /** Reward units to redeem (integer ≥ 1). */
402
+ /**
403
+ * Reward units to redeem (integer ≥ 1). With `payment_id` it is
404
+ * informational: `amount` and `points` already cover every unit.
405
+ */
403
406
  quantity: number;
404
407
  /** 0–1, compounded per unit over the remaining value. */
405
408
  discount_rate?: number;
@@ -414,11 +417,16 @@ type ApplyRedeemInput = {
414
417
  line_uid?: string;
415
418
  /**
416
419
  * Points / balance: the merchant `REDEMPTION` payment that pays `amount`
417
- * (a tender, not a discount). Requires `amount` and `points`.
420
+ * (a tender, not a discount). Requires `amount` and `points`. Redeems
421
+ * with the same `payment_id` share one tender (`details.rewards[]`).
418
422
  */
419
423
  payment_id?: string;
420
- /** Money the points cover; trimmed to total − tip − delivery. */
424
+ /**
425
+ * Total money the points cover for the whole entry (all `quantity`
426
+ * units, not per unit); trimmed to total − tip − delivery.
427
+ */
421
428
  amount?: number;
429
+ /** Total points spent for the whole entry (not per unit). */
422
430
  points?: number;
423
431
  program?: string;
424
432
  /** Provider of the REDEMPTION payment (default `firespark`). */
@@ -496,14 +504,19 @@ declare class Order {
496
504
  /**
497
505
  * Appends a redeem to `line_uid` (root line) or to the order. Steps keep
498
506
  * the order in which redeems were applied. With `payment_id` (points /
499
- * balance) it is not a discount: the order gets a REDEMPTION tender for
500
- * it, capped at total − tip − delivery (D15, D18, D19).
507
+ * balance) it is not a discount: `amount` and `points` are totals of the
508
+ * whole entry (every unit, not per unit) and `quantity` is informational.
509
+ * Every redeem with the same `payment_id` is paid by one REDEMPTION
510
+ * tender whose `details.rewards[]` lists them; their summed amount is
511
+ * capped at total − tip − delivery (D15, D18, D19).
501
512
  */
502
513
  applyRedeem(input: ApplyRedeemInput): void;
503
514
  /**
504
515
  * Removes `quantity` units of `reward_id` from `line_uid` or the order,
505
516
  * latest applied first. Removing more units than applied clears them all
506
- * (and the REDEMPTION tender of a points / balance redeem).
517
+ * (and the REDEMPTION tender of a points / balance redeem). A points /
518
+ * balance entry that keeps some units keeps the same share of its
519
+ * `amount` and `points`.
507
520
  */
508
521
  removeRedeem(input: RemoveRedeemInput): void;
509
522
  private rememberLogScope;
@@ -810,7 +823,17 @@ declare const listMenus: (scope?: StorefrontMenuScope, options?: ServiceHttpOpti
810
823
  declare const listMenusStream: (scope?: StorefrontMenuScope, options?: ListMenusStreamOptions) => AsyncGenerator<StorefrontMenu[], any, any>;
811
824
  //#endregion
812
825
  //#region src/services/payments.d.ts
813
- declare const listPayments: (input: StorefrontPaymentsListInput, options?: ServiceHttpOptions) => Promise<MerchantPayment[]>;
826
+ type ListPaymentsOptions = ServiceHttpOptions & {
827
+ /** Keep `REDEMPTION` payments (points / balance) for redeem flows. */
828
+ includeRedemptions?: boolean;
829
+ };
830
+ /**
831
+ * Payments a customer can pick at checkout. `REDEMPTION` payments are
832
+ * applied through the order's `redeem` entries, never chosen as a method.
833
+ */
834
+ declare const selectablePayments: <T extends MerchantPayment>(payments: readonly T[]) => T[];
835
+ /** Lists payments without `REDEMPTION` unless `includeRedemptions` is set. */
836
+ declare const listPayments: (input: StorefrontPaymentsListInput, options?: ListPaymentsOptions) => Promise<MerchantPayment[]>;
814
837
  type PaymentOperationBody = {
815
838
  order_id: string | null;
816
839
  attempt_reference: string | null;
@@ -1263,4 +1286,4 @@ declare const validateCardholderName: (value: string) => CardholderNameError | n
1263
1286
  */
1264
1287
  declare const cardPreviewGroups: (value: string) => CardPreviewSlot[][];
1265
1288
  //#endregion
1266
- export { type ApplyRedeemInput, type AuthConfigureOptions, CARD_BRANDS, type CardBrand, type CardBrandSpec, type CardCvcError, type CardExpiry, type CardExpiryError, type CardNumberError, type CardPreviewSlot, type CardholderNameError, type CreateOrderOptions, type CreateSessionOptions, type CustomizationPath, type CustomizationSession, DEFAULT_RECOMMENDATION_TYPES, type ExchangeOptions, type FailedCharge, type FlatMenuCategory, type GroupDisplayType, type IdBuilder, type ListMenusStreamOptions, type Menu, type MenuCategoryNode, type MenuLookup, type MilestoneSteps, type MilestoneTrackItem, type ModifierControlType, type ModifierCtx, type ModifierGroupCtx, type NestedMenuCategory, Order, type OrderCustomerSource, type OrderDraft, type OrderIssue, type OrderIssueCode, type OrderLineDiff, type OrderLineIssue, type OrderLineIssueCode, type OrderScope, OrderSyncPendingError, OrderValidationError, type OrderValidationResult, type PayIntentOptions, type PayIntentResult, type PayOptions, type PaymentCardBrand, type PaymentProgressEvent, type PaymentProgressListener, type PaymentRunOptions, type PaymentSessionOptions, type PricingModifier, type Product, type ProductCtx, type QuantitiesByPath, type RecommendationType, RecurringDateCron, type RemoveRedeemInput, type ReorderOrderOptions, type ResetOptions, type ReversalOutcome, type ReverseAllOptions, RulesEngine, type ScheduleWindow, type SelectionStatus, type SelectionsByPath, type SerializedError, type ServiceHttpOptions, type SimpleTenderPayment, type Snapshot, type StorefrontAccessToken, type StorefrontErrorDetails, StorefrontHttpError, type TrackWorkflow, type ValidateOptions, type ValidateOrderAgainstMenuInput, type Variant, type VariantGroup, type VariantGroupCtx, type VariantOptionCtx, type VariantSelection, type VerifyWebhookSignatureInput, type VisitedState, addLines, auth, buildCustomerSnapshot, cardBrandSpec, cardDigits, cardNumberGaps, cardNumberMaxLength, cardPreviewGroups, caretAfterDigits, collectOrderLineDiffs, computeStartingPrice, countCartProducts, coveredAmount, createSession, currentNodes, cvcMaxLength, defaultConditionError, detectCardBrand, flattenMenuCategories, flushLogs, formatCardNumber, formatCvc, formatExpiry, fromOrderLines, genId, genOrderId, getLogContext, getScheduleWindow, indexMenu, isCardNumberComplete, isCardNumberDefinitelyInvalid, isCheckoutFieldFilled, isCvcComplete, isDeviceCharged, isDeviceNotLinked, isExpiryComplete, isKioskUnauthorized, isMilestoneStepDone, isOnSchedule, isOrderValidationError, isPosDeviceNotLinked, isPosUnauthorized, isRealPaymentMethod, isStorefrontNotFound, isVariantBase, listMenusStream, localizePosError, log, logError, luhnCheck, matchAbsoluteDateOperator, matchBooleanOperator, matchCurrencyOperator, matchEnumOperator, matchNumberOperator, matchRecurringDateOperator, matchRelativeDateOperator, matchStringOperator, milestoneSteps, milestoneTrack, nestMenuCategories, normalizeCardholderName, parseExpiry, paymentMatchesClientConditions, recomputeRedemptions, recomputeTotals, redemptionCap, remainingAmount, removeLine, replaceLine, resolveCheckout, reversePayment, runPaymentAttempt, serializeError, services, setLineQuantity, storefrontJson, stripRedemptionLines, toOrderLines, toPaymentCardBrand, validateCardNumber, validateCardholderName, validateCvc, validateExpiry, validateOrderAgainstMenu, verifyWebhookSignature, visitedStates };
1289
+ export { type ApplyRedeemInput, type AuthConfigureOptions, CARD_BRANDS, type CardBrand, type CardBrandSpec, type CardCvcError, type CardExpiry, type CardExpiryError, type CardNumberError, type CardPreviewSlot, type CardholderNameError, type CreateOrderOptions, type CreateSessionOptions, type CustomizationPath, type CustomizationSession, DEFAULT_RECOMMENDATION_TYPES, type ExchangeOptions, type FailedCharge, type FlatMenuCategory, type GroupDisplayType, type IdBuilder, type ListMenusStreamOptions, type ListPaymentsOptions, type Menu, type MenuCategoryNode, type MenuLookup, type MilestoneSteps, type MilestoneTrackItem, type ModifierControlType, type ModifierCtx, type ModifierGroupCtx, type NestedMenuCategory, Order, type OrderCustomerSource, type OrderDraft, type OrderIssue, type OrderIssueCode, type OrderLineDiff, type OrderLineIssue, type OrderLineIssueCode, type OrderScope, OrderSyncPendingError, OrderValidationError, type OrderValidationResult, type PayIntentOptions, type PayIntentResult, type PayOptions, type PaymentCardBrand, type PaymentProgressEvent, type PaymentProgressListener, type PaymentRunOptions, type PaymentSessionOptions, type PricingModifier, type Product, type ProductCtx, type QuantitiesByPath, type RecommendationType, RecurringDateCron, type RemoveRedeemInput, type ReorderOrderOptions, type ResetOptions, type ReversalOutcome, type ReverseAllOptions, RulesEngine, type ScheduleWindow, type SelectionStatus, type SelectionsByPath, type SerializedError, type ServiceHttpOptions, type SimpleTenderPayment, type Snapshot, type StorefrontAccessToken, type StorefrontErrorDetails, StorefrontHttpError, type TrackWorkflow, type ValidateOptions, type ValidateOrderAgainstMenuInput, type Variant, type VariantGroup, type VariantGroupCtx, type VariantOptionCtx, type VariantSelection, type VerifyWebhookSignatureInput, type VisitedState, addLines, auth, buildCustomerSnapshot, cardBrandSpec, cardDigits, cardNumberGaps, cardNumberMaxLength, cardPreviewGroups, caretAfterDigits, collectOrderLineDiffs, computeStartingPrice, countCartProducts, coveredAmount, createSession, currentNodes, cvcMaxLength, defaultConditionError, detectCardBrand, flattenMenuCategories, flushLogs, formatCardNumber, formatCvc, formatExpiry, fromOrderLines, genId, genOrderId, getLogContext, getScheduleWindow, indexMenu, isCardNumberComplete, isCardNumberDefinitelyInvalid, isCheckoutFieldFilled, isCvcComplete, isDeviceCharged, isDeviceNotLinked, isExpiryComplete, isKioskUnauthorized, isMilestoneStepDone, isOnSchedule, isOrderValidationError, isPosDeviceNotLinked, isPosUnauthorized, isRealPaymentMethod, isStorefrontNotFound, isVariantBase, listMenusStream, localizePosError, log, logError, luhnCheck, matchAbsoluteDateOperator, matchBooleanOperator, matchCurrencyOperator, matchEnumOperator, matchNumberOperator, matchRecurringDateOperator, matchRelativeDateOperator, matchStringOperator, milestoneSteps, milestoneTrack, nestMenuCategories, normalizeCardholderName, parseExpiry, paymentMatchesClientConditions, recomputeRedemptions, recomputeTotals, redemptionCap, remainingAmount, removeLine, replaceLine, resolveCheckout, reversePayment, runPaymentAttempt, selectablePayments, serializeError, services, setLineQuantity, storefrontJson, stripRedemptionLines, toOrderLines, toPaymentCardBrand, validateCardNumber, validateCardholderName, validateCvc, validateExpiry, validateOrderAgainstMenu, verifyWebhookSignature, visitedStates };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { DIGITAL_COLLECT_AT, PARTIAL_APPROVAL_ERROR, activeIntent, amountTolerance, createAttemptReference, createPaymentError, currencyDecimals, currentIntent, defaultReversalFor, isDeliveryFee, isPaymentError, isRealPaymentMethod, isTenderSettled, isTipFee, liveTenders, memoryPaymentStorage, missingDeviceFields, resolvePaymentPolicy, resolveProviderEnvironment, roundTo, scopedPaymentStorage, taxBreakdown, toChargeAmount, withTerminalLock } from "@fire-spark/payments";
1
+ import { DIGITAL_COLLECT_AT, PARTIAL_APPROVAL_ERROR, activeIntent, amountTolerance, createAttemptReference, createPaymentError, currencyDecimals, currentIntent, defaultReversalFor, groupPaymentRedeems, isDeliveryFee, isPaymentError, isRealPaymentMethod, isRealPaymentMethod as isRealPaymentMethod$1, isTenderSettled, isTipFee, liveTenders, memoryPaymentStorage, missingDeviceFields, resolvePaymentPolicy, resolveProviderEnvironment, roundTo, scopedPaymentStorage, taxBreakdown, toChargeAmount, withTerminalLock } from "@fire-spark/payments";
2
2
  import advancedFormat from "dayjs/plugin/advancedFormat.js";
3
3
  import isBetween from "dayjs/plugin/isBetween.js";
4
4
  import isSameOrAfter from "dayjs/plugin/isSameOrAfter.js";
@@ -2641,10 +2641,21 @@ const validateOrder = async (body, options) => {
2641
2641
  };
2642
2642
  //#endregion
2643
2643
  //#region src/services/payments.ts
2644
- const listPayments = (input, options) => {
2644
+ /**
2645
+ * Payments a customer can pick at checkout. `REDEMPTION` payments are
2646
+ * applied through the order's `redeem` entries, never chosen as a method.
2647
+ */
2648
+ const selectablePayments = (payments) => {
2649
+ return payments.filter((payment) => isRealPaymentMethod$1(payment.method.method));
2650
+ };
2651
+ /** Lists payments without `REDEMPTION` unless `includeRedemptions` is set. */
2652
+ const listPayments = async (input, options = {}) => {
2653
+ const { includeRedemptions = false, ...http } = options;
2645
2654
  const params = new URLSearchParams();
2646
2655
  for (const [key, value] of Object.entries(input)) if (value) params.set(key, value);
2647
- return storefrontJson(`/api/storefront/v1/payments?${params.toString()}`, {}, options);
2656
+ const payments = await storefrontJson(`/api/storefront/v1/payments?${params.toString()}`, {}, http);
2657
+ if (includeRedemptions) return payments;
2658
+ return selectablePayments(payments);
2648
2659
  };
2649
2660
  /** Server half of an adapter (`POST /payments/:id/operations/:operation`). */
2650
2661
  const callPaymentOperation = (paymentId, operation, body, options) => {
@@ -3532,6 +3543,22 @@ const buildRedeem = (input) => {
3532
3543
  if (expires_at !== void 0) redeem.expires_at = expires_at;
3533
3544
  return redeem;
3534
3545
  };
3546
+ /** Payment redeems hold totals, so the kept units keep their share. */
3547
+ const keepUnits = (item, rest) => {
3548
+ if (!isPaymentRedeem(item) || rest === item.quantity) return {
3549
+ ...item,
3550
+ quantity: rest
3551
+ };
3552
+ const ratio = new Big(rest).div(item.quantity);
3553
+ const amount = new Big(item.amount ?? 0).times(ratio).round(6).toNumber();
3554
+ const points = new Big(item.points ?? 0).times(ratio).round(0).toNumber();
3555
+ return {
3556
+ ...item,
3557
+ quantity: rest,
3558
+ amount,
3559
+ points
3560
+ };
3561
+ };
3535
3562
  /**
3536
3563
  * Takes `quantity` units of `reward_id` off the latest entries first, so the
3537
3564
  * earlier redeems keep their step position. Entries that reach 0 are removed.
@@ -3549,10 +3576,7 @@ const subtractRedeem = (items, reward_id, quantity) => {
3549
3576
  const taken = Math.min(item.quantity, pending);
3550
3577
  pending -= taken;
3551
3578
  const rest = item.quantity - taken;
3552
- if (rest > 0) kept.unshift({
3553
- ...item,
3554
- quantity: rest
3555
- });
3579
+ if (rest > 0) kept.unshift(keepUnits(item, rest));
3556
3580
  }
3557
3581
  return kept;
3558
3582
  };
@@ -3888,29 +3912,16 @@ const clampPaymentRedeems = (redeem, cap, currency) => {
3888
3912
  }];
3889
3913
  });
3890
3914
  };
3891
- /** One REDEMPTION tender per payment redeem of the order (D15, D19). */
3915
+ /**
3916
+ * One REDEMPTION tender per `payment_id` of the payment redeems (D15,
3917
+ * D19); its `details.rewards[]` lists every grouped redeem.
3918
+ */
3892
3919
  const redemptionTenderInputs = (redeem, providers = /* @__PURE__ */ new Map()) => {
3893
- return redeem.filter(isPaymentRedeem).map((item) => {
3894
- const payment_id = item.payment_id;
3920
+ return groupPaymentRedeems(redeem).map(({ payment_id, details }) => {
3895
3921
  const fallback = DEFAULT_REDEMPTION_PROVIDER;
3896
- const provider = providers.get(payment_id) ?? fallback;
3897
- const program = item.program ?? item.reward_id;
3898
- const d1 = {
3899
- method: "REDEMPTION",
3900
- reward_id: item.reward_id
3901
- };
3902
- const d2 = {
3903
- program,
3904
- points: item.points ?? 0
3905
- };
3906
- const details = {
3907
- ...d1,
3908
- ...d2,
3909
- points_value: item.amount ?? 0
3910
- };
3911
3922
  const t1 = {
3912
3923
  method: "REDEMPTION",
3913
- provider,
3924
+ provider: providers.get(payment_id) ?? fallback,
3914
3925
  payment_id
3915
3926
  };
3916
3927
  const t2 = {
@@ -5472,8 +5483,11 @@ var Order = class Order {
5472
5483
  /**
5473
5484
  * Appends a redeem to `line_uid` (root line) or to the order. Steps keep
5474
5485
  * the order in which redeems were applied. With `payment_id` (points /
5475
- * balance) it is not a discount: the order gets a REDEMPTION tender for
5476
- * it, capped at total − tip − delivery (D15, D18, D19).
5486
+ * balance) it is not a discount: `amount` and `points` are totals of the
5487
+ * whole entry (every unit, not per unit) and `quantity` is informational.
5488
+ * Every redeem with the same `payment_id` is paid by one REDEMPTION
5489
+ * tender whose `details.rewards[]` lists them; their summed amount is
5490
+ * capped at total − tip − delivery (D15, D18, D19).
5477
5491
  */
5478
5492
  applyRedeem(input) {
5479
5493
  if (this.deleted) return;
@@ -5499,7 +5513,9 @@ var Order = class Order {
5499
5513
  /**
5500
5514
  * Removes `quantity` units of `reward_id` from `line_uid` or the order,
5501
5515
  * latest applied first. Removing more units than applied clears them all
5502
- * (and the REDEMPTION tender of a points / balance redeem).
5516
+ * (and the REDEMPTION tender of a points / balance redeem). A points /
5517
+ * balance entry that keeps some units keeps the same share of its
5518
+ * `amount` and `points`.
5503
5519
  */
5504
5520
  removeRedeem(input) {
5505
5521
  if (this.deleted) return;
@@ -8531,4 +8547,4 @@ const cardPreviewGroups = (value) => {
8531
8547
  return groups;
8532
8548
  };
8533
8549
  //#endregion
8534
- export { CARD_BRANDS, DEFAULT_RECOMMENDATION_TYPES, Order, OrderSyncPendingError, OrderValidationError, RecurringDateCron, RulesEngine, StorefrontHttpError, addLines, auth, buildCustomerSnapshot, cardBrandSpec, cardDigits, cardNumberGaps, cardNumberMaxLength, cardPreviewGroups, caretAfterDigits, collectOrderLineDiffs, computeStartingPrice, countCartProducts, coveredAmount, createSession, currentNodes, cvcMaxLength, defaultConditionError, detectCardBrand, flattenMenuCategories, flushLogs, formatCardNumber, formatCvc, formatExpiry, fromOrderLines, genId, genOrderId, getLogContext, getScheduleWindow, indexMenu, isCardNumberComplete, isCardNumberDefinitelyInvalid, isCheckoutFieldFilled, isCvcComplete, isDeviceCharged, isDeviceNotLinked, isExpiryComplete, isKioskUnauthorized, isMilestoneStepDone, isOnSchedule, isOrderValidationError, isPosDeviceNotLinked, isPosUnauthorized, isRealPaymentMethod, isStorefrontNotFound, isVariantBase, listMenusStream, localizePosError, log, logError, luhnCheck, matchAbsoluteDateOperator, matchBooleanOperator, matchCurrencyOperator, matchEnumOperator, matchNumberOperator, matchRecurringDateOperator, matchRelativeDateOperator, matchStringOperator, milestoneSteps, milestoneTrack, nestMenuCategories, normalizeCardholderName, parseExpiry, paymentMatchesClientConditions, recomputeRedemptions, recomputeTotals, redemptionCap, remainingAmount, removeLine, replaceLine, resolveCheckout, reversePayment, runPaymentAttempt, serializeError, services, setLineQuantity, storefrontJson, stripRedemptionLines, toOrderLines, toPaymentCardBrand, validateCardNumber, validateCardholderName, validateCvc, validateExpiry, validateOrderAgainstMenu, verifyWebhookSignature, visitedStates };
8550
+ export { CARD_BRANDS, DEFAULT_RECOMMENDATION_TYPES, Order, OrderSyncPendingError, OrderValidationError, RecurringDateCron, RulesEngine, StorefrontHttpError, addLines, auth, buildCustomerSnapshot, cardBrandSpec, cardDigits, cardNumberGaps, cardNumberMaxLength, cardPreviewGroups, caretAfterDigits, collectOrderLineDiffs, computeStartingPrice, countCartProducts, coveredAmount, createSession, currentNodes, cvcMaxLength, defaultConditionError, detectCardBrand, flattenMenuCategories, flushLogs, formatCardNumber, formatCvc, formatExpiry, fromOrderLines, genId, genOrderId, getLogContext, getScheduleWindow, indexMenu, isCardNumberComplete, isCardNumberDefinitelyInvalid, isCheckoutFieldFilled, isCvcComplete, isDeviceCharged, isDeviceNotLinked, isExpiryComplete, isKioskUnauthorized, isMilestoneStepDone, isOnSchedule, isOrderValidationError, isPosDeviceNotLinked, isPosUnauthorized, isRealPaymentMethod, isStorefrontNotFound, isVariantBase, listMenusStream, localizePosError, log, logError, luhnCheck, matchAbsoluteDateOperator, matchBooleanOperator, matchCurrencyOperator, matchEnumOperator, matchNumberOperator, matchRecurringDateOperator, matchRelativeDateOperator, matchStringOperator, milestoneSteps, milestoneTrack, nestMenuCategories, normalizeCardholderName, parseExpiry, paymentMatchesClientConditions, recomputeRedemptions, recomputeTotals, redemptionCap, remainingAmount, removeLine, replaceLine, resolveCheckout, reversePayment, runPaymentAttempt, selectablePayments, serializeError, services, setLineQuantity, storefrontJson, stripRedemptionLines, toOrderLines, toPaymentCardBrand, validateCardNumber, validateCardholderName, validateCvc, validateExpiry, validateOrderAgainstMenu, verifyWebhookSignature, visitedStates };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fire-spark/core",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Fire Spark headless SDK",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -20,8 +20,8 @@
20
20
  "big.js": "6.2.1",
21
21
  "dayjs": "1.11.9",
22
22
  "@types/big.js": "6.2.2",
23
- "@fire-spark/payments": "^0.3.0",
24
- "@fire-spark/types": "^0.3.0"
23
+ "@fire-spark/payments": "^0.3.1",
24
+ "@fire-spark/types": "^0.3.1"
25
25
  },
26
26
  "devDependencies": {
27
27
  "tsdown": "^0.22.14",