@rezfiliate/sdk 0.0.0-stage → 1.0.2
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/README.md +24 -2
- package/dist/index.d.ts +33 -0
- package/dist/index.js +88 -0
- package/package.json +27 -4
package/README.md
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @rezfiliate/sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Typed browser loader for the Rezfiliate Stripe, Paddle, and Lemon Squeezy storefront SDKs.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install @rezfiliate/sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Load the storefront SDK
|
|
12
|
+
|
|
13
|
+
Call `Rezfiliate` in browser code. It loads the selected hosted script, returns the typed API, and reuses the script if that integration is already loaded.
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { Rezfiliate } from "@rezfiliate/sdk";
|
|
17
|
+
|
|
18
|
+
const rezfiliate = await Rezfiliate("stripe");
|
|
19
|
+
await rezfiliate.ready;
|
|
20
|
+
|
|
21
|
+
const attribution = rezfiliate.attachAttribution();
|
|
22
|
+
await rezfiliate.track("signup");
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Supported platforms are `stripe`, `paddle`, and `lemonsqueezy`. The package loads hosted scripts from `https://rezfiliate.com/sdk/`.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export type RezfiliatePlatform = "stripe" | "paddle" | "lemonsqueezy";
|
|
2
|
+
export type ConsentState = "granted" | "denied" | "unknown";
|
|
3
|
+
export type ConversionType = "signup" | "sign_up" | "purchase" | "refund" | "subscription_started" | "subscription_renewed" | "subscription_cancelled" | "subscription_ended";
|
|
4
|
+
export interface Attribution {
|
|
5
|
+
ref_code?: string;
|
|
6
|
+
click_id?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface RezfiliateApi {
|
|
9
|
+
readonly platform: RezfiliatePlatform;
|
|
10
|
+
readonly ready: Promise<void>;
|
|
11
|
+
getClickId(): string | null;
|
|
12
|
+
getReferralCode(): string | null;
|
|
13
|
+
attachAttribution<T extends Record<string, unknown> = Record<string, unknown>>(existing?: T): T & Attribution;
|
|
14
|
+
track(type: ConversionType, amount?: number): Promise<boolean>;
|
|
15
|
+
setConsent(consent: ConsentState): void;
|
|
16
|
+
getConsent(): ConsentState;
|
|
17
|
+
setupBanner(): void;
|
|
18
|
+
}
|
|
19
|
+
export interface RezfiliateConfig {
|
|
20
|
+
domain?: string;
|
|
21
|
+
showBanner?: boolean;
|
|
22
|
+
bannerText?: string;
|
|
23
|
+
bannerBgColor?: string;
|
|
24
|
+
bannerTextColor?: string;
|
|
25
|
+
}
|
|
26
|
+
declare global {
|
|
27
|
+
interface Window {
|
|
28
|
+
Rezfiliate?: RezfiliateApi;
|
|
29
|
+
RezfiliateConfig?: RezfiliateConfig;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/** Loads the matching browser SDK and returns its common typed global API. */
|
|
33
|
+
export declare function Rezfiliate(platform: RezfiliatePlatform): Promise<RezfiliateApi>;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
const SDK_ORIGIN = "https://rezfiliate.com";
|
|
2
|
+
const pendingLoads = new Map();
|
|
3
|
+
function isApi(value, platform) {
|
|
4
|
+
if (!value || typeof value !== "object")
|
|
5
|
+
return false;
|
|
6
|
+
const api = value;
|
|
7
|
+
return api.platform === platform &&
|
|
8
|
+
!!api.ready && typeof api.ready.then === "function" &&
|
|
9
|
+
typeof api.getClickId === "function" &&
|
|
10
|
+
typeof api.getReferralCode === "function" &&
|
|
11
|
+
typeof api.attachAttribution === "function" &&
|
|
12
|
+
typeof api.track === "function" &&
|
|
13
|
+
typeof api.setConsent === "function" &&
|
|
14
|
+
typeof api.getConsent === "function" &&
|
|
15
|
+
typeof api.setupBanner === "function";
|
|
16
|
+
}
|
|
17
|
+
function sdkUrl(platform) {
|
|
18
|
+
return new URL(`/sdk/${platform}.js`, SDK_ORIGIN).toString();
|
|
19
|
+
}
|
|
20
|
+
function findScript(url) {
|
|
21
|
+
const expected = new URL(url);
|
|
22
|
+
return Array.from(document.scripts).find((script) => {
|
|
23
|
+
if (!script.src)
|
|
24
|
+
return false;
|
|
25
|
+
try {
|
|
26
|
+
const actual = new URL(script.src, document.baseURI);
|
|
27
|
+
return actual.origin === expected.origin && actual.pathname === expected.pathname;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/** Loads the matching browser SDK and returns its common typed global API. */
|
|
35
|
+
export function Rezfiliate(platform) {
|
|
36
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
37
|
+
return Promise.reject(new Error("Rezfiliate can only run in a browser."));
|
|
38
|
+
}
|
|
39
|
+
const existingApi = window.Rezfiliate;
|
|
40
|
+
if (existingApi?.platform && existingApi.platform !== platform) {
|
|
41
|
+
return Promise.reject(new Error(`The ${existingApi.platform} Rezfiliate SDK is already loaded on this page.`));
|
|
42
|
+
}
|
|
43
|
+
if (isApi(existingApi, platform))
|
|
44
|
+
return Promise.resolve(existingApi);
|
|
45
|
+
const url = sdkUrl(platform);
|
|
46
|
+
const cached = pendingLoads.get(url);
|
|
47
|
+
if (cached)
|
|
48
|
+
return cached;
|
|
49
|
+
const loading = new Promise((resolve, reject) => {
|
|
50
|
+
let script = findScript(url);
|
|
51
|
+
const isNewScript = !script;
|
|
52
|
+
if (!script) {
|
|
53
|
+
script = document.createElement("script");
|
|
54
|
+
script.src = url;
|
|
55
|
+
script.async = true;
|
|
56
|
+
script.dataset.rezfiliatePlatform = platform;
|
|
57
|
+
}
|
|
58
|
+
const timeout = window.setTimeout(() => {
|
|
59
|
+
cleanup();
|
|
60
|
+
reject(new Error(`Timed out loading the Rezfiliate ${platform} SDK.`));
|
|
61
|
+
}, 20000);
|
|
62
|
+
const cleanup = () => {
|
|
63
|
+
window.clearTimeout(timeout);
|
|
64
|
+
script?.removeEventListener("load", onLoad);
|
|
65
|
+
script?.removeEventListener("error", onError);
|
|
66
|
+
};
|
|
67
|
+
const onLoad = () => {
|
|
68
|
+
cleanup();
|
|
69
|
+
const api = window.Rezfiliate;
|
|
70
|
+
if (!isApi(api, platform)) {
|
|
71
|
+
reject(new Error(`The Rezfiliate ${platform} SDK loaded without its expected API.`));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
resolve(api);
|
|
75
|
+
};
|
|
76
|
+
const onError = () => {
|
|
77
|
+
cleanup();
|
|
78
|
+
reject(new Error(`Could not load the Rezfiliate ${platform} SDK from ${url}.`));
|
|
79
|
+
};
|
|
80
|
+
script.addEventListener("load", onLoad, { once: true });
|
|
81
|
+
script.addEventListener("error", onError, { once: true });
|
|
82
|
+
if (isNewScript)
|
|
83
|
+
document.head.appendChild(script);
|
|
84
|
+
});
|
|
85
|
+
pendingLoads.set(url, loading);
|
|
86
|
+
loading.catch(() => pendingLoads.delete(url));
|
|
87
|
+
return loading;
|
|
88
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rezfiliate/sdk",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "Typed browser loader and API for Rezfiliate storefront SDKs",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc -p tsconfig.json",
|
|
21
|
+
"prepublishOnly": "npm run build"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"typescript": "^5.8.3"
|
|
25
|
+
},
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
}
|
|
29
|
+
}
|