@followgate/js 0.1.0 → 0.2.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,65 @@ 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
+ * Authentication options
49
+ */
50
+ interface AuthOptions {
51
+ /** Where to redirect after auth (defaults to current page) */
52
+ redirectUri?: string;
53
+ /** Open in popup instead of redirect */
54
+ popup?: boolean;
55
+ }
39
56
  /**
40
57
  * FollowGate SDK Client
41
58
  */
42
59
  declare class FollowGateClient {
43
60
  private config;
44
61
  private listeners;
62
+ private currentUser;
63
+ private authToken;
45
64
  /**
46
65
  * Initialize the SDK
47
66
  */
48
67
  init(config: FollowGateConfig): void;
68
+ /**
69
+ * Authenticate user via Twitter OAuth (handled by FollowGate)
70
+ * This identifies WHO is completing the social actions.
71
+ */
72
+ authenticate(options?: AuthOptions): void;
73
+ /**
74
+ * Get current authenticated user
75
+ */
76
+ getUser(): AuthenticatedUser | null;
77
+ /**
78
+ * Check if user is authenticated
79
+ */
80
+ isAuthenticated(): boolean;
81
+ /**
82
+ * Logout - clear stored session
83
+ */
84
+ logout(): void;
85
+ /**
86
+ * Handle auth callback from URL params
87
+ */
88
+ private handleAuthCallback;
89
+ /**
90
+ * Restore session from localStorage
91
+ */
92
+ private restoreSession;
49
93
  /**
50
94
  * Open social action popup
51
95
  */
@@ -77,4 +121,4 @@ declare class FollowGateClient {
77
121
  }
78
122
  declare const FollowGate: FollowGateClient;
79
123
 
80
- export { type EventCallback, type EventType, FollowGate, FollowGateClient, type FollowGateConfig, type LinkedInTargetType, type OpenOptions, type Platform, type SocialAction };
124
+ export { type AuthOptions, type AuthenticatedUser, type EventCallback, type EventType, FollowGate, FollowGateClient, type FollowGateConfig, type LinkedInTargetType, type OpenOptions, type Platform, type SocialAction };
package/dist/index.d.ts CHANGED
@@ -31,21 +31,65 @@ 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
+ * Authentication options
49
+ */
50
+ interface AuthOptions {
51
+ /** Where to redirect after auth (defaults to current page) */
52
+ redirectUri?: string;
53
+ /** Open in popup instead of redirect */
54
+ popup?: boolean;
55
+ }
39
56
  /**
40
57
  * FollowGate SDK Client
41
58
  */
42
59
  declare class FollowGateClient {
43
60
  private config;
44
61
  private listeners;
62
+ private currentUser;
63
+ private authToken;
45
64
  /**
46
65
  * Initialize the SDK
47
66
  */
48
67
  init(config: FollowGateConfig): void;
68
+ /**
69
+ * Authenticate user via Twitter OAuth (handled by FollowGate)
70
+ * This identifies WHO is completing the social actions.
71
+ */
72
+ authenticate(options?: AuthOptions): void;
73
+ /**
74
+ * Get current authenticated user
75
+ */
76
+ getUser(): AuthenticatedUser | null;
77
+ /**
78
+ * Check if user is authenticated
79
+ */
80
+ isAuthenticated(): boolean;
81
+ /**
82
+ * Logout - clear stored session
83
+ */
84
+ logout(): void;
85
+ /**
86
+ * Handle auth callback from URL params
87
+ */
88
+ private handleAuthCallback;
89
+ /**
90
+ * Restore session from localStorage
91
+ */
92
+ private restoreSession;
49
93
  /**
50
94
  * Open social action popup
51
95
  */
@@ -77,4 +121,4 @@ declare class FollowGateClient {
77
121
  }
78
122
  declare const FollowGate: FollowGateClient;
79
123
 
80
- export { type EventCallback, type EventType, FollowGate, FollowGateClient, type FollowGateConfig, type LinkedInTargetType, type OpenOptions, type Platform, type SocialAction };
124
+ export { type AuthOptions, type AuthenticatedUser, type EventCallback, type EventType, FollowGate, FollowGateClient, type FollowGateConfig, type LinkedInTargetType, type OpenOptions, type Platform, type SocialAction };
package/dist/index.js CHANGED
@@ -24,10 +24,12 @@ __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;
31
33
  /**
32
34
  * Initialize the SDK
33
35
  */
@@ -36,8 +38,115 @@ var FollowGateClient = class {
36
38
  ...config,
37
39
  apiUrl: config.apiUrl || DEFAULT_API_URL
38
40
  };
41
+ this.handleAuthCallback();
42
+ this.restoreSession();
39
43
  if (config.debug) {
40
44
  console.log("[FollowGate] Initialized with appId:", config.appId);
45
+ if (this.currentUser) {
46
+ console.log("[FollowGate] Restored user:", this.currentUser.username);
47
+ }
48
+ }
49
+ }
50
+ /**
51
+ * Authenticate user via Twitter OAuth (handled by FollowGate)
52
+ * This identifies WHO is completing the social actions.
53
+ */
54
+ authenticate(options = {}) {
55
+ if (!this.config) {
56
+ throw new Error("[FollowGate] SDK not initialized. Call init() first.");
57
+ }
58
+ const redirectUri = options.redirectUri || window.location.href.split("?")[0];
59
+ const authUrl = `${this.config.apiUrl}/api/v1/auth/twitter?app_id=${encodeURIComponent(this.config.appId)}&redirect_uri=${encodeURIComponent(redirectUri)}`;
60
+ if (this.config.debug) {
61
+ console.log("[FollowGate] Starting auth flow:", authUrl);
62
+ }
63
+ if (options.popup) {
64
+ const popup = window.open(
65
+ authUrl,
66
+ "followgate_auth",
67
+ "width=600,height=700"
68
+ );
69
+ if (!popup) {
70
+ this.emit("error", { message: "Popup blocked" });
71
+ }
72
+ } else {
73
+ window.location.href = authUrl;
74
+ }
75
+ }
76
+ /**
77
+ * Get current authenticated user
78
+ */
79
+ getUser() {
80
+ return this.currentUser;
81
+ }
82
+ /**
83
+ * Check if user is authenticated
84
+ */
85
+ isAuthenticated() {
86
+ return this.currentUser !== null && this.authToken !== null;
87
+ }
88
+ /**
89
+ * Logout - clear stored session
90
+ */
91
+ logout() {
92
+ this.currentUser = null;
93
+ this.authToken = null;
94
+ if (typeof localStorage !== "undefined") {
95
+ localStorage.removeItem("followgate_token");
96
+ localStorage.removeItem("followgate_user");
97
+ }
98
+ if (this.config?.debug) {
99
+ console.log("[FollowGate] User logged out");
100
+ }
101
+ }
102
+ /**
103
+ * Handle auth callback from URL params
104
+ */
105
+ handleAuthCallback() {
106
+ if (typeof window === "undefined") return;
107
+ const params = new URLSearchParams(window.location.search);
108
+ const token = params.get("followgate_token");
109
+ const username = params.get("followgate_user");
110
+ if (token && username) {
111
+ this.authToken = token;
112
+ this.currentUser = {
113
+ userId: "",
114
+ // Will be set from token verification
115
+ username,
116
+ platform: "twitter"
117
+ };
118
+ if (typeof localStorage !== "undefined") {
119
+ localStorage.setItem("followgate_token", token);
120
+ localStorage.setItem(
121
+ "followgate_user",
122
+ JSON.stringify(this.currentUser)
123
+ );
124
+ }
125
+ const url = new URL(window.location.href);
126
+ url.searchParams.delete("followgate_token");
127
+ url.searchParams.delete("followgate_user");
128
+ window.history.replaceState({}, "", url.toString());
129
+ this.emit("authenticated", this.currentUser);
130
+ if (this.config?.debug) {
131
+ console.log("[FollowGate] User authenticated:", username);
132
+ }
133
+ }
134
+ }
135
+ /**
136
+ * Restore session from localStorage
137
+ */
138
+ restoreSession() {
139
+ if (typeof localStorage === "undefined") return;
140
+ const token = localStorage.getItem("followgate_token");
141
+ const userJson = localStorage.getItem("followgate_user");
142
+ if (token && userJson) {
143
+ try {
144
+ this.authToken = token;
145
+ this.currentUser = JSON.parse(userJson);
146
+ } catch {
147
+ localStorage.removeItem("followgate_token");
148
+ localStorage.removeItem("followgate_user");
149
+ }
41
150
  }
42
151
  }
43
152
  /**
package/dist/index.mjs CHANGED
@@ -1,8 +1,10 @@
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;
6
8
  /**
7
9
  * Initialize the SDK
8
10
  */
@@ -11,8 +13,115 @@ var FollowGateClient = class {
11
13
  ...config,
12
14
  apiUrl: config.apiUrl || DEFAULT_API_URL
13
15
  };
16
+ this.handleAuthCallback();
17
+ this.restoreSession();
14
18
  if (config.debug) {
15
19
  console.log("[FollowGate] Initialized with appId:", config.appId);
20
+ if (this.currentUser) {
21
+ console.log("[FollowGate] Restored user:", this.currentUser.username);
22
+ }
23
+ }
24
+ }
25
+ /**
26
+ * Authenticate user via Twitter OAuth (handled by FollowGate)
27
+ * This identifies WHO is completing the social actions.
28
+ */
29
+ authenticate(options = {}) {
30
+ if (!this.config) {
31
+ throw new Error("[FollowGate] SDK not initialized. Call init() first.");
32
+ }
33
+ const redirectUri = options.redirectUri || window.location.href.split("?")[0];
34
+ const authUrl = `${this.config.apiUrl}/api/v1/auth/twitter?app_id=${encodeURIComponent(this.config.appId)}&redirect_uri=${encodeURIComponent(redirectUri)}`;
35
+ if (this.config.debug) {
36
+ console.log("[FollowGate] Starting auth flow:", authUrl);
37
+ }
38
+ if (options.popup) {
39
+ const popup = window.open(
40
+ authUrl,
41
+ "followgate_auth",
42
+ "width=600,height=700"
43
+ );
44
+ if (!popup) {
45
+ this.emit("error", { message: "Popup blocked" });
46
+ }
47
+ } else {
48
+ window.location.href = authUrl;
49
+ }
50
+ }
51
+ /**
52
+ * Get current authenticated user
53
+ */
54
+ getUser() {
55
+ return this.currentUser;
56
+ }
57
+ /**
58
+ * Check if user is authenticated
59
+ */
60
+ isAuthenticated() {
61
+ return this.currentUser !== null && this.authToken !== null;
62
+ }
63
+ /**
64
+ * Logout - clear stored session
65
+ */
66
+ logout() {
67
+ this.currentUser = null;
68
+ this.authToken = null;
69
+ if (typeof localStorage !== "undefined") {
70
+ localStorage.removeItem("followgate_token");
71
+ localStorage.removeItem("followgate_user");
72
+ }
73
+ if (this.config?.debug) {
74
+ console.log("[FollowGate] User logged out");
75
+ }
76
+ }
77
+ /**
78
+ * Handle auth callback from URL params
79
+ */
80
+ handleAuthCallback() {
81
+ if (typeof window === "undefined") return;
82
+ const params = new URLSearchParams(window.location.search);
83
+ const token = params.get("followgate_token");
84
+ const username = params.get("followgate_user");
85
+ if (token && username) {
86
+ this.authToken = token;
87
+ this.currentUser = {
88
+ userId: "",
89
+ // Will be set from token verification
90
+ username,
91
+ platform: "twitter"
92
+ };
93
+ if (typeof localStorage !== "undefined") {
94
+ localStorage.setItem("followgate_token", token);
95
+ localStorage.setItem(
96
+ "followgate_user",
97
+ JSON.stringify(this.currentUser)
98
+ );
99
+ }
100
+ const url = new URL(window.location.href);
101
+ url.searchParams.delete("followgate_token");
102
+ url.searchParams.delete("followgate_user");
103
+ window.history.replaceState({}, "", url.toString());
104
+ this.emit("authenticated", this.currentUser);
105
+ if (this.config?.debug) {
106
+ console.log("[FollowGate] User authenticated:", username);
107
+ }
108
+ }
109
+ }
110
+ /**
111
+ * Restore session from localStorage
112
+ */
113
+ restoreSession() {
114
+ if (typeof localStorage === "undefined") return;
115
+ const token = localStorage.getItem("followgate_token");
116
+ const userJson = localStorage.getItem("followgate_user");
117
+ if (token && userJson) {
118
+ try {
119
+ this.authToken = token;
120
+ this.currentUser = JSON.parse(userJson);
121
+ } catch {
122
+ localStorage.removeItem("followgate_token");
123
+ localStorage.removeItem("followgate_user");
124
+ }
16
125
  }
17
126
  }
18
127
  /**
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@followgate/js",
3
- "version": "0.1.0",
3
+ "version": "0.2.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": {