@delopay/sdk 0.74.0 → 0.76.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
@@ -20,15 +20,22 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ ALL_CUSTOM_FIELD_CONDITION_SOURCES: () => ALL_CUSTOM_FIELD_CONDITION_SOURCES,
24
+ ALL_CUSTOM_FIELD_OPERATORS: () => ALL_CUSTOM_FIELD_OPERATORS,
23
25
  ALL_CUSTOM_FIELD_TYPES: () => ALL_CUSTOM_FIELD_TYPES,
24
26
  Analytics: () => Analytics,
25
27
  AnalyticsDashboard: () => AnalyticsDashboard,
26
28
  AvailabilityOverrides: () => AvailabilityOverrides,
27
29
  BRANDING_EXPORT_FORMAT: () => BRANDING_EXPORT_FORMAT,
28
30
  BRANDING_EXPORT_VERSION: () => BRANDING_EXPORT_VERSION,
31
+ CHECKBOX_CHECKED: () => CHECKBOX_CHECKED,
32
+ CHECKBOX_UNCHECKED: () => CHECKBOX_UNCHECKED,
29
33
  CUSTOM_CSS_MAX_LENGTH: () => CUSTOM_CSS_MAX_LENGTH,
30
34
  CUSTOM_FIELDS_MAX: () => CUSTOM_FIELDS_MAX,
35
+ CUSTOM_FIELD_CONDITIONS_MAX: () => CUSTOM_FIELD_CONDITIONS_MAX,
31
36
  CUSTOM_FIELD_KEY_PATTERN: () => CUSTOM_FIELD_KEY_PATTERN,
37
+ CUSTOM_FIELD_OPERATORS_BY_SOURCE: () => CUSTOM_FIELD_OPERATORS_BY_SOURCE,
38
+ CUSTOM_FIELD_VALUELESS_OPERATORS: () => CUSTOM_FIELD_VALUELESS_OPERATORS,
32
39
  Cards: () => Cards,
33
40
  DEFAULT_BADGES: () => DEFAULT_BADGES,
34
41
  DEFAULT_BADGES_DARK: () => DEFAULT_BADGES_DARK,
@@ -53,19 +60,27 @@ __export(index_exports, {
53
60
  buttonPadValue: () => buttonPadValue,
54
61
  cloneBranding: () => cloneBranding,
55
62
  cloneCustomField: () => cloneCustomField,
63
+ customFieldContextFromMetadata: () => customFieldContextFromMetadata,
64
+ customFieldIsTextLike: () => customFieldIsTextLike,
65
+ customFieldOperatorTakesValue: () => customFieldOperatorTakesValue,
56
66
  customFieldOptionLabel: () => customFieldOptionLabel,
57
67
  customFieldText: () => customFieldText,
58
68
  decodeBadges: () => decodeBadges,
59
69
  decodeBranding: () => decodeBranding,
60
70
  decodeCustomFields: () => decodeCustomFields,
61
71
  defaultBranding: () => defaultBranding,
72
+ defaultCustomFieldVisibility: () => defaultCustomFieldVisibility,
73
+ defaultOperatorForSource: () => defaultOperatorForSource,
62
74
  encodeBadges: () => encodeBadges,
63
75
  encodeBranding: () => encodeBranding,
64
76
  encodeCustomFields: () => encodeCustomFields,
77
+ evaluateCustomFieldCondition: () => evaluateCustomFieldCondition,
78
+ evaluateCustomFieldVisibility: () => evaluateCustomFieldVisibility,
65
79
  feeProgram: () => feeProgram,
66
80
  fontStack: () => fontStack,
67
81
  fontWeightValue: () => fontWeightValue,
68
82
  inputPadValue: () => inputPadValue,
83
+ isCheckboxChecked: () => isCheckboxChecked,
69
84
  isDarkSurface: () => isDarkSurface,
70
85
  isHexColor: () => isHexColor,
71
86
  leaf: () => leaf,
@@ -78,7 +93,8 @@ __export(index_exports, {
78
93
  sanitizeCustomCss: () => sanitizeCustomCss,
79
94
  shadowFor: () => shadowFor,
80
95
  surfacePadValue: () => surfacePadValue,
81
- verticalGapValue: () => verticalGapValue
96
+ verticalGapValue: () => verticalGapValue,
97
+ visibleCustomFields: () => visibleCustomFields
82
98
  });
83
99
  module.exports = __toCommonJS(index_exports);
84
100
 
@@ -3995,7 +4011,11 @@ function cloneCustomField(f) {
3995
4011
  labelTranslations: { ...f.labelTranslations },
3996
4012
  placeholderTranslations: { ...f.placeholderTranslations },
3997
4013
  helpTextTranslations: { ...f.helpTextTranslations },
3998
- options: f.options.map((o) => ({ ...o, labelTranslations: { ...o.labelTranslations } }))
4014
+ options: f.options.map((o) => ({ ...o, labelTranslations: { ...o.labelTranslations } })),
4015
+ visibility: {
4016
+ ...f.visibility,
4017
+ conditions: f.visibility.conditions.map((c) => ({ ...c }))
4018
+ }
3999
4019
  };
4000
4020
  }
4001
4021
  var CUSTOM_CSS_MAX_LENGTH = 5e4;
@@ -4081,8 +4101,57 @@ var ALL_CUSTOM_FIELD_TYPES = [
4081
4101
  "textarea",
4082
4102
  "password",
4083
4103
  "email",
4084
- "select"
4104
+ "select",
4105
+ "checkbox"
4106
+ ];
4107
+ var CHECKBOX_CHECKED = "true";
4108
+ var CHECKBOX_UNCHECKED = "false";
4109
+ function isCheckboxChecked(value) {
4110
+ return typeof value === "string" && value.trim().toLowerCase() === CHECKBOX_CHECKED;
4111
+ }
4112
+ function customFieldIsTextLike(type) {
4113
+ return type !== "select" && type !== "checkbox";
4114
+ }
4115
+ var CUSTOM_FIELD_CONDITIONS_MAX = 10;
4116
+ var ALL_CUSTOM_FIELD_CONDITION_SOURCES = [
4117
+ "metadata",
4118
+ "currency",
4119
+ "amount"
4120
+ ];
4121
+ var ALL_CUSTOM_FIELD_OPERATORS = [
4122
+ "equals",
4123
+ "not_equals",
4124
+ "contains",
4125
+ "not_contains",
4126
+ "starts_with",
4127
+ "ends_with",
4128
+ "in",
4129
+ "not_in",
4130
+ "exists",
4131
+ "not_exists",
4132
+ "gt",
4133
+ "gte",
4134
+ "lt",
4135
+ "lte"
4085
4136
  ];
4137
+ var CUSTOM_FIELD_OPERATORS_BY_SOURCE = {
4138
+ metadata: ALL_CUSTOM_FIELD_OPERATORS,
4139
+ currency: ["equals", "not_equals", "in", "not_in"],
4140
+ amount: ["equals", "not_equals", "gt", "gte", "lt", "lte"]
4141
+ };
4142
+ var CUSTOM_FIELD_VALUELESS_OPERATORS = [
4143
+ "exists",
4144
+ "not_exists"
4145
+ ];
4146
+ function customFieldOperatorTakesValue(operator) {
4147
+ return !CUSTOM_FIELD_VALUELESS_OPERATORS.includes(operator);
4148
+ }
4149
+ function defaultOperatorForSource(source) {
4150
+ return CUSTOM_FIELD_OPERATORS_BY_SOURCE[source][0] ?? "equals";
4151
+ }
4152
+ function defaultCustomFieldVisibility() {
4153
+ return { mode: "always", match: "all", conditions: [] };
4154
+ }
4086
4155
  function parseTranslations(raw) {
4087
4156
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return {};
4088
4157
  const out = {};
@@ -4091,6 +4160,41 @@ function parseTranslations(raw) {
4091
4160
  }
4092
4161
  return out;
4093
4162
  }
4163
+ function normalizeCondition(raw, index) {
4164
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
4165
+ const c = raw;
4166
+ const source = pickEnum(
4167
+ c["source"],
4168
+ ALL_CUSTOM_FIELD_CONDITION_SOURCES,
4169
+ "metadata"
4170
+ );
4171
+ const allowed = CUSTOM_FIELD_OPERATORS_BY_SOURCE[source];
4172
+ const operator = pickEnum(
4173
+ c["operator"],
4174
+ allowed,
4175
+ defaultOperatorForSource(source)
4176
+ );
4177
+ const rawValue = c["value"];
4178
+ return {
4179
+ id: typeof c["id"] === "string" && c["id"] ? c["id"] : `cond-${index}`,
4180
+ source,
4181
+ // Only metadata conditions carry a key; drop anything else so the
4182
+ // encoded form stays canonical.
4183
+ key: source === "metadata" && typeof c["key"] === "string" ? c["key"].trim() : "",
4184
+ operator,
4185
+ value: typeof rawValue === "string" ? rawValue : typeof rawValue === "number" || typeof rawValue === "boolean" ? String(rawValue) : ""
4186
+ };
4187
+ }
4188
+ function normalizeVisibility(raw) {
4189
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return defaultCustomFieldVisibility();
4190
+ const v = raw;
4191
+ const conditions = Array.isArray(v["conditions"]) ? v["conditions"].slice(0, CUSTOM_FIELD_CONDITIONS_MAX).map(normalizeCondition).filter((c) => c !== null) : [];
4192
+ return {
4193
+ mode: pickEnum(v["mode"], ["always", "match"], "always"),
4194
+ match: pickEnum(v["match"], ["all", "any"], "all"),
4195
+ conditions
4196
+ };
4197
+ }
4094
4198
  function parseBoundedInt(raw) {
4095
4199
  const n = typeof raw === "number" ? raw : typeof raw === "string" ? Number(raw) : NaN;
4096
4200
  if (!Number.isInteger(n) || n < 0) return null;
@@ -4110,8 +4214,11 @@ function normalizeCustomField(raw, index) {
4110
4214
  labelTranslations: parseTranslations(o["labelTranslations"])
4111
4215
  };
4112
4216
  }).filter((o) => o.value.length > 0) : [];
4113
- const minLength = parseBoundedInt(f["minLength"]);
4114
- const maxLength = parseBoundedInt(f["maxLength"]);
4217
+ const textLike = customFieldIsTextLike(type);
4218
+ const minLength = textLike ? parseBoundedInt(f["minLength"]) : null;
4219
+ const maxLength = textLike ? parseBoundedInt(f["maxLength"]) : null;
4220
+ const rawDefault = typeof f["defaultValue"] === "string" ? f["defaultValue"] : "";
4221
+ const defaultValue = type === "checkbox" ? isCheckboxChecked(rawDefault) ? CHECKBOX_CHECKED : CHECKBOX_UNCHECKED : rawDefault;
4115
4222
  return {
4116
4223
  id: typeof f["id"] === "string" && f["id"] ? f["id"] : `field-${index}`,
4117
4224
  key,
@@ -4127,8 +4234,9 @@ function normalizeCustomField(raw, index) {
4127
4234
  minLength,
4128
4235
  // Guard inverted bounds at decode so consumers never see min > max.
4129
4236
  maxLength: maxLength !== null && minLength !== null && maxLength < minLength ? null : maxLength,
4130
- defaultValue: typeof f["defaultValue"] === "string" ? f["defaultValue"] : "",
4131
- options
4237
+ defaultValue,
4238
+ options,
4239
+ visibility: normalizeVisibility(f["visibility"])
4132
4240
  };
4133
4241
  }
4134
4242
  function parseCustomFieldsLoose(raw) {
@@ -4169,13 +4277,125 @@ function encodeCustomFields(fields) {
4169
4277
  ...nonEmpty(f.helpTextTranslations) ? { helpTextTranslations: nonEmpty(f.helpTextTranslations) } : {},
4170
4278
  ...f.required ? { required: true } : {},
4171
4279
  ...f.enabled ? {} : { enabled: false },
4172
- ...f.minLength !== null ? { minLength: f.minLength } : {},
4173
- ...f.maxLength !== null ? { maxLength: f.maxLength } : {},
4174
- ...f.defaultValue ? { defaultValue: f.defaultValue } : {},
4175
- ...f.type === "select" ? { options: f.options } : {}
4280
+ // Length bounds only exist for free-text types; a choice control that
4281
+ // still carries them is stale state the decoder would drop anyway.
4282
+ ...customFieldIsTextLike(f.type) && f.minLength !== null ? { minLength: f.minLength } : {},
4283
+ ...customFieldIsTextLike(f.type) && f.maxLength !== null ? { maxLength: f.maxLength } : {},
4284
+ // A checkbox persists only "starts ticked"; unticked is the decoder's
4285
+ // default, so writing 'false' would be noise on every such field.
4286
+ ...f.type === "checkbox" ? isCheckboxChecked(f.defaultValue) ? { defaultValue: CHECKBOX_CHECKED } : {} : f.defaultValue ? { defaultValue: f.defaultValue } : {},
4287
+ ...f.type === "select" ? { options: f.options } : {},
4288
+ // Omitted for unconditional fields so the stored blob (and every
4289
+ // pre-feature payload) stays byte-identical to what it was.
4290
+ ...f.visibility.mode === "match" ? { visibility: encodeVisibility(f.visibility) } : {}
4176
4291
  }))
4177
4292
  );
4178
4293
  }
4294
+ function encodeVisibility(v) {
4295
+ return {
4296
+ mode: v.mode,
4297
+ match: v.match,
4298
+ conditions: v.conditions.map((c) => ({
4299
+ id: c.id,
4300
+ source: c.source,
4301
+ ...c.source === "metadata" && c.key ? { key: c.key } : {},
4302
+ operator: c.operator,
4303
+ ...customFieldOperatorTakesValue(c.operator) && c.value ? { value: c.value } : {}
4304
+ }))
4305
+ };
4306
+ }
4307
+ function customFieldContextFromMetadata(raw) {
4308
+ const out = {};
4309
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return out;
4310
+ for (const [key, value] of Object.entries(raw)) {
4311
+ const flat = flattenMetadataValue(value);
4312
+ if (flat !== null) out[key] = flat;
4313
+ }
4314
+ return out;
4315
+ }
4316
+ function flattenMetadataValue(value) {
4317
+ if (typeof value === "string") return value;
4318
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
4319
+ if (value === null || value === void 0) return null;
4320
+ if (Array.isArray(value)) {
4321
+ return value.map((v) => flattenMetadataValue(v)).filter((v) => v !== null).join(",");
4322
+ }
4323
+ try {
4324
+ return JSON.stringify(value);
4325
+ } catch {
4326
+ return null;
4327
+ }
4328
+ }
4329
+ function norm(value) {
4330
+ return value.trim().toLowerCase();
4331
+ }
4332
+ var DECIMAL_NUMBER_PATTERN = /^[+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?$/;
4333
+ function numeric(value) {
4334
+ const trimmed = value.trim();
4335
+ if (!DECIMAL_NUMBER_PATTERN.test(trimmed)) return null;
4336
+ const n = Number(trimmed);
4337
+ return Number.isFinite(n) ? n : null;
4338
+ }
4339
+ function splitList(value) {
4340
+ return value.split(",").map((part) => norm(part)).filter((part) => part.length > 0);
4341
+ }
4342
+ function operandFor(condition, ctx) {
4343
+ switch (condition.source) {
4344
+ case "currency":
4345
+ return ctx.currency;
4346
+ case "amount":
4347
+ return String(ctx.amount);
4348
+ case "metadata":
4349
+ return Object.prototype.hasOwnProperty.call(ctx.metadata, condition.key) ? ctx.metadata[condition.key] : void 0;
4350
+ }
4351
+ }
4352
+ function evaluateCustomFieldCondition(condition, ctx) {
4353
+ const raw = operandFor(condition, ctx);
4354
+ const actual = raw ?? "";
4355
+ const expected = condition.value;
4356
+ switch (condition.operator) {
4357
+ case "exists":
4358
+ return raw !== void 0 && raw.trim().length > 0;
4359
+ case "not_exists":
4360
+ return raw === void 0 || raw.trim().length === 0;
4361
+ case "equals":
4362
+ return norm(actual) === norm(expected);
4363
+ case "not_equals":
4364
+ return norm(actual) !== norm(expected);
4365
+ case "contains":
4366
+ return norm(actual).includes(norm(expected));
4367
+ case "not_contains":
4368
+ return !norm(actual).includes(norm(expected));
4369
+ case "starts_with":
4370
+ return norm(actual).startsWith(norm(expected));
4371
+ case "ends_with":
4372
+ return norm(actual).endsWith(norm(expected));
4373
+ case "in":
4374
+ return splitList(expected).includes(norm(actual));
4375
+ case "not_in":
4376
+ return !splitList(expected).includes(norm(actual));
4377
+ case "gt":
4378
+ case "gte":
4379
+ case "lt":
4380
+ case "lte": {
4381
+ const a = numeric(actual);
4382
+ const b = numeric(expected);
4383
+ if (a === null || b === null) return false;
4384
+ if (condition.operator === "gt") return a > b;
4385
+ if (condition.operator === "gte") return a >= b;
4386
+ if (condition.operator === "lt") return a < b;
4387
+ return a <= b;
4388
+ }
4389
+ }
4390
+ }
4391
+ function evaluateCustomFieldVisibility(field, ctx) {
4392
+ const { mode, match, conditions } = field.visibility;
4393
+ if (mode !== "match" || conditions.length === 0) return true;
4394
+ return match === "any" ? conditions.some((c) => evaluateCustomFieldCondition(c, ctx)) : conditions.every((c) => evaluateCustomFieldCondition(c, ctx));
4395
+ }
4396
+ function visibleCustomFields(fields, ctx) {
4397
+ return fields.filter((f) => f.enabled && evaluateCustomFieldVisibility(f, ctx));
4398
+ }
4179
4399
  function translationFor(map, locale) {
4180
4400
  if (!locale) return null;
4181
4401
  const own = (k) => {
@@ -4553,15 +4773,22 @@ function shadowFor(style) {
4553
4773
  }
4554
4774
  // Annotate the CommonJS export names for ESM import in node:
4555
4775
  0 && (module.exports = {
4776
+ ALL_CUSTOM_FIELD_CONDITION_SOURCES,
4777
+ ALL_CUSTOM_FIELD_OPERATORS,
4556
4778
  ALL_CUSTOM_FIELD_TYPES,
4557
4779
  Analytics,
4558
4780
  AnalyticsDashboard,
4559
4781
  AvailabilityOverrides,
4560
4782
  BRANDING_EXPORT_FORMAT,
4561
4783
  BRANDING_EXPORT_VERSION,
4784
+ CHECKBOX_CHECKED,
4785
+ CHECKBOX_UNCHECKED,
4562
4786
  CUSTOM_CSS_MAX_LENGTH,
4563
4787
  CUSTOM_FIELDS_MAX,
4788
+ CUSTOM_FIELD_CONDITIONS_MAX,
4564
4789
  CUSTOM_FIELD_KEY_PATTERN,
4790
+ CUSTOM_FIELD_OPERATORS_BY_SOURCE,
4791
+ CUSTOM_FIELD_VALUELESS_OPERATORS,
4565
4792
  Cards,
4566
4793
  DEFAULT_BADGES,
4567
4794
  DEFAULT_BADGES_DARK,
@@ -4586,19 +4813,27 @@ function shadowFor(style) {
4586
4813
  buttonPadValue,
4587
4814
  cloneBranding,
4588
4815
  cloneCustomField,
4816
+ customFieldContextFromMetadata,
4817
+ customFieldIsTextLike,
4818
+ customFieldOperatorTakesValue,
4589
4819
  customFieldOptionLabel,
4590
4820
  customFieldText,
4591
4821
  decodeBadges,
4592
4822
  decodeBranding,
4593
4823
  decodeCustomFields,
4594
4824
  defaultBranding,
4825
+ defaultCustomFieldVisibility,
4826
+ defaultOperatorForSource,
4595
4827
  encodeBadges,
4596
4828
  encodeBranding,
4597
4829
  encodeCustomFields,
4830
+ evaluateCustomFieldCondition,
4831
+ evaluateCustomFieldVisibility,
4598
4832
  feeProgram,
4599
4833
  fontStack,
4600
4834
  fontWeightValue,
4601
4835
  inputPadValue,
4836
+ isCheckboxChecked,
4602
4837
  isDarkSurface,
4603
4838
  isHexColor,
4604
4839
  leaf,
@@ -4611,6 +4846,7 @@ function shadowFor(style) {
4611
4846
  sanitizeCustomCss,
4612
4847
  shadowFor,
4613
4848
  surfacePadValue,
4614
- verticalGapValue
4849
+ verticalGapValue,
4850
+ visibleCustomFields
4615
4851
  });
4616
4852
  //# sourceMappingURL=index.cjs.map