@delopay/sdk 0.74.0 → 0.75.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,6 +20,8 @@ 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,
@@ -28,7 +30,10 @@ __export(index_exports, {
28
30
  BRANDING_EXPORT_VERSION: () => BRANDING_EXPORT_VERSION,
29
31
  CUSTOM_CSS_MAX_LENGTH: () => CUSTOM_CSS_MAX_LENGTH,
30
32
  CUSTOM_FIELDS_MAX: () => CUSTOM_FIELDS_MAX,
33
+ CUSTOM_FIELD_CONDITIONS_MAX: () => CUSTOM_FIELD_CONDITIONS_MAX,
31
34
  CUSTOM_FIELD_KEY_PATTERN: () => CUSTOM_FIELD_KEY_PATTERN,
35
+ CUSTOM_FIELD_OPERATORS_BY_SOURCE: () => CUSTOM_FIELD_OPERATORS_BY_SOURCE,
36
+ CUSTOM_FIELD_VALUELESS_OPERATORS: () => CUSTOM_FIELD_VALUELESS_OPERATORS,
32
37
  Cards: () => Cards,
33
38
  DEFAULT_BADGES: () => DEFAULT_BADGES,
34
39
  DEFAULT_BADGES_DARK: () => DEFAULT_BADGES_DARK,
@@ -53,15 +58,21 @@ __export(index_exports, {
53
58
  buttonPadValue: () => buttonPadValue,
54
59
  cloneBranding: () => cloneBranding,
55
60
  cloneCustomField: () => cloneCustomField,
61
+ customFieldContextFromMetadata: () => customFieldContextFromMetadata,
62
+ customFieldOperatorTakesValue: () => customFieldOperatorTakesValue,
56
63
  customFieldOptionLabel: () => customFieldOptionLabel,
57
64
  customFieldText: () => customFieldText,
58
65
  decodeBadges: () => decodeBadges,
59
66
  decodeBranding: () => decodeBranding,
60
67
  decodeCustomFields: () => decodeCustomFields,
61
68
  defaultBranding: () => defaultBranding,
69
+ defaultCustomFieldVisibility: () => defaultCustomFieldVisibility,
70
+ defaultOperatorForSource: () => defaultOperatorForSource,
62
71
  encodeBadges: () => encodeBadges,
63
72
  encodeBranding: () => encodeBranding,
64
73
  encodeCustomFields: () => encodeCustomFields,
74
+ evaluateCustomFieldCondition: () => evaluateCustomFieldCondition,
75
+ evaluateCustomFieldVisibility: () => evaluateCustomFieldVisibility,
65
76
  feeProgram: () => feeProgram,
66
77
  fontStack: () => fontStack,
67
78
  fontWeightValue: () => fontWeightValue,
@@ -78,7 +89,8 @@ __export(index_exports, {
78
89
  sanitizeCustomCss: () => sanitizeCustomCss,
79
90
  shadowFor: () => shadowFor,
80
91
  surfacePadValue: () => surfacePadValue,
81
- verticalGapValue: () => verticalGapValue
92
+ verticalGapValue: () => verticalGapValue,
93
+ visibleCustomFields: () => visibleCustomFields
82
94
  });
83
95
  module.exports = __toCommonJS(index_exports);
84
96
 
@@ -3995,7 +4007,11 @@ function cloneCustomField(f) {
3995
4007
  labelTranslations: { ...f.labelTranslations },
3996
4008
  placeholderTranslations: { ...f.placeholderTranslations },
3997
4009
  helpTextTranslations: { ...f.helpTextTranslations },
3998
- options: f.options.map((o) => ({ ...o, labelTranslations: { ...o.labelTranslations } }))
4010
+ options: f.options.map((o) => ({ ...o, labelTranslations: { ...o.labelTranslations } })),
4011
+ visibility: {
4012
+ ...f.visibility,
4013
+ conditions: f.visibility.conditions.map((c) => ({ ...c }))
4014
+ }
3999
4015
  };
4000
4016
  }
4001
4017
  var CUSTOM_CSS_MAX_LENGTH = 5e4;
@@ -4083,6 +4099,46 @@ var ALL_CUSTOM_FIELD_TYPES = [
4083
4099
  "email",
4084
4100
  "select"
4085
4101
  ];
4102
+ var CUSTOM_FIELD_CONDITIONS_MAX = 10;
4103
+ var ALL_CUSTOM_FIELD_CONDITION_SOURCES = [
4104
+ "metadata",
4105
+ "currency",
4106
+ "amount"
4107
+ ];
4108
+ var ALL_CUSTOM_FIELD_OPERATORS = [
4109
+ "equals",
4110
+ "not_equals",
4111
+ "contains",
4112
+ "not_contains",
4113
+ "starts_with",
4114
+ "ends_with",
4115
+ "in",
4116
+ "not_in",
4117
+ "exists",
4118
+ "not_exists",
4119
+ "gt",
4120
+ "gte",
4121
+ "lt",
4122
+ "lte"
4123
+ ];
4124
+ var CUSTOM_FIELD_OPERATORS_BY_SOURCE = {
4125
+ metadata: ALL_CUSTOM_FIELD_OPERATORS,
4126
+ currency: ["equals", "not_equals", "in", "not_in"],
4127
+ amount: ["equals", "not_equals", "gt", "gte", "lt", "lte"]
4128
+ };
4129
+ var CUSTOM_FIELD_VALUELESS_OPERATORS = [
4130
+ "exists",
4131
+ "not_exists"
4132
+ ];
4133
+ function customFieldOperatorTakesValue(operator) {
4134
+ return !CUSTOM_FIELD_VALUELESS_OPERATORS.includes(operator);
4135
+ }
4136
+ function defaultOperatorForSource(source) {
4137
+ return CUSTOM_FIELD_OPERATORS_BY_SOURCE[source][0] ?? "equals";
4138
+ }
4139
+ function defaultCustomFieldVisibility() {
4140
+ return { mode: "always", match: "all", conditions: [] };
4141
+ }
4086
4142
  function parseTranslations(raw) {
4087
4143
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return {};
4088
4144
  const out = {};
@@ -4091,6 +4147,41 @@ function parseTranslations(raw) {
4091
4147
  }
4092
4148
  return out;
4093
4149
  }
4150
+ function normalizeCondition(raw, index) {
4151
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
4152
+ const c = raw;
4153
+ const source = pickEnum(
4154
+ c["source"],
4155
+ ALL_CUSTOM_FIELD_CONDITION_SOURCES,
4156
+ "metadata"
4157
+ );
4158
+ const allowed = CUSTOM_FIELD_OPERATORS_BY_SOURCE[source];
4159
+ const operator = pickEnum(
4160
+ c["operator"],
4161
+ allowed,
4162
+ defaultOperatorForSource(source)
4163
+ );
4164
+ const rawValue = c["value"];
4165
+ return {
4166
+ id: typeof c["id"] === "string" && c["id"] ? c["id"] : `cond-${index}`,
4167
+ source,
4168
+ // Only metadata conditions carry a key; drop anything else so the
4169
+ // encoded form stays canonical.
4170
+ key: source === "metadata" && typeof c["key"] === "string" ? c["key"].trim() : "",
4171
+ operator,
4172
+ value: typeof rawValue === "string" ? rawValue : typeof rawValue === "number" || typeof rawValue === "boolean" ? String(rawValue) : ""
4173
+ };
4174
+ }
4175
+ function normalizeVisibility(raw) {
4176
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return defaultCustomFieldVisibility();
4177
+ const v = raw;
4178
+ const conditions = Array.isArray(v["conditions"]) ? v["conditions"].slice(0, CUSTOM_FIELD_CONDITIONS_MAX).map(normalizeCondition).filter((c) => c !== null) : [];
4179
+ return {
4180
+ mode: pickEnum(v["mode"], ["always", "match"], "always"),
4181
+ match: pickEnum(v["match"], ["all", "any"], "all"),
4182
+ conditions
4183
+ };
4184
+ }
4094
4185
  function parseBoundedInt(raw) {
4095
4186
  const n = typeof raw === "number" ? raw : typeof raw === "string" ? Number(raw) : NaN;
4096
4187
  if (!Number.isInteger(n) || n < 0) return null;
@@ -4128,7 +4219,8 @@ function normalizeCustomField(raw, index) {
4128
4219
  // Guard inverted bounds at decode so consumers never see min > max.
4129
4220
  maxLength: maxLength !== null && minLength !== null && maxLength < minLength ? null : maxLength,
4130
4221
  defaultValue: typeof f["defaultValue"] === "string" ? f["defaultValue"] : "",
4131
- options
4222
+ options,
4223
+ visibility: normalizeVisibility(f["visibility"])
4132
4224
  };
4133
4225
  }
4134
4226
  function parseCustomFieldsLoose(raw) {
@@ -4172,10 +4264,118 @@ function encodeCustomFields(fields) {
4172
4264
  ...f.minLength !== null ? { minLength: f.minLength } : {},
4173
4265
  ...f.maxLength !== null ? { maxLength: f.maxLength } : {},
4174
4266
  ...f.defaultValue ? { defaultValue: f.defaultValue } : {},
4175
- ...f.type === "select" ? { options: f.options } : {}
4267
+ ...f.type === "select" ? { options: f.options } : {},
4268
+ // Omitted for unconditional fields so the stored blob (and every
4269
+ // pre-feature payload) stays byte-identical to what it was.
4270
+ ...f.visibility.mode === "match" ? { visibility: encodeVisibility(f.visibility) } : {}
4176
4271
  }))
4177
4272
  );
4178
4273
  }
4274
+ function encodeVisibility(v) {
4275
+ return {
4276
+ mode: v.mode,
4277
+ match: v.match,
4278
+ conditions: v.conditions.map((c) => ({
4279
+ id: c.id,
4280
+ source: c.source,
4281
+ ...c.source === "metadata" && c.key ? { key: c.key } : {},
4282
+ operator: c.operator,
4283
+ ...customFieldOperatorTakesValue(c.operator) && c.value ? { value: c.value } : {}
4284
+ }))
4285
+ };
4286
+ }
4287
+ function customFieldContextFromMetadata(raw) {
4288
+ const out = {};
4289
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return out;
4290
+ for (const [key, value] of Object.entries(raw)) {
4291
+ const flat = flattenMetadataValue(value);
4292
+ if (flat !== null) out[key] = flat;
4293
+ }
4294
+ return out;
4295
+ }
4296
+ function flattenMetadataValue(value) {
4297
+ if (typeof value === "string") return value;
4298
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
4299
+ if (value === null || value === void 0) return null;
4300
+ if (Array.isArray(value)) {
4301
+ return value.map((v) => flattenMetadataValue(v)).filter((v) => v !== null).join(",");
4302
+ }
4303
+ try {
4304
+ return JSON.stringify(value);
4305
+ } catch {
4306
+ return null;
4307
+ }
4308
+ }
4309
+ function norm(value) {
4310
+ return value.trim().toLowerCase();
4311
+ }
4312
+ var DECIMAL_NUMBER_PATTERN = /^[+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?$/;
4313
+ function numeric(value) {
4314
+ const trimmed = value.trim();
4315
+ if (!DECIMAL_NUMBER_PATTERN.test(trimmed)) return null;
4316
+ const n = Number(trimmed);
4317
+ return Number.isFinite(n) ? n : null;
4318
+ }
4319
+ function splitList(value) {
4320
+ return value.split(",").map((part) => norm(part)).filter((part) => part.length > 0);
4321
+ }
4322
+ function operandFor(condition, ctx) {
4323
+ switch (condition.source) {
4324
+ case "currency":
4325
+ return ctx.currency;
4326
+ case "amount":
4327
+ return String(ctx.amount);
4328
+ case "metadata":
4329
+ return Object.prototype.hasOwnProperty.call(ctx.metadata, condition.key) ? ctx.metadata[condition.key] : void 0;
4330
+ }
4331
+ }
4332
+ function evaluateCustomFieldCondition(condition, ctx) {
4333
+ const raw = operandFor(condition, ctx);
4334
+ const actual = raw ?? "";
4335
+ const expected = condition.value;
4336
+ switch (condition.operator) {
4337
+ case "exists":
4338
+ return raw !== void 0 && raw.trim().length > 0;
4339
+ case "not_exists":
4340
+ return raw === void 0 || raw.trim().length === 0;
4341
+ case "equals":
4342
+ return norm(actual) === norm(expected);
4343
+ case "not_equals":
4344
+ return norm(actual) !== norm(expected);
4345
+ case "contains":
4346
+ return norm(actual).includes(norm(expected));
4347
+ case "not_contains":
4348
+ return !norm(actual).includes(norm(expected));
4349
+ case "starts_with":
4350
+ return norm(actual).startsWith(norm(expected));
4351
+ case "ends_with":
4352
+ return norm(actual).endsWith(norm(expected));
4353
+ case "in":
4354
+ return splitList(expected).includes(norm(actual));
4355
+ case "not_in":
4356
+ return !splitList(expected).includes(norm(actual));
4357
+ case "gt":
4358
+ case "gte":
4359
+ case "lt":
4360
+ case "lte": {
4361
+ const a = numeric(actual);
4362
+ const b = numeric(expected);
4363
+ if (a === null || b === null) return false;
4364
+ if (condition.operator === "gt") return a > b;
4365
+ if (condition.operator === "gte") return a >= b;
4366
+ if (condition.operator === "lt") return a < b;
4367
+ return a <= b;
4368
+ }
4369
+ }
4370
+ }
4371
+ function evaluateCustomFieldVisibility(field, ctx) {
4372
+ const { mode, match, conditions } = field.visibility;
4373
+ if (mode !== "match" || conditions.length === 0) return true;
4374
+ return match === "any" ? conditions.some((c) => evaluateCustomFieldCondition(c, ctx)) : conditions.every((c) => evaluateCustomFieldCondition(c, ctx));
4375
+ }
4376
+ function visibleCustomFields(fields, ctx) {
4377
+ return fields.filter((f) => f.enabled && evaluateCustomFieldVisibility(f, ctx));
4378
+ }
4179
4379
  function translationFor(map, locale) {
4180
4380
  if (!locale) return null;
4181
4381
  const own = (k) => {
@@ -4553,6 +4753,8 @@ function shadowFor(style) {
4553
4753
  }
4554
4754
  // Annotate the CommonJS export names for ESM import in node:
4555
4755
  0 && (module.exports = {
4756
+ ALL_CUSTOM_FIELD_CONDITION_SOURCES,
4757
+ ALL_CUSTOM_FIELD_OPERATORS,
4556
4758
  ALL_CUSTOM_FIELD_TYPES,
4557
4759
  Analytics,
4558
4760
  AnalyticsDashboard,
@@ -4561,7 +4763,10 @@ function shadowFor(style) {
4561
4763
  BRANDING_EXPORT_VERSION,
4562
4764
  CUSTOM_CSS_MAX_LENGTH,
4563
4765
  CUSTOM_FIELDS_MAX,
4766
+ CUSTOM_FIELD_CONDITIONS_MAX,
4564
4767
  CUSTOM_FIELD_KEY_PATTERN,
4768
+ CUSTOM_FIELD_OPERATORS_BY_SOURCE,
4769
+ CUSTOM_FIELD_VALUELESS_OPERATORS,
4565
4770
  Cards,
4566
4771
  DEFAULT_BADGES,
4567
4772
  DEFAULT_BADGES_DARK,
@@ -4586,15 +4791,21 @@ function shadowFor(style) {
4586
4791
  buttonPadValue,
4587
4792
  cloneBranding,
4588
4793
  cloneCustomField,
4794
+ customFieldContextFromMetadata,
4795
+ customFieldOperatorTakesValue,
4589
4796
  customFieldOptionLabel,
4590
4797
  customFieldText,
4591
4798
  decodeBadges,
4592
4799
  decodeBranding,
4593
4800
  decodeCustomFields,
4594
4801
  defaultBranding,
4802
+ defaultCustomFieldVisibility,
4803
+ defaultOperatorForSource,
4595
4804
  encodeBadges,
4596
4805
  encodeBranding,
4597
4806
  encodeCustomFields,
4807
+ evaluateCustomFieldCondition,
4808
+ evaluateCustomFieldVisibility,
4598
4809
  feeProgram,
4599
4810
  fontStack,
4600
4811
  fontWeightValue,
@@ -4611,6 +4822,7 @@ function shadowFor(style) {
4611
4822
  sanitizeCustomCss,
4612
4823
  shadowFor,
4613
4824
  surfacePadValue,
4614
- verticalGapValue
4825
+ verticalGapValue,
4826
+ visibleCustomFields
4615
4827
  });
4616
4828
  //# sourceMappingURL=index.cjs.map