@delopay/sdk 0.134.0 → 0.137.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.
@@ -870,10 +870,68 @@ var Customers = class {
870
870
  query: toQuery(params)
871
871
  });
872
872
  }
873
+ /**
874
+ * Retrieve one customer, scoped to the authenticated dashboard user's shop
875
+ * (business profile). The shop-scoped counterpart of {@link retrieve}, and
876
+ * what makes a shop's own customer list clickable: the list is
877
+ * `ProfileCustomerRead` while {@link retrieve} is merchant-level, so a shop
878
+ * member could see a customer they could not open.
879
+ *
880
+ * A customer belonging to a sibling shop answers `CustomerNotFound` — the
881
+ * same answer as a customer that does not exist, deliberately, so one shop
882
+ * cannot enumerate another's customer ids.
883
+ *
884
+ * `GET /customers/profile/{customerId}`
885
+ *
886
+ * @param customerId - The unique customer ID.
887
+ * @returns The customer, with `profile_ids` narrowed to the caller's own shop.
888
+ */
889
+ async retrieveByProfile(customerId) {
890
+ return this.request("GET", `/customers/profile/${encodeURIComponent(customerId)}`);
891
+ }
892
+ /**
893
+ * Create a customer from a shop, recording that it belongs to that shop so
894
+ * the shop can see the customer it just created. The shop is taken from the
895
+ * credential; a caller-chosen `customer_id` is rejected.
896
+ *
897
+ * `POST /customers/profile`
898
+ *
899
+ * @param params - The customer to create.
900
+ * @returns The created customer.
901
+ */
902
+ async createByProfile(params) {
903
+ return this.request("POST", "/customers/profile", { body: params });
904
+ }
905
+ /**
906
+ * Update a customer from a shop, if the customer belongs to that shop.
907
+ * A sibling shop's customer answers `CustomerNotFound`, as with
908
+ * {@link retrieveByProfile}.
909
+ *
910
+ * `POST /customers/profile/{customerId}`
911
+ *
912
+ * @param customerId - The customer ID to update.
913
+ * @param params - Fields to update.
914
+ * @returns The updated customer.
915
+ */
916
+ async updateByProfile(customerId, params) {
917
+ return this.request("POST", `/customers/profile/${encodeURIComponent(customerId)}`, {
918
+ body: params
919
+ });
920
+ }
873
921
  /** List mandates for a customer. `GET /customers/{customerId}/mandates` */
874
922
  async listMandates(customerId) {
875
923
  return this.request("GET", `/customers/${encodeURIComponent(customerId)}/mandates`);
876
924
  }
925
+ /**
926
+ * List one customer's mandates, scoped to the caller's shop. Same membership
927
+ * rule as {@link retrieveByProfile}: a sibling shop's customer answers
928
+ * `CustomerNotFound` before any mandate is read.
929
+ *
930
+ * `GET /customers/profile/{customerId}/mandates`
931
+ */
932
+ async listMandatesByProfile(customerId) {
933
+ return this.request("GET", `/customers/profile/${encodeURIComponent(customerId)}/mandates`);
934
+ }
877
935
  };
878
936
 
879
937
  // src/resources/disputes.ts
@@ -1605,6 +1663,43 @@ var Payments = class {
1605
1663
  options
1606
1664
  );
1607
1665
  }
1666
+ /**
1667
+ * What the payment's rail says about settling each attempt: whether the
1668
+ * money is still `pending` in the rail's hands, `available` in its balance
1669
+ * (**not** paid out), `paid_out` to a bank — with the payout's date and
1670
+ * reference — or came back as `payout_failed`; and, for the rest, which
1671
+ * kind of not-knowing applies (`unavailable`, `unknown`, `not_recorded`).
1672
+ * See {@link ConnectorSettlementStatus} for the seven values. The same
1673
+ * status for the active attempt rides on every list row and retrieve as
1674
+ * `connector_settlement_status`, and the list filters on it.
1675
+ *
1676
+ * Not the hosted-shop settlement API under `settlement.*`, which is host →
1677
+ * shop owner and manual; this is acquirer → merchant bank, per payment.
1678
+ *
1679
+ * `GET /payments/{paymentId}/settlement`
1680
+ *
1681
+ * @param paymentId - The payment intent ID.
1682
+ * @param options - Optional per-call extras: extra `headers`, a `timeout`
1683
+ * override, and an `AbortSignal`.
1684
+ * @returns The attempts this caller may see, oldest first, each with its
1685
+ * settlement status.
1686
+ * @throws If the payment does not exist (404), or the caller is a
1687
+ * profile-scoped (shop) role, who is refused rather than shown a redacted
1688
+ * body (403).
1689
+ *
1690
+ * @example
1691
+ * ```typescript
1692
+ * const { attempts } = await delopay.payments.settlement('pay_abc123');
1693
+ * for (const attempt of attempts) {
1694
+ * if (attempt.status === 'paid_out') {
1695
+ * console.log(attempt.paid_out_at, attempt.payout_reference);
1696
+ * }
1697
+ * }
1698
+ * ```
1699
+ */
1700
+ async settlement(paymentId, options) {
1701
+ return this.request("GET", `/payments/${encodeURIComponent(paymentId)}/settlement`, options);
1702
+ }
1608
1703
  /**
1609
1704
  * Update an existing payment intent before it is confirmed.
1610
1705
  *
@@ -1776,7 +1871,10 @@ var Payments = class {
1776
1871
  /**
1777
1872
  * List payments by filter, scoped to the caller's profile (the shop-user
1778
1873
  * twin of `listByFilter`). The backend narrows to the profile from the
1779
- * auth context, so `profile_id` / `project_id` must not be sent.
1874
+ * auth context, so `profile_id` / `project_id` must not be sent — and
1875
+ * neither may `connector_settlement_status`, which this route refuses
1876
+ * (403): a shop-scoped viewer is not shown the settlement state, and the
1877
+ * type leaves the key out so it cannot be probed through `total_count`.
1780
1878
  *
1781
1879
  * Not to be confused with {@link Payments.listByProfile}, which is the GET
1782
1880
  * cursor variant and rejects this body.
@@ -5214,6 +5312,120 @@ function feeProgram() {
5214
5312
  return new FeeProgramBuilder();
5215
5313
  }
5216
5314
 
5315
+ // src/airwallexCard.ts
5316
+ var AIRWALLEX_CARD_PRESETS = [
5317
+ "single_row",
5318
+ "split_fields",
5319
+ "split_fields_labelled",
5320
+ "stacked",
5321
+ "number_expiry_row",
5322
+ "compact"
5323
+ ];
5324
+ var SPLIT = ["cardNumber", "expiry", "cvc"];
5325
+ var AIRWALLEX_CARD_LAYOUTS = {
5326
+ // Airwallex's combined element. One iframe, one row, and the only preset
5327
+ // whose insides are not ours to lay out — which is why it carries no
5328
+ // captions: there is nothing to caption but the row as a whole.
5329
+ single_row: {
5330
+ elements: ["card"],
5331
+ rows: [["card"]],
5332
+ labels: false,
5333
+ density: "default"
5334
+ },
5335
+ // The trio with placeholders carrying the meaning. Shorter than the
5336
+ // labelled variant and fine on a wide surface.
5337
+ split_fields: {
5338
+ elements: SPLIT,
5339
+ rows: [["cardNumber"], ["expiry", "cvc"]],
5340
+ labels: false,
5341
+ density: "default"
5342
+ },
5343
+ // The default. The same geometry, captioned — which is what makes it
5344
+ // survive a narrow embed, where a bare field row stops being self-evident.
5345
+ split_fields_labelled: {
5346
+ elements: SPLIT,
5347
+ rows: [["cardNumber"], ["expiry", "cvc"]],
5348
+ labels: true,
5349
+ density: "default"
5350
+ },
5351
+ // Every field full width. Expiry and CVC side by side start to crowd below
5352
+ // roughly 320px, and this is the layout that does not.
5353
+ stacked: {
5354
+ elements: SPLIT,
5355
+ rows: [["cardNumber"], ["expiry"], ["cvc"]],
5356
+ labels: true,
5357
+ density: "default"
5358
+ },
5359
+ // Two rows instead of two-plus-one: shorter than the split forms without
5360
+ // the ambiguity of a single combined field.
5361
+ //
5362
+ // 3:2, not an even split. A card number is nineteen characters and an expiry
5363
+ // is five, so halving the row clipped the number's own placeholder at 460px
5364
+ // — seen in the preview before this was weighted. The proposal drew it even;
5365
+ // the merchant-facing decision was taken on the two drawn side by side and
5366
+ // the weighted one was chosen, so do not "restore" the even split to match
5367
+ // the original mock.
5368
+ number_expiry_row: {
5369
+ elements: SPLIT,
5370
+ rows: [["cardNumber", "expiry"], ["cvc"]],
5371
+ weights: { cardNumber: 3, expiry: 2 },
5372
+ labels: true,
5373
+ density: "default"
5374
+ },
5375
+ // Split geometry at reduced density and type size, for a checkout embedded
5376
+ // in a page that already has its own chrome.
5377
+ compact: {
5378
+ elements: SPLIT,
5379
+ rows: [["cardNumber"], ["expiry", "cvc"]],
5380
+ labels: false,
5381
+ density: "compact"
5382
+ }
5383
+ };
5384
+ var AIRWALLEX_CARD_PRESET_FALLBACK = "split_fields_labelled";
5385
+ function resolveAirwallexCardPreset(fromBranding, fromConnector) {
5386
+ return asPreset(fromBranding) ?? asPreset(fromConnector) ?? AIRWALLEX_CARD_PRESET_FALLBACK;
5387
+ }
5388
+ function asAirwallexCardPreset(value) {
5389
+ return asPreset(value);
5390
+ }
5391
+ function asPreset(value) {
5392
+ if (typeof value !== "string") return null;
5393
+ const trimmed = value.trim().toLowerCase();
5394
+ return AIRWALLEX_CARD_PRESETS.includes(trimmed) ? trimmed : null;
5395
+ }
5396
+ function airwallexCardLayout(preset) {
5397
+ return AIRWALLEX_CARD_LAYOUTS[preset];
5398
+ }
5399
+ function airwallexCellWeight(layout, field) {
5400
+ const weight = layout.weights?.[field];
5401
+ return typeof weight === "number" && Number.isFinite(weight) && weight > 0 ? weight : 1;
5402
+ }
5403
+ function airwallexCardLayoutIsCoherent(layout) {
5404
+ const drawn = layout.rows.flat();
5405
+ if (drawn.length !== layout.elements.length) return false;
5406
+ return layout.elements.every((field) => drawn.filter((f) => f === field).length === 1);
5407
+ }
5408
+ var AIRWALLEX_LABEL_STYLES = ["above", "inline", "floating", "none"];
5409
+ function resolveAirwallexLabelStyle(override, layout) {
5410
+ if (typeof override === "string" && AIRWALLEX_LABEL_STYLES.includes(override)) {
5411
+ return override;
5412
+ }
5413
+ return layout.labels ? "above" : "none";
5414
+ }
5415
+ var AIRWALLEX_FIELD_CHROMES = ["outlined", "filled", "underline"];
5416
+ var AIRWALLEX_FOCUS_RINGS = ["none", "subtle", "strong"];
5417
+ var AIRWALLEX_AUTOFILL_TREATMENTS = ["system", "brand", "neutral"];
5418
+ var AIRWALLEX_FIELD_FONT_SIZES = ["sm", "md", "lg"];
5419
+ var AIRWALLEX_FIELD_WEIGHTS = ["regular", "medium", "semibold"];
5420
+ function airwallexFieldFontPx(size, density) {
5421
+ const base = size === "sm" ? 14 : size === "lg" ? 18 : 16;
5422
+ return density === "compact" ? Math.max(13, base - 1) : base;
5423
+ }
5424
+ function airwallexFieldWeightValue(weight) {
5425
+ return weight === "regular" ? 400 : weight === "semibold" ? 600 : 500;
5426
+ }
5427
+ var AIRWALLEX_NETWORK_MARKS = ["visa", "mastercard", "amex", "discover"];
5428
+
5217
5429
  // src/branding.ts
5218
5430
  function surchargeShowsLabel(labelMode, style, position) {
5219
5431
  if (labelMode !== "labelled") return false;
@@ -5749,6 +5961,25 @@ var DEFAULT_BRANDING_BASE = {
5749
5961
  paymentLayout: "tabs",
5750
5962
  labelStyle: "above",
5751
5963
  showPoweredBy: true,
5964
+ // Every one of these defaults to what the Airwallex pane already did before
5965
+ // the section existed, so a merchant who never opens it sees no change:
5966
+ // empty preset (defer to the connector account), an outlined box, 16px /
5967
+ // 500 type, no focus ring, the browser's own autofill highlight, no valid
5968
+ // tint, no marks. The single deliberate change of behaviour is not here —
5969
+ // it is the fallback at the END of `resolveAirwallexCardPreset`, which
5970
+ // moves a shop that configured NOTHING from the combined row to the
5971
+ // labelled split form.
5972
+ airwallexCardPreset: "",
5973
+ // Off. With this on, no buyer can pay by card on the shop.
5974
+ airwallexHideCard: false,
5975
+ airwallexFieldChrome: "outlined",
5976
+ airwallexLabelStyle: "",
5977
+ airwallexFieldFontSize: "md",
5978
+ airwallexFieldWeight: "medium",
5979
+ airwallexFocusRing: "none",
5980
+ airwallexAutofill: "system",
5981
+ airwallexValidTint: false,
5982
+ airwallexNetworkMarks: false,
5752
5983
  customCss: ""
5753
5984
  };
5754
5985
  var DEFAULT_BRANDING = {
@@ -5858,6 +6089,10 @@ function pickEnum(value, allowed, fallback) {
5858
6089
  if (typeof value !== "string") return fallback;
5859
6090
  return allowed.includes(value) ? value : fallback;
5860
6091
  }
6092
+ function pickEnumOrEmpty(value, allowed) {
6093
+ if (typeof value !== "string") return "";
6094
+ return allowed.includes(value) ? value : "";
6095
+ }
5861
6096
  function parseBool(value, fallback) {
5862
6097
  if (typeof value === "boolean") return value;
5863
6098
  if (value === "true") return true;
@@ -6428,6 +6663,53 @@ function decodeBranding(source) {
6428
6663
  ),
6429
6664
  labelStyle,
6430
6665
  showPoweredBy: source.branding_visibility !== false,
6666
+ // The two that can be empty use `pickEnumOrEmpty`, not `pickEnum`: a
6667
+ // value this build does not know has to decode to "unset" and defer, the
6668
+ // same as a key that was never written. Sending it to a concrete default
6669
+ // instead would make an older checkout override the connector account of
6670
+ // a merchant who picked a preset a newer dashboard offers.
6671
+ airwallexCardPreset: pickEnumOrEmpty(
6672
+ extras["airwallexCardPreset"],
6673
+ AIRWALLEX_CARD_PRESETS
6674
+ ),
6675
+ airwallexHideCard: parseBool(extras["airwallexHideCard"], DEFAULT_BRANDING.airwallexHideCard),
6676
+ airwallexFieldChrome: pickEnum(
6677
+ extras["airwallexFieldChrome"],
6678
+ AIRWALLEX_FIELD_CHROMES,
6679
+ DEFAULT_BRANDING.airwallexFieldChrome
6680
+ ),
6681
+ airwallexLabelStyle: pickEnumOrEmpty(
6682
+ extras["airwallexLabelStyle"],
6683
+ AIRWALLEX_LABEL_STYLES
6684
+ ),
6685
+ airwallexFieldFontSize: pickEnum(
6686
+ extras["airwallexFieldFontSize"],
6687
+ AIRWALLEX_FIELD_FONT_SIZES,
6688
+ DEFAULT_BRANDING.airwallexFieldFontSize
6689
+ ),
6690
+ airwallexFieldWeight: pickEnum(
6691
+ extras["airwallexFieldWeight"],
6692
+ AIRWALLEX_FIELD_WEIGHTS,
6693
+ DEFAULT_BRANDING.airwallexFieldWeight
6694
+ ),
6695
+ airwallexFocusRing: pickEnum(
6696
+ extras["airwallexFocusRing"],
6697
+ AIRWALLEX_FOCUS_RINGS,
6698
+ DEFAULT_BRANDING.airwallexFocusRing
6699
+ ),
6700
+ airwallexAutofill: pickEnum(
6701
+ extras["airwallexAutofill"],
6702
+ AIRWALLEX_AUTOFILL_TREATMENTS,
6703
+ DEFAULT_BRANDING.airwallexAutofill
6704
+ ),
6705
+ airwallexValidTint: parseBool(
6706
+ extras["airwallexValidTint"],
6707
+ DEFAULT_BRANDING.airwallexValidTint
6708
+ ),
6709
+ airwallexNetworkMarks: parseBool(
6710
+ extras["airwallexNetworkMarks"],
6711
+ DEFAULT_BRANDING.airwallexNetworkMarks
6712
+ ),
6431
6713
  customCss: s(extras["customCss"])
6432
6714
  };
6433
6715
  }
@@ -6483,6 +6765,21 @@ function encodeBranding(branding, base) {
6483
6765
  logoShape: branding.logoShape,
6484
6766
  logoSize: branding.logoSize,
6485
6767
  labelStyle: branding.labelStyle,
6768
+ // Written unconditionally, empty string included. The encoder REPLACES
6769
+ // `sdk_ui_rules.branding` wholesale, so a key it skips is a key it
6770
+ // deletes — and here the empty string is a real value ("no choice made"),
6771
+ // not an absence. Omitting it would be indistinguishable from omitting it
6772
+ // by accident, which is how `summaryOrder` was lost.
6773
+ airwallexCardPreset: branding.airwallexCardPreset,
6774
+ airwallexHideCard: String(branding.airwallexHideCard),
6775
+ airwallexFieldChrome: branding.airwallexFieldChrome,
6776
+ airwallexLabelStyle: branding.airwallexLabelStyle,
6777
+ airwallexFieldFontSize: branding.airwallexFieldFontSize,
6778
+ airwallexFieldWeight: branding.airwallexFieldWeight,
6779
+ airwallexFocusRing: branding.airwallexFocusRing,
6780
+ airwallexAutofill: branding.airwallexAutofill,
6781
+ airwallexValidTint: String(branding.airwallexValidTint),
6782
+ airwallexNetworkMarks: String(branding.airwallexNetworkMarks),
6486
6783
  trustBadges: encodeBadges(branding.trustBadges),
6487
6784
  [METHOD_SECTION_ORDER_KEY]: encodeMethodSectionOrder(branding.methodSectionOrder)
6488
6785
  };
@@ -6710,6 +7007,47 @@ function parseImportedBranding(raw) {
6710
7007
  ),
6711
7008
  labelStyle,
6712
7009
  showPoweredBy: parseBool(root["showPoweredBy"], dflt.showPoweredBy),
7010
+ // An imported profile that predates this section carries none of these
7011
+ // and lands on the defaults — which is to say on "defer", so importing an
7012
+ // old export into a shop does not take that shop's connector setting
7013
+ // away. The one field that would be dangerous to import loosely is the
7014
+ // hide switch, and `parseBool` only says true for a literal `true`.
7015
+ airwallexCardPreset: pickEnumOrEmpty(
7016
+ root["airwallexCardPreset"],
7017
+ AIRWALLEX_CARD_PRESETS
7018
+ ),
7019
+ airwallexHideCard: parseBool(root["airwallexHideCard"], dflt.airwallexHideCard),
7020
+ airwallexFieldChrome: pickEnum(
7021
+ root["airwallexFieldChrome"],
7022
+ AIRWALLEX_FIELD_CHROMES,
7023
+ dflt.airwallexFieldChrome
7024
+ ),
7025
+ airwallexLabelStyle: pickEnumOrEmpty(
7026
+ root["airwallexLabelStyle"],
7027
+ AIRWALLEX_LABEL_STYLES
7028
+ ),
7029
+ airwallexFieldFontSize: pickEnum(
7030
+ root["airwallexFieldFontSize"],
7031
+ AIRWALLEX_FIELD_FONT_SIZES,
7032
+ dflt.airwallexFieldFontSize
7033
+ ),
7034
+ airwallexFieldWeight: pickEnum(
7035
+ root["airwallexFieldWeight"],
7036
+ AIRWALLEX_FIELD_WEIGHTS,
7037
+ dflt.airwallexFieldWeight
7038
+ ),
7039
+ airwallexFocusRing: pickEnum(
7040
+ root["airwallexFocusRing"],
7041
+ AIRWALLEX_FOCUS_RINGS,
7042
+ dflt.airwallexFocusRing
7043
+ ),
7044
+ airwallexAutofill: pickEnum(
7045
+ root["airwallexAutofill"],
7046
+ AIRWALLEX_AUTOFILL_TREATMENTS,
7047
+ dflt.airwallexAutofill
7048
+ ),
7049
+ airwallexValidTint: parseBool(root["airwallexValidTint"], dflt.airwallexValidTint),
7050
+ airwallexNetworkMarks: parseBool(root["airwallexNetworkMarks"], dflt.airwallexNetworkMarks),
6713
7051
  customCss: sStr(root["customCss"], dflt.customCss).slice(0, CUSTOM_CSS_MAX_LENGTH)
6714
7052
  };
6715
7053
  }
@@ -7574,6 +7912,24 @@ export {
7574
7912
  programToTree,
7575
7913
  FeeProgramBuilder,
7576
7914
  feeProgram,
7915
+ AIRWALLEX_CARD_PRESETS,
7916
+ AIRWALLEX_CARD_LAYOUTS,
7917
+ AIRWALLEX_CARD_PRESET_FALLBACK,
7918
+ resolveAirwallexCardPreset,
7919
+ asAirwallexCardPreset,
7920
+ airwallexCardLayout,
7921
+ airwallexCellWeight,
7922
+ airwallexCardLayoutIsCoherent,
7923
+ AIRWALLEX_LABEL_STYLES,
7924
+ resolveAirwallexLabelStyle,
7925
+ AIRWALLEX_FIELD_CHROMES,
7926
+ AIRWALLEX_FOCUS_RINGS,
7927
+ AIRWALLEX_AUTOFILL_TREATMENTS,
7928
+ AIRWALLEX_FIELD_FONT_SIZES,
7929
+ AIRWALLEX_FIELD_WEIGHTS,
7930
+ airwallexFieldFontPx,
7931
+ airwallexFieldWeightValue,
7932
+ AIRWALLEX_NETWORK_MARKS,
7577
7933
  surchargeShowsLabel,
7578
7934
  surchargeFigurePlan,
7579
7935
  readableInkOn,
@@ -7699,4 +8055,4 @@ export {
7699
8055
  decodeNativePanes,
7700
8056
  encodeNativePanes
7701
8057
  };
7702
- //# sourceMappingURL=chunk-R4MDAZWF.js.map
8058
+ //# sourceMappingURL=chunk-OMJ6MVD4.js.map