react-native-nami-sdk
Version:
React Native SDK for Nami - No-code paywall and onboarding flows with A/B testing.
369 lines (368 loc) • 12.8 kB
TypeScript
export type NamiConfiguration = {
appPlatformID: string;
logLevel: string;
namiCommands?: string[];
namiLanguageCode?: NamiLanguageCodes;
initialConfig?: string;
};
export type NamiLanguageCodes = 'af' | 'ar' | 'ar-dz' | 'ast' | 'az' | 'bg' | 'be' | 'bn' | 'br' | 'bs' | 'ca' | 'cs' | 'cy' | 'da' | 'de' | 'dsb' | 'el' | 'en' | 'en-au' | 'en-gb' | 'eo' | 'es' | 'es-ar' | 'es-co' | 'es-mx' | 'es-ni' | 'es-ve' | 'et' | 'eu' | 'fa' | 'fi' | 'fr' | 'fy' | 'ga' | 'gd' | 'gl' | 'he' | 'hi' | 'hr' | 'hsb' | 'hu' | 'hy' | 'ia' | 'id' | 'ig' | 'io' | 'is' | 'it' | 'ja' | 'ka' | 'kab' | 'kk' | 'km' | 'kn' | 'ko' | 'ky' | 'lb' | 'lt' | 'lv' | 'mk' | 'ml' | 'mn' | 'mr' | 'my' | 'nb' | 'ne' | 'nl' | 'nn' | 'os' | 'pa' | 'pl' | 'pt' | 'pt-br' | 'ro' | 'ru' | 'sk' | 'sl' | 'sq' | 'sr' | 'sr-latn' | 'sv' | 'sw' | 'ta' | 'te' | 'tg' | 'th' | 'tk' | 'tr' | 'tt' | 'udm' | 'uk' | 'ur' | 'uz' | 'vi' | 'zh-hans' | 'zh-hant';
export type NamiSKU = {
id: string;
name?: string;
skuId: string;
appleProduct?: AppleProduct;
googleProduct?: GoogleProduct;
amazonProduct?: AmazonProduct;
type: NamiSKUType;
promoId?: string | null;
promoToken?: string | null;
promoOffer?: {
[key: string]: string;
} | null;
};
export declare enum NamiPurchaseState {
PENDING = "pending",
PURCHASED = "purchased",
CONSUMED = "consumed",
RESUBSCRIBED = "resubscribed",
UNSUBSCRIBED = "unsubscribed",
DEFERRED = "deferred",
FAILED = "failed",
CANCELLED = "cancelled",
UNKNOWN = "unknown"
}
export declare enum NamiRestorePurchasesState {
STARTED = "started",
FINISHED = "finished",
ERROR = "error"
}
export type NamiSKUType = 'unknown' | 'one_time_purchase' | 'subscription';
export type AppleProduct = {
localizedDescription: string;
localizedMultipliedPrice: string;
localizedPrice: string;
localizedTitle: string;
price: string;
priceCurrency: string;
priceLanguage: string;
};
export type GoogleProduct = Record<string, never>;
export type AmazonProduct = Record<string, never>;
export type NamiCampaign = {
name: string;
rule: string;
segment: string;
paywall: string;
type: NamiCampaignRuleType;
value?: string | null;
form_factors: NamiFormFactor[];
external_segment: string | null;
};
export declare enum NamiCampaignRuleType {
DEFAULT = "default",
LABEL = "label",
UNKNOWN = "unknown",
URL = "url"
}
type NamiFormFactor = {
form_factor?: string;
supports_portrait?: boolean;
supports_landscape?: boolean;
};
export declare enum LaunchCampaignError {
DEFAULT_CAMPAIGN_NOT_FOUND = 0,
LABELED_CAMPAIGN_NOT_FOUND = 1,
CAMPAIGN_DATA_NOT_FOUND = 2,
PAYWALL_ALREADY_DISPLAYED = 3,
SDK_NOT_INITIALIZED = 4,
PAYWALL_COULD_NOT_DISPLAY = 5,
URL_CAMPAIGN_NOT_FOUND = 6,
PRODUCT_DATA_NOT_FOUND = 7,
PRODUCT_GROUPS_NOT_FOUND = 8
}
export type NamiError = {
domain: string;
code: number;
message: string;
};
export declare enum LaunchCampaignResultAction {
FAILURE = "FAILURE",
SUCCESS = "SUCCESS"
}
export type FailureResultObject = {
error: string;
};
/**
* Permitted value types for entries in {@link PaywallLaunchContext.customAttributes}.
*
* Values are matched strictly by type: the string "true" and the boolean true are
* distinct values that never compare equal. A key present with any non-null value —
* including false or "false" — is considered "set". Passing `null` (or omitting the
* key) means the attribute is not set; the native bridge omits null values entirely.
*/
export type CustomAttributeValue = string | boolean | number | null;
export type PaywallLaunchContext = {
productGroups?: string[];
customAttributes: {
[key: string]: CustomAttributeValue;
};
customObject?: {
[key: string]: unknown;
};
};
export type CustomerJourneyState = {
formerSubscriber: boolean;
inGracePeriod: boolean;
inTrialPeriod: boolean;
inIntroOfferPeriod: boolean;
isCancelled: boolean;
inPause: boolean;
inAccountHold: boolean;
};
export type AccountStateAction = 'login' | 'logout' | 'advertising_id_set' | 'vendor_id_set' | 'customer_data_platform_id_set' | 'nami_device_id_set' | 'advertising_id_cleared' | 'vendor_id_cleared' | 'customer_data_platform_id_cleared' | 'nami_device_id_cleared' | 'anonymous_mode_on' | 'anonymous_mode_off';
export type NamiEntitlement = {
activePurchases: NamiPurchase[];
desc: string;
name: string;
purchasedSkus: NamiSKU[];
referenceId: string;
relatedSkus: NamiSKU[];
};
/**
* Host-managed purchase payload handed back to the SDK on a successful
* `buysku` handoff (`complete({ kind: 'purchase', result: 'success', details })`).
* Fields are a superset across stores; the native bridge maps them onto the
* platform's own `NamiPurchaseSuccess` (Apple flat class / Android sealed
* GooglePlay|Amazon) at the boundary. Renamed from `NamiPurchaseDetails` for
* cross-SDK naming consistency (NAM-1560 §2.3).
*/
export type NamiPurchaseSuccess = {
product: NamiSKU;
transactionID?: string;
originalTransactionID?: string;
orderId?: string;
purchaseToken?: string;
receiptId?: string;
localizedPrice?: string;
price?: string;
currencyCode?: string;
userId?: string;
marketplace?: string;
storeType?: string;
};
/**
* @deprecated Renamed to {@link NamiPurchaseSuccess} for cross-SDK naming
* consistency. Structurally identical; kept so existing host code keeps
* compiling. Prefer `NamiPurchaseSuccess` in new code.
*/
export type NamiPurchaseDetails = NamiPurchaseSuccess;
export type NamiPurchaseSuccessApple = {
product: NamiSKU;
transactionID: string;
originalTransactionID: string;
price: string;
currencyCode: string;
};
export type NamiPurchaseSuccessGooglePlay = {
product: NamiSKU;
orderId: string;
purchaseToken: string;
};
export type NamiPurchaseSuccessAmazon = {
product: NamiSKU;
receiptId: string;
localizedPrice: string;
userId: string;
marketplace: string;
};
export declare enum NamiPaywallAction {
BUY_SKU = "BUY_SKU",
SELECT_SKU = "SELECT_SKU",
RESTORE_PURCHASES = "RESTORE_PURCHASES",
SIGN_IN = "SIGN_IN",
CLOSE_PAYWALL = "CLOSE_PAYWALL",
SHOW_PAYWALL = "SHOW_PAYWALL",
PURCHASE_SELECTED_SKU = "PURCHASE_SELECTED_SKU",
PURCHASE_SUCCESS = "PURCHASE_SUCCESS",
PURCHASE_FAILED = "PURCHASE_FAILED",
PURCHASE_CANCELLED = "PURCHASE_CANCELLED",
PURCHASE_PENDING = "PURCHASE_PENDING",
PURCHASE_UNKNOWN = "PURCHASE_UNKNOWN",
PURCHASE_DEFERRED = "PURCHASE_DEFERRED",
DEEPLINK = "DEEPLINK",
TOGGLE_CHANGE = "TOGGLE_CHANGE",
PAGE_CHANGE = "PAGE_CHANGE",
SLIDE_CHANGE = "SLIDE_CHANGE",
COLLAPSIBLE_DRAWER_OPEN = "COLLAPSIBLE_DRAWER_OPEN",
COLLAPSIBLE_DRAWER_CLOSE = "COLLAPSIBLE_DRAWER_CLOSE",
VIDEO_STARTED = "VIDEO_STARTED",
VIDEO_PAUSED = "VIDEO_PAUSED",
VIDEO_RESUMED = "VIDEO_RESUMED",
VIDEO_ENDED = "VIDEO_ENDED",
VIDEO_CHANGED = "VIDEO_CHANGED",
VIDEO_MUTED = "VIDEO_MUTED",
VIDEO_UNMUTED = "VIDEO_UNMUTED",
UNKNOWN = "UNKNOWN"
}
export type NamiPurchase = {
sku?: NamiSKU;
skuId: string;
transactionIdentifier?: string;
originalTransactionIdentifier?: string;
purchaseToken?: string;
expires?: Date;
purchaseInitiatedTimestamp: Date;
purchaseSource?: 'CAMPAIGN' | 'MARKETPLACE' | 'UNKNOWN';
};
export type NamiPurchaseFromBridge = {
sku?: NamiSKU;
skuId: string;
transactionIdentifier?: string;
originalTransactionIdentifier?: string;
purchaseToken?: string;
expires?: number;
purchaseInitiatedTimestamp: number;
purchaseSource?: 'CAMPAIGN' | 'MARKETPLACE' | 'UNKNOWN';
};
export type NamiPurchasesState = 'pending' | 'purchased' | 'consumed' | 'resubscribed' | 'unsubscribed' | 'deferred' | 'failed' | 'cancelled' | 'unknown';
export type NamiPaywallEvent = {
action: NamiPaywallAction;
campaignId?: string;
campaignName?: string;
campaignType?: string;
campaignLabel?: string;
campaignUrl?: string;
paywallId?: string;
paywallName?: string;
componentChange?: NamiPaywallComponentChange;
segmentId?: string;
externalSegmentId?: string;
deeplinkUrl?: string;
sku?: NamiSKU;
purchaseError?: string;
purchases?: NamiPurchase[];
videoMetadata?: NamiPaywallEventVideoMetadata;
timeSpentOnPaywall?: number;
};
export type NamiPaywallActionHandler = (event: NamiPaywallEvent) => void;
export type NamiPaywallComponentChange = {
id?: string;
name?: string;
};
export type NamiPaywallEventVideoMetadata = {
id?: string;
name?: string;
url?: string;
loopVideo: boolean;
muteByDefault: boolean;
autoplayVideo: boolean;
contentTimecode?: number;
contentDuration?: number;
};
/**
* Native → JS handoff delivery payload. `handoffId` correlates the eventual
* `complete(outcome)` back to the native pending handoff (NAM-1560 §2.8).
*/
export type NamiFlowHandoffPayload = {
handoffId: string;
handoffTag: string;
handoffData?: Record<string, unknown>;
};
/** Open-ended host-asserted attribute values — primitives only (no nesting). */
export type NamiHandoffAttributeValue = string | number | boolean;
/**
* Host-asserted login result. Only `loginId` is required. `attributes` is
* open-ended experience data (e.g. `{ subscriberStatus, subscribedTier }`) read
* by branch conditions and smart text via `login.<hostKey>`; never merged into
* Nami subscriber state and never touches entitlements.
*/
export type NamiLoginSuccess = {
loginId: string;
cdpId?: string;
attributes?: Record<string, NamiHandoffAttributeValue>;
};
/** Permission types reportable from a handoff. Tier-1 (push/location/tracking)
* carry completion wire values natively; the rest are state/lifecycle only. */
export declare const NamiPermissionOutcome: {
readonly Push: "push";
readonly Location: "location";
readonly Tracking: "tracking";
readonly Camera: "camera";
readonly Microphone: "microphone";
readonly Photos: "photos";
readonly Contacts: "contacts";
readonly Bluetooth: "bluetooth";
readonly Calendar: "calendar";
readonly Biometrics: "biometrics";
readonly Health: "health";
readonly Motion: "motion";
readonly Speech: "speech";
readonly LocalNetwork: "localNetwork";
};
export type NamiPermissionOutcome = (typeof NamiPermissionOutcome)[keyof typeof NamiPermissionOutcome];
/** Typed outcome reported by the host's `complete(...)`. Discriminated on `kind`
* (purchase/login further discriminated on `result`). */
export type NamiHandoffOutcome = {
kind: 'done';
} | {
kind: 'permission';
permission: NamiPermissionOutcome;
granted: boolean;
detail?: string;
} | {
kind: 'purchase';
result: 'success';
details: NamiPurchaseSuccess;
} | {
kind: 'purchase';
result: 'cancelled';
} | {
kind: 'purchase';
result: 'failed';
error?: unknown;
} | {
kind: 'login';
result: 'success';
details: NamiLoginSuccess;
} | {
kind: 'login';
result: 'cancelled';
} | {
kind: 'login';
result: 'failed';
error?: unknown;
};
/** Per-handoff completion callback. Bare `complete()` ≙ `complete({kind:'done'})`. */
export type NamiHandoffComplete = (outcome?: NamiHandoffOutcome) => void;
/** The single handoff handler shape (NAM-1560 §2.1 — no dual registration). */
export type NamiFlowHandoffStepHandler = (handoffTag: string, handoffData: Record<string, unknown> | undefined, complete: NamiHandoffComplete) => void;
/** Closed-but-extensible handoff tag vocabulary (mirrors the builder's
* `FlowHandoffTag`, minus `__*__` internals). Unknown future tags still pass. */
export declare const NamiHandoffTag: {
readonly Push: "push";
readonly Location: "location";
readonly Tracking: "att";
readonly Deeplink: "deeplink";
readonly Complete: "complete";
readonly SignIn: "signin";
readonly Restore: "restore";
readonly SignInMvpd: "signin_mvpd";
readonly BuySku: "buysku";
readonly UserData: "userdata";
};
export type NamiKnownHandoffTag = (typeof NamiHandoffTag)[keyof typeof NamiHandoffTag];
export type NamiHandoffTagValue = NamiKnownHandoffTag | (string & {});
/** Outbound `userdata` envelope (Nami → customer) delivered with the `userdata` tag. */
export type NamiUserDataEnvelope = {
form_id: string;
step_id: string;
/** ISO-8601 UTC timestamp of delivery. */
collected_at: string;
fields: Record<string, boolean | string>;
};
export type NamiAccountStateEvent = {
action: AccountStateAction;
success: boolean;
error?: number;
};
export {};