browser-extension-manager 1.2.3 → 1.2.5
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/CLAUDE.md +104 -0
- package/README.md +109 -0
- package/dist/assets/themes/classy/css/base/_utilities.scss +0 -51
- package/dist/assets/themes/classy/css/components/_text.scss +11 -0
- package/dist/background.js +220 -9
- package/dist/defaults/_.env +4 -0
- package/dist/defaults/config/browser-extension-manager.json +9 -11
- package/dist/gulp/main.js +4 -0
- package/dist/gulp/tasks/audit.js +1 -1
- package/dist/gulp/tasks/defaults.js +8 -1
- package/dist/gulp/tasks/distribute.js +6 -1
- package/dist/gulp/tasks/package.js +12 -3
- package/dist/gulp/tasks/publish.js +60 -10
- package/dist/gulp/tasks/webpack.js +8 -6
- package/dist/lib/auth-helpers.js +184 -0
- package/dist/lib/logger.js +1 -1
- package/dist/options.js +17 -0
- package/dist/page.js +17 -0
- package/dist/popup.js +17 -0
- package/dist/sidepanel.js +17 -0
- package/firebase-debug.log +280 -0
- package/package.json +12 -6
|
@@ -15,6 +15,9 @@ const config = Manager.getConfig('project');
|
|
|
15
15
|
const rootPathPackage = Manager.getRootPath('main');
|
|
16
16
|
const rootPathProject = Manager.getRootPath('project');
|
|
17
17
|
|
|
18
|
+
// Constants
|
|
19
|
+
const LOUD = process.env.BXM_LOUD_LOGS === 'true';
|
|
20
|
+
|
|
18
21
|
// Glob
|
|
19
22
|
const input = [
|
|
20
23
|
// Files to include
|
|
@@ -108,7 +111,9 @@ function customTransform() {
|
|
|
108
111
|
const relativePath = path.relative(file.base, file.path).replace(/\\/g, '/');
|
|
109
112
|
|
|
110
113
|
// Log
|
|
111
|
-
|
|
114
|
+
if (LOUD) {
|
|
115
|
+
logger.log(`Processing file: ${relativePath}`);
|
|
116
|
+
}
|
|
112
117
|
|
|
113
118
|
// Change path if it starts with 'pages/'
|
|
114
119
|
// if (relativePath.startsWith('pages/')) {
|
|
@@ -58,6 +58,7 @@ async function generateBuildJs(outputDir) {
|
|
|
58
58
|
},
|
|
59
59
|
config: {
|
|
60
60
|
// Core metadata
|
|
61
|
+
runtime: 'browser-extension',
|
|
61
62
|
version: project.version,
|
|
62
63
|
environment: Manager.getEnvironment(),
|
|
63
64
|
buildTime: Date.now(),
|
|
@@ -97,8 +98,11 @@ async function generateBuildJs(outputDir) {
|
|
|
97
98
|
refreshNewVersion: { enabled: true, config: {} },
|
|
98
99
|
serviceWorker: { enabled: false, config: {} },
|
|
99
100
|
|
|
100
|
-
//
|
|
101
|
-
|
|
101
|
+
// Tracking
|
|
102
|
+
tracking: {
|
|
103
|
+
'google-analytics': config.google_analytics?.id || '',
|
|
104
|
+
'google-analytics-secret': config.google_analytics?.secret || '',
|
|
105
|
+
},
|
|
102
106
|
|
|
103
107
|
// Theme config
|
|
104
108
|
theme: config.theme || {},
|
|
@@ -282,7 +286,12 @@ async function packageZip() {
|
|
|
282
286
|
|
|
283
287
|
// Create packed extension (.zip)
|
|
284
288
|
if (Manager.isBuildMode()) {
|
|
285
|
-
|
|
289
|
+
// Remove existing zip if it exists
|
|
290
|
+
jetpack.remove(zipPath);
|
|
291
|
+
|
|
292
|
+
// Zip contents of raw directory (not the directory itself)
|
|
293
|
+
// This ensures manifest.json is at the root of the zip
|
|
294
|
+
await execute(`cd ${inputDir} && zip -r ../../${zipPath} .`);
|
|
286
295
|
logger.log(`Zipped package created at ${zipPath}`);
|
|
287
296
|
} else {
|
|
288
297
|
logger.log(`Skipping zip (not in build mode)`);
|
|
@@ -12,19 +12,36 @@ const project = Manager.getPackage('project');
|
|
|
12
12
|
// Paths
|
|
13
13
|
const zipPath = path.join(process.cwd(), 'packaged', 'extension.zip');
|
|
14
14
|
|
|
15
|
+
// Helper to check if a credential is valid (not empty or placeholder)
|
|
16
|
+
function isValidCredential(value) {
|
|
17
|
+
return value && !value.startsWith('your-');
|
|
18
|
+
}
|
|
19
|
+
|
|
15
20
|
// Store configurations - all credentials come from .env file
|
|
16
21
|
const STORES = {
|
|
17
22
|
chrome: {
|
|
18
23
|
name: 'Chrome Web Store',
|
|
19
|
-
|
|
24
|
+
submitUrl: 'https://chrome.google.com/webstore/devconsole',
|
|
25
|
+
apiUrl: 'https://developer.chrome.com/docs/webstore/using_webstore_api/',
|
|
26
|
+
enabled: () => isValidCredential(process.env.CHROME_EXTENSION_ID) && isValidCredential(process.env.CHROME_CLIENT_ID),
|
|
20
27
|
},
|
|
21
28
|
firefox: {
|
|
22
29
|
name: 'Firefox Add-ons',
|
|
23
|
-
|
|
30
|
+
submitUrl: 'https://addons.mozilla.org/en-US/developers/addon/submit/distribution',
|
|
31
|
+
apiUrl: 'https://addons.mozilla.org/developers/addon/api/key/',
|
|
32
|
+
enabled: () => isValidCredential(process.env.FIREFOX_API_KEY) && isValidCredential(process.env.FIREFOX_API_SECRET),
|
|
24
33
|
},
|
|
25
34
|
edge: {
|
|
26
35
|
name: 'Microsoft Edge Add-ons',
|
|
27
|
-
|
|
36
|
+
submitUrl: 'https://partner.microsoft.com/dashboard/microsoftedge/',
|
|
37
|
+
apiUrl: 'https://learn.microsoft.com/en-us/microsoft-edge/extensions-chromium/publish/api/using-addons-api',
|
|
38
|
+
enabled: () => isValidCredential(process.env.EDGE_PRODUCT_ID) && isValidCredential(process.env.EDGE_CLIENT_ID),
|
|
39
|
+
},
|
|
40
|
+
opera: {
|
|
41
|
+
name: 'Opera Add-ons',
|
|
42
|
+
submitUrl: 'https://addons.opera.com/developer/',
|
|
43
|
+
apiUrl: null,
|
|
44
|
+
enabled: () => false,
|
|
28
45
|
},
|
|
29
46
|
};
|
|
30
47
|
|
|
@@ -50,20 +67,30 @@ async function publish(complete) {
|
|
|
50
67
|
|
|
51
68
|
// Get enabled stores
|
|
52
69
|
const enabledStores = Object.entries(STORES)
|
|
53
|
-
.filter(([
|
|
70
|
+
.filter(([, store]) => store.enabled())
|
|
54
71
|
.map(([key]) => key);
|
|
55
72
|
|
|
73
|
+
// If no stores are configured, error and show all store info
|
|
56
74
|
if (enabledStores.length === 0) {
|
|
57
|
-
logger.
|
|
58
|
-
logger.log('
|
|
59
|
-
logger.log('
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
75
|
+
logger.error('No stores configured for publishing. Add credentials to .env file');
|
|
76
|
+
logger.log('');
|
|
77
|
+
logger.log('Store URLs and API documentation:');
|
|
78
|
+
Object.entries(STORES).forEach(([, store]) => {
|
|
79
|
+
logger.log(` ${store.name}:`);
|
|
80
|
+
logger.log(` Submit: ${store.submitUrl}`);
|
|
81
|
+
logger.log(` API: ${store.apiUrl || 'N/A (manual submission only)'}`);
|
|
82
|
+
});
|
|
83
|
+
throw new Error('No stores configured for publishing');
|
|
63
84
|
}
|
|
64
85
|
|
|
65
86
|
logger.log(`Publishing to: ${enabledStores.join(', ')}`);
|
|
66
87
|
|
|
88
|
+
// Track results
|
|
89
|
+
const results = {
|
|
90
|
+
success: [],
|
|
91
|
+
failed: [],
|
|
92
|
+
};
|
|
93
|
+
|
|
67
94
|
// Run publish tasks in parallel
|
|
68
95
|
const publishTasks = enabledStores.map(async (store) => {
|
|
69
96
|
try {
|
|
@@ -79,14 +106,37 @@ async function publish(complete) {
|
|
|
79
106
|
break;
|
|
80
107
|
}
|
|
81
108
|
logger.log(`[${store}] Published successfully`);
|
|
109
|
+
results.success.push(store);
|
|
82
110
|
} catch (e) {
|
|
83
111
|
logger.error(`[${store}] Publish failed: ${e.message}`);
|
|
112
|
+
results.failed.push(store);
|
|
84
113
|
}
|
|
85
114
|
});
|
|
86
115
|
|
|
87
116
|
await Promise.all(publishTasks);
|
|
88
117
|
|
|
118
|
+
// Log completion and show all store URLs
|
|
119
|
+
logger.log('');
|
|
120
|
+
logger.log('Store URLs:');
|
|
121
|
+
Object.entries(STORES).forEach(([key, store]) => {
|
|
122
|
+
let status = '○ Manual';
|
|
123
|
+
if (results.success.includes(key)) {
|
|
124
|
+
status = '✓ Published';
|
|
125
|
+
} else if (results.failed.includes(key)) {
|
|
126
|
+
status = '✗ Failed';
|
|
127
|
+
}
|
|
128
|
+
logger.log(` ${store.name}: ${status}`);
|
|
129
|
+
logger.log(` Submit: ${store.submitUrl}`);
|
|
130
|
+
logger.log(` API: ${store.apiUrl || 'N/A (manual submission only)'}`);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// Throw error if any failed
|
|
134
|
+
if (results.failed.length > 0) {
|
|
135
|
+
throw new Error(`Publish failed for: ${results.failed.join(', ')}`);
|
|
136
|
+
}
|
|
137
|
+
|
|
89
138
|
// Log
|
|
139
|
+
logger.log('');
|
|
90
140
|
logger.log('Publish finished!');
|
|
91
141
|
|
|
92
142
|
// Complete
|
|
@@ -49,12 +49,11 @@ const watchInput = [
|
|
|
49
49
|
`${rootPathPackage}/dist/assets/themes/**/*.js`,
|
|
50
50
|
'src/assets/themes/**/*.js',
|
|
51
51
|
|
|
52
|
-
//
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
`${rootPathPackage}/src
|
|
57
|
-
`${rootPathPackage}/src/index.js`,
|
|
52
|
+
// All project assets js - watch for changes but don't compile as entry points
|
|
53
|
+
'src/assets/js/**/*.js',
|
|
54
|
+
|
|
55
|
+
// All BEM package src files - watch for changes (includes background.js, popup.js, etc.)
|
|
56
|
+
`${rootPathPackage}/src/**/*.js`,
|
|
58
57
|
|
|
59
58
|
// So we can watch for changes while we're developing web-manager
|
|
60
59
|
`${rootPathPackage}/../web-manager/src`,
|
|
@@ -108,6 +107,9 @@ function getSettings() {
|
|
|
108
107
|
},
|
|
109
108
|
// Add module resolution paths
|
|
110
109
|
modules: [
|
|
110
|
+
// Local web-manager's node_modules (for when we're using "web-manager": "file:../web-manager")
|
|
111
|
+
path.resolve(rootPathPackage, '../web-manager/node_modules'),
|
|
112
|
+
|
|
111
113
|
// Package's node_modules
|
|
112
114
|
path.resolve(rootPathPackage, 'node_modules'),
|
|
113
115
|
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
// Auth helpers for cross-context auth sync in browser extensions
|
|
2
|
+
// Used by popup.js, options.js, sidepanel.js, page.js
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Sign in with custom token from storage
|
|
6
|
+
* @param {Object} context - The manager instance
|
|
7
|
+
* @param {Object} authState - Auth state with token
|
|
8
|
+
*/
|
|
9
|
+
async function signInWithStoredToken(context, authState) {
|
|
10
|
+
const { webManager, logger } = context;
|
|
11
|
+
|
|
12
|
+
// Skip if no token
|
|
13
|
+
if (!authState?.token) {
|
|
14
|
+
logger.log('[AUTH-SYNC] No token in auth state, skipping sign in');
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
logger.log('[AUTH-SYNC] Signing in with stored token...');
|
|
20
|
+
|
|
21
|
+
// Sign in using webManager's auth which initializes Firebase
|
|
22
|
+
await webManager.auth().signInWithCustomToken(authState.token);
|
|
23
|
+
|
|
24
|
+
logger.log('[AUTH-SYNC] Signed in successfully:', authState.user?.email);
|
|
25
|
+
} catch (error) {
|
|
26
|
+
// Token may have expired, clear it
|
|
27
|
+
logger.error('[AUTH-SYNC] Error signing in with token:', error.message);
|
|
28
|
+
|
|
29
|
+
// If token is invalid/expired, clear the auth state
|
|
30
|
+
if (error.code === 'auth/invalid-custom-token' || error.code === 'auth/custom-token-expired') {
|
|
31
|
+
logger.log('[AUTH-SYNC] Token expired, clearing auth state');
|
|
32
|
+
context.extension.storage.remove('bxm:authState');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Set up storage listener for cross-context auth sync
|
|
39
|
+
* Listens for auth state changes from background.js and syncs Firebase auth
|
|
40
|
+
* @param {Object} context - The manager instance (must have extension, webManager, logger)
|
|
41
|
+
*/
|
|
42
|
+
export function setupAuthStorageListener(context) {
|
|
43
|
+
const { extension, webManager, logger } = context;
|
|
44
|
+
|
|
45
|
+
// Check existing auth state on load and sign in
|
|
46
|
+
extension.storage.get('bxm:authState', (result) => {
|
|
47
|
+
const authState = result['bxm:authState'];
|
|
48
|
+
|
|
49
|
+
if (authState?.token) {
|
|
50
|
+
logger.log('[AUTH-SYNC] Found existing auth state, signing in...', authState.user?.email);
|
|
51
|
+
signInWithStoredToken(context, authState);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Listen for WM auth state changes and sync to storage
|
|
56
|
+
// When user signs out via WM, clear storage so background.js knows
|
|
57
|
+
webManager.auth().listen((state) => {
|
|
58
|
+
if (!state.user) {
|
|
59
|
+
// User signed out - clear storage so all contexts sync
|
|
60
|
+
logger.log('[AUTH-SYNC] WM auth signed out, clearing storage...');
|
|
61
|
+
extension.storage.remove('bxm:authState');
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Listen for storage changes from background.js
|
|
66
|
+
// Note: BEM normalizes storage to sync or local, so we listen to all areas
|
|
67
|
+
extension.storage.onChanged.addListener((changes) => {
|
|
68
|
+
// Check for auth state change
|
|
69
|
+
const authChange = changes['bxm:authState'];
|
|
70
|
+
if (!authChange) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Log
|
|
75
|
+
logger.log('[AUTH-SYNC] Auth state changed in storage:', authChange);
|
|
76
|
+
|
|
77
|
+
// Get the new auth state
|
|
78
|
+
const newAuthState = authChange.newValue;
|
|
79
|
+
|
|
80
|
+
// If auth state was cleared (signed out)
|
|
81
|
+
if (!newAuthState) {
|
|
82
|
+
logger.log('[AUTH-SYNC] Auth state cleared, signing out...');
|
|
83
|
+
webManager.auth().signOut();
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Sign in with the new token
|
|
88
|
+
if (newAuthState?.token) {
|
|
89
|
+
signInWithStoredToken(context, newAuthState);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Log
|
|
94
|
+
logger.log('Auth storage listener set up');
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Open auth page in new tab (for signing in via website)
|
|
99
|
+
* @param {Object} context - The manager instance (must have extension, webManager, logger)
|
|
100
|
+
* @param {Object} options - Options object
|
|
101
|
+
* @param {string} options.path - Path to open (default: '/token')
|
|
102
|
+
* @param {string} options.authReturnUrl - Return URL for electron/deep links
|
|
103
|
+
*/
|
|
104
|
+
export function openAuthPage(context, options = {}) {
|
|
105
|
+
const { extension, webManager, logger } = context;
|
|
106
|
+
|
|
107
|
+
// Get auth domain from config
|
|
108
|
+
const authDomain = webManager.config?.firebase?.app?.config?.authDomain;
|
|
109
|
+
|
|
110
|
+
if (!authDomain) {
|
|
111
|
+
logger.error('No authDomain configured');
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Build the URL
|
|
116
|
+
const path = options.path || '/token';
|
|
117
|
+
const authUrl = new URL(path, `https://${authDomain}`);
|
|
118
|
+
|
|
119
|
+
// Add return URL if provided (for electron/deep links)
|
|
120
|
+
if (options.authReturnUrl) {
|
|
121
|
+
authUrl.searchParams.set('authReturnUrl', options.authReturnUrl);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Log
|
|
125
|
+
logger.log('Opening auth page:', authUrl.toString());
|
|
126
|
+
|
|
127
|
+
// Get current active tab so we can restore it after auth
|
|
128
|
+
extension.tabs.query({ active: true, currentWindow: true }, (tabs) => {
|
|
129
|
+
const authSourceTabId = tabs[0]?.id;
|
|
130
|
+
|
|
131
|
+
// Add source tab ID to URL so background can restore it
|
|
132
|
+
if (authSourceTabId) {
|
|
133
|
+
authUrl.searchParams.set('authSourceTabId', authSourceTabId);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Open in new tab
|
|
137
|
+
extension.tabs.create({ url: authUrl.toString() });
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Set up DOM event listeners for auth buttons (sign in, account)
|
|
143
|
+
* Uses event delegation so it works with dynamically rendered content
|
|
144
|
+
* @param {Object} context - The manager instance (must have extension, webManager, logger)
|
|
145
|
+
*/
|
|
146
|
+
export function setupAuthEventListeners(context) {
|
|
147
|
+
// Only set up once DOM is ready
|
|
148
|
+
if (typeof document === 'undefined') {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Sign in button (.auth-signin-btn) - opens auth page
|
|
153
|
+
document.addEventListener('click', (event) => {
|
|
154
|
+
const $signInBtn = event.target.closest('.auth-signin-btn');
|
|
155
|
+
if (!$signInBtn) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
event.preventDefault();
|
|
160
|
+
event.stopPropagation();
|
|
161
|
+
|
|
162
|
+
openAuthPage(context);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
// Account button (.auth-account-btn) - opens account page on website
|
|
166
|
+
document.addEventListener('click', (event) => {
|
|
167
|
+
const $accountBtn = event.target.closest('.auth-account-btn');
|
|
168
|
+
if (!$accountBtn) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
event.preventDefault();
|
|
173
|
+
event.stopPropagation();
|
|
174
|
+
|
|
175
|
+
openAuthPage(context, { path: '/account' });
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// Note: .auth-signout-btn is handled by web-manager's auth module
|
|
179
|
+
// BEM's storage listener will detect the sign-out via onAuthStateChanged in background.js
|
|
180
|
+
// If background hasn't initialized Firebase yet, stale storage is cleared on next auth attempt
|
|
181
|
+
|
|
182
|
+
// Log
|
|
183
|
+
context.logger.log('Auth event listeners set up');
|
|
184
|
+
}
|
package/dist/lib/logger.js
CHANGED
package/dist/options.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { Manager as WebManager } from 'web-manager';
|
|
3
3
|
import extension from './lib/extension.js';
|
|
4
4
|
import LoggerLite from './lib/logger-lite.js';
|
|
5
|
+
import { setupAuthStorageListener, setupAuthEventListeners, openAuthPage as openAuthPageHelper } from './lib/auth-helpers.js';
|
|
5
6
|
|
|
6
7
|
// Import theme (exposes Bootstrap to window.bootstrap)
|
|
7
8
|
import '__theme__/_theme.js';
|
|
@@ -29,12 +30,28 @@ class Manager {
|
|
|
29
30
|
// Initialize
|
|
30
31
|
await this.webManager.initialize(configuration);
|
|
31
32
|
|
|
33
|
+
// Set up auth state listener (updates bindings with user/account state)
|
|
34
|
+
this.webManager.auth().listen((state) => {
|
|
35
|
+
this.logger.log('Auth state changed:', state);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Set up storage listener for cross-context auth sync
|
|
39
|
+
setupAuthStorageListener(this);
|
|
40
|
+
|
|
41
|
+
// Set up auth event listeners (sign in, account buttons)
|
|
42
|
+
setupAuthEventListeners(this);
|
|
43
|
+
|
|
32
44
|
// Log
|
|
33
45
|
this.logger.log('Initialized!', this);
|
|
34
46
|
|
|
35
47
|
// Return manager instance
|
|
36
48
|
return this;
|
|
37
49
|
}
|
|
50
|
+
|
|
51
|
+
// Open auth page in new tab (for signing in via website)
|
|
52
|
+
openAuthPage(options = {}) {
|
|
53
|
+
openAuthPageHelper(this, options);
|
|
54
|
+
}
|
|
38
55
|
}
|
|
39
56
|
|
|
40
57
|
// Export
|
package/dist/page.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { Manager as WebManager } from 'web-manager';
|
|
3
3
|
import extension from './lib/extension.js';
|
|
4
4
|
import LoggerLite from './lib/logger-lite.js';
|
|
5
|
+
import { setupAuthStorageListener, setupAuthEventListeners, openAuthPage as openAuthPageHelper } from './lib/auth-helpers.js';
|
|
5
6
|
|
|
6
7
|
// Import theme (exposes Bootstrap to window.bootstrap)
|
|
7
8
|
import '__theme__/_theme.js';
|
|
@@ -29,12 +30,28 @@ class Manager {
|
|
|
29
30
|
// Initialize
|
|
30
31
|
await this.webManager.initialize(configuration);
|
|
31
32
|
|
|
33
|
+
// Set up auth state listener (updates bindings with user/account state)
|
|
34
|
+
this.webManager.auth().listen((state) => {
|
|
35
|
+
this.logger.log('Auth state changed:', state);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Set up storage listener for cross-context auth sync
|
|
39
|
+
setupAuthStorageListener(this);
|
|
40
|
+
|
|
41
|
+
// Set up auth event listeners (sign in, account buttons)
|
|
42
|
+
setupAuthEventListeners(this);
|
|
43
|
+
|
|
32
44
|
// Log
|
|
33
45
|
this.logger.log('Initialized!', this);
|
|
34
46
|
|
|
35
47
|
// Return manager instance
|
|
36
48
|
return this;
|
|
37
49
|
}
|
|
50
|
+
|
|
51
|
+
// Open auth page in new tab (for signing in via website)
|
|
52
|
+
openAuthPage(options = {}) {
|
|
53
|
+
openAuthPageHelper(this, options);
|
|
54
|
+
}
|
|
38
55
|
}
|
|
39
56
|
|
|
40
57
|
// Export
|
package/dist/popup.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { Manager as WebManager } from 'web-manager';
|
|
3
3
|
import extension from './lib/extension.js';
|
|
4
4
|
import LoggerLite from './lib/logger-lite.js';
|
|
5
|
+
import { setupAuthStorageListener, setupAuthEventListeners, openAuthPage as openAuthPageHelper } from './lib/auth-helpers.js';
|
|
5
6
|
|
|
6
7
|
// Import theme (exposes Bootstrap to window.bootstrap)
|
|
7
8
|
import '__theme__/_theme.js';
|
|
@@ -29,12 +30,28 @@ class Manager {
|
|
|
29
30
|
// Initialize
|
|
30
31
|
await this.webManager.initialize(configuration);
|
|
31
32
|
|
|
33
|
+
// Set up auth state listener (updates bindings with user/account state)
|
|
34
|
+
this.webManager.auth().listen((state) => {
|
|
35
|
+
this.logger.log('Auth state changed:', state);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Set up storage listener for cross-context auth sync
|
|
39
|
+
setupAuthStorageListener(this);
|
|
40
|
+
|
|
41
|
+
// Set up auth event listeners (sign in, account buttons)
|
|
42
|
+
setupAuthEventListeners(this);
|
|
43
|
+
|
|
32
44
|
// Log
|
|
33
45
|
this.logger.log('Initialized!', this);
|
|
34
46
|
|
|
35
47
|
// Return manager instance
|
|
36
48
|
return this;
|
|
37
49
|
}
|
|
50
|
+
|
|
51
|
+
// Open auth page in new tab (for signing in via website)
|
|
52
|
+
openAuthPage(options = {}) {
|
|
53
|
+
openAuthPageHelper(this, options);
|
|
54
|
+
}
|
|
38
55
|
}
|
|
39
56
|
|
|
40
57
|
// Export
|
package/dist/sidepanel.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { Manager as WebManager } from 'web-manager';
|
|
3
3
|
import extension from './lib/extension.js';
|
|
4
4
|
import LoggerLite from './lib/logger-lite.js';
|
|
5
|
+
import { setupAuthStorageListener, setupAuthEventListeners, openAuthPage as openAuthPageHelper } from './lib/auth-helpers.js';
|
|
5
6
|
|
|
6
7
|
// Import theme (exposes Bootstrap to window.bootstrap)
|
|
7
8
|
import '__theme__/_theme.js';
|
|
@@ -29,12 +30,28 @@ class Manager {
|
|
|
29
30
|
// Initialize
|
|
30
31
|
await this.webManager.initialize(configuration);
|
|
31
32
|
|
|
33
|
+
// Set up auth state listener (updates bindings with user/account state)
|
|
34
|
+
this.webManager.auth().listen((state) => {
|
|
35
|
+
this.logger.log('Auth state changed:', state);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Set up storage listener for cross-context auth sync
|
|
39
|
+
setupAuthStorageListener(this);
|
|
40
|
+
|
|
41
|
+
// Set up auth event listeners (sign in, account buttons)
|
|
42
|
+
setupAuthEventListeners(this);
|
|
43
|
+
|
|
32
44
|
// Log
|
|
33
45
|
this.logger.log('Initialized!', this);
|
|
34
46
|
|
|
35
47
|
// Return manager instance
|
|
36
48
|
return this;
|
|
37
49
|
}
|
|
50
|
+
|
|
51
|
+
// Open auth page in new tab (for signing in via website)
|
|
52
|
+
openAuthPage(options = {}) {
|
|
53
|
+
openAuthPageHelper(this, options);
|
|
54
|
+
}
|
|
38
55
|
}
|
|
39
56
|
|
|
40
57
|
// Export
|