@namiml/sdk-core 3.4.12-dev.202609302156 → 3.4.12-dev.202610051759

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
@@ -106,7 +106,7 @@ const {
106
106
  // version — stamped by scripts/version.sh
107
107
  NAMI_SDK_VERSION: exports.NAMI_SDK_VERSION = "3.4.12",
108
108
  // full package version including dev suffix — stamped by scripts/version.sh
109
- NAMI_SDK_PACKAGE_VERSION: exports.NAMI_SDK_PACKAGE_VERSION = "3.4.12-dev.202609302156",
109
+ NAMI_SDK_PACKAGE_VERSION: exports.NAMI_SDK_PACKAGE_VERSION = "3.4.12-dev.202610051759",
110
110
  // environments
111
111
  PRODUCTION: exports.PRODUCTION = "production", DEVELOPMENT: exports.DEVELOPMENT = "development",
112
112
  // error messages
@@ -61301,6 +61301,168 @@ class SimpleEventTarget {
61301
61301
  }
61302
61302
  }
61303
61303
 
61304
+ /**
61305
+ * `${system.time.*}` Page conditions — the reference implementation of the cross-SDK contract in
61306
+ * `shared/time_conditions/README.md`, verified against `shared/time_conditions/vectors.json`.
61307
+ *
61308
+ * Every token resolves to the per-presentation snapshot instant; the zone lives on `expected`
61309
+ * (`Sunday@America/New_York`), so the instant is projected into that zone at comparison time and
61310
+ * the device zone and locale never matter. Invalid input fails closed: the assertion is `false`
61311
+ * for every operator, `notEquals` included.
61312
+ */
61313
+ const DAYS = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
61314
+ const TIME_OF_DAY = /^([01]?\d|2[0-3]):([0-5]\d)$/;
61315
+ const INSTANT = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2}(\.\d+)?)?(Z|[+-]\d{2}:\d{2})$/;
61316
+ const ORDERING = {
61317
+ equals: (a, b) => a === b,
61318
+ gt: (a, b) => a > b,
61319
+ gte: (a, b) => a >= b,
61320
+ lt: (a, b) => a < b,
61321
+ lte: (a, b) => a <= b,
61322
+ };
61323
+ const isOrderingOperator = (operator) => Object.prototype.hasOwnProperty.call(ORDERING, operator);
61324
+ /** True when `value` is a `${system.time.<leaf>}` token (any leaf; unknown leaves evaluate `false`). */
61325
+ const isSystemTimeAssertion = (assertion) => typeof assertion.value === "string" &&
61326
+ assertion.value.startsWith(exports.SYSTEM_TIME_TOKEN_PREFIX) &&
61327
+ assertion.value.endsWith("}");
61328
+ /** An ISO-8601 instant with a required offset, or `null`. */
61329
+ const parseInstant = (value) => {
61330
+ if (typeof value !== "string" || !INSTANT.test(value))
61331
+ return null;
61332
+ const date = new Date(value);
61333
+ return Number.isNaN(date.getTime()) ? null : date;
61334
+ };
61335
+ const isValidZone = (zone) => {
61336
+ if (!zone)
61337
+ return false;
61338
+ try {
61339
+ new Intl.DateTimeFormat("en-US", { timeZone: zone });
61340
+ return true;
61341
+ }
61342
+ catch {
61343
+ return false;
61344
+ }
61345
+ };
61346
+ /** Splits `<value>@<zone>` into its parts when there is exactly one `@` and the zone resolves. */
61347
+ const splitZoned = (expected) => {
61348
+ if (typeof expected !== "string")
61349
+ return null;
61350
+ const parts = expected.split("@");
61351
+ if (parts.length !== 2 || !parts[0] || !isValidZone(parts[1]))
61352
+ return null;
61353
+ return { value: parts[0], zone: parts[1] };
61354
+ };
61355
+ /** The snapshot seen in `zone`: English day name and minutes since local midnight. */
61356
+ const projectInZone = (now, zone) => {
61357
+ try {
61358
+ const [dayOfWeek, time] = formatInTimeZone(now, zone, "EEEE|HH:mm", { locale: enUS }).split("|");
61359
+ const [hours, minutes] = time.split(":").map(Number);
61360
+ return { dayOfWeek, minutes: hours * 60 + minutes };
61361
+ }
61362
+ catch {
61363
+ // Runtimes without Intl time-zone support (e.g. Hermes) fail closed.
61364
+ return null;
61365
+ }
61366
+ };
61367
+ const parseDay = (expected) => {
61368
+ const zoned = splitZoned(expected);
61369
+ return zoned && DAYS.includes(zoned.value) ? { day: zoned.value, zone: zoned.zone } : null;
61370
+ };
61371
+ const evaluateDayOfWeek = (operator, expected, now) => {
61372
+ const isDay = ({ day, zone }) => projectInZone(now, zone)?.dayOfWeek === day;
61373
+ if (operator === "in") {
61374
+ if (!Array.isArray(expected) || expected.length === 0)
61375
+ return false;
61376
+ const days = expected.map(parseDay);
61377
+ // Any invalid element invalidates the whole assertion, even when another element matches.
61378
+ if (days.some((day) => day === null))
61379
+ return false;
61380
+ return days.some((day) => isDay(day));
61381
+ }
61382
+ if (operator !== "equals" && operator !== "notEquals")
61383
+ return false;
61384
+ const day = parseDay(expected);
61385
+ if (!day)
61386
+ return false;
61387
+ const projected = projectInZone(now, day.zone);
61388
+ if (!projected)
61389
+ return false;
61390
+ return operator === "equals" ? projected.dayOfWeek === day.day : projected.dayOfWeek !== day.day;
61391
+ };
61392
+ const evaluateTimeOfDay = (operator, expected, now) => {
61393
+ if (!isOrderingOperator(operator))
61394
+ return false;
61395
+ const zoned = splitZoned(expected);
61396
+ const match = zoned && TIME_OF_DAY.exec(zoned.value);
61397
+ if (!zoned || !match)
61398
+ return false;
61399
+ const projected = projectInZone(now, zoned.zone);
61400
+ if (!projected)
61401
+ return false;
61402
+ return ORDERING[operator](projected.minutes, Number(match[1]) * 60 + Number(match[2]));
61403
+ };
61404
+ const evaluateNow = (operator, expected, now) => {
61405
+ if (!isOrderingOperator(operator))
61406
+ return false;
61407
+ const instant = parseInstant(expected);
61408
+ return instant !== null && ORDERING[operator](now.getTime(), instant.getTime());
61409
+ };
61410
+ /**
61411
+ * Evaluates a `${system.time.*}` assertion against the snapshot instant `now`.
61412
+ * Returns `null` when the assertion is not a time assertion, so callers fall through to their
61413
+ * existing evaluator; otherwise `true`/`false`, with every invalid input `false`.
61414
+ */
61415
+ const evaluateSystemTimeAssertion = (assertion, now) => {
61416
+ if (!isSystemTimeAssertion(assertion))
61417
+ return null;
61418
+ if (Number.isNaN(now.getTime()))
61419
+ return false;
61420
+ const leaf = assertion.value.slice(exports.SYSTEM_TIME_TOKEN_PREFIX.length, -1);
61421
+ switch (leaf) {
61422
+ case "dayOfWeek":
61423
+ return evaluateDayOfWeek(assertion.operator, assertion.expected, now);
61424
+ case "timeOfDay":
61425
+ return evaluateTimeOfDay(assertion.operator, assertion.expected, now);
61426
+ case "now":
61427
+ return evaluateNow(assertion.operator, assertion.expected, now);
61428
+ default:
61429
+ return false;
61430
+ }
61431
+ };
61432
+ /** Parses a `timeOverride=<ISO-8601 with offset>` namiCommand; `null` when it is not a valid one. */
61433
+ const parseTimeOverride = (command) => command.startsWith(exports.TIME_OVERRIDE_PREFIX) ? parseInstant(command.slice(exports.TIME_OVERRIDE_PREFIX.length)) : null;
61434
+ /**
61435
+ * The instant to snapshot for a Page or flow-screen presentation: the `timeOverride=` namiCommand
61436
+ * when present and valid, otherwise the device clock. Call it once per presentation.
61437
+ */
61438
+ const getSystemTimeNow = () => {
61439
+ const command = storageService
61440
+ .getNamiConfig()
61441
+ ?.namiCommands?.find((cmd) => cmd.startsWith(exports.TIME_OVERRIDE_PREFIX));
61442
+ if (command === undefined)
61443
+ return new Date();
61444
+ const override = parseTimeOverride(command);
61445
+ if (override === null) {
61446
+ logger.warn(`Ignoring invalid ${command}: expected ISO-8601 with an offset, e.g. ${exports.TIME_OVERRIDE_PREFIX}2026-09-13T13:00:00-04:00`);
61447
+ return new Date();
61448
+ }
61449
+ return override;
61450
+ };
61451
+ /**
61452
+ * Evaluates a Page assertion against a presentation's `PaywallState` snapshot
61453
+ * (`state.systemTimeSnapshot`, taken once in `PaywallState.setPaywall`). This is the one entry
61454
+ * point the core-based renderers (web, Expo/Vega) call ahead of their own operator switch.
61455
+ * Returns `null` for a non-time assertion, without touching the clock or the override; for a
61456
+ * state that was never presented it falls back to {@link getSystemTimeNow}.
61457
+ */
61458
+ const evaluateSystemTimeCondition = (assertion, state) => {
61459
+ if (!isSystemTimeAssertion(assertion))
61460
+ return null;
61461
+ const snapshot = state?.systemTimeSnapshot;
61462
+ const now = typeof snapshot === "number" && Number.isFinite(snapshot) ? new Date(snapshot) : getSystemTimeNow();
61463
+ return evaluateSystemTimeAssertion(assertion, now);
61464
+ };
61465
+
61304
61466
  let productDetails = [];
61305
61467
  function createEventWithDetail(name, payload) {
61306
61468
  if (typeof Event === 'function') {
@@ -61352,6 +61514,8 @@ const initialState = {
61352
61514
  darkMode: false,
61353
61515
  safeAreaTop: 0,
61354
61516
  safeAreaBottom: 0,
61517
+ safeAreaLeft: 0,
61518
+ safeAreaRight: 0,
61355
61519
  groups: [],
61356
61520
  selectedProducts: {},
61357
61521
  formStates: {},
@@ -61607,6 +61771,10 @@ class PaywallState extends SimpleEventTarget {
61607
61771
  // touching storage on the per-assertion render path. Assigned after the template's
61608
61772
  // initialState so an authored `platformId` cannot shadow the real one.
61609
61773
  state.platformId = storageService.getNamiConfig()?.appPlatformID ?? '';
61774
+ // NAM-4637: one instant per Page / flow-screen presentation for every `${system.time.*}`
61775
+ // condition, captured with `launch` and never re-read while the page stays up. Also after
61776
+ // the initialState spread, so authored data cannot pin it; `timeOverride=` can.
61777
+ state.systemTimeSnapshot = getSystemTimeNow().getTime();
61610
61778
  const launch = normalizeLaunchContext(state.launch, context, paywall.sku_menus);
61611
61779
  this.filteredSkuMenus = paywall.sku_menus ?? [];
61612
61780
  if (launch.productGroups.length) {
@@ -61723,6 +61891,12 @@ class PaywallState extends SimpleEventTarget {
61723
61891
  setSafeAreaBottom(safeAreaBottom) {
61724
61892
  this.setState({ ...this.state, safeAreaBottom });
61725
61893
  }
61894
+ setSafeAreaLeft(safeAreaLeft) {
61895
+ this.setState({ ...this.state, safeAreaLeft });
61896
+ }
61897
+ setSafeAreaRight(safeAreaRight) {
61898
+ this.setState({ ...this.state, safeAreaRight });
61899
+ }
61726
61900
  setFullScreenPresentation(fullScreenPresentation) {
61727
61901
  this.setState({ ...this.state, fullScreenPresentation });
61728
61902
  }
@@ -66416,154 +66590,6 @@ function resolveLoopSource(loopSource) {
66416
66590
  return [];
66417
66591
  }
66418
66592
 
66419
- /**
66420
- * `${system.time.*}` Page conditions — the reference implementation of the cross-SDK contract in
66421
- * `shared/time_conditions/README.md`, verified against `shared/time_conditions/vectors.json`.
66422
- *
66423
- * Every token resolves to the per-presentation snapshot instant; the zone lives on `expected`
66424
- * (`Sunday@America/New_York`), so the instant is projected into that zone at comparison time and
66425
- * the device zone and locale never matter. Invalid input fails closed: the assertion is `false`
66426
- * for every operator, `notEquals` included.
66427
- */
66428
- const DAYS = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
66429
- const TIME_OF_DAY = /^([01]?\d|2[0-3]):([0-5]\d)$/;
66430
- const INSTANT = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2}(\.\d+)?)?(Z|[+-]\d{2}:\d{2})$/;
66431
- const ORDERING = {
66432
- equals: (a, b) => a === b,
66433
- gt: (a, b) => a > b,
66434
- gte: (a, b) => a >= b,
66435
- lt: (a, b) => a < b,
66436
- lte: (a, b) => a <= b,
66437
- };
66438
- const isOrderingOperator = (operator) => Object.prototype.hasOwnProperty.call(ORDERING, operator);
66439
- /** True when `value` is a `${system.time.<leaf>}` token (any leaf; unknown leaves evaluate `false`). */
66440
- const isSystemTimeAssertion = (assertion) => typeof assertion.value === "string" &&
66441
- assertion.value.startsWith(exports.SYSTEM_TIME_TOKEN_PREFIX) &&
66442
- assertion.value.endsWith("}");
66443
- /** An ISO-8601 instant with a required offset, or `null`. */
66444
- const parseInstant = (value) => {
66445
- if (typeof value !== "string" || !INSTANT.test(value))
66446
- return null;
66447
- const date = new Date(value);
66448
- return Number.isNaN(date.getTime()) ? null : date;
66449
- };
66450
- const isValidZone = (zone) => {
66451
- if (!zone)
66452
- return false;
66453
- try {
66454
- new Intl.DateTimeFormat("en-US", { timeZone: zone });
66455
- return true;
66456
- }
66457
- catch {
66458
- return false;
66459
- }
66460
- };
66461
- /** Splits `<value>@<zone>` into its parts when there is exactly one `@` and the zone resolves. */
66462
- const splitZoned = (expected) => {
66463
- if (typeof expected !== "string")
66464
- return null;
66465
- const parts = expected.split("@");
66466
- if (parts.length !== 2 || !parts[0] || !isValidZone(parts[1]))
66467
- return null;
66468
- return { value: parts[0], zone: parts[1] };
66469
- };
66470
- /** The snapshot seen in `zone`: English day name and minutes since local midnight. */
66471
- const projectInZone = (now, zone) => {
66472
- try {
66473
- const [dayOfWeek, time] = formatInTimeZone(now, zone, "EEEE|HH:mm", { locale: enUS }).split("|");
66474
- const [hours, minutes] = time.split(":").map(Number);
66475
- return { dayOfWeek, minutes: hours * 60 + minutes };
66476
- }
66477
- catch {
66478
- // Runtimes without Intl time-zone support (e.g. Hermes) fail closed.
66479
- return null;
66480
- }
66481
- };
66482
- const parseDay = (expected) => {
66483
- const zoned = splitZoned(expected);
66484
- return zoned && DAYS.includes(zoned.value) ? { day: zoned.value, zone: zoned.zone } : null;
66485
- };
66486
- const evaluateDayOfWeek = (operator, expected, now) => {
66487
- const isDay = ({ day, zone }) => projectInZone(now, zone)?.dayOfWeek === day;
66488
- if (operator === "in") {
66489
- if (!Array.isArray(expected) || expected.length === 0)
66490
- return false;
66491
- const days = expected.map(parseDay);
66492
- // Any invalid element invalidates the whole assertion, even when another element matches.
66493
- if (days.some((day) => day === null))
66494
- return false;
66495
- return days.some((day) => isDay(day));
66496
- }
66497
- if (operator !== "equals" && operator !== "notEquals")
66498
- return false;
66499
- const day = parseDay(expected);
66500
- if (!day)
66501
- return false;
66502
- const projected = projectInZone(now, day.zone);
66503
- if (!projected)
66504
- return false;
66505
- return operator === "equals" ? projected.dayOfWeek === day.day : projected.dayOfWeek !== day.day;
66506
- };
66507
- const evaluateTimeOfDay = (operator, expected, now) => {
66508
- if (!isOrderingOperator(operator))
66509
- return false;
66510
- const zoned = splitZoned(expected);
66511
- const match = zoned && TIME_OF_DAY.exec(zoned.value);
66512
- if (!zoned || !match)
66513
- return false;
66514
- const projected = projectInZone(now, zoned.zone);
66515
- if (!projected)
66516
- return false;
66517
- return ORDERING[operator](projected.minutes, Number(match[1]) * 60 + Number(match[2]));
66518
- };
66519
- const evaluateNow = (operator, expected, now) => {
66520
- if (!isOrderingOperator(operator))
66521
- return false;
66522
- const instant = parseInstant(expected);
66523
- return instant !== null && ORDERING[operator](now.getTime(), instant.getTime());
66524
- };
66525
- /**
66526
- * Evaluates a `${system.time.*}` assertion against the snapshot instant `now`.
66527
- * Returns `null` when the assertion is not a time assertion, so callers fall through to their
66528
- * existing evaluator; otherwise `true`/`false`, with every invalid input `false`.
66529
- */
66530
- const evaluateSystemTimeAssertion = (assertion, now) => {
66531
- if (!isSystemTimeAssertion(assertion))
66532
- return null;
66533
- if (Number.isNaN(now.getTime()))
66534
- return false;
66535
- const leaf = assertion.value.slice(exports.SYSTEM_TIME_TOKEN_PREFIX.length, -1);
66536
- switch (leaf) {
66537
- case "dayOfWeek":
66538
- return evaluateDayOfWeek(assertion.operator, assertion.expected, now);
66539
- case "timeOfDay":
66540
- return evaluateTimeOfDay(assertion.operator, assertion.expected, now);
66541
- case "now":
66542
- return evaluateNow(assertion.operator, assertion.expected, now);
66543
- default:
66544
- return false;
66545
- }
66546
- };
66547
- /** Parses a `timeOverride=<ISO-8601 with offset>` namiCommand; `null` when it is not a valid one. */
66548
- const parseTimeOverride = (command) => command.startsWith(exports.TIME_OVERRIDE_PREFIX) ? parseInstant(command.slice(exports.TIME_OVERRIDE_PREFIX.length)) : null;
66549
- /**
66550
- * The instant to snapshot for a Page or flow-screen presentation: the `timeOverride=` namiCommand
66551
- * when present and valid, otherwise the device clock. Call it once per presentation.
66552
- */
66553
- const getSystemTimeNow = () => {
66554
- const command = storageService
66555
- .getNamiConfig()
66556
- ?.namiCommands?.find((cmd) => cmd.startsWith(exports.TIME_OVERRIDE_PREFIX));
66557
- if (command === undefined)
66558
- return new Date();
66559
- const override = parseTimeOverride(command);
66560
- if (override === null) {
66561
- logger.warn(`Ignoring invalid ${command}: expected ISO-8601 with an offset, e.g. ${exports.TIME_OVERRIDE_PREFIX}2026-09-13T13:00:00-04:00`);
66562
- return new Date();
66563
- }
66564
- return override;
66565
- };
66566
-
66567
66593
  /**
66568
66594
  * Components that are skipped entirely (they and their subtree do not
66569
66595
  * contribute text to the page-level announcement).
@@ -66927,6 +66953,7 @@ exports.currentSku = currentSku;
66927
66953
  exports.didReceiveResponse = didReceiveResponse;
66928
66954
  exports.empty = empty;
66929
66955
  exports.evaluateSystemTimeAssertion = evaluateSystemTimeAssertion;
66956
+ exports.evaluateSystemTimeCondition = evaluateSystemTimeCondition;
66930
66957
  exports.extractStandardPricingPhases = extractStandardPricingPhases;
66931
66958
  exports.formatDate = formatDate;
66932
66959
  exports.formattedPrice = formattedPrice;
package/dist/index.d.ts CHANGED
@@ -1836,6 +1836,8 @@ type TPaywallContext = TInitialState & {
1836
1836
  anySkuHasPromoOffer: boolean;
1837
1837
  safeAreaTop: number;
1838
1838
  safeAreaBottom: number;
1839
+ safeAreaLeft: number;
1840
+ safeAreaRight: number;
1839
1841
  slides?: TCarouselSlidesState;
1840
1842
  currentPage: string;
1841
1843
  pageHistory: string[];
@@ -1845,6 +1847,11 @@ type TPaywallContext = TInitialState & {
1845
1847
  orientation: TDeviceOrientation;
1846
1848
  focusedState: boolean;
1847
1849
  platformId: string;
1850
+ /**
1851
+ * Epoch ms every `${system.time.*}` condition on this presentation evaluates against
1852
+ * (NAM-4637). Taken once in `PaywallState.setPaywall`; `timeOverride=` pins it.
1853
+ */
1854
+ systemTimeSnapshot?: number;
1848
1855
  mediaList: {
1849
1856
  [key: string]: any;
1850
1857
  };
@@ -2575,6 +2582,8 @@ declare class PaywallState extends SimpleEventTarget {
2575
2582
  setMediaList(media: TPaywallMedia[]): void;
2576
2583
  setSafeAreaTop(safeAreaTop: number): void;
2577
2584
  setSafeAreaBottom(safeAreaBottom: number): void;
2585
+ setSafeAreaLeft(safeAreaLeft: number): void;
2586
+ setSafeAreaRight(safeAreaRight: number): void;
2578
2587
  setFullScreenPresentation(fullScreenPresentation: boolean): void;
2579
2588
  setFormFactor(formFactor: TDevice): void;
2580
2589
  getFormFactor(): TDevice;
@@ -3334,6 +3343,16 @@ declare const parseTimeOverride: (command: string) => Date | null;
3334
3343
  * when present and valid, otherwise the device clock. Call it once per presentation.
3335
3344
  */
3336
3345
  declare const getSystemTimeNow: () => Date;
3346
+ /**
3347
+ * Evaluates a Page assertion against a presentation's `PaywallState` snapshot
3348
+ * (`state.systemTimeSnapshot`, taken once in `PaywallState.setPaywall`). This is the one entry
3349
+ * point the core-based renderers (web, Expo/Vega) call ahead of their own operator switch.
3350
+ * Returns `null` for a non-time assertion, without touching the clock or the override; for a
3351
+ * state that was never presented it falls back to {@link getSystemTimeNow}.
3352
+ */
3353
+ declare const evaluateSystemTimeCondition: (assertion: TTestObject, state: {
3354
+ systemTimeSnapshot?: number;
3355
+ } | undefined) => boolean | null;
3337
3356
 
3338
3357
  declare const getUrlParams: () => Record<string, string>;
3339
3358
 
@@ -4383,5 +4402,5 @@ declare namespace internal {
4383
4402
  };
4384
4403
  }
4385
4404
 
4386
- export { ALREADY_CONFIGURED, ANONYMOUS_MODE, ANONYMOUS_MODE_ALREADY_OFF, ANONYMOUS_MODE_ALREADY_ON, ANONYMOUS_MODE_LOGIN_NOT_ALLOWED, ANONYMOUS_UUID, APIError, API_ACTIVE_ENTITLEMENTS, API_CAMPAIGN_RULES, API_CAMPAIGN_SESSION_TIMESTAMP, API_CONFIG, API_MAX_CALLS_LIMIT, API_PAYWALLS, API_PRODUCTS, API_RETRY_DELAY_SEC, API_TIMEOUT_LIMIT, API_TRAFFIC_OBSERVER, API_VERSION, AUTH_DEVICE, AVAILABLE_ACTIVE_ENTITLEMENTS_CHANGED, AVAILABLE_CAMPAIGNS_CHANGED, AccountStateAction, AnonymousCDPError, AnonymousLoginError, AnonymousModeAlreadyOffError, AnonymousModeAlreadyOnError, BASE_STAGING_URL, BASE_URL, BASE_URL_PATH, BadRequestError, BasicNamiFlow, BorderMap, BorderSideMap, CAMPAIGN_CACHE_TTL_PREFIX, CAMPAIGN_NOT_AVAILABLE, CONFIG_API_TIMEOUT_LIMIT, CONFIG_MAX_ATTEMPTS, CUSTOMER_ATTRIBUTES_KEY_PREFIX, CUSTOMER_JOURNEY_STATE_CHANGED, CUSTOM_HOST_PREFIX, CampaignNotAvailableError, CampaignRuleConversionEventType, CampaignRuleRepository, Capabilities, ClientError, ConfigRepository, ConflictError, CustomerJourneyRepository, DEFAULT_JOURNEY_SETTINGS, DEVELOPMENT, DEVICE_API_TIMEOUT_LIMIT, DEVICE_ID_NOT_SET, DEVICE_ID_REQUIRED, DISABLE_ASYNC_LOGIN_LOGOUT, DeviceIDRequiredError, DeviceRepository, EXTENDED_CLIENT_INFO_DELIMITER, EXTENDED_CLIENT_INFO_PREFIX, EXTENDED_PLATFORM, EXTENDED_PLATFORM_VERSION, EXTERNAL_ID_REQUIRED, EntitlementRepository, EntitlementUtils, ExternalIDRequiredError, FLOW_SCREENS_NOT_AVAILABLE, FlowScreensNotAvailableError, HTML_REGEX, INITIAL_APP_CONFIG, INITIAL_CAMPAIGN_RULES, INITIAL_PAYWALLS, INITIAL_PRODUCTS, INITIAL_SESSION_COUNTER_VALUE, INITIAL_SUCCESS, InternalServerError, KEY_SESSION_COUNTER, LIQUID_VARIABLE_REGEX, LOCAL_NAMI_ENTITLEMENTS, LOG_HTTP_REQUESTS, LOG_HTTP_TRAFFIC, LaunchCampaignError, LaunchContextResolver, LogLevel, NAMI_CONFIGURATION, NAMI_CUSTOMER_JOURNEY_STATE, NAMI_LANGUAGE_CODE, NAMI_LAST_IMPRESSION_ID, NAMI_LAUNCH_ID, NAMI_PROFILE, NAMI_PURCHASE_CHANNEL, NAMI_PURCHASE_IMPRESSION_ID, NAMI_SDK_PACKAGE_VERSION, NAMI_SDK_VERSION, NAMI_SESSION_ID, NAMI_STORAGE_KEYS, Nami, NamiAPI, NamiAnimationType, NamiCampaignManager$2 as NamiCampaignManager, NamiCampaignRuleType, NamiConditionEvaluator, NamiCustomerManager$2 as NamiCustomerManager, NamiEntitlementManager$2 as NamiEntitlementManager, NamiEventEmitter, NamiFlow, NamiFlowActionFunction, NamiFlowManager$1 as NamiFlowManager, NamiFlowStepType, NamiHandoffTag, NamiPaywallAction, NamiPaywallManager$2 as NamiPaywallManager, PaywallManagerEvents as NamiPaywallManagerEvents, NamiPermissionOutcome, NamiPurchaseManager$2 as NamiPurchaseManager, NamiRefs, NamiReservedActions, NotFoundError, PAYWALL_ACTION_EVENT, PLATFORM_ID_REQUIRED, PRODUCTION, PaywallManagerEvents, PaywallRepository, PaywallState, PlacementLabelResolver, PlatformIDRequiredError, ProductRepository, RECONFIG_SUCCESS, RESUME_THROTTLE_MS, RetryLimitExceededError, SDKNotInitializedError, SDK_NOT_INITIALIZED, SERVER_NAMI_ENTITLEMENTS, SESSION_REQUIRED, SHOULD_SHOW_LOADING_INDICATOR, SIMULATE_CONFIG_FETCH_FAILURE, SIMULATE_PAYWALL_FETCH_FAILURE, SKU_TEXT_REGEX, SMART_TEXT_PATTERN, STARTUP_TELEMETRY, STATUS_BAD_REQUEST, STATUS_CONFLICT, STATUS_INTERNAL_SERVER_ERROR, STATUS_NOT_FOUND, STATUS_SUCCESS, SYSTEM_TIME_TOKEN_PREFIX, SessionService, SimpleEventTarget, StorageService, TIME_OVERRIDE_PREFIX, TRANSPORT_FAILURE_STATUS, UNABLE_TO_UPDATE_CDP_ID, USE_STAGING_API, VALIDATE_PRODUCT_GROUPS, VAR_REGEX, NamiProfileManager$1 as _NamiProfileManager, internal as _internal, activateEntitlementByPurchase, activeEntitlements, aggregateScreenreaderText, allCampaigns, allPaywalls, applyEntitlementActivation, audienceSplitPosition, bestUrlCampaignMatch, bigintToUuid, checkAnySkuHasPromoOffer, checkAnySkuHasTrialOffer, convertISO8601PeriodToText, convertLocale, convertOfferToPricingPhase, createNamiEntitlements, currentSku, didReceiveResponse, empty, evaluateSystemTimeAssertion, extractStandardPricingPhases, formatDate, formattedPrice, generateUUID, getApiCampaigns, getApiPaywalls, getBaseUrl, getBillingPeriodNumber, getCurrencyFormat, getDeviceData, getDeviceFormFactor, getDeviceScaleFactor, getEffectiveWebStyle, getEntitlementRefIdsForSku, getExtendedClientInfo, getFreeTrialPeriod, getInitialCampaigns, getInitialPaywalls, getJourneySettings, getPaywall, getPaywallDataFromLabel, getPercentagePriceDifference, getPeriodNumberInDays, getPeriodNumberInWeeks, getPlatformAdapters, getPriceDifference, getPricePerMonth, getProductDetail, getPurchaseAdapter, getReferenceSku, getSkuProductDetailKeys, getSkuSmartTextValue, getSlideSmartTextValue, getStandardBillingPeriod, getSystemTimeNow, getTranslate, getUrlParams, handleErrors, hasAllPaywalls, hasCapability, hasPurchaseManagement, initialState, invokeHandler, isAnonymousMode, isInitialConfigCompressed, isNamiFlowCampaign, isSubscription, isSystemTimeAssertion, isValidISODate, isValidUrl, logger, mapAnonymousCampaigns, namiBuySKU, normalizeLaunchContext, parseTimeOverride, parseToSemver, postConversion, productDetail, registerAPITrafficObserver, registerPlatformAdapters, registerPurchaseAdapter, resolveLoopSource, selectSegment, setActiveNamiEntitlements, shouldValidateProductGroups, skuItems, skuMapFromEntitlements, storageService, toDouble, toNamiEntitlements, toNamiSKU, tryParseB64Gzip, tryParseJson, updateRelatedSKUsForNamiEntitlement, uuidFromSplitPosition, validateForm, validateMinSDKVersion, validateTextInput };
4405
+ export { ALREADY_CONFIGURED, ANONYMOUS_MODE, ANONYMOUS_MODE_ALREADY_OFF, ANONYMOUS_MODE_ALREADY_ON, ANONYMOUS_MODE_LOGIN_NOT_ALLOWED, ANONYMOUS_UUID, APIError, API_ACTIVE_ENTITLEMENTS, API_CAMPAIGN_RULES, API_CAMPAIGN_SESSION_TIMESTAMP, API_CONFIG, API_MAX_CALLS_LIMIT, API_PAYWALLS, API_PRODUCTS, API_RETRY_DELAY_SEC, API_TIMEOUT_LIMIT, API_TRAFFIC_OBSERVER, API_VERSION, AUTH_DEVICE, AVAILABLE_ACTIVE_ENTITLEMENTS_CHANGED, AVAILABLE_CAMPAIGNS_CHANGED, AccountStateAction, AnonymousCDPError, AnonymousLoginError, AnonymousModeAlreadyOffError, AnonymousModeAlreadyOnError, BASE_STAGING_URL, BASE_URL, BASE_URL_PATH, BadRequestError, BasicNamiFlow, BorderMap, BorderSideMap, CAMPAIGN_CACHE_TTL_PREFIX, CAMPAIGN_NOT_AVAILABLE, CONFIG_API_TIMEOUT_LIMIT, CONFIG_MAX_ATTEMPTS, CUSTOMER_ATTRIBUTES_KEY_PREFIX, CUSTOMER_JOURNEY_STATE_CHANGED, CUSTOM_HOST_PREFIX, CampaignNotAvailableError, CampaignRuleConversionEventType, CampaignRuleRepository, Capabilities, ClientError, ConfigRepository, ConflictError, CustomerJourneyRepository, DEFAULT_JOURNEY_SETTINGS, DEVELOPMENT, DEVICE_API_TIMEOUT_LIMIT, DEVICE_ID_NOT_SET, DEVICE_ID_REQUIRED, DISABLE_ASYNC_LOGIN_LOGOUT, DeviceIDRequiredError, DeviceRepository, EXTENDED_CLIENT_INFO_DELIMITER, EXTENDED_CLIENT_INFO_PREFIX, EXTENDED_PLATFORM, EXTENDED_PLATFORM_VERSION, EXTERNAL_ID_REQUIRED, EntitlementRepository, EntitlementUtils, ExternalIDRequiredError, FLOW_SCREENS_NOT_AVAILABLE, FlowScreensNotAvailableError, HTML_REGEX, INITIAL_APP_CONFIG, INITIAL_CAMPAIGN_RULES, INITIAL_PAYWALLS, INITIAL_PRODUCTS, INITIAL_SESSION_COUNTER_VALUE, INITIAL_SUCCESS, InternalServerError, KEY_SESSION_COUNTER, LIQUID_VARIABLE_REGEX, LOCAL_NAMI_ENTITLEMENTS, LOG_HTTP_REQUESTS, LOG_HTTP_TRAFFIC, LaunchCampaignError, LaunchContextResolver, LogLevel, NAMI_CONFIGURATION, NAMI_CUSTOMER_JOURNEY_STATE, NAMI_LANGUAGE_CODE, NAMI_LAST_IMPRESSION_ID, NAMI_LAUNCH_ID, NAMI_PROFILE, NAMI_PURCHASE_CHANNEL, NAMI_PURCHASE_IMPRESSION_ID, NAMI_SDK_PACKAGE_VERSION, NAMI_SDK_VERSION, NAMI_SESSION_ID, NAMI_STORAGE_KEYS, Nami, NamiAPI, NamiAnimationType, NamiCampaignManager$2 as NamiCampaignManager, NamiCampaignRuleType, NamiConditionEvaluator, NamiCustomerManager$2 as NamiCustomerManager, NamiEntitlementManager$2 as NamiEntitlementManager, NamiEventEmitter, NamiFlow, NamiFlowActionFunction, NamiFlowManager$1 as NamiFlowManager, NamiFlowStepType, NamiHandoffTag, NamiPaywallAction, NamiPaywallManager$2 as NamiPaywallManager, PaywallManagerEvents as NamiPaywallManagerEvents, NamiPermissionOutcome, NamiPurchaseManager$2 as NamiPurchaseManager, NamiRefs, NamiReservedActions, NotFoundError, PAYWALL_ACTION_EVENT, PLATFORM_ID_REQUIRED, PRODUCTION, PaywallManagerEvents, PaywallRepository, PaywallState, PlacementLabelResolver, PlatformIDRequiredError, ProductRepository, RECONFIG_SUCCESS, RESUME_THROTTLE_MS, RetryLimitExceededError, SDKNotInitializedError, SDK_NOT_INITIALIZED, SERVER_NAMI_ENTITLEMENTS, SESSION_REQUIRED, SHOULD_SHOW_LOADING_INDICATOR, SIMULATE_CONFIG_FETCH_FAILURE, SIMULATE_PAYWALL_FETCH_FAILURE, SKU_TEXT_REGEX, SMART_TEXT_PATTERN, STARTUP_TELEMETRY, STATUS_BAD_REQUEST, STATUS_CONFLICT, STATUS_INTERNAL_SERVER_ERROR, STATUS_NOT_FOUND, STATUS_SUCCESS, SYSTEM_TIME_TOKEN_PREFIX, SessionService, SimpleEventTarget, StorageService, TIME_OVERRIDE_PREFIX, TRANSPORT_FAILURE_STATUS, UNABLE_TO_UPDATE_CDP_ID, USE_STAGING_API, VALIDATE_PRODUCT_GROUPS, VAR_REGEX, NamiProfileManager$1 as _NamiProfileManager, internal as _internal, activateEntitlementByPurchase, activeEntitlements, aggregateScreenreaderText, allCampaigns, allPaywalls, applyEntitlementActivation, audienceSplitPosition, bestUrlCampaignMatch, bigintToUuid, checkAnySkuHasPromoOffer, checkAnySkuHasTrialOffer, convertISO8601PeriodToText, convertLocale, convertOfferToPricingPhase, createNamiEntitlements, currentSku, didReceiveResponse, empty, evaluateSystemTimeAssertion, evaluateSystemTimeCondition, extractStandardPricingPhases, formatDate, formattedPrice, generateUUID, getApiCampaigns, getApiPaywalls, getBaseUrl, getBillingPeriodNumber, getCurrencyFormat, getDeviceData, getDeviceFormFactor, getDeviceScaleFactor, getEffectiveWebStyle, getEntitlementRefIdsForSku, getExtendedClientInfo, getFreeTrialPeriod, getInitialCampaigns, getInitialPaywalls, getJourneySettings, getPaywall, getPaywallDataFromLabel, getPercentagePriceDifference, getPeriodNumberInDays, getPeriodNumberInWeeks, getPlatformAdapters, getPriceDifference, getPricePerMonth, getProductDetail, getPurchaseAdapter, getReferenceSku, getSkuProductDetailKeys, getSkuSmartTextValue, getSlideSmartTextValue, getStandardBillingPeriod, getSystemTimeNow, getTranslate, getUrlParams, handleErrors, hasAllPaywalls, hasCapability, hasPurchaseManagement, initialState, invokeHandler, isAnonymousMode, isInitialConfigCompressed, isNamiFlowCampaign, isSubscription, isSystemTimeAssertion, isValidISODate, isValidUrl, logger, mapAnonymousCampaigns, namiBuySKU, normalizeLaunchContext, parseTimeOverride, parseToSemver, postConversion, productDetail, registerAPITrafficObserver, registerPlatformAdapters, registerPurchaseAdapter, resolveLoopSource, selectSegment, setActiveNamiEntitlements, shouldValidateProductGroups, skuItems, skuMapFromEntitlements, storageService, toDouble, toNamiEntitlements, toNamiSKU, tryParseB64Gzip, tryParseJson, updateRelatedSKUsForNamiEntitlement, uuidFromSplitPosition, validateForm, validateMinSDKVersion, validateTextInput };
4387
4406
  export type { AccountStateHandler$1 as AccountStateHandler, AlignmentType, AmazonProduct, ApiResponse, AppleProduct, AvailableCampaignsResponseHandler, BorderLocationType, BorderSideType, Callback$1 as Callback, CloseHandler, CustomerJourneyState, DeepLinkUrlHandler, Device, DevicePayload, DeviceProfile, DirectionType, ExtendedPlatformInfo, FlexDirectionObject, FlowNavigationOptions, FontCollection, FontDetails, FormFactor, FormFieldValidator, GoogleProduct, IConfig, IDeviceAdapter, IEntitlements$1 as IEntitlements, IPaywall, IPlatformAdapters, IProductsWithComponents, IPurchaseAdapter, ISkuMenu, IStorageAdapter, IUIAdapter, Impression, InitialConfig, InitialConfigCompressed, InitiateStateGroup, JourneySettings, LoginResponse, NamiAPITrafficKind, NamiAPITrafficObserver, NamiAPITrafficRecord, NamiAnimation, NamiAnimationObjectSpec, NamiAnimationSpec, NamiAnonymousCampaign, NamiAppSuppliedVideoDetails, NamiCampaign, NamiCampaignManagerStatic, NamiCampaignSegment, NamiCompletionResult, NamiConfiguration, NamiConfigurationState, NamiCustomAttributeValue, NamiCustomerManagerStatic, NamiEntitlement$1 as NamiEntitlement, NamiEntitlementManagerStatic, NamiFlowAction, NamiFlowAnimation, NamiFlowCampaign, NamiFlowCompletionCondition, NamiFlowDTO, NamiFlowEventHandler, NamiFlowHandoffStepHandler, NamiFlowManagerStatic, NamiFlowObjectDTO, NamiFlowOn, NamiFlowStep, NamiFlowTransition, NamiFlowTransitionDirection, NamiFlowWithObject, NamiHandoffAttributeValue, NamiHandoffComplete, NamiHandoffOutcome, NamiHandoffTagValue, NamiInitialConfig, NamiKnownHandoffTag, NamiLanguageCodes, NamiLogLevel, NamiLoginSuccess, NamiPaywallActionHandler, NamiPaywallComponentChange, NamiPaywallEvent, NamiPaywallEventVideoMetadata, NamiPaywallLaunchContext, NamiPaywallManagerStatic, NamiPresentationStyle, NamiProductDetails, NamiProductOffer, NamiProfile, NamiPurchase, NamiPurchaseCompleteResult, NamiPurchaseDetails, NamiPurchaseManagerStatic, NamiPurchaseSuccess, NamiPurchasesState, NamiSKU, NamiSKUType, NamiSubscriptionInterval, NamiSubscriptionPeriod, NamiUserDataEnvelope, None, NoneSpec, PaywallActionEvent, PaywallHandle, PaywallResultHandler, PaywallSKU, PricingPhase, ProductGroup, Pulse, PulseSpec, PurchaseContext, PurchaseResult, PurchaseValidationRequest, SKU, SKUActionHandler, ScreenInfo, Session, TBaseComponent, TButtonContainer, TCarouselContainer, TCarouselSlide, TCarouselSlidesState, TCollapseContainer, TComponent, TConditionalAttributes, TConditionalComponent, TContainer, TContainerPosition, TCountdownTimerTextComponent, TDevice, TDisabledButton, TField, TFieldSettings, TFlexProductContainer, THeaderFooter, TImageComponent, TInitialState, TMediaTypes, TOffer, TPages, TPaywallContext, TPaywallLaunchContext, TPaywallMedia, TPaywallTemplate, TPlayPauseButton, TProductContainer, TProductGroup, TProgressBarComponent, TProgressIndicatorComponent, TQRCodeComponent, TRadioButton, TRepeatingGrid, TResponsiveGrid, TSegmentPicker, TSegmentPickerItem, TSemverObj, TSlot, TSlotGroupSelector, TSpacerComponent, TStack, TSvgImageComponent, TSymbolComponent, TTestObject, TTextComponent, TTextInputComponent, TTextInputType, TTextLikeComponent, TTextListComponent, TTimelineRail, TToggleButtonComponent, TToggleSwitch, TVariablePattern, TVideoComponent, TVolumeButton, TimerState, TransactionRequest, UserAction, UserActionParameters, Wave, WaveSpec };
package/dist/index.mjs CHANGED
@@ -104,7 +104,7 @@ const {
104
104
  // version — stamped by scripts/version.sh
105
105
  NAMI_SDK_VERSION = "3.4.12",
106
106
  // full package version including dev suffix — stamped by scripts/version.sh
107
- NAMI_SDK_PACKAGE_VERSION = "3.4.12-dev.202609302156",
107
+ NAMI_SDK_PACKAGE_VERSION = "3.4.12-dev.202610051759",
108
108
  // environments
109
109
  PRODUCTION = "production", DEVELOPMENT = "development",
110
110
  // error messages
@@ -61299,6 +61299,168 @@ class SimpleEventTarget {
61299
61299
  }
61300
61300
  }
61301
61301
 
61302
+ /**
61303
+ * `${system.time.*}` Page conditions — the reference implementation of the cross-SDK contract in
61304
+ * `shared/time_conditions/README.md`, verified against `shared/time_conditions/vectors.json`.
61305
+ *
61306
+ * Every token resolves to the per-presentation snapshot instant; the zone lives on `expected`
61307
+ * (`Sunday@America/New_York`), so the instant is projected into that zone at comparison time and
61308
+ * the device zone and locale never matter. Invalid input fails closed: the assertion is `false`
61309
+ * for every operator, `notEquals` included.
61310
+ */
61311
+ const DAYS = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
61312
+ const TIME_OF_DAY = /^([01]?\d|2[0-3]):([0-5]\d)$/;
61313
+ const INSTANT = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2}(\.\d+)?)?(Z|[+-]\d{2}:\d{2})$/;
61314
+ const ORDERING = {
61315
+ equals: (a, b) => a === b,
61316
+ gt: (a, b) => a > b,
61317
+ gte: (a, b) => a >= b,
61318
+ lt: (a, b) => a < b,
61319
+ lte: (a, b) => a <= b,
61320
+ };
61321
+ const isOrderingOperator = (operator) => Object.prototype.hasOwnProperty.call(ORDERING, operator);
61322
+ /** True when `value` is a `${system.time.<leaf>}` token (any leaf; unknown leaves evaluate `false`). */
61323
+ const isSystemTimeAssertion = (assertion) => typeof assertion.value === "string" &&
61324
+ assertion.value.startsWith(SYSTEM_TIME_TOKEN_PREFIX) &&
61325
+ assertion.value.endsWith("}");
61326
+ /** An ISO-8601 instant with a required offset, or `null`. */
61327
+ const parseInstant = (value) => {
61328
+ if (typeof value !== "string" || !INSTANT.test(value))
61329
+ return null;
61330
+ const date = new Date(value);
61331
+ return Number.isNaN(date.getTime()) ? null : date;
61332
+ };
61333
+ const isValidZone = (zone) => {
61334
+ if (!zone)
61335
+ return false;
61336
+ try {
61337
+ new Intl.DateTimeFormat("en-US", { timeZone: zone });
61338
+ return true;
61339
+ }
61340
+ catch {
61341
+ return false;
61342
+ }
61343
+ };
61344
+ /** Splits `<value>@<zone>` into its parts when there is exactly one `@` and the zone resolves. */
61345
+ const splitZoned = (expected) => {
61346
+ if (typeof expected !== "string")
61347
+ return null;
61348
+ const parts = expected.split("@");
61349
+ if (parts.length !== 2 || !parts[0] || !isValidZone(parts[1]))
61350
+ return null;
61351
+ return { value: parts[0], zone: parts[1] };
61352
+ };
61353
+ /** The snapshot seen in `zone`: English day name and minutes since local midnight. */
61354
+ const projectInZone = (now, zone) => {
61355
+ try {
61356
+ const [dayOfWeek, time] = formatInTimeZone(now, zone, "EEEE|HH:mm", { locale: enUS }).split("|");
61357
+ const [hours, minutes] = time.split(":").map(Number);
61358
+ return { dayOfWeek, minutes: hours * 60 + minutes };
61359
+ }
61360
+ catch {
61361
+ // Runtimes without Intl time-zone support (e.g. Hermes) fail closed.
61362
+ return null;
61363
+ }
61364
+ };
61365
+ const parseDay = (expected) => {
61366
+ const zoned = splitZoned(expected);
61367
+ return zoned && DAYS.includes(zoned.value) ? { day: zoned.value, zone: zoned.zone } : null;
61368
+ };
61369
+ const evaluateDayOfWeek = (operator, expected, now) => {
61370
+ const isDay = ({ day, zone }) => projectInZone(now, zone)?.dayOfWeek === day;
61371
+ if (operator === "in") {
61372
+ if (!Array.isArray(expected) || expected.length === 0)
61373
+ return false;
61374
+ const days = expected.map(parseDay);
61375
+ // Any invalid element invalidates the whole assertion, even when another element matches.
61376
+ if (days.some((day) => day === null))
61377
+ return false;
61378
+ return days.some((day) => isDay(day));
61379
+ }
61380
+ if (operator !== "equals" && operator !== "notEquals")
61381
+ return false;
61382
+ const day = parseDay(expected);
61383
+ if (!day)
61384
+ return false;
61385
+ const projected = projectInZone(now, day.zone);
61386
+ if (!projected)
61387
+ return false;
61388
+ return operator === "equals" ? projected.dayOfWeek === day.day : projected.dayOfWeek !== day.day;
61389
+ };
61390
+ const evaluateTimeOfDay = (operator, expected, now) => {
61391
+ if (!isOrderingOperator(operator))
61392
+ return false;
61393
+ const zoned = splitZoned(expected);
61394
+ const match = zoned && TIME_OF_DAY.exec(zoned.value);
61395
+ if (!zoned || !match)
61396
+ return false;
61397
+ const projected = projectInZone(now, zoned.zone);
61398
+ if (!projected)
61399
+ return false;
61400
+ return ORDERING[operator](projected.minutes, Number(match[1]) * 60 + Number(match[2]));
61401
+ };
61402
+ const evaluateNow = (operator, expected, now) => {
61403
+ if (!isOrderingOperator(operator))
61404
+ return false;
61405
+ const instant = parseInstant(expected);
61406
+ return instant !== null && ORDERING[operator](now.getTime(), instant.getTime());
61407
+ };
61408
+ /**
61409
+ * Evaluates a `${system.time.*}` assertion against the snapshot instant `now`.
61410
+ * Returns `null` when the assertion is not a time assertion, so callers fall through to their
61411
+ * existing evaluator; otherwise `true`/`false`, with every invalid input `false`.
61412
+ */
61413
+ const evaluateSystemTimeAssertion = (assertion, now) => {
61414
+ if (!isSystemTimeAssertion(assertion))
61415
+ return null;
61416
+ if (Number.isNaN(now.getTime()))
61417
+ return false;
61418
+ const leaf = assertion.value.slice(SYSTEM_TIME_TOKEN_PREFIX.length, -1);
61419
+ switch (leaf) {
61420
+ case "dayOfWeek":
61421
+ return evaluateDayOfWeek(assertion.operator, assertion.expected, now);
61422
+ case "timeOfDay":
61423
+ return evaluateTimeOfDay(assertion.operator, assertion.expected, now);
61424
+ case "now":
61425
+ return evaluateNow(assertion.operator, assertion.expected, now);
61426
+ default:
61427
+ return false;
61428
+ }
61429
+ };
61430
+ /** Parses a `timeOverride=<ISO-8601 with offset>` namiCommand; `null` when it is not a valid one. */
61431
+ const parseTimeOverride = (command) => command.startsWith(TIME_OVERRIDE_PREFIX) ? parseInstant(command.slice(TIME_OVERRIDE_PREFIX.length)) : null;
61432
+ /**
61433
+ * The instant to snapshot for a Page or flow-screen presentation: the `timeOverride=` namiCommand
61434
+ * when present and valid, otherwise the device clock. Call it once per presentation.
61435
+ */
61436
+ const getSystemTimeNow = () => {
61437
+ const command = storageService
61438
+ .getNamiConfig()
61439
+ ?.namiCommands?.find((cmd) => cmd.startsWith(TIME_OVERRIDE_PREFIX));
61440
+ if (command === undefined)
61441
+ return new Date();
61442
+ const override = parseTimeOverride(command);
61443
+ if (override === null) {
61444
+ logger.warn(`Ignoring invalid ${command}: expected ISO-8601 with an offset, e.g. ${TIME_OVERRIDE_PREFIX}2026-09-13T13:00:00-04:00`);
61445
+ return new Date();
61446
+ }
61447
+ return override;
61448
+ };
61449
+ /**
61450
+ * Evaluates a Page assertion against a presentation's `PaywallState` snapshot
61451
+ * (`state.systemTimeSnapshot`, taken once in `PaywallState.setPaywall`). This is the one entry
61452
+ * point the core-based renderers (web, Expo/Vega) call ahead of their own operator switch.
61453
+ * Returns `null` for a non-time assertion, without touching the clock or the override; for a
61454
+ * state that was never presented it falls back to {@link getSystemTimeNow}.
61455
+ */
61456
+ const evaluateSystemTimeCondition = (assertion, state) => {
61457
+ if (!isSystemTimeAssertion(assertion))
61458
+ return null;
61459
+ const snapshot = state?.systemTimeSnapshot;
61460
+ const now = typeof snapshot === "number" && Number.isFinite(snapshot) ? new Date(snapshot) : getSystemTimeNow();
61461
+ return evaluateSystemTimeAssertion(assertion, now);
61462
+ };
61463
+
61302
61464
  let productDetails = [];
61303
61465
  function createEventWithDetail(name, payload) {
61304
61466
  if (typeof Event === 'function') {
@@ -61350,6 +61512,8 @@ const initialState = {
61350
61512
  darkMode: false,
61351
61513
  safeAreaTop: 0,
61352
61514
  safeAreaBottom: 0,
61515
+ safeAreaLeft: 0,
61516
+ safeAreaRight: 0,
61353
61517
  groups: [],
61354
61518
  selectedProducts: {},
61355
61519
  formStates: {},
@@ -61605,6 +61769,10 @@ class PaywallState extends SimpleEventTarget {
61605
61769
  // touching storage on the per-assertion render path. Assigned after the template's
61606
61770
  // initialState so an authored `platformId` cannot shadow the real one.
61607
61771
  state.platformId = storageService.getNamiConfig()?.appPlatformID ?? '';
61772
+ // NAM-4637: one instant per Page / flow-screen presentation for every `${system.time.*}`
61773
+ // condition, captured with `launch` and never re-read while the page stays up. Also after
61774
+ // the initialState spread, so authored data cannot pin it; `timeOverride=` can.
61775
+ state.systemTimeSnapshot = getSystemTimeNow().getTime();
61608
61776
  const launch = normalizeLaunchContext(state.launch, context, paywall.sku_menus);
61609
61777
  this.filteredSkuMenus = paywall.sku_menus ?? [];
61610
61778
  if (launch.productGroups.length) {
@@ -61721,6 +61889,12 @@ class PaywallState extends SimpleEventTarget {
61721
61889
  setSafeAreaBottom(safeAreaBottom) {
61722
61890
  this.setState({ ...this.state, safeAreaBottom });
61723
61891
  }
61892
+ setSafeAreaLeft(safeAreaLeft) {
61893
+ this.setState({ ...this.state, safeAreaLeft });
61894
+ }
61895
+ setSafeAreaRight(safeAreaRight) {
61896
+ this.setState({ ...this.state, safeAreaRight });
61897
+ }
61724
61898
  setFullScreenPresentation(fullScreenPresentation) {
61725
61899
  this.setState({ ...this.state, fullScreenPresentation });
61726
61900
  }
@@ -66414,154 +66588,6 @@ function resolveLoopSource(loopSource) {
66414
66588
  return [];
66415
66589
  }
66416
66590
 
66417
- /**
66418
- * `${system.time.*}` Page conditions — the reference implementation of the cross-SDK contract in
66419
- * `shared/time_conditions/README.md`, verified against `shared/time_conditions/vectors.json`.
66420
- *
66421
- * Every token resolves to the per-presentation snapshot instant; the zone lives on `expected`
66422
- * (`Sunday@America/New_York`), so the instant is projected into that zone at comparison time and
66423
- * the device zone and locale never matter. Invalid input fails closed: the assertion is `false`
66424
- * for every operator, `notEquals` included.
66425
- */
66426
- const DAYS = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
66427
- const TIME_OF_DAY = /^([01]?\d|2[0-3]):([0-5]\d)$/;
66428
- const INSTANT = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2}(\.\d+)?)?(Z|[+-]\d{2}:\d{2})$/;
66429
- const ORDERING = {
66430
- equals: (a, b) => a === b,
66431
- gt: (a, b) => a > b,
66432
- gte: (a, b) => a >= b,
66433
- lt: (a, b) => a < b,
66434
- lte: (a, b) => a <= b,
66435
- };
66436
- const isOrderingOperator = (operator) => Object.prototype.hasOwnProperty.call(ORDERING, operator);
66437
- /** True when `value` is a `${system.time.<leaf>}` token (any leaf; unknown leaves evaluate `false`). */
66438
- const isSystemTimeAssertion = (assertion) => typeof assertion.value === "string" &&
66439
- assertion.value.startsWith(SYSTEM_TIME_TOKEN_PREFIX) &&
66440
- assertion.value.endsWith("}");
66441
- /** An ISO-8601 instant with a required offset, or `null`. */
66442
- const parseInstant = (value) => {
66443
- if (typeof value !== "string" || !INSTANT.test(value))
66444
- return null;
66445
- const date = new Date(value);
66446
- return Number.isNaN(date.getTime()) ? null : date;
66447
- };
66448
- const isValidZone = (zone) => {
66449
- if (!zone)
66450
- return false;
66451
- try {
66452
- new Intl.DateTimeFormat("en-US", { timeZone: zone });
66453
- return true;
66454
- }
66455
- catch {
66456
- return false;
66457
- }
66458
- };
66459
- /** Splits `<value>@<zone>` into its parts when there is exactly one `@` and the zone resolves. */
66460
- const splitZoned = (expected) => {
66461
- if (typeof expected !== "string")
66462
- return null;
66463
- const parts = expected.split("@");
66464
- if (parts.length !== 2 || !parts[0] || !isValidZone(parts[1]))
66465
- return null;
66466
- return { value: parts[0], zone: parts[1] };
66467
- };
66468
- /** The snapshot seen in `zone`: English day name and minutes since local midnight. */
66469
- const projectInZone = (now, zone) => {
66470
- try {
66471
- const [dayOfWeek, time] = formatInTimeZone(now, zone, "EEEE|HH:mm", { locale: enUS }).split("|");
66472
- const [hours, minutes] = time.split(":").map(Number);
66473
- return { dayOfWeek, minutes: hours * 60 + minutes };
66474
- }
66475
- catch {
66476
- // Runtimes without Intl time-zone support (e.g. Hermes) fail closed.
66477
- return null;
66478
- }
66479
- };
66480
- const parseDay = (expected) => {
66481
- const zoned = splitZoned(expected);
66482
- return zoned && DAYS.includes(zoned.value) ? { day: zoned.value, zone: zoned.zone } : null;
66483
- };
66484
- const evaluateDayOfWeek = (operator, expected, now) => {
66485
- const isDay = ({ day, zone }) => projectInZone(now, zone)?.dayOfWeek === day;
66486
- if (operator === "in") {
66487
- if (!Array.isArray(expected) || expected.length === 0)
66488
- return false;
66489
- const days = expected.map(parseDay);
66490
- // Any invalid element invalidates the whole assertion, even when another element matches.
66491
- if (days.some((day) => day === null))
66492
- return false;
66493
- return days.some((day) => isDay(day));
66494
- }
66495
- if (operator !== "equals" && operator !== "notEquals")
66496
- return false;
66497
- const day = parseDay(expected);
66498
- if (!day)
66499
- return false;
66500
- const projected = projectInZone(now, day.zone);
66501
- if (!projected)
66502
- return false;
66503
- return operator === "equals" ? projected.dayOfWeek === day.day : projected.dayOfWeek !== day.day;
66504
- };
66505
- const evaluateTimeOfDay = (operator, expected, now) => {
66506
- if (!isOrderingOperator(operator))
66507
- return false;
66508
- const zoned = splitZoned(expected);
66509
- const match = zoned && TIME_OF_DAY.exec(zoned.value);
66510
- if (!zoned || !match)
66511
- return false;
66512
- const projected = projectInZone(now, zoned.zone);
66513
- if (!projected)
66514
- return false;
66515
- return ORDERING[operator](projected.minutes, Number(match[1]) * 60 + Number(match[2]));
66516
- };
66517
- const evaluateNow = (operator, expected, now) => {
66518
- if (!isOrderingOperator(operator))
66519
- return false;
66520
- const instant = parseInstant(expected);
66521
- return instant !== null && ORDERING[operator](now.getTime(), instant.getTime());
66522
- };
66523
- /**
66524
- * Evaluates a `${system.time.*}` assertion against the snapshot instant `now`.
66525
- * Returns `null` when the assertion is not a time assertion, so callers fall through to their
66526
- * existing evaluator; otherwise `true`/`false`, with every invalid input `false`.
66527
- */
66528
- const evaluateSystemTimeAssertion = (assertion, now) => {
66529
- if (!isSystemTimeAssertion(assertion))
66530
- return null;
66531
- if (Number.isNaN(now.getTime()))
66532
- return false;
66533
- const leaf = assertion.value.slice(SYSTEM_TIME_TOKEN_PREFIX.length, -1);
66534
- switch (leaf) {
66535
- case "dayOfWeek":
66536
- return evaluateDayOfWeek(assertion.operator, assertion.expected, now);
66537
- case "timeOfDay":
66538
- return evaluateTimeOfDay(assertion.operator, assertion.expected, now);
66539
- case "now":
66540
- return evaluateNow(assertion.operator, assertion.expected, now);
66541
- default:
66542
- return false;
66543
- }
66544
- };
66545
- /** Parses a `timeOverride=<ISO-8601 with offset>` namiCommand; `null` when it is not a valid one. */
66546
- const parseTimeOverride = (command) => command.startsWith(TIME_OVERRIDE_PREFIX) ? parseInstant(command.slice(TIME_OVERRIDE_PREFIX.length)) : null;
66547
- /**
66548
- * The instant to snapshot for a Page or flow-screen presentation: the `timeOverride=` namiCommand
66549
- * when present and valid, otherwise the device clock. Call it once per presentation.
66550
- */
66551
- const getSystemTimeNow = () => {
66552
- const command = storageService
66553
- .getNamiConfig()
66554
- ?.namiCommands?.find((cmd) => cmd.startsWith(TIME_OVERRIDE_PREFIX));
66555
- if (command === undefined)
66556
- return new Date();
66557
- const override = parseTimeOverride(command);
66558
- if (override === null) {
66559
- logger.warn(`Ignoring invalid ${command}: expected ISO-8601 with an offset, e.g. ${TIME_OVERRIDE_PREFIX}2026-09-13T13:00:00-04:00`);
66560
- return new Date();
66561
- }
66562
- return override;
66563
- };
66564
-
66565
66591
  /**
66566
66592
  * Components that are skipped entirely (they and their subtree do not
66567
66593
  * contribute text to the page-level announcement).
@@ -66847,4 +66873,4 @@ var internal = /*#__PURE__*/Object.freeze({
66847
66873
  NamiPurchaseManager: NamiPurchaseManager
66848
66874
  });
66849
66875
 
66850
- export { ALREADY_CONFIGURED, ANONYMOUS_MODE, ANONYMOUS_MODE_ALREADY_OFF, ANONYMOUS_MODE_ALREADY_ON, ANONYMOUS_MODE_LOGIN_NOT_ALLOWED, ANONYMOUS_UUID, APIError, API_ACTIVE_ENTITLEMENTS, API_CAMPAIGN_RULES, API_CAMPAIGN_SESSION_TIMESTAMP, API_CONFIG, API_MAX_CALLS_LIMIT, API_PAYWALLS, API_PRODUCTS, API_RETRY_DELAY_SEC, API_TIMEOUT_LIMIT, API_TRAFFIC_OBSERVER, API_VERSION, AUTH_DEVICE, AVAILABLE_ACTIVE_ENTITLEMENTS_CHANGED, AVAILABLE_CAMPAIGNS_CHANGED, AccountStateAction, AnonymousCDPError, AnonymousLoginError, AnonymousModeAlreadyOffError, AnonymousModeAlreadyOnError, BASE_STAGING_URL, BASE_URL, BASE_URL_PATH, BadRequestError, BasicNamiFlow, BorderMap, BorderSideMap, CAMPAIGN_CACHE_TTL_PREFIX, CAMPAIGN_NOT_AVAILABLE, CONFIG_API_TIMEOUT_LIMIT, CONFIG_MAX_ATTEMPTS, CUSTOMER_ATTRIBUTES_KEY_PREFIX, CUSTOMER_JOURNEY_STATE_CHANGED, CUSTOM_HOST_PREFIX, CampaignNotAvailableError, CampaignRuleConversionEventType, CampaignRuleRepository, Capabilities, ClientError, ConfigRepository, ConflictError, CustomerJourneyRepository, DEFAULT_JOURNEY_SETTINGS, DEVELOPMENT, DEVICE_API_TIMEOUT_LIMIT, DEVICE_ID_NOT_SET, DEVICE_ID_REQUIRED, DISABLE_ASYNC_LOGIN_LOGOUT, DeviceIDRequiredError, DeviceRepository, EXTENDED_CLIENT_INFO_DELIMITER, EXTENDED_CLIENT_INFO_PREFIX, EXTENDED_PLATFORM, EXTENDED_PLATFORM_VERSION, EXTERNAL_ID_REQUIRED, EntitlementRepository, EntitlementUtils, ExternalIDRequiredError, FLOW_SCREENS_NOT_AVAILABLE, FlowScreensNotAvailableError, HTML_REGEX, INITIAL_APP_CONFIG, INITIAL_CAMPAIGN_RULES, INITIAL_PAYWALLS, INITIAL_PRODUCTS, INITIAL_SESSION_COUNTER_VALUE, INITIAL_SUCCESS, InternalServerError, KEY_SESSION_COUNTER, LIQUID_VARIABLE_REGEX, LOCAL_NAMI_ENTITLEMENTS, LOG_HTTP_REQUESTS, LOG_HTTP_TRAFFIC, LaunchCampaignError, LaunchContextResolver, LogLevel, NAMI_CONFIGURATION, NAMI_CUSTOMER_JOURNEY_STATE, NAMI_LANGUAGE_CODE, NAMI_LAST_IMPRESSION_ID, NAMI_LAUNCH_ID, NAMI_PROFILE, NAMI_PURCHASE_CHANNEL, NAMI_PURCHASE_IMPRESSION_ID, NAMI_SDK_PACKAGE_VERSION, NAMI_SDK_VERSION, NAMI_SESSION_ID, NAMI_STORAGE_KEYS, Nami, NamiAPI, NamiAnimationType, NamiCampaignManager$1 as NamiCampaignManager, NamiCampaignRuleType, NamiConditionEvaluator, NamiCustomerManager$1 as NamiCustomerManager, NamiEntitlementManager$1 as NamiEntitlementManager, NamiEventEmitter, NamiFlow, NamiFlowActionFunction, NamiFlowManager$1 as NamiFlowManager, NamiFlowStepType, NamiHandoffTag, NamiPaywallAction, NamiPaywallManager$1 as NamiPaywallManager, PaywallManagerEvents as NamiPaywallManagerEvents, NamiPermissionOutcome, NamiPurchaseManager$1 as NamiPurchaseManager, NamiRefs, NamiReservedActions, NotFoundError, PAYWALL_ACTION_EVENT, PLATFORM_ID_REQUIRED, PRODUCTION, PaywallManagerEvents, PaywallRepository, PaywallState, PlacementLabelResolver, PlatformIDRequiredError, ProductRepository, RECONFIG_SUCCESS, RESUME_THROTTLE_MS, RetryLimitExceededError, SDKNotInitializedError, SDK_NOT_INITIALIZED, SERVER_NAMI_ENTITLEMENTS, SESSION_REQUIRED, SHOULD_SHOW_LOADING_INDICATOR, SIMULATE_CONFIG_FETCH_FAILURE, SIMULATE_PAYWALL_FETCH_FAILURE, SKU_TEXT_REGEX, SMART_TEXT_PATTERN, STARTUP_TELEMETRY, STATUS_BAD_REQUEST, STATUS_CONFLICT, STATUS_INTERNAL_SERVER_ERROR, STATUS_NOT_FOUND, STATUS_SUCCESS, SYSTEM_TIME_TOKEN_PREFIX, SessionService, SimpleEventTarget, StorageService, TIME_OVERRIDE_PREFIX, TRANSPORT_FAILURE_STATUS, UNABLE_TO_UPDATE_CDP_ID, USE_STAGING_API, VALIDATE_PRODUCT_GROUPS, VAR_REGEX, NamiProfileManager$1 as _NamiProfileManager, internal as _internal, activateEntitlementByPurchase, activeEntitlements, aggregateScreenreaderText, allCampaigns, allPaywalls, applyEntitlementActivation, audienceSplitPosition, bestUrlCampaignMatch, bigintToUuid, checkAnySkuHasPromoOffer, checkAnySkuHasTrialOffer, convertISO8601PeriodToText, convertLocale, convertOfferToPricingPhase, createNamiEntitlements, currentSku, didReceiveResponse, empty, evaluateSystemTimeAssertion, extractStandardPricingPhases, formatDate, formattedPrice, generateUUID, getApiCampaigns, getApiPaywalls, getBaseUrl, getBillingPeriodNumber, getCurrencyFormat, getDeviceData, getDeviceFormFactor, getDeviceScaleFactor, getEffectiveWebStyle, getEntitlementRefIdsForSku, getExtendedClientInfo, getFreeTrialPeriod, getInitialCampaigns, getInitialPaywalls, getJourneySettings, getPaywall, getPaywallDataFromLabel, getPercentagePriceDifference, getPeriodNumberInDays, getPeriodNumberInWeeks, getPlatformAdapters, getPriceDifference, getPricePerMonth, getProductDetail, getPurchaseAdapter, getReferenceSku, getSkuProductDetailKeys, getSkuSmartTextValue, getSlideSmartTextValue, getStandardBillingPeriod, getSystemTimeNow, getTranslate, getUrlParams, handleErrors, hasAllPaywalls, hasCapability, hasPurchaseManagement, initialState, invokeHandler, isAnonymousMode, isInitialConfigCompressed, isNamiFlowCampaign, isSubscription, isSystemTimeAssertion, isValidISODate, isValidUrl, logger, mapAnonymousCampaigns, namiBuySKU, normalizeLaunchContext, parseTimeOverride, parseToSemver, postConversion, productDetail, registerAPITrafficObserver, registerPlatformAdapters, registerPurchaseAdapter, resolveLoopSource, selectSegment, setActiveNamiEntitlements, shouldValidateProductGroups, skuItems, skuMapFromEntitlements, storageService, toDouble, toNamiEntitlements, toNamiSKU, tryParseB64Gzip, tryParseJson, updateRelatedSKUsForNamiEntitlement, uuidFromSplitPosition, validateForm, validateMinSDKVersion, validateTextInput };
66876
+ export { ALREADY_CONFIGURED, ANONYMOUS_MODE, ANONYMOUS_MODE_ALREADY_OFF, ANONYMOUS_MODE_ALREADY_ON, ANONYMOUS_MODE_LOGIN_NOT_ALLOWED, ANONYMOUS_UUID, APIError, API_ACTIVE_ENTITLEMENTS, API_CAMPAIGN_RULES, API_CAMPAIGN_SESSION_TIMESTAMP, API_CONFIG, API_MAX_CALLS_LIMIT, API_PAYWALLS, API_PRODUCTS, API_RETRY_DELAY_SEC, API_TIMEOUT_LIMIT, API_TRAFFIC_OBSERVER, API_VERSION, AUTH_DEVICE, AVAILABLE_ACTIVE_ENTITLEMENTS_CHANGED, AVAILABLE_CAMPAIGNS_CHANGED, AccountStateAction, AnonymousCDPError, AnonymousLoginError, AnonymousModeAlreadyOffError, AnonymousModeAlreadyOnError, BASE_STAGING_URL, BASE_URL, BASE_URL_PATH, BadRequestError, BasicNamiFlow, BorderMap, BorderSideMap, CAMPAIGN_CACHE_TTL_PREFIX, CAMPAIGN_NOT_AVAILABLE, CONFIG_API_TIMEOUT_LIMIT, CONFIG_MAX_ATTEMPTS, CUSTOMER_ATTRIBUTES_KEY_PREFIX, CUSTOMER_JOURNEY_STATE_CHANGED, CUSTOM_HOST_PREFIX, CampaignNotAvailableError, CampaignRuleConversionEventType, CampaignRuleRepository, Capabilities, ClientError, ConfigRepository, ConflictError, CustomerJourneyRepository, DEFAULT_JOURNEY_SETTINGS, DEVELOPMENT, DEVICE_API_TIMEOUT_LIMIT, DEVICE_ID_NOT_SET, DEVICE_ID_REQUIRED, DISABLE_ASYNC_LOGIN_LOGOUT, DeviceIDRequiredError, DeviceRepository, EXTENDED_CLIENT_INFO_DELIMITER, EXTENDED_CLIENT_INFO_PREFIX, EXTENDED_PLATFORM, EXTENDED_PLATFORM_VERSION, EXTERNAL_ID_REQUIRED, EntitlementRepository, EntitlementUtils, ExternalIDRequiredError, FLOW_SCREENS_NOT_AVAILABLE, FlowScreensNotAvailableError, HTML_REGEX, INITIAL_APP_CONFIG, INITIAL_CAMPAIGN_RULES, INITIAL_PAYWALLS, INITIAL_PRODUCTS, INITIAL_SESSION_COUNTER_VALUE, INITIAL_SUCCESS, InternalServerError, KEY_SESSION_COUNTER, LIQUID_VARIABLE_REGEX, LOCAL_NAMI_ENTITLEMENTS, LOG_HTTP_REQUESTS, LOG_HTTP_TRAFFIC, LaunchCampaignError, LaunchContextResolver, LogLevel, NAMI_CONFIGURATION, NAMI_CUSTOMER_JOURNEY_STATE, NAMI_LANGUAGE_CODE, NAMI_LAST_IMPRESSION_ID, NAMI_LAUNCH_ID, NAMI_PROFILE, NAMI_PURCHASE_CHANNEL, NAMI_PURCHASE_IMPRESSION_ID, NAMI_SDK_PACKAGE_VERSION, NAMI_SDK_VERSION, NAMI_SESSION_ID, NAMI_STORAGE_KEYS, Nami, NamiAPI, NamiAnimationType, NamiCampaignManager$1 as NamiCampaignManager, NamiCampaignRuleType, NamiConditionEvaluator, NamiCustomerManager$1 as NamiCustomerManager, NamiEntitlementManager$1 as NamiEntitlementManager, NamiEventEmitter, NamiFlow, NamiFlowActionFunction, NamiFlowManager$1 as NamiFlowManager, NamiFlowStepType, NamiHandoffTag, NamiPaywallAction, NamiPaywallManager$1 as NamiPaywallManager, PaywallManagerEvents as NamiPaywallManagerEvents, NamiPermissionOutcome, NamiPurchaseManager$1 as NamiPurchaseManager, NamiRefs, NamiReservedActions, NotFoundError, PAYWALL_ACTION_EVENT, PLATFORM_ID_REQUIRED, PRODUCTION, PaywallManagerEvents, PaywallRepository, PaywallState, PlacementLabelResolver, PlatformIDRequiredError, ProductRepository, RECONFIG_SUCCESS, RESUME_THROTTLE_MS, RetryLimitExceededError, SDKNotInitializedError, SDK_NOT_INITIALIZED, SERVER_NAMI_ENTITLEMENTS, SESSION_REQUIRED, SHOULD_SHOW_LOADING_INDICATOR, SIMULATE_CONFIG_FETCH_FAILURE, SIMULATE_PAYWALL_FETCH_FAILURE, SKU_TEXT_REGEX, SMART_TEXT_PATTERN, STARTUP_TELEMETRY, STATUS_BAD_REQUEST, STATUS_CONFLICT, STATUS_INTERNAL_SERVER_ERROR, STATUS_NOT_FOUND, STATUS_SUCCESS, SYSTEM_TIME_TOKEN_PREFIX, SessionService, SimpleEventTarget, StorageService, TIME_OVERRIDE_PREFIX, TRANSPORT_FAILURE_STATUS, UNABLE_TO_UPDATE_CDP_ID, USE_STAGING_API, VALIDATE_PRODUCT_GROUPS, VAR_REGEX, NamiProfileManager$1 as _NamiProfileManager, internal as _internal, activateEntitlementByPurchase, activeEntitlements, aggregateScreenreaderText, allCampaigns, allPaywalls, applyEntitlementActivation, audienceSplitPosition, bestUrlCampaignMatch, bigintToUuid, checkAnySkuHasPromoOffer, checkAnySkuHasTrialOffer, convertISO8601PeriodToText, convertLocale, convertOfferToPricingPhase, createNamiEntitlements, currentSku, didReceiveResponse, empty, evaluateSystemTimeAssertion, evaluateSystemTimeCondition, extractStandardPricingPhases, formatDate, formattedPrice, generateUUID, getApiCampaigns, getApiPaywalls, getBaseUrl, getBillingPeriodNumber, getCurrencyFormat, getDeviceData, getDeviceFormFactor, getDeviceScaleFactor, getEffectiveWebStyle, getEntitlementRefIdsForSku, getExtendedClientInfo, getFreeTrialPeriod, getInitialCampaigns, getInitialPaywalls, getJourneySettings, getPaywall, getPaywallDataFromLabel, getPercentagePriceDifference, getPeriodNumberInDays, getPeriodNumberInWeeks, getPlatformAdapters, getPriceDifference, getPricePerMonth, getProductDetail, getPurchaseAdapter, getReferenceSku, getSkuProductDetailKeys, getSkuSmartTextValue, getSlideSmartTextValue, getStandardBillingPeriod, getSystemTimeNow, getTranslate, getUrlParams, handleErrors, hasAllPaywalls, hasCapability, hasPurchaseManagement, initialState, invokeHandler, isAnonymousMode, isInitialConfigCompressed, isNamiFlowCampaign, isSubscription, isSystemTimeAssertion, isValidISODate, isValidUrl, logger, mapAnonymousCampaigns, namiBuySKU, normalizeLaunchContext, parseTimeOverride, parseToSemver, postConversion, productDetail, registerAPITrafficObserver, registerPlatformAdapters, registerPurchaseAdapter, resolveLoopSource, selectSegment, setActiveNamiEntitlements, shouldValidateProductGroups, skuItems, skuMapFromEntitlements, storageService, toDouble, toNamiEntitlements, toNamiSKU, tryParseB64Gzip, tryParseJson, updateRelatedSKUsForNamiEntitlement, uuidFromSplitPosition, validateForm, validateMinSDKVersion, validateTextInput };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@namiml/sdk-core",
3
- "version": "3.4.12-dev.202609302156",
3
+ "version": "3.4.12-dev.202610051759",
4
4
  "description": "Platform-agnostic core for the Nami SDK — business logic, API, types, and state management",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",