') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); feat(clerk-js): Sign Out from multiple tabs at once by octoper · Pull Request #2094 · clerk/javascript · GitHub
Skip to content

feat(clerk-js): Sign Out from multiple tabs at once - #2094

Merged
octoper merged 7 commits into
mainfrom
vaggelis/sdk-767-re-introduce-broadcastchannel-in-clerk-js
Nov 13, 2023
Merged

feat(clerk-js): Sign Out from multiple tabs at once#2094
octoper merged 7 commits into
mainfrom
vaggelis/sdk-767-re-introduce-broadcastchannel-in-clerk-js

Conversation

@octoper

Copy link
Copy Markdown
Contributor

Description

This PR enables the BrodcastChannel functionallity, that is going to allow us to signout from multiple tabs at once.

Checklist

  • npm test runs as expected.
  • npm run build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

Packages affected

  • @clerk/backend
  • @clerk/chrome-extension
  • @clerk/clerk-js
  • @clerk/clerk-expo
  • @clerk/fastify
  • gatsby-plugin-clerk
  • @clerk/localizations
  • @clerk/nextjs
  • @clerk/clerk-react
  • @clerk/remix
  • @clerk/clerk-sdk-node
  • @clerk/shared
  • @clerk/themes
  • @clerk/types
  • build/tooling/chore

@octoper
octoper requested a review from a team as a code ownerNovember 9, 2023 11:16
@changeset-bot

changeset-botBot commented Nov 9, 2023

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 3391990

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
NameType
@clerk/clerk-jsMinor
@clerk/chrome-extensionPatch
@clerk/clerk-expoPatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@octoper
octoperforce-pushed the vaggelis/sdk-767-re-introduce-broadcastchannel-in-clerk-js branch from 2f0d78b to 1601f5dCompareNovember 9, 2023 11:17
@octoperoctoper self-assigned this Nov 9, 2023

@dimkldimkl left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a good candidate for adding a test to our suite.

@nikosdouvlisnikosdouvlis left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Welcome back LocalStorageBroadcastChannel :)

Comment threadpackages/clerk-js/src/core/clerk.ts Outdated
this.#broadcastChannel?.addEventListener('message', ({ data }) => {
if (data.type === 'signout') {
void this.handleUnauthenticated({ broadcast: false });
void this.handleUnauthenticated({ broadcast: true });

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's necessary to have broadcast to default to enable post the sign-out message to the BroadcastChannel, but it's not necessary to fill the this. handleUnauthenticated as broadcast prop is always true.

@nikosdouvlis

Copy link
Copy Markdown
Member

@octoper good job on this! I've approved as I don't want to block, but this is the perfect case for an e2e test. Let's write one before merging.

@octoper

Copy link
Copy Markdown
ContributorAuthor

@nikosdouvlis Already on it's way!

@octoper
octoperforce-pushed the vaggelis/sdk-767-re-introduce-broadcastchannel-in-clerk-js branch from 1601f5d to e334c0aCompareNovember 9, 2023 15:00
@octoper
octoperforce-pushed the vaggelis/sdk-767-re-introduce-broadcastchannel-in-clerk-js branch from da6936f to 4294999CompareNovember 10, 2023 09:57
@octoper
octoperforce-pushed the vaggelis/sdk-767-re-introduce-broadcastchannel-in-clerk-js branch from ec2e590 to d017be1CompareNovember 10, 2023 11:58
});
});

expect(await mainTab.page.evaluate('!window.Clerk.user')).toBe(false);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🙃 let's add a await m.po.expect.toBeSignedOut(); test helper and use it here.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The helper exists but there is a problem with it, the page.waitFucntion that is underneath mainTab.po.expect.toBeSignedOut() helper is getting a timeout at this point, I'm not exactly sure why is that, but it's probably has something to do with with the new tab we are opening.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's add a comment about why we cannot use the helper and fix this later.

Comment threadintegration/tests/sign-out-smoke.test.ts
@octoper
octoperforce-pushed the vaggelis/sdk-767-re-introduce-broadcastchannel-in-clerk-js branch from e883e80 to 93278c7CompareNovember 10, 2023 18:46
@octoper
octoper requested a review from dimklNovember 13, 2023 16:21
@octoper
octoperforce-pushed the vaggelis/sdk-767-re-introduce-broadcastchannel-in-clerk-js branch from 93278c7 to 3391990CompareNovember 13, 2023 16:31
@octoper
octoper added this pull request to the merge queue Nov 13, 2023
Merged via the queue into main with commit 08dd88cNov 13, 2023
@octoper
octoper deleted the vaggelis/sdk-767-re-introduce-broadcastchannel-in-clerk-js branch November 13, 2023 17:44
await m.po.expect.toBeSignedOut();
});

expect(await mainTab.page.evaluate('!window.Clerk.user')).toBe(false);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❓ shouldn't this be toBe(true)? If we're trying to replicate toBeSignedOut().

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right! Just opened a PR for that #2125

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@octoper@nikosdouvlis@brkalow@dimkl@desiprisg@clerk-cookie