@followgate/js 0.2.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/dist/index.d.mts CHANGED
@@ -44,6 +44,13 @@ interface AuthenticatedUser {
44
44
  username: string;
45
45
  platform: Platform;
46
46
  }
47
+ /**
48
+ * Auth state when username input is needed
49
+ */
50
+ interface PendingUsernameState {
51
+ needsUsername: true;
52
+ token: string;
53
+ }
47
54
  /**
48
55
  * Authentication options
49
56
  */
@@ -61,6 +68,7 @@ declare class FollowGateClient {
61
68
  private listeners;
62
69
  private currentUser;
63
70
  private authToken;
71
+ private pendingUsername;
64
72
  /**
65
73
  * Initialize the SDK
66
74
  */
@@ -82,6 +90,14 @@ declare class FollowGateClient {
82
90
  * Logout - clear stored session
83
91
  */
84
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;
85
101
  /**
86
102
  * Handle auth callback from URL params
87
103
  */
@@ -121,4 +137,4 @@ declare class FollowGateClient {
121
137
  }
122
138
  declare const FollowGate: FollowGateClient;
123
139
 
124
- export { type AuthOptions, type AuthenticatedUser, 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
@@ -44,6 +44,13 @@ interface AuthenticatedUser {
44
44
  username: string;
45
45
  platform: Platform;
46
46
  }
47
+ /**
48
+ * Auth state when username input is needed
49
+ */
50
+ interface PendingUsernameState {
51
+ needsUsername: true;
52
+ token: string;
53
+ }
47
54
  /**
48
55
  * Authentication options
49
56
  */
@@ -61,6 +68,7 @@ declare class FollowGateClient {
61
68
  private listeners;
62
69
  private currentUser;
63
70
  private authToken;
71
+ private pendingUsername;
64
72
  /**
65
73
  * Initialize the SDK
66
74
  */
@@ -82,6 +90,14 @@ declare class FollowGateClient {
82
90
  * Logout - clear stored session
83
91
  */
84
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;
85
101
  /**
86
102
  * Handle auth callback from URL params
87
103
  */
@@ -121,4 +137,4 @@ declare class FollowGateClient {
121
137
  }
122
138
  declare const FollowGate: FollowGateClient;
123
139
 
124
- export { type AuthOptions, type AuthenticatedUser, 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
@@ -30,6 +30,7 @@ var FollowGateClient = class {
30
30
  listeners = /* @__PURE__ */ new Map();
31
31
  currentUser = null;
32
32
  authToken = null;
33
+ pendingUsername = null;
33
34
  /**
34
35
  * Initialize the SDK
35
36
  */
@@ -91,14 +92,49 @@ var FollowGateClient = class {
91
92
  logout() {
92
93
  this.currentUser = null;
93
94
  this.authToken = null;
95
+ this.pendingUsername = null;
94
96
  if (typeof localStorage !== "undefined") {
95
97
  localStorage.removeItem("followgate_token");
96
98
  localStorage.removeItem("followgate_user");
99
+ localStorage.removeItem("followgate_pending_username");
97
100
  }
98
101
  if (this.config?.debug) {
99
102
  console.log("[FollowGate] User logged out");
100
103
  }
101
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
+ }
102
138
  /**
103
139
  * Handle auth callback from URL params
104
140
  */
@@ -107,7 +143,26 @@ var FollowGateClient = class {
107
143
  const params = new URLSearchParams(window.location.search);
108
144
  const token = params.get("followgate_token");
109
145
  const username = params.get("followgate_user");
110
- if (token && username) {
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) {
111
166
  this.authToken = token;
112
167
  this.currentUser = {
113
168
  userId: "",
@@ -137,6 +192,18 @@ var FollowGateClient = class {
137
192
  */
138
193
  restoreSession() {
139
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
+ }
140
207
  const token = localStorage.getItem("followgate_token");
141
208
  const userJson = localStorage.getItem("followgate_user");
142
209
  if (token && userJson) {
package/dist/index.mjs CHANGED
@@ -5,6 +5,7 @@ var FollowGateClient = class {
5
5
  listeners = /* @__PURE__ */ new Map();
6
6
  currentUser = null;
7
7
  authToken = null;
8
+ pendingUsername = null;
8
9
  /**
9
10
  * Initialize the SDK
10
11
  */
@@ -66,14 +67,49 @@ var FollowGateClient = class {
66
67
  logout() {
67
68
  this.currentUser = null;
68
69
  this.authToken = null;
70
+ this.pendingUsername = null;
69
71
  if (typeof localStorage !== "undefined") {
70
72
  localStorage.removeItem("followgate_token");
71
73
  localStorage.removeItem("followgate_user");
74
+ localStorage.removeItem("followgate_pending_username");
72
75
  }
73
76
  if (this.config?.debug) {
74
77
  console.log("[FollowGate] User logged out");
75
78
  }
76
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
+ }
77
113
  /**
78
114
  * Handle auth callback from URL params
79
115
  */
@@ -82,7 +118,26 @@ var FollowGateClient = class {
82
118
  const params = new URLSearchParams(window.location.search);
83
119
  const token = params.get("followgate_token");
84
120
  const username = params.get("followgate_user");
85
- if (token && username) {
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) {
86
141
  this.authToken = token;
87
142
  this.currentUser = {
88
143
  userId: "",
@@ -112,6 +167,18 @@ var FollowGateClient = class {
112
167
  */
113
168
  restoreSession() {
114
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
+ }
115
182
  const token = localStorage.getItem("followgate_token");
116
183
  const userJson = localStorage.getItem("followgate_user");
117
184
  if (token && userJson) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@followgate/js",
3
- "version": "0.2.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
5
  "author": "FollowGate <hello@followgate.app>",
6
6
  "homepage": "https://followgate.app",