@followgate/js 0.1.0 → 0.3.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/README.md CHANGED
@@ -32,11 +32,11 @@ FollowGate.open({
32
32
 
33
33
  ## Supported Platforms
34
34
 
35
- | Platform | Actions |
36
- |----------|---------|
35
+ | Platform | Actions |
36
+ | --------- | -------------------------- |
37
37
  | Twitter/X | `follow`, `repost`, `like` |
38
- | Bluesky | `follow`, `repost`, `like` |
39
- | LinkedIn | `follow` |
38
+ | Bluesky | `follow`, `repost`, `like` |
39
+ | LinkedIn | `follow` |
40
40
 
41
41
  ## API Reference
42
42
 
@@ -46,10 +46,10 @@ Initialize the SDK with your credentials.
46
46
 
47
47
  ```typescript
48
48
  FollowGate.init({
49
- appId: 'your-app-id', // Required: Your app ID from dashboard
50
- apiKey: 'fg_live_xxx', // Required: Your API key
51
- apiUrl: 'https://...', // Optional: Custom API URL
52
- debug: false, // Optional: Enable debug logging
49
+ appId: 'your-app-id', // Required: Your app ID from dashboard
50
+ apiKey: 'fg_live_xxx', // Required: Your API key
51
+ apiUrl: 'https://...', // Optional: Custom API URL
52
+ debug: false, // Optional: Enable debug logging
53
53
  });
54
54
  ```
55
55
 
@@ -59,10 +59,10 @@ Open a social action popup/intent.
59
59
 
60
60
  ```typescript
61
61
  await FollowGate.open({
62
- platform: 'twitter', // 'twitter' | 'bluesky' | 'linkedin'
63
- action: 'follow', // 'follow' | 'repost' | 'like'
64
- target: 'username', // Username or post ID
65
- userId: 'user-123', // Optional: Your app's user ID
62
+ platform: 'twitter', // 'twitter' | 'bluesky' | 'linkedin'
63
+ action: 'follow', // 'follow' | 'repost' | 'like'
64
+ target: 'username', // Username or post ID
65
+ userId: 'user-123', // Optional: Your app's user ID
66
66
  });
67
67
  ```
68
68
 
@@ -106,7 +106,11 @@ FollowGate.on('error', (error) => {
106
106
  FollowGate.open({ platform: 'twitter', action: 'follow', target: 'elonmusk' });
107
107
 
108
108
  // Repost a tweet
109
- FollowGate.open({ platform: 'twitter', action: 'repost', target: '1234567890' });
109
+ FollowGate.open({
110
+ platform: 'twitter',
111
+ action: 'repost',
112
+ target: '1234567890',
113
+ });
110
114
  ```
111
115
 
112
116
  ### Bluesky
@@ -116,7 +120,11 @@ FollowGate.open({ platform: 'twitter', action: 'repost', target: '1234567890' })
116
120
 
117
121
  ```typescript
118
122
  // Follow
119
- FollowGate.open({ platform: 'bluesky', action: 'follow', target: 'alice.bsky.social' });
123
+ FollowGate.open({
124
+ platform: 'bluesky',
125
+ action: 'follow',
126
+ target: 'alice.bsky.social',
127
+ });
120
128
  ```
121
129
 
122
130
  ### LinkedIn
@@ -125,19 +133,27 @@ FollowGate.open({ platform: 'bluesky', action: 'follow', target: 'alice.bsky.soc
125
133
 
126
134
  ```typescript
127
135
  // Follow a company
128
- FollowGate.open({ platform: 'linkedin', action: 'follow', target: 'microsoft' });
136
+ FollowGate.open({
137
+ platform: 'linkedin',
138
+ action: 'follow',
139
+ target: 'microsoft',
140
+ });
129
141
 
130
142
  // Follow a personal profile
131
- FollowGate.open({ platform: 'linkedin', action: 'follow', target: 'in:satyanadella' });
143
+ FollowGate.open({
144
+ platform: 'linkedin',
145
+ action: 'follow',
146
+ target: 'in:satyanadella',
147
+ });
132
148
  ```
133
149
 
134
150
  ## Pricing
135
151
 
136
- | Tier | Price | Users | Verification |
137
- |------|-------|-------|--------------|
138
- | Free | $0 | 100 | Intent-URL only |
139
- | Starter | $15/mo | 500 | Weekly sampling |
140
- | Pro | $49/mo | 2,000 | OAuth verification |
152
+ | Tier | Price | Users | Verification |
153
+ | -------- | ------ | ------ | ------------------ |
154
+ | Free | $0 | 100 | Intent-URL only |
155
+ | Starter | $15/mo | 500 | Weekly sampling |
156
+ | Pro | $49/mo | 2,000 | OAuth verification |
141
157
  | Business | $99/mo | 5,000+ | Daily verification |
142
158
 
143
159
  ## TypeScript
package/dist/index.d.mts CHANGED
@@ -31,21 +31,81 @@ type LinkedInTargetType = 'company' | 'profile';
31
31
  /**
32
32
  * Event types
33
33
  */
34
- type EventType = 'complete' | 'error' | 'cancel';
34
+ type EventType = 'complete' | 'error' | 'cancel' | 'authenticated';
35
35
  /**
36
36
  * Event callback
37
37
  */
38
38
  type EventCallback = (data: unknown) => void;
39
+ /**
40
+ * Authenticated user info
41
+ */
42
+ interface AuthenticatedUser {
43
+ userId: string;
44
+ username: string;
45
+ platform: Platform;
46
+ }
47
+ /**
48
+ * Auth state when username input is needed
49
+ */
50
+ interface PendingUsernameState {
51
+ needsUsername: true;
52
+ token: string;
53
+ }
54
+ /**
55
+ * Authentication options
56
+ */
57
+ interface AuthOptions {
58
+ /** Where to redirect after auth (defaults to current page) */
59
+ redirectUri?: string;
60
+ /** Open in popup instead of redirect */
61
+ popup?: boolean;
62
+ }
39
63
  /**
40
64
  * FollowGate SDK Client
41
65
  */
42
66
  declare class FollowGateClient {
43
67
  private config;
44
68
  private listeners;
69
+ private currentUser;
70
+ private authToken;
71
+ private pendingUsername;
45
72
  /**
46
73
  * Initialize the SDK
47
74
  */
48
75
  init(config: FollowGateConfig): void;
76
+ /**
77
+ * Authenticate user via Twitter OAuth (handled by FollowGate)
78
+ * This identifies WHO is completing the social actions.
79
+ */
80
+ authenticate(options?: AuthOptions): void;
81
+ /**
82
+ * Get current authenticated user
83
+ */
84
+ getUser(): AuthenticatedUser | null;
85
+ /**
86
+ * Check if user is authenticated
87
+ */
88
+ isAuthenticated(): boolean;
89
+ /**
90
+ * Logout - clear stored session
91
+ */
92
+ logout(): void;
93
+ /**
94
+ * Check if username input is needed (Twitter Free Tier limitation)
95
+ */
96
+ needsUsernameInput(): boolean;
97
+ /**
98
+ * Set username manually (when needsUsernameInput() returns true)
99
+ */
100
+ setUsername(username: string): void;
101
+ /**
102
+ * Handle auth callback from URL params
103
+ */
104
+ private handleAuthCallback;
105
+ /**
106
+ * Restore session from localStorage
107
+ */
108
+ private restoreSession;
49
109
  /**
50
110
  * Open social action popup
51
111
  */
@@ -77,4 +137,4 @@ declare class FollowGateClient {
77
137
  }
78
138
  declare const FollowGate: FollowGateClient;
79
139
 
80
- export { type EventCallback, type EventType, FollowGate, FollowGateClient, type FollowGateConfig, type LinkedInTargetType, type OpenOptions, type Platform, type SocialAction };
140
+ export { type AuthOptions, type AuthenticatedUser, type EventCallback, type EventType, FollowGate, FollowGateClient, type FollowGateConfig, type LinkedInTargetType, type OpenOptions, type PendingUsernameState, type Platform, type SocialAction };
package/dist/index.d.ts CHANGED
@@ -31,21 +31,81 @@ type LinkedInTargetType = 'company' | 'profile';
31
31
  /**
32
32
  * Event types
33
33
  */
34
- type EventType = 'complete' | 'error' | 'cancel';
34
+ type EventType = 'complete' | 'error' | 'cancel' | 'authenticated';
35
35
  /**
36
36
  * Event callback
37
37
  */
38
38
  type EventCallback = (data: unknown) => void;
39
+ /**
40
+ * Authenticated user info
41
+ */
42
+ interface AuthenticatedUser {
43
+ userId: string;
44
+ username: string;
45
+ platform: Platform;
46
+ }
47
+ /**
48
+ * Auth state when username input is needed
49
+ */
50
+ interface PendingUsernameState {
51
+ needsUsername: true;
52
+ token: string;
53
+ }
54
+ /**
55
+ * Authentication options
56
+ */
57
+ interface AuthOptions {
58
+ /** Where to redirect after auth (defaults to current page) */
59
+ redirectUri?: string;
60
+ /** Open in popup instead of redirect */
61
+ popup?: boolean;
62
+ }
39
63
  /**
40
64
  * FollowGate SDK Client
41
65
  */
42
66
  declare class FollowGateClient {
43
67
  private config;
44
68
  private listeners;
69
+ private currentUser;
70
+ private authToken;
71
+ private pendingUsername;
45
72
  /**
46
73
  * Initialize the SDK
47
74
  */
48
75
  init(config: FollowGateConfig): void;
76
+ /**
77
+ * Authenticate user via Twitter OAuth (handled by FollowGate)
78
+ * This identifies WHO is completing the social actions.
79
+ */
80
+ authenticate(options?: AuthOptions): void;
81
+ /**
82
+ * Get current authenticated user
83
+ */
84
+ getUser(): AuthenticatedUser | null;
85
+ /**
86
+ * Check if user is authenticated
87
+ */
88
+ isAuthenticated(): boolean;
89
+ /**
90
+ * Logout - clear stored session
91
+ */
92
+ logout(): void;
93
+ /**
94
+ * Check if username input is needed (Twitter Free Tier limitation)
95
+ */
96
+ needsUsernameInput(): boolean;
97
+ /**
98
+ * Set username manually (when needsUsernameInput() returns true)
99
+ */
100
+ setUsername(username: string): void;
101
+ /**
102
+ * Handle auth callback from URL params
103
+ */
104
+ private handleAuthCallback;
105
+ /**
106
+ * Restore session from localStorage
107
+ */
108
+ private restoreSession;
49
109
  /**
50
110
  * Open social action popup
51
111
  */
@@ -77,4 +137,4 @@ declare class FollowGateClient {
77
137
  }
78
138
  declare const FollowGate: FollowGateClient;
79
139
 
80
- export { type EventCallback, type EventType, FollowGate, FollowGateClient, type FollowGateConfig, type LinkedInTargetType, type OpenOptions, type Platform, type SocialAction };
140
+ export { type AuthOptions, type AuthenticatedUser, type EventCallback, type EventType, FollowGate, FollowGateClient, type FollowGateConfig, type LinkedInTargetType, type OpenOptions, type PendingUsernameState, type Platform, type SocialAction };
package/dist/index.js CHANGED
@@ -24,10 +24,13 @@ __export(index_exports, {
24
24
  FollowGateClient: () => FollowGateClient
25
25
  });
26
26
  module.exports = __toCommonJS(index_exports);
27
- var DEFAULT_API_URL = "https://api.followgate.io";
27
+ var DEFAULT_API_URL = "https://api.followgate.app";
28
28
  var FollowGateClient = class {
29
29
  config = null;
30
30
  listeners = /* @__PURE__ */ new Map();
31
+ currentUser = null;
32
+ authToken = null;
33
+ pendingUsername = null;
31
34
  /**
32
35
  * Initialize the SDK
33
36
  */
@@ -36,8 +39,181 @@ var FollowGateClient = class {
36
39
  ...config,
37
40
  apiUrl: config.apiUrl || DEFAULT_API_URL
38
41
  };
42
+ this.handleAuthCallback();
43
+ this.restoreSession();
39
44
  if (config.debug) {
40
45
  console.log("[FollowGate] Initialized with appId:", config.appId);
46
+ if (this.currentUser) {
47
+ console.log("[FollowGate] Restored user:", this.currentUser.username);
48
+ }
49
+ }
50
+ }
51
+ /**
52
+ * Authenticate user via Twitter OAuth (handled by FollowGate)
53
+ * This identifies WHO is completing the social actions.
54
+ */
55
+ authenticate(options = {}) {
56
+ if (!this.config) {
57
+ throw new Error("[FollowGate] SDK not initialized. Call init() first.");
58
+ }
59
+ const redirectUri = options.redirectUri || window.location.href.split("?")[0];
60
+ const authUrl = `${this.config.apiUrl}/api/v1/auth/twitter?app_id=${encodeURIComponent(this.config.appId)}&redirect_uri=${encodeURIComponent(redirectUri)}`;
61
+ if (this.config.debug) {
62
+ console.log("[FollowGate] Starting auth flow:", authUrl);
63
+ }
64
+ if (options.popup) {
65
+ const popup = window.open(
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;
75
+ }
76
+ }
77
+ /**
78
+ * Get current authenticated user
79
+ */
80
+ getUser() {
81
+ return this.currentUser;
82
+ }
83
+ /**
84
+ * Check if user is authenticated
85
+ */
86
+ isAuthenticated() {
87
+ return this.currentUser !== null && this.authToken !== null;
88
+ }
89
+ /**
90
+ * Logout - clear stored session
91
+ */
92
+ logout() {
93
+ this.currentUser = null;
94
+ this.authToken = null;
95
+ this.pendingUsername = null;
96
+ if (typeof localStorage !== "undefined") {
97
+ localStorage.removeItem("followgate_token");
98
+ localStorage.removeItem("followgate_user");
99
+ localStorage.removeItem("followgate_pending_username");
100
+ }
101
+ if (this.config?.debug) {
102
+ console.log("[FollowGate] User logged out");
103
+ }
104
+ }
105
+ /**
106
+ * Check if username input is needed (Twitter Free Tier limitation)
107
+ */
108
+ needsUsernameInput() {
109
+ return this.pendingUsername !== null;
110
+ }
111
+ /**
112
+ * Set username manually (when needsUsernameInput() returns true)
113
+ */
114
+ setUsername(username) {
115
+ if (!this.pendingUsername) {
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
+ }
137
+ }
138
+ /**
139
+ * Handle auth callback from URL params
140
+ */
141
+ handleAuthCallback() {
142
+ if (typeof window === "undefined") return;
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
+ }
189
+ }
190
+ /**
191
+ * Restore session from localStorage
192
+ */
193
+ restoreSession() {
194
+ if (typeof localStorage === "undefined") return;
195
+ const pendingJson = localStorage.getItem("followgate_pending_username");
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
+ }
206
+ }
207
+ const token = localStorage.getItem("followgate_token");
208
+ const userJson = localStorage.getItem("followgate_user");
209
+ if (token && userJson) {
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
+ }
41
217
  }
42
218
  }
43
219
  /**
package/dist/index.mjs CHANGED
@@ -1,8 +1,11 @@
1
1
  // src/index.ts
2
- var DEFAULT_API_URL = "https://api.followgate.io";
2
+ var DEFAULT_API_URL = "https://api.followgate.app";
3
3
  var FollowGateClient = class {
4
4
  config = null;
5
5
  listeners = /* @__PURE__ */ new Map();
6
+ currentUser = null;
7
+ authToken = null;
8
+ pendingUsername = null;
6
9
  /**
7
10
  * Initialize the SDK
8
11
  */
@@ -11,8 +14,181 @@ var FollowGateClient = class {
11
14
  ...config,
12
15
  apiUrl: config.apiUrl || DEFAULT_API_URL
13
16
  };
17
+ this.handleAuthCallback();
18
+ this.restoreSession();
14
19
  if (config.debug) {
15
20
  console.log("[FollowGate] Initialized with appId:", config.appId);
21
+ if (this.currentUser) {
22
+ console.log("[FollowGate] Restored user:", this.currentUser.username);
23
+ }
24
+ }
25
+ }
26
+ /**
27
+ * Authenticate user via Twitter OAuth (handled by FollowGate)
28
+ * This identifies WHO is completing the social actions.
29
+ */
30
+ authenticate(options = {}) {
31
+ if (!this.config) {
32
+ throw new Error("[FollowGate] SDK not initialized. Call init() first.");
33
+ }
34
+ const redirectUri = options.redirectUri || window.location.href.split("?")[0];
35
+ const authUrl = `${this.config.apiUrl}/api/v1/auth/twitter?app_id=${encodeURIComponent(this.config.appId)}&redirect_uri=${encodeURIComponent(redirectUri)}`;
36
+ if (this.config.debug) {
37
+ console.log("[FollowGate] Starting auth flow:", authUrl);
38
+ }
39
+ if (options.popup) {
40
+ const popup = window.open(
41
+ authUrl,
42
+ "followgate_auth",
43
+ "width=600,height=700"
44
+ );
45
+ if (!popup) {
46
+ this.emit("error", { message: "Popup blocked" });
47
+ }
48
+ } else {
49
+ window.location.href = authUrl;
50
+ }
51
+ }
52
+ /**
53
+ * Get current authenticated user
54
+ */
55
+ getUser() {
56
+ return this.currentUser;
57
+ }
58
+ /**
59
+ * Check if user is authenticated
60
+ */
61
+ isAuthenticated() {
62
+ return this.currentUser !== null && this.authToken !== null;
63
+ }
64
+ /**
65
+ * Logout - clear stored session
66
+ */
67
+ logout() {
68
+ this.currentUser = null;
69
+ this.authToken = null;
70
+ this.pendingUsername = null;
71
+ if (typeof localStorage !== "undefined") {
72
+ localStorage.removeItem("followgate_token");
73
+ localStorage.removeItem("followgate_user");
74
+ localStorage.removeItem("followgate_pending_username");
75
+ }
76
+ if (this.config?.debug) {
77
+ console.log("[FollowGate] User logged out");
78
+ }
79
+ }
80
+ /**
81
+ * Check if username input is needed (Twitter Free Tier limitation)
82
+ */
83
+ needsUsernameInput() {
84
+ return this.pendingUsername !== null;
85
+ }
86
+ /**
87
+ * Set username manually (when needsUsernameInput() returns true)
88
+ */
89
+ setUsername(username) {
90
+ if (!this.pendingUsername) {
91
+ throw new Error(
92
+ "[FollowGate] No pending username state. User is either not authenticated or username is already set."
93
+ );
94
+ }
95
+ const normalizedUsername = username.startsWith("@") ? username.slice(1) : username;
96
+ this.currentUser = {
97
+ userId: "user_input",
98
+ username: normalizedUsername,
99
+ platform: "twitter"
100
+ };
101
+ this.authToken = this.pendingUsername.token;
102
+ if (typeof localStorage !== "undefined") {
103
+ localStorage.setItem("followgate_token", this.authToken);
104
+ localStorage.setItem("followgate_user", JSON.stringify(this.currentUser));
105
+ localStorage.removeItem("followgate_pending_username");
106
+ }
107
+ this.pendingUsername = null;
108
+ this.emit("authenticated", this.currentUser);
109
+ if (this.config?.debug) {
110
+ console.log("[FollowGate] Username set manually:", normalizedUsername);
111
+ }
112
+ }
113
+ /**
114
+ * Handle auth callback from URL params
115
+ */
116
+ handleAuthCallback() {
117
+ if (typeof window === "undefined") return;
118
+ const params = new URLSearchParams(window.location.search);
119
+ const token = params.get("followgate_token");
120
+ const username = params.get("followgate_user");
121
+ const needsUsername = params.get("followgate_needs_username") === "true";
122
+ if (token && needsUsername) {
123
+ this.pendingUsername = {
124
+ needsUsername: true,
125
+ token
126
+ };
127
+ if (typeof localStorage !== "undefined") {
128
+ localStorage.setItem(
129
+ "followgate_pending_username",
130
+ JSON.stringify(this.pendingUsername)
131
+ );
132
+ }
133
+ const url = new URL(window.location.href);
134
+ url.searchParams.delete("followgate_token");
135
+ url.searchParams.delete("followgate_needs_username");
136
+ window.history.replaceState({}, "", url.toString());
137
+ if (this.config?.debug) {
138
+ console.log("[FollowGate] OAuth successful, username input needed");
139
+ }
140
+ } else if (token && username) {
141
+ this.authToken = token;
142
+ this.currentUser = {
143
+ userId: "",
144
+ // Will be set from token verification
145
+ username,
146
+ platform: "twitter"
147
+ };
148
+ if (typeof localStorage !== "undefined") {
149
+ localStorage.setItem("followgate_token", token);
150
+ localStorage.setItem(
151
+ "followgate_user",
152
+ JSON.stringify(this.currentUser)
153
+ );
154
+ }
155
+ const url = new URL(window.location.href);
156
+ url.searchParams.delete("followgate_token");
157
+ url.searchParams.delete("followgate_user");
158
+ window.history.replaceState({}, "", url.toString());
159
+ this.emit("authenticated", this.currentUser);
160
+ if (this.config?.debug) {
161
+ console.log("[FollowGate] User authenticated:", username);
162
+ }
163
+ }
164
+ }
165
+ /**
166
+ * Restore session from localStorage
167
+ */
168
+ restoreSession() {
169
+ if (typeof localStorage === "undefined") return;
170
+ const pendingJson = localStorage.getItem("followgate_pending_username");
171
+ if (pendingJson) {
172
+ try {
173
+ this.pendingUsername = JSON.parse(pendingJson);
174
+ if (this.config?.debug) {
175
+ console.log("[FollowGate] Restored pending username state");
176
+ }
177
+ return;
178
+ } catch {
179
+ localStorage.removeItem("followgate_pending_username");
180
+ }
181
+ }
182
+ const token = localStorage.getItem("followgate_token");
183
+ const userJson = localStorage.getItem("followgate_user");
184
+ if (token && userJson) {
185
+ try {
186
+ this.authToken = token;
187
+ this.currentUser = JSON.parse(userJson);
188
+ } catch {
189
+ localStorage.removeItem("followgate_token");
190
+ localStorage.removeItem("followgate_user");
191
+ }
16
192
  }
17
193
  }
18
194
  /**
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@followgate/js",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "FollowGate SDK - Grow your audience with every download. Require social actions (follow, repost) before users can access your app.",
5
- "author": "FollowGate <hello@followgate.io>",
6
- "homepage": "https://followgate.io",
5
+ "author": "FollowGate <hello@followgate.app>",
6
+ "homepage": "https://followgate.app",
7
7
  "main": "dist/index.js",
8
8
  "module": "dist/index.mjs",
9
9
  "types": "dist/index.d.ts",
@@ -43,7 +43,7 @@
43
43
  "license": "MIT",
44
44
  "repository": {
45
45
  "type": "git",
46
- "url": "https://github.com/JustFF5/FollowGate.git",
46
+ "url": "git+https://github.com/JustFF5/FollowGate.git",
47
47
  "directory": "packages/sdk"
48
48
  },
49
49
  "bugs": {