@followgate/js 0.3.0 → 0.5.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.d.mts +74 -50
- package/dist/index.d.ts +74 -50
- package/dist/index.js +223 -194
- package/dist/index.mjs +221 -193
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -21,281 +21,249 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
FollowGate: () => FollowGate,
|
|
24
|
-
FollowGateClient: () => FollowGateClient
|
|
24
|
+
FollowGateClient: () => FollowGateClient,
|
|
25
|
+
FollowGateError: () => FollowGateError
|
|
25
26
|
});
|
|
26
27
|
module.exports = __toCommonJS(index_exports);
|
|
27
28
|
var DEFAULT_API_URL = "https://api.followgate.app";
|
|
29
|
+
var FollowGateError = class extends Error {
|
|
30
|
+
constructor(message, code, hint) {
|
|
31
|
+
super(message);
|
|
32
|
+
this.code = code;
|
|
33
|
+
this.hint = hint;
|
|
34
|
+
this.name = "FollowGateError";
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
function isValidApiKeyFormat(apiKey) {
|
|
38
|
+
return /^fg_(live|test)_[a-zA-Z0-9_-]+$/.test(apiKey);
|
|
39
|
+
}
|
|
28
40
|
var FollowGateClient = class {
|
|
29
41
|
config = null;
|
|
30
42
|
listeners = /* @__PURE__ */ new Map();
|
|
31
43
|
currentUser = null;
|
|
32
|
-
|
|
33
|
-
pendingUsername = null;
|
|
44
|
+
completedActions = [];
|
|
34
45
|
/**
|
|
35
46
|
* Initialize the SDK
|
|
47
|
+
* @throws {FollowGateError} If configuration is invalid
|
|
36
48
|
*/
|
|
37
49
|
init(config) {
|
|
50
|
+
if (!config.appId || typeof config.appId !== "string") {
|
|
51
|
+
throw new FollowGateError(
|
|
52
|
+
"[FollowGate] Missing or invalid appId",
|
|
53
|
+
"INVALID_APP_ID",
|
|
54
|
+
"Get your App ID from https://followgate.app/dashboard. Make sure NEXT_PUBLIC_FOLLOWGATE_APP_ID is set in your environment."
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
if (config.appId.trim() === "" || config.appId === "undefined") {
|
|
58
|
+
throw new FollowGateError(
|
|
59
|
+
"[FollowGate] appId is empty or undefined",
|
|
60
|
+
"EMPTY_APP_ID",
|
|
61
|
+
"Your appId appears to be empty. This often happens when environment variables are not properly configured. Check that NEXT_PUBLIC_FOLLOWGATE_APP_ID is set and rebuild your application."
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
if (!config.apiKey || typeof config.apiKey !== "string") {
|
|
65
|
+
throw new FollowGateError(
|
|
66
|
+
"[FollowGate] Missing or invalid apiKey",
|
|
67
|
+
"INVALID_API_KEY",
|
|
68
|
+
"Get your API Key from https://followgate.app/dashboard. Make sure NEXT_PUBLIC_FOLLOWGATE_API_KEY is set in your environment."
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
if (config.apiKey.trim() === "" || config.apiKey === "undefined") {
|
|
72
|
+
throw new FollowGateError(
|
|
73
|
+
"[FollowGate] apiKey is empty or undefined",
|
|
74
|
+
"EMPTY_API_KEY",
|
|
75
|
+
"Your apiKey appears to be empty. This often happens when environment variables are not properly configured at BUILD TIME (not runtime). Set NEXT_PUBLIC_FOLLOWGATE_API_KEY and REBUILD your application."
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
if (!isValidApiKeyFormat(config.apiKey)) {
|
|
79
|
+
throw new FollowGateError(
|
|
80
|
+
`[FollowGate] Invalid API key format: "${config.apiKey.substring(0, 10)}..."`,
|
|
81
|
+
"INVALID_API_KEY_FORMAT",
|
|
82
|
+
'API keys should start with "fg_live_" (production) or "fg_test_" (development). Get a valid key from https://followgate.app/dashboard'
|
|
83
|
+
);
|
|
84
|
+
}
|
|
38
85
|
this.config = {
|
|
39
86
|
...config,
|
|
40
87
|
apiUrl: config.apiUrl || DEFAULT_API_URL
|
|
41
88
|
};
|
|
42
|
-
this.handleAuthCallback();
|
|
43
89
|
this.restoreSession();
|
|
44
90
|
if (config.debug) {
|
|
45
91
|
console.log("[FollowGate] Initialized with appId:", config.appId);
|
|
92
|
+
console.log(
|
|
93
|
+
"[FollowGate] API Key:",
|
|
94
|
+
config.apiKey.substring(0, 12) + "..."
|
|
95
|
+
);
|
|
46
96
|
if (this.currentUser) {
|
|
47
97
|
console.log("[FollowGate] Restored user:", this.currentUser.username);
|
|
48
98
|
}
|
|
49
99
|
}
|
|
50
100
|
}
|
|
51
101
|
/**
|
|
52
|
-
*
|
|
53
|
-
* This
|
|
102
|
+
* Set the user's social username
|
|
103
|
+
* This is the main entry point - no OAuth needed!
|
|
54
104
|
*/
|
|
55
|
-
|
|
105
|
+
setUsername(username, platform = "twitter") {
|
|
56
106
|
if (!this.config) {
|
|
57
107
|
throw new Error("[FollowGate] SDK not initialized. Call init() first.");
|
|
58
108
|
}
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
109
|
+
const normalizedUsername = username.startsWith("@") ? username.slice(1) : username;
|
|
110
|
+
this.currentUser = {
|
|
111
|
+
username: normalizedUsername,
|
|
112
|
+
platform
|
|
113
|
+
};
|
|
114
|
+
if (typeof localStorage !== "undefined") {
|
|
115
|
+
localStorage.setItem("followgate_user", JSON.stringify(this.currentUser));
|
|
63
116
|
}
|
|
64
|
-
if (
|
|
65
|
-
|
|
66
|
-
authUrl,
|
|
67
|
-
"followgate_auth",
|
|
68
|
-
"width=600,height=700"
|
|
69
|
-
);
|
|
70
|
-
if (!popup) {
|
|
71
|
-
this.emit("error", { message: "Popup blocked" });
|
|
72
|
-
}
|
|
73
|
-
} else {
|
|
74
|
-
window.location.href = authUrl;
|
|
117
|
+
if (this.config.debug) {
|
|
118
|
+
console.log("[FollowGate] Username set:", normalizedUsername);
|
|
75
119
|
}
|
|
76
120
|
}
|
|
77
121
|
/**
|
|
78
|
-
* Get current
|
|
122
|
+
* Get current user
|
|
79
123
|
*/
|
|
80
124
|
getUser() {
|
|
81
125
|
return this.currentUser;
|
|
82
126
|
}
|
|
83
127
|
/**
|
|
84
|
-
* Check if
|
|
128
|
+
* Check if username is set
|
|
85
129
|
*/
|
|
86
|
-
|
|
87
|
-
return this.currentUser !== null
|
|
130
|
+
hasUsername() {
|
|
131
|
+
return this.currentUser !== null;
|
|
88
132
|
}
|
|
89
133
|
/**
|
|
90
|
-
*
|
|
134
|
+
* Clear stored session
|
|
91
135
|
*/
|
|
92
|
-
|
|
136
|
+
reset() {
|
|
93
137
|
this.currentUser = null;
|
|
94
|
-
this.
|
|
95
|
-
this.pendingUsername = null;
|
|
138
|
+
this.completedActions = [];
|
|
96
139
|
if (typeof localStorage !== "undefined") {
|
|
97
|
-
localStorage.removeItem("followgate_token");
|
|
98
140
|
localStorage.removeItem("followgate_user");
|
|
99
|
-
localStorage.removeItem("
|
|
141
|
+
localStorage.removeItem("followgate_actions");
|
|
142
|
+
localStorage.removeItem("followgate_unlocked");
|
|
100
143
|
}
|
|
101
144
|
if (this.config?.debug) {
|
|
102
|
-
console.log("[FollowGate]
|
|
145
|
+
console.log("[FollowGate] Session reset");
|
|
103
146
|
}
|
|
104
147
|
}
|
|
148
|
+
// ============================================
|
|
149
|
+
// Intent URL Methods
|
|
150
|
+
// ============================================
|
|
105
151
|
/**
|
|
106
|
-
*
|
|
152
|
+
* Get follow intent URL for a platform
|
|
107
153
|
*/
|
|
108
|
-
|
|
109
|
-
return this.
|
|
154
|
+
getFollowUrl(platform, target) {
|
|
155
|
+
return this.buildIntentUrl({ platform, action: "follow", target });
|
|
110
156
|
}
|
|
111
157
|
/**
|
|
112
|
-
*
|
|
158
|
+
* Get repost/retweet intent URL for a platform
|
|
113
159
|
*/
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
throw new Error(
|
|
117
|
-
"[FollowGate] No pending username state. User is either not authenticated or username is already set."
|
|
118
|
-
);
|
|
119
|
-
}
|
|
120
|
-
const normalizedUsername = username.startsWith("@") ? username.slice(1) : username;
|
|
121
|
-
this.currentUser = {
|
|
122
|
-
userId: "user_input",
|
|
123
|
-
username: normalizedUsername,
|
|
124
|
-
platform: "twitter"
|
|
125
|
-
};
|
|
126
|
-
this.authToken = this.pendingUsername.token;
|
|
127
|
-
if (typeof localStorage !== "undefined") {
|
|
128
|
-
localStorage.setItem("followgate_token", this.authToken);
|
|
129
|
-
localStorage.setItem("followgate_user", JSON.stringify(this.currentUser));
|
|
130
|
-
localStorage.removeItem("followgate_pending_username");
|
|
131
|
-
}
|
|
132
|
-
this.pendingUsername = null;
|
|
133
|
-
this.emit("authenticated", this.currentUser);
|
|
134
|
-
if (this.config?.debug) {
|
|
135
|
-
console.log("[FollowGate] Username set manually:", normalizedUsername);
|
|
136
|
-
}
|
|
160
|
+
getRepostUrl(platform, target) {
|
|
161
|
+
return this.buildIntentUrl({ platform, action: "repost", target });
|
|
137
162
|
}
|
|
138
163
|
/**
|
|
139
|
-
*
|
|
164
|
+
* Get like intent URL for a platform
|
|
140
165
|
*/
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
const params = new URLSearchParams(window.location.search);
|
|
144
|
-
const token = params.get("followgate_token");
|
|
145
|
-
const username = params.get("followgate_user");
|
|
146
|
-
const needsUsername = params.get("followgate_needs_username") === "true";
|
|
147
|
-
if (token && needsUsername) {
|
|
148
|
-
this.pendingUsername = {
|
|
149
|
-
needsUsername: true,
|
|
150
|
-
token
|
|
151
|
-
};
|
|
152
|
-
if (typeof localStorage !== "undefined") {
|
|
153
|
-
localStorage.setItem(
|
|
154
|
-
"followgate_pending_username",
|
|
155
|
-
JSON.stringify(this.pendingUsername)
|
|
156
|
-
);
|
|
157
|
-
}
|
|
158
|
-
const url = new URL(window.location.href);
|
|
159
|
-
url.searchParams.delete("followgate_token");
|
|
160
|
-
url.searchParams.delete("followgate_needs_username");
|
|
161
|
-
window.history.replaceState({}, "", url.toString());
|
|
162
|
-
if (this.config?.debug) {
|
|
163
|
-
console.log("[FollowGate] OAuth successful, username input needed");
|
|
164
|
-
}
|
|
165
|
-
} else if (token && username) {
|
|
166
|
-
this.authToken = token;
|
|
167
|
-
this.currentUser = {
|
|
168
|
-
userId: "",
|
|
169
|
-
// Will be set from token verification
|
|
170
|
-
username,
|
|
171
|
-
platform: "twitter"
|
|
172
|
-
};
|
|
173
|
-
if (typeof localStorage !== "undefined") {
|
|
174
|
-
localStorage.setItem("followgate_token", token);
|
|
175
|
-
localStorage.setItem(
|
|
176
|
-
"followgate_user",
|
|
177
|
-
JSON.stringify(this.currentUser)
|
|
178
|
-
);
|
|
179
|
-
}
|
|
180
|
-
const url = new URL(window.location.href);
|
|
181
|
-
url.searchParams.delete("followgate_token");
|
|
182
|
-
url.searchParams.delete("followgate_user");
|
|
183
|
-
window.history.replaceState({}, "", url.toString());
|
|
184
|
-
this.emit("authenticated", this.currentUser);
|
|
185
|
-
if (this.config?.debug) {
|
|
186
|
-
console.log("[FollowGate] User authenticated:", username);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
166
|
+
getLikeUrl(platform, target) {
|
|
167
|
+
return this.buildIntentUrl({ platform, action: "like", target });
|
|
189
168
|
}
|
|
190
169
|
/**
|
|
191
|
-
*
|
|
170
|
+
* Open intent URL in new window
|
|
192
171
|
*/
|
|
193
|
-
|
|
194
|
-
if (
|
|
195
|
-
|
|
196
|
-
if (pendingJson) {
|
|
197
|
-
try {
|
|
198
|
-
this.pendingUsername = JSON.parse(pendingJson);
|
|
199
|
-
if (this.config?.debug) {
|
|
200
|
-
console.log("[FollowGate] Restored pending username state");
|
|
201
|
-
}
|
|
202
|
-
return;
|
|
203
|
-
} catch {
|
|
204
|
-
localStorage.removeItem("followgate_pending_username");
|
|
205
|
-
}
|
|
172
|
+
async openIntent(options) {
|
|
173
|
+
if (!this.config) {
|
|
174
|
+
throw new Error("[FollowGate] SDK not initialized. Call init() first.");
|
|
206
175
|
}
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
try {
|
|
211
|
-
this.authToken = token;
|
|
212
|
-
this.currentUser = JSON.parse(userJson);
|
|
213
|
-
} catch {
|
|
214
|
-
localStorage.removeItem("followgate_token");
|
|
215
|
-
localStorage.removeItem("followgate_user");
|
|
216
|
-
}
|
|
176
|
+
const url = this.buildIntentUrl(options);
|
|
177
|
+
if (this.config.debug) {
|
|
178
|
+
console.log("[FollowGate] Opening intent:", url);
|
|
217
179
|
}
|
|
180
|
+
await this.trackEvent("intent_opened", { ...options });
|
|
181
|
+
window.open(url, "_blank", "width=600,height=700");
|
|
218
182
|
}
|
|
183
|
+
// ============================================
|
|
184
|
+
// Completion Methods
|
|
185
|
+
// ============================================
|
|
219
186
|
/**
|
|
220
|
-
*
|
|
187
|
+
* Mark an action as completed (trust-first)
|
|
188
|
+
* Call this when user confirms they did the action
|
|
221
189
|
*/
|
|
222
|
-
async
|
|
190
|
+
async complete(options) {
|
|
223
191
|
if (!this.config) {
|
|
224
192
|
throw new Error("[FollowGate] SDK not initialized. Call init() first.");
|
|
225
193
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
194
|
+
if (!this.currentUser) {
|
|
195
|
+
throw new Error(
|
|
196
|
+
"[FollowGate] No username set. Call setUsername() first."
|
|
197
|
+
);
|
|
229
198
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
199
|
+
const alreadyCompleted = this.completedActions.some(
|
|
200
|
+
(a) => a.platform === options.platform && a.action === options.action && a.target === options.target
|
|
201
|
+
);
|
|
202
|
+
if (!alreadyCompleted) {
|
|
203
|
+
this.completedActions.push(options);
|
|
204
|
+
this.saveCompletedActions();
|
|
235
205
|
}
|
|
236
|
-
await this.trackEvent("
|
|
206
|
+
await this.trackEvent("action_completed", {
|
|
207
|
+
...options,
|
|
208
|
+
username: this.currentUser.username
|
|
209
|
+
});
|
|
237
210
|
this.emit("complete", {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
target: options.target
|
|
211
|
+
...options,
|
|
212
|
+
username: this.currentUser.username
|
|
241
213
|
});
|
|
214
|
+
if (this.config.debug) {
|
|
215
|
+
console.log("[FollowGate] Action completed:", options);
|
|
216
|
+
}
|
|
242
217
|
}
|
|
243
218
|
/**
|
|
244
|
-
*
|
|
219
|
+
* Mark the gate as unlocked
|
|
220
|
+
* Call this when all required actions are done
|
|
245
221
|
*/
|
|
246
|
-
async
|
|
222
|
+
async unlock() {
|
|
247
223
|
if (!this.config) {
|
|
248
224
|
throw new Error("[FollowGate] SDK not initialized. Call init() first.");
|
|
249
225
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
});
|
|
264
|
-
const data = await response.json();
|
|
265
|
-
return data.success && data.data?.verified === true;
|
|
266
|
-
} catch (error) {
|
|
267
|
-
if (this.config.debug) {
|
|
268
|
-
console.error("[FollowGate] Verification error:", error);
|
|
269
|
-
}
|
|
270
|
-
return false;
|
|
226
|
+
if (typeof localStorage !== "undefined") {
|
|
227
|
+
localStorage.setItem("followgate_unlocked", "true");
|
|
228
|
+
}
|
|
229
|
+
await this.trackEvent("gate_unlocked", {
|
|
230
|
+
username: this.currentUser?.username,
|
|
231
|
+
actions: this.completedActions
|
|
232
|
+
});
|
|
233
|
+
this.emit("unlocked", {
|
|
234
|
+
username: this.currentUser?.username,
|
|
235
|
+
actions: this.completedActions
|
|
236
|
+
});
|
|
237
|
+
if (this.config.debug) {
|
|
238
|
+
console.log("[FollowGate] Gate unlocked!");
|
|
271
239
|
}
|
|
272
240
|
}
|
|
273
241
|
/**
|
|
274
|
-
*
|
|
242
|
+
* Check if gate is unlocked
|
|
275
243
|
*/
|
|
276
|
-
|
|
277
|
-
if (
|
|
278
|
-
|
|
279
|
-
await fetch(`${this.config.apiUrl}/api/v1/events`, {
|
|
280
|
-
method: "POST",
|
|
281
|
-
headers: {
|
|
282
|
-
"Content-Type": "application/json",
|
|
283
|
-
"X-API-Key": this.config.apiKey
|
|
284
|
-
},
|
|
285
|
-
body: JSON.stringify({
|
|
286
|
-
event,
|
|
287
|
-
platform: options.platform,
|
|
288
|
-
action: options.action,
|
|
289
|
-
target: options.target,
|
|
290
|
-
externalUserId: options.userId
|
|
291
|
-
})
|
|
292
|
-
});
|
|
293
|
-
} catch (error) {
|
|
294
|
-
if (this.config.debug) {
|
|
295
|
-
console.warn("[FollowGate] Failed to track event:", error);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
244
|
+
isUnlocked() {
|
|
245
|
+
if (typeof localStorage === "undefined") return false;
|
|
246
|
+
return localStorage.getItem("followgate_unlocked") === "true";
|
|
298
247
|
}
|
|
248
|
+
/**
|
|
249
|
+
* Get unlock status with details
|
|
250
|
+
*/
|
|
251
|
+
getUnlockStatus() {
|
|
252
|
+
return {
|
|
253
|
+
unlocked: this.isUnlocked(),
|
|
254
|
+
username: this.currentUser?.username,
|
|
255
|
+
completedActions: [...this.completedActions]
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Get completed actions
|
|
260
|
+
*/
|
|
261
|
+
getCompletedActions() {
|
|
262
|
+
return [...this.completedActions];
|
|
263
|
+
}
|
|
264
|
+
// ============================================
|
|
265
|
+
// Event System
|
|
266
|
+
// ============================================
|
|
299
267
|
/**
|
|
300
268
|
* Register event listener
|
|
301
269
|
*/
|
|
@@ -311,6 +279,42 @@ var FollowGateClient = class {
|
|
|
311
279
|
off(event, callback) {
|
|
312
280
|
this.listeners.get(event)?.delete(callback);
|
|
313
281
|
}
|
|
282
|
+
// ============================================
|
|
283
|
+
// Private Methods
|
|
284
|
+
// ============================================
|
|
285
|
+
/**
|
|
286
|
+
* Restore session from localStorage
|
|
287
|
+
*/
|
|
288
|
+
restoreSession() {
|
|
289
|
+
if (typeof localStorage === "undefined") return;
|
|
290
|
+
const userJson = localStorage.getItem("followgate_user");
|
|
291
|
+
if (userJson) {
|
|
292
|
+
try {
|
|
293
|
+
this.currentUser = JSON.parse(userJson);
|
|
294
|
+
} catch {
|
|
295
|
+
localStorage.removeItem("followgate_user");
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
const actionsJson = localStorage.getItem("followgate_actions");
|
|
299
|
+
if (actionsJson) {
|
|
300
|
+
try {
|
|
301
|
+
this.completedActions = JSON.parse(actionsJson);
|
|
302
|
+
} catch {
|
|
303
|
+
localStorage.removeItem("followgate_actions");
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Save completed actions to localStorage
|
|
309
|
+
*/
|
|
310
|
+
saveCompletedActions() {
|
|
311
|
+
if (typeof localStorage !== "undefined") {
|
|
312
|
+
localStorage.setItem(
|
|
313
|
+
"followgate_actions",
|
|
314
|
+
JSON.stringify(this.completedActions)
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
314
318
|
/**
|
|
315
319
|
* Build intent URL for platform
|
|
316
320
|
*/
|
|
@@ -372,6 +376,30 @@ var FollowGateClient = class {
|
|
|
372
376
|
throw new Error(`[FollowGate] Unsupported LinkedIn action: ${action}`);
|
|
373
377
|
}
|
|
374
378
|
}
|
|
379
|
+
/**
|
|
380
|
+
* Track analytics event
|
|
381
|
+
*/
|
|
382
|
+
async trackEvent(event, data) {
|
|
383
|
+
if (!this.config) return;
|
|
384
|
+
try {
|
|
385
|
+
await fetch(`${this.config.apiUrl}/api/v1/events`, {
|
|
386
|
+
method: "POST",
|
|
387
|
+
headers: {
|
|
388
|
+
"Content-Type": "application/json",
|
|
389
|
+
"X-API-Key": this.config.apiKey
|
|
390
|
+
},
|
|
391
|
+
body: JSON.stringify({
|
|
392
|
+
event,
|
|
393
|
+
appId: this.config.appId,
|
|
394
|
+
...data
|
|
395
|
+
})
|
|
396
|
+
});
|
|
397
|
+
} catch (error) {
|
|
398
|
+
if (this.config.debug) {
|
|
399
|
+
console.warn("[FollowGate] Failed to track event:", error);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
375
403
|
emit(event, data) {
|
|
376
404
|
this.listeners.get(event)?.forEach((callback) => callback(data));
|
|
377
405
|
}
|
|
@@ -380,5 +408,6 @@ var FollowGate = new FollowGateClient();
|
|
|
380
408
|
// Annotate the CommonJS export names for ESM import in node:
|
|
381
409
|
0 && (module.exports = {
|
|
382
410
|
FollowGate,
|
|
383
|
-
FollowGateClient
|
|
411
|
+
FollowGateClient,
|
|
412
|
+
FollowGateError
|
|
384
413
|
});
|