@withone/connect 0.15.0 → 0.16.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.esm.js CHANGED
@@ -1 +1 @@
1
- const e="one_connect",t="one_connect_error",n={declined:"You cancelled the connection.",expired:"The connection attempt expired. Please try again.",failed:"The connection could not be completed. Please try again."};function o(o){const i=new URLSearchParams(o),a=i.get(e);if("success"===a)return{status:a};if("error"!==a)return null;const r=i.get(t),l=null!==(s=r)&&Object.prototype.hasOwnProperty.call(n,s)?r:"failed";var s;return{status:a,code:l,message:n[l]}}const i=[e,t,"one_connect_message"];function a(e){const t=new URLSearchParams(e);return i.some(e=>t.has(e))}let r,l=!1,s=!1,c=!1;const d=[];function p(){return u()}function u(){return"undefined"==typeof window?null:(void 0===r&&(r=o(window.location.search),(r||a(window.location.search))&&function(){const e=()=>{a(window.location.search)&&window.history.replaceState(window.history.state,"",function(e){const t=new URLSearchParams(e.search);for(const e of i)t.delete(e);const n=t.toString();return`${e.pathname}${n?`?${n}`:""}${e.hash}`}(window.location))};e();for(const t of[50,500,2e3])window.setTimeout(e,t)}()),r)}function h(e){let t=e,n=!1;const o={deliver:e=>{try{var n,o,i,a,r,l;"success"===e.status?null===(n=(o=t).onSuccess)||void 0===n||n.call(o):null===(i=(a=t).onError)||void 0===i||i.call(a,null!==(r=e.message)&&void 0!==r?r:"",null!==(l=e.code)&&void 0!==l?l:"failed")}catch{}},restored:()=>{if(n){n=!1;try{var e,o;null===(e=(o=t).onCancel)||void 0===e||e.call(o)}catch{}}}};return"undefined"!=typeof window&&(d.push(o),c||"undefined"==typeof window||(c=!0,window.addEventListener("pageshow",e=>{if(e.persisted)for(const e of[...d])e.restored()})),function(){if(l||s)return;const e=u();e&&(s=!0,window.setTimeout(()=>{s=!1;const t=d[0];t&&!l&&(l=!0,t.deliver(e))},0))}()),{open:()=>{"undefined"!=typeof window&&(n=!0,window.location.assign((e=>{const t=e.connectTheme;try{const n=new URL(e.authorizeUrl,window.location.origin);return t&&(n.hash=`one_theme=${t}`),n.toString()}catch{return e.authorizeUrl}})(t)))},update:e=>{t=e},destroy:()=>{const e=d.indexOf(o);e>=0&&d.splice(e,1)}}}const C=e=>h(e);function f(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var n=e[Symbol.toPrimitive];if(void 0!==n){var o=n.call(e,t);if("object"!=typeof o)return o;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:t+""}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function b(e){return e.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}const g={"cal-com":"Cal.com","click-up":"ClickUp",clickup:"ClickUp",docusign:"DocuSign",elevenlabs:"ElevenLabs","fireflies-ai":"Fireflies.ai",github:"GitHub",gitlab:"GitLab",hubspot:"HubSpot","linked-in":"LinkedIn",linkedin:"LinkedIn","one-drive":"OneDrive",onedrive:"OneDrive",openai:"OpenAI","otter-ai":"Otter.ai",paypal:"PayPal",posthog:"PostHog",quickbooks:"QuickBooks",sharepoint:"SharePoint","spotify-web":"Spotify",teams:"Microsoft Teams","telegram-bot":"Telegram","whatsapp-business":"WhatsApp Business",woocommerce:"WooCommerce",x:"X","youtube-data":"YouTube",youtube:"YouTube"};function v(e){var t;return null!==(t=g[e])&&void 0!==t?t:e.split(/[-_]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}function m(e){return e?`https://assets.withone.ai/connectors/${e}.svg`:""}function x(e){var t,n,o,i;const a="string"==typeof e?{slug:e}:e,r=null!==(t=a.slug)&&void 0!==t&&t.trim()?b(a.slug):null!==(n=a.name)&&void 0!==n&&n.trim()?b(a.name):"";return r?{slug:r,name:(null===(o=a.name)||void 0===o?void 0:o.trim())||v(r),imageUrl:(null===(i=a.imageUrl)||void 0===i?void 0:i.trim())||m(r)}:null}function w(e){const t=null==e?void 0:e.trim();if(!t)return[];if(t.startsWith("["))try{const e=JSON.parse(t);return Array.isArray(e)?e.filter(e=>"string"==typeof e||"object"==typeof e&&null!==e):[]}catch{return[]}return t.split(",").map(e=>e.trim()).filter(Boolean)}const y="#CCFF00",k="#0A0C0B",A="#FFFFFF",S=`\n:host{display:inline-block;vertical-align:middle;max-width:100%}\n:host([data-full-width]),:host([full-width]:not([full-width="false"])),\n:host([data-variant="block"]),:host([variant="block"]){display:block;width:100%}\n.b{all:unset;box-sizing:border-box;position:relative;display:inline-flex;align-items:center;gap:var(--gap);\n max-width:100%;cursor:pointer;user-select:none;-webkit-tap-highlight-color:transparent;\n font-family:var(--one-connect-font,inherit);font-size:var(--fs);font-weight:500;line-height:1.2;letter-spacing:-.01em;\n padding:var(--pad);border-radius:var(--one-connect-radius,12px);background:var(--bg);color:var(--fg);\n box-shadow:var(--shadow);transition:box-shadow .2s var(--ease),background-color .2s var(--ease),opacity .2s var(--ease)}\n.b[data-full-width]{display:flex;width:100%;justify-content:center}\n.b:focus-visible{outline:2px solid var(--ring);outline-offset:2px}\n.b:hover{box-shadow:var(--shadow-hover)}\n.b[disabled]{cursor:not-allowed;opacity:.5;box-shadow:none}\n.b[aria-busy="true"]{cursor:progress}\n.b{--ease:cubic-bezier(.2,.9,.25,1)}\n.b[data-size="sm"]{--fs:13px;--pad:8px 12px 8px 10px;--gap:8px;--chip:18px;--logo:12px}\n.b[data-size="md"]{--fs:14.5px;--pad:12px 16px 12px 14px;--gap:12px;--chip:22px;--logo:14px}\n.b[data-size="lg"]{--fs:16px;--pad:14px 20px 14px 16px;--gap:12px;--chip:26px;--logo:16px}\n.b[data-theme="light"],.b[data-theme="auto"]{--ink-bg:${k};--ink-fg:${A};--surface:${A};--surface-fg:${k};\n --muted:#5B6560;--line:#D5DAD7;--ring:${k};--shadow-base:0 1px 2px rgba(10,12,11,.08),0 4px 14px rgba(10,12,11,.06);\n --shadow-strong:0 1px 2px rgba(10,12,11,.12),0 6px 18px rgba(10,12,11,.1)}\n.b[data-theme="dark"]{--ink-bg:#F2F5F3;--ink-fg:${k};--surface:#101312;--surface-fg:#F2F5F3;\n --muted:#9AA39E;--line:#2A302D;--ring:${y};--shadow-base:0 1px 2px rgba(0,0,0,.4),0 8px 24px rgba(0,0,0,.35);\n --shadow-strong:0 1px 2px rgba(0,0,0,.5),0 10px 28px rgba(0,0,0,.45)}\n@media (prefers-color-scheme:dark){.b[data-theme="auto"]{--ink-bg:#F2F5F3;--ink-fg:${k};--surface:#101312;--surface-fg:#F2F5F3;\n --muted:#9AA39E;--line:#2A302D;--ring:${y};--shadow-base:0 1px 2px rgba(0,0,0,.4),0 8px 24px rgba(0,0,0,.35);\n --shadow-strong:0 1px 2px rgba(0,0,0,.5),0 10px 28px rgba(0,0,0,.45)}}\n.b[data-variant="default"]{--bg:var(--ink-bg);--fg:var(--ink-fg);--shadow:var(--shadow-base);--shadow-hover:var(--shadow-strong)}\n.b[data-variant="accent"]{--bg:var(--one-connect-accent,${y});--fg:var(--one-connect-accent-fg,${k});\n --shadow:0 1px 2px rgba(10,12,11,.1);--shadow-hover:0 1px 2px rgba(10,12,11,.12),0 6px 18px rgba(10,12,11,.12)}\n.b[data-variant="block"]{--bg:var(--surface);--fg:var(--surface-fg);--shadow:inset 0 0 0 1px var(--line);\n --shadow-hover:inset 0 0 0 1px var(--muted);flex-direction:column;align-items:stretch;gap:0;\n width:100%;max-width:420px;text-align:left;padding:16px;border-radius:var(--one-connect-radius,14px)}\n.b[data-variant="block"][data-full-width]{max-width:none}\n.stack{display:inline-flex;align-items:center;flex-shrink:0}\n.chip{width:var(--chip);height:var(--chip);border-radius:6px;display:grid;place-items:center;overflow:hidden;\n margin-left:-7px;position:relative;background:${A};color:${k};box-shadow:0 0 0 1.5px var(--bg);\n transition:margin-left .28s var(--ease)}\n.chip:first-child{margin-left:0}\n.b[data-variant="block"] .chip{box-shadow:0 0 0 1.5px var(--bg),0 0 0 2.5px var(--line)}\n.chip img{width:var(--logo);height:var(--logo);display:block;object-fit:contain}\n.chip.more,.chip.letter{font:500 9px/1 ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:-.02em}\n.chip.letter{font-size:10px;font-weight:600}\n.b:hover .chip{margin-left:-2px}.b:hover .chip:first-child{margin-left:0}\n.label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.icon{display:inline-flex;flex-shrink:0}\n.arrow{opacity:.55;transition:transform .2s var(--ease),opacity .2s var(--ease)}\n.b:hover .arrow{transform:translateX(2px);opacity:.85}\n.spinner{width:16px;height:16px;border-radius:50%;border:2px solid currentColor;border-top-color:transparent;\n opacity:.7;animation:spin .7s linear infinite;flex-shrink:0}\n@keyframes spin{to{transform:rotate(360deg)}}\n.top{display:flex;align-items:center;justify-content:space-between;gap:12px}\n.title{font-size:15px;font-weight:600;letter-spacing:-.01em}\n.sub{font-size:13px;line-height:1.5;margin-top:6px;font-weight:400;color:var(--muted)}\n.foot{margin-top:14px;padding-top:12px;display:flex;align-items:center;gap:6px;font-size:11px;font-weight:400;\n color:var(--muted);border-top:1px solid var(--line)}\n.lockup{display:inline-flex;color:var(--surface-fg)}\n.sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}\n@media (prefers-reduced-motion:reduce){.b,.chip,.arrow{transition:none}.spinner{animation-duration:1.6s}}\n@media (forced-colors:active){.b{border:1px solid ButtonText}.b:focus-visible{outline-color:Highlight}}\n`;let L=null;const E=(e,t,n)=>{const o=document.createElement(e);return t&&(o.className=t),void 0!==n&&(o.textContent=n),o},z=(e,t="icon")=>{const n=E("span",t);return n.innerHTML=e,n};function F(e){var t;const n=(null!=(o=null!==(t=e.logos)&&void 0!==t?t:e.platforms)?o:[]).map(x).filter(e=>null!==e);var o;if(0===n.length)return null;const i=E("span","stack");i.setAttribute("aria-hidden","true");for(const e of n.slice(0,3)){const t=E("span","chip");t.title=e.name;const n=E("img");n.alt="",n.decoding="async",n.src=e.imageUrl,n.addEventListener("error",()=>{n.remove(),t.classList.add("letter"),t.textContent=e.name.charAt(0).toUpperCase()}),t.appendChild(n),i.appendChild(t)}const a=n.length-3;return a>0&&i.appendChild(E("span","chip more",`+${a}`)),i}const M=(e,t)=>({authorizeUrl:e.authorizeUrl,connectTheme:e.connectTheme,...t});function $(e,t){var n;const o=null!==(n=e.shadowRoot)&&void 0!==n?n:e.attachShadow({mode:"open"});!function(e){if("undefined"!=typeof CSSStyleSheet&&"replaceSync"in CSSStyleSheet.prototype&&"adoptedStyleSheets"in e)try{return L||(L=new CSSStyleSheet,L.replaceSync(S)),void(e.adoptedStyleSheets=[L])}catch{}const t=document.createElement("style");t.textContent=S,e.appendChild(t)}(o);let i=t,a=!1,r=!1,l=null;const s=E("button","b");s.type="button",s.setAttribute("part","button");const c=E("span","sr");c.setAttribute("role","status"),c.setAttribute("aria-live","polite"),o.append(s,c);const d=()=>{return a?"connecting":void 0!==i.connected?i.connected?"connected":"idle":"success"===(null===(e=p())||void 0===e?void 0:e.status)?"connected":"idle";var e},u={onSuccess:()=>{var e,t;return null===(e=(t=i).onSuccess)||void 0===e?void 0:e.call(t)},onError:(e,t)=>{var n,o;return null===(n=(o=i).onError)||void 0===n?void 0:n.call(o,e,t)},onCancel:()=>{var e,t;a=!1,f(),null===(e=(t=i).onCancel)||void 0===e||e.call(t)}},C=h(M(i,u)),f=()=>{var e,t,n,o,a;if(r)return;const p=d(),u=null!==(e=i.variant)&&void 0!==e?e:"default",h="connecting"===p?"Connecting…":"connected"===p?null!==(t=i.connectedLabel)&&void 0!==t?t:"Connected":null!==(n=i.label)&&void 0!==n?n:"Connect your apps";s.dataset.variant=u,s.dataset.size=null!==(o=i.size)&&void 0!==o?o:"md",s.dataset.theme=null!==(a=i.theme)&&void 0!==a?a:"light",s.dataset.state=p,s.toggleAttribute("data-full-width",Boolean(i.fullWidth)),s.disabled=Boolean(i.disabled),s.setAttribute("aria-busy",String("connecting"===p)),"connecting"===p?s.setAttribute("aria-disabled","true"):s.removeAttribute("aria-disabled");const C="idle"===p?F(i):null,f="connecting"===p?E("span","spinner"):"connected"===p?z('<svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M3 8.5l3.5 3.5L13 5"/></svg>'):C;if(s.replaceChildren(),s.removeAttribute("aria-labelledby"),s.removeAttribute("aria-describedby"),"block"===u){const e=E("span","top"),t=E("span","title",h);if(t.id="one-connect-title",t.setAttribute("part","label"),e.appendChild(t),f&&e.appendChild(f),s.appendChild(e),s.setAttribute("aria-labelledby",t.id),i.description){const e=E("span","sub",i.description);e.id="one-connect-description",s.appendChild(e),s.setAttribute("aria-describedby",e.id)}const n=E("span","foot");n.setAttribute("aria-hidden","true"),n.append(E("span","","Secured by"),z('<svg viewBox="0 0 3152 990" width="35" height="11" fill="none" aria-hidden="true" focusable="false"><path d="M1698.02 793.203C1525.75 793.203 1401 666.834 1401 495.102C1401 323.909 1524.67 197 1698.02 197C1870.83 197 1996.12 323.909 1996.12 495.102C1996.12 666.834 1869.75 793.203 1698.02 793.203ZM1698.02 694.916C1801.71 694.916 1884.88 615.53 1884.88 495.102C1884.88 374.133 1801.71 295.827 1698.02 295.827C1594.87 295.827 1511.71 373.053 1511.71 495.102C1511.71 616.61 1595.41 694.916 1698.02 694.916Z" fill="currentColor"/><path d="M2326.71 197.54C2480.62 197.54 2565.95 289.887 2565.95 467.56V779.702H2455.24V468.64C2455.24 361.172 2411.5 292.587 2308.35 292.587C2217.63 292.587 2140.4 356.852 2140.4 484.841V779.702H2030.77V211.041H2140.4V272.065C2185.76 225.082 2248.41 197.54 2326.71 197.54Z" fill="currentColor"/><path d="M3151.98 493.481C3151.98 514.003 3150.36 520.483 3148.74 529.124H2700.51C2715.63 637.672 2794.47 686.815 2922.46 686.815C3031.01 686.815 3099.6 650.633 3116.88 643.072V747.84C3100.68 755.4 3023.45 793.203 2908.96 793.203C2699.97 793.203 2588.18 661.434 2588.18 497.802C2588.18 332.55 2702.67 197 2871.7 197C3031.55 197 3151.98 317.969 3151.98 493.481ZM2876.02 300.688C2784.75 300.688 2720.49 345.511 2702.67 434.617H3050.45C3034.79 344.971 2967.29 300.688 2876.02 300.688Z" fill="currentColor"/><path d="M537.494 782.175C641.011 827.7 767.922 858.83 880.501 839.875C983.155 822.599 1069.64 764.946 1094.39 659.271C1114.47 573.493 1088.54 481.273 1047.27 405.311C983.124 287.246 874.768 183.791 759.847 114.657C644.926 45.5225 507.181 -5.02605 372.102 0.398669C289.698 3.69665 205.938 26.536 146.544 85.6685C112.069 119.989 88.3818 171.231 83.1266 219.823C78.1642 265.64 84.3749 310.317 99.8478 354.007C168.243 547.14 354.009 701.467 537.51 782.191L537.494 782.175ZM751.956 818.053C583.05 796.2 415.7 707.108 292.472 593.004C222.536 528.246 159.366 444.979 125.985 355.471C102.961 293.734 96.3956 223.367 122.41 161.969C137.158 127.14 160.367 98.244 190.743 75.9133C275.581 13.5752 395.819 6.99464 495.977 26.8596C608.848 49.252 713.875 99.4615 806.712 166.515C907.085 239.025 999.537 339.922 1048.42 454.627C1072.45 511.001 1083.99 570.103 1075.64 630.869C1067.38 690.957 1034.57 742.353 983.987 775.379C917.626 818.715 830.861 828.255 751.972 818.053H751.956Z" fill="currentColor"/><path d="M1103.27 661.228C1086.68 755.313 1024.9 818.622 934.021 848.69C821.751 885.846 685.146 860.263 576.251 818.915C452.515 771.942 340.336 699.91 245.157 607.813C209.002 572.83 177.255 534.456 148.837 493.031C100.384 422.402 61.7024 335.19 65.8326 248.071C68.2213 197.769 83.987 159.241 111.403 116.938C45.8289 171.308 31.404 262.511 47.1543 342.002C53.4728 373.841 62.9815 403.23 76.528 432.958C100.338 485.202 130.914 532.992 167.747 577.238C255.452 682.573 367.83 765.13 491.073 824.124C614.317 883.118 769.307 920.691 900.471 889.128C985.788 868.601 1061.47 816.095 1090.83 730.856C1098.18 708.71 1104.61 686.564 1103.25 661.244L1103.27 661.228Z" fill="currentColor"/><path d="M883.297 963.502C923.15 947.074 960.877 926.022 988.309 893.967C954.265 917.839 920.931 934.807 882.403 944.993C751.747 979.53 595.123 942.589 474.731 886.57C422.102 862.082 372.617 834.018 325.181 800.591C205.128 715.984 89.4825 597.996 36.7762 458.756C20.2092 414.973 11.7793 370.404 11.5327 323.739C11.4249 302.641 15.4627 283.747 19.0226 263.004C-2.52219 310.486 -3.66265 380.915 5.21419 431.617C32.0605 584.881 147.151 721.146 266.988 813.983C343.443 873.224 436.403 924.913 528.424 954.672C620.444 984.431 713.851 999.426 808.491 983.598C834.459 979.252 858.362 973.781 883.297 963.502Z" fill="currentColor"/><path d="M1045.09 830.737C1053.55 816.158 1061.75 802.95 1066.99 787.061C1043.75 824.541 1013.3 854.408 974.29 874.982C947.752 888.991 920.228 899.27 890.577 905.219C864.578 910.428 839.673 914.481 812.781 914.851C739.716 915.852 668.717 903.092 599.459 880.854C418.686 822.8 238.422 697.6 127.985 543.165C94.8819 496.87 68.8679 447.847 50.7135 394.031C28.1978 324.45 25.7782 258.69 53.4104 189.078C36.1345 211.825 26.9956 237.793 20.4151 264.916C18.3654 282.732 14.713 299.345 15.0828 317.561C15.9613 360.774 23.5436 402.692 38.477 443.562C73.1522 538.464 134.936 621.869 207.368 691.913C307.34 788.587 426.762 862.268 558.127 907.993C689.491 953.718 871.975 973.768 992.614 885.446C1013.28 870.312 1029.39 851.773 1045.07 830.752L1045.09 830.737Z" fill="currentColor"/><path d="M552.552 745.664C671.079 797.831 835.825 835.526 954.768 769.12C999.137 744.354 1031.99 705.626 1047.99 657.312C1086.75 540.264 1020.28 405.817 947.124 315.631C855.536 202.745 729.688 114.516 592.76 66.0323C506.349 35.4412 418.968 22.0797 328.211 37.46C262.313 48.6177 195.29 81.7054 157.563 138.234C118.912 196.133 115.891 270.785 136.758 335.882C176.519 459.926 276.769 570.763 381.01 646.277C434.995 685.391 491.662 718.864 552.567 745.664H552.552ZM210.162 422.955C199.898 402.381 189.141 382.701 184.733 360.385C182.267 347.918 184.625 333.477 184.564 320.64C184.44 293.223 194.072 269.059 209.992 247.93C219.609 235.17 229.456 224.844 243.018 215.906C341.218 151.179 476.051 175.991 576.763 223.904C661.971 264.435 737.394 321.534 796.11 395.862C836.919 447.52 871.193 513.634 880.502 579.501C888.238 634.272 873.243 695.485 826.763 729.189C807.853 742.905 785.045 751.721 761.728 755.974C721.921 763.217 688.802 758.008 649.565 748.916C594.27 736.094 542.488 715.212 492.279 688.889C441.977 662.521 396.745 631.483 353.008 595.436C314.372 563.597 280.252 537.845 248.458 498.007L248.274 497.837L221.504 461.945L211.379 445.84C194.103 418.408 177.398 391.346 165.238 361.202C151.291 326.604 142.676 291.852 143.678 254.279C146.19 160.564 203.766 96.7467 290.238 67.82C434.394 19.5985 611.561 79.4246 735.298 157.636C825.099 214.411 904.435 286.581 963.321 375.134C989.767 414.894 1010.42 456.998 1023.78 502.646C1049.84 591.66 1036.79 685.884 957.404 742.659C890.257 790.68 785.6 793.146 707.295 776.486C680.403 769.736 654.065 766.007 629.222 754.818C732.107 783.93 882.397 797.723 963.938 715.35C990.599 688.412 1007.55 656.218 1013.75 618.537C1020.87 575.232 1016.12 531.634 1002.62 489.931C985.498 437.071 956.34 384.026 922.405 340.289C876.911 281.665 823.188 230.531 762.468 187.981C681.112 130.975 588.783 88.887 490.799 71.0872C425.595 59.2514 349.463 60.4072 287.557 85.0959C256.441 97.5019 228.501 114.5 205.924 138.85C158.303 190.2 147.176 256.036 161.539 323.383C166.856 348.334 175.456 371.296 185.596 394.737C194.488 415.295 222.676 461.883 236.022 477.649L226.729 456.196L210.162 423.001V422.955ZM832.342 286.936C756.904 211.544 666.44 154.076 564.896 120.249C526.553 107.473 487.948 99.4899 447.648 96.084C401.26 92.1696 356.167 96.7313 312.215 111.341C222.337 141.208 169.399 217.277 175.255 312.333C177.567 324.847 179.555 335.774 180.603 348.503C152.971 264.944 174.454 175.236 251.356 125.581C310.797 87.2072 387.39 78.2071 456.694 86.7603C503.714 92.5549 555.387 106.656 599.078 124.317C706.016 167.546 800.764 234.615 876.741 321.395C912.002 361.664 942.085 405.756 963.876 454.532C996.779 528.166 1011.85 610.046 965.895 681.369C952.379 702.359 935.427 718.818 914.283 731.871C884.432 747.421 852.947 758.671 818.872 761.06C839.523 755.959 859.404 750.981 878.637 740.424C929.186 717.061 964.601 671.567 974.818 616.488C987.671 547.245 964.693 475.429 930.881 415.357C903.834 367.305 871.471 326.049 832.311 286.905L832.342 286.936ZM890.673 420.18C861.623 370.387 825.515 327.621 783.288 287.999C721.659 230.161 650.028 185.345 570.598 156.033C513.623 135.013 454.506 124.394 393.786 128.108C353.316 130.59 315.728 139.867 280.498 159.516C245.268 179.166 216.819 204.918 201.023 240.394L188.617 268.242C204.583 180.445 278.325 132.054 361.931 119.355C412.757 111.634 462.658 116.643 512.421 129.048C596.905 150.116 674.1 189.923 743.45 242.028C816.607 296.999 885.526 373.531 924.578 456.982C949.713 510.675 965.094 571.61 949.837 630.234C939.018 671.768 912.511 706.566 875.308 727.987C847.013 744.292 816.191 754.679 783.242 758.101C825.915 745.926 863.75 731.917 895.327 698.799C913.512 679.72 926.535 657.62 933.054 631.714C951.347 558.989 927.49 483.274 890.642 420.134L890.673 420.18ZM726.19 279.369C625.678 198.799 493.404 141.917 362.655 156.973C343.854 159.131 326.547 164.17 308.639 169.195C301.18 171.29 295.201 177.732 286.493 176.253C378.313 130.081 492.063 149.545 583.143 188.119C684.102 230.87 775.952 302.825 840.664 391.069C871.794 433.527 895.805 479.652 909.506 530.386C918.382 563.273 920.232 596.654 911.941 629.294C905.622 654.153 895.481 677.778 875.786 694.9C893.987 666.327 905.452 637.693 907.086 604.128C908.72 570.562 903.141 536.565 891.567 503.57C861.392 417.53 797.066 336.19 726.205 279.384L726.19 279.369Z" fill="currentColor"/></svg>',"lockup")),s.appendChild(n)}else{f&&s.appendChild(f);const e=E("span","label",h);e.setAttribute("part","label"),s.appendChild(e),"idle"===p&&s.appendChild(z('<svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M6 3l5 5-5 5"/></svg>',"icon arrow"))}var b,g;b=p,null!==l?b!==l&&(l=b,c.textContent="connecting"===b?"Connecting to One…":"connected"===b?null!==(g=i.connectedLabel)&&void 0!==g?g:"Connected":""):l=b};return s.addEventListener("click",()=>{r||i.disabled||a||(a=!0,f(),C.open())}),f(),{update:e=>{i=e,C.update(M(i,u)),f()},destroy:()=>{r=!0,C.destroy(),o.replaceChildren()}}}function T(e,t){const n=document.createElement("span");n.className="one-connect";const o=e=>{var t;n.setAttribute("data-variant",null!==(t=e.variant)&&void 0!==t?t:"default"),n.toggleAttribute("data-full-width",Boolean(e.fullWidth))};o(t),e.appendChild(n);const i=$(n,t);return{update:e=>{o(e),i.update(e)},destroy:()=>{i.destroy(),n.remove()}}}const U=["authorize-url","logos","platforms","connected","disabled","variant","size","full-width","theme","connect-theme","label","connected-label","description"];function Z(e,t,n){const o=e.getAttribute(t);return o&&n.includes(o)?o:void 0}const B=(e,t)=>e.hasAttribute(t)?"false"!==e.getAttribute(t):void 0;function H(){if("undefined"!=typeof window&&"undefined"!=typeof customElements&&!customElements.get("one-connect-button")){class e extends HTMLElement{constructor(...e){super(...e),f(this,"onSuccess",null),f(this,"onError",null),f(this,"onCancel",null),f(this,"handle",null)}connectedCallback(){this.sync()}disconnectedCallback(){var e;null===(e=this.handle)||void 0===e||e.destroy(),this.handle=null}attributeChangedCallback(){this.isConnected&&this.sync()}props(e){var t,n,o,i;return{authorizeUrl:e,logos:w(null!==(t=this.getAttribute("logos"))&&void 0!==t?t:this.getAttribute("platforms")),connected:B(this,"connected"),disabled:B(this,"disabled"),variant:Z(this,"variant",["default","accent","block"]),size:Z(this,"size",["sm","md","lg"]),fullWidth:B(this,"full-width"),theme:Z(this,"theme",["light","dark","auto"]),connectTheme:Z(this,"connect-theme",["light","dark"]),label:null!==(n=this.getAttribute("label"))&&void 0!==n?n:void 0,connectedLabel:null!==(o=this.getAttribute("connected-label"))&&void 0!==o?o:void 0,description:null!==(i=this.getAttribute("description"))&&void 0!==i?i:void 0,onSuccess:()=>{var e;null===(e=this.onSuccess)||void 0===e||e.call(this),this.dispatchEvent(new CustomEvent("success"))},onError:(e,t)=>{var n;null===(n=this.onError)||void 0===n||n.call(this,e,t),this.dispatchEvent(new CustomEvent("error",{detail:{message:e,code:t}}))},onCancel:()=>{var e;null===(e=this.onCancel)||void 0===e||e.call(this),this.dispatchEvent(new CustomEvent("cancel"))}}}sync(){const e=this.getAttribute("authorize-url");var t;if(!e)return null===(t=this.handle)||void 0===t||t.destroy(),void(this.handle=null);const n=this.props(e);this.handle?this.handle.update(n):this.handle=$(this,n)}}f(e,"observedAttributes",[...U]),customElements.define("one-connect-button",e)}}H();export{h as createConnectFlow,T as mountConnectButton,p as readConnectReturn,H as registerConnectButton,$ as renderConnectButton,C as useOneConnect};
1
+ const e="one_connect",t="one_connect_error",n={declined:"You cancelled the connection.",expired:"The connection attempt expired. Please try again.",failed:"The connection could not be completed. Please try again."};function o(o){const i=new URLSearchParams(o),a=i.get(e);if("success"===a)return{status:a};if("error"!==a)return null;const r=i.get(t),l=null!==(s=r)&&Object.prototype.hasOwnProperty.call(n,s)?r:"failed";var s;return{status:a,code:l,message:n[l]}}const i=[e,t,"one_connect_message"];function a(e){const t=new URLSearchParams(e);return i.some(e=>t.has(e))}let r,l=!1,s=!1,c=!1;const d=[];function p(){return u()}function u(){return"undefined"==typeof window?null:(void 0===r&&(r=o(window.location.search),(r||a(window.location.search))&&function(){const e=()=>{a(window.location.search)&&window.history.replaceState(window.history.state,"",function(e){const t=new URLSearchParams(e.search);for(const e of i)t.delete(e);const n=t.toString();return`${e.pathname}${n?`?${n}`:""}${e.hash}`}(window.location))};e();for(const t of[50,500,2e3])window.setTimeout(e,t)}()),r)}function h(e){let t=e,n=!1;const o={deliver:e=>{try{var n,o,i,a,r,l;"success"===e.status?null===(n=(o=t).onSuccess)||void 0===n||n.call(o):null===(i=(a=t).onError)||void 0===i||i.call(a,null!==(r=e.message)&&void 0!==r?r:"",null!==(l=e.code)&&void 0!==l?l:"failed")}catch{}},restored:()=>{if(n){n=!1;try{var e,o;null===(e=(o=t).onCancel)||void 0===e||e.call(o)}catch{}}}};return"undefined"!=typeof window&&(d.push(o),c||"undefined"==typeof window||(c=!0,window.addEventListener("pageshow",e=>{if(e.persisted)for(const e of[...d])e.restored()})),function(){if(l||s)return;const e=u();e&&(s=!0,window.setTimeout(()=>{s=!1;const t=d[0];t&&!l&&(l=!0,t.deliver(e))},0))}()),{open:()=>{"undefined"!=typeof window&&(n=!0,window.location.assign((e=>{const t=e.connectTheme;try{const n=new URL(e.authorizeUrl,window.location.origin);return t&&(n.hash=`one_theme=${t}`),n.toString()}catch{return e.authorizeUrl}})(t)))},update:e=>{t=e},destroy:()=>{const e=d.indexOf(o);e>=0&&d.splice(e,1)}}}function C(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var n=e[Symbol.toPrimitive];if(void 0!==n){var o=n.call(e,t);if("object"!=typeof o)return o;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:t+""}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function f(e){return e.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}const b={"cal-com":"Cal.com","click-up":"ClickUp",clickup:"ClickUp",docusign:"DocuSign",elevenlabs:"ElevenLabs","fireflies-ai":"Fireflies.ai",github:"GitHub",gitlab:"GitLab",hubspot:"HubSpot","linked-in":"LinkedIn",linkedin:"LinkedIn","one-drive":"OneDrive",onedrive:"OneDrive",openai:"OpenAI","otter-ai":"Otter.ai",paypal:"PayPal",posthog:"PostHog",quickbooks:"QuickBooks",sharepoint:"SharePoint","spotify-web":"Spotify",teams:"Microsoft Teams","telegram-bot":"Telegram","whatsapp-business":"WhatsApp Business",woocommerce:"WooCommerce",x:"X","youtube-data":"YouTube",youtube:"YouTube"};function g(e){var t;return null!==(t=b[e])&&void 0!==t?t:e.split(/[-_]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}function v(e){return e?`https://assets.withone.ai/connectors/${e}.svg`:""}function m(e){var t,n,o,i;const a="string"==typeof e?{slug:e}:e,r=null!==(t=a.slug)&&void 0!==t&&t.trim()?f(a.slug):null!==(n=a.name)&&void 0!==n&&n.trim()?f(a.name):"";return r?{slug:r,name:(null===(o=a.name)||void 0===o?void 0:o.trim())||g(r),imageUrl:(null===(i=a.imageUrl)||void 0===i?void 0:i.trim())||v(r)}:null}function x(e){const t=null==e?void 0:e.trim();if(!t)return[];if(t.startsWith("["))try{const e=JSON.parse(t);return Array.isArray(e)?e.filter(e=>"string"==typeof e||"object"==typeof e&&null!==e):[]}catch{return[]}return t.split(",").map(e=>e.trim()).filter(Boolean)}const w="#CCFF00",y="#0A0C0B",k="#FFFFFF",A=`\n:host{display:inline-block;vertical-align:middle;max-width:100%}\n:host([data-full-width]),:host([full-width]:not([full-width="false"])),\n:host([data-variant="block"]),:host([variant="block"]){display:block;width:100%}\n.b{all:unset;box-sizing:border-box;position:relative;display:inline-flex;align-items:center;gap:var(--gap);\n max-width:100%;cursor:pointer;user-select:none;-webkit-tap-highlight-color:transparent;\n font-family:var(--one-connect-font,inherit);font-size:var(--fs);font-weight:500;line-height:1.2;letter-spacing:-.01em;\n padding:var(--pad);border-radius:var(--one-connect-radius,12px);background:var(--bg);color:var(--fg);\n box-shadow:var(--shadow);transition:box-shadow .2s var(--ease),background-color .2s var(--ease),opacity .2s var(--ease)}\n.b[data-full-width]{display:flex;width:100%;justify-content:center}\n.b:focus-visible{outline:2px solid var(--ring);outline-offset:2px}\n.b:hover{box-shadow:var(--shadow-hover)}\n.b[disabled]{cursor:not-allowed;opacity:.5;box-shadow:none}\n.b[aria-busy="true"]{cursor:progress}\n.b{--ease:cubic-bezier(.2,.9,.25,1)}\n.b[data-size="sm"]{--fs:13px;--pad:8px 12px 8px 10px;--gap:8px;--chip:18px;--logo:12px}\n.b[data-size="md"]{--fs:14.5px;--pad:12px 16px 12px 14px;--gap:12px;--chip:22px;--logo:14px}\n.b[data-size="lg"]{--fs:16px;--pad:14px 20px 14px 16px;--gap:12px;--chip:26px;--logo:16px}\n.b[data-theme="light"],.b[data-theme="auto"]{--ink-bg:${y};--ink-fg:${k};--surface:${k};--surface-fg:${y};\n --muted:#5B6560;--line:#D5DAD7;--ring:${y};--shadow-base:0 1px 2px rgba(10,12,11,.08),0 4px 14px rgba(10,12,11,.06);\n --shadow-strong:0 1px 2px rgba(10,12,11,.12),0 6px 18px rgba(10,12,11,.1)}\n.b[data-theme="dark"]{--ink-bg:#F2F5F3;--ink-fg:${y};--surface:#101312;--surface-fg:#F2F5F3;\n --muted:#9AA39E;--line:#2A302D;--ring:${w};--shadow-base:0 1px 2px rgba(0,0,0,.4),0 8px 24px rgba(0,0,0,.35);\n --shadow-strong:0 1px 2px rgba(0,0,0,.5),0 10px 28px rgba(0,0,0,.45)}\n@media (prefers-color-scheme:dark){.b[data-theme="auto"]{--ink-bg:#F2F5F3;--ink-fg:${y};--surface:#101312;--surface-fg:#F2F5F3;\n --muted:#9AA39E;--line:#2A302D;--ring:${w};--shadow-base:0 1px 2px rgba(0,0,0,.4),0 8px 24px rgba(0,0,0,.35);\n --shadow-strong:0 1px 2px rgba(0,0,0,.5),0 10px 28px rgba(0,0,0,.45)}}\n.b[data-variant="default"]{--bg:var(--ink-bg);--fg:var(--ink-fg);--shadow:var(--shadow-base);--shadow-hover:var(--shadow-strong)}\n.b[data-variant="accent"]{--bg:var(--one-connect-accent,${w});--fg:var(--one-connect-accent-fg,${y});\n --shadow:0 1px 2px rgba(10,12,11,.1);--shadow-hover:0 1px 2px rgba(10,12,11,.12),0 6px 18px rgba(10,12,11,.12)}\n.b[data-variant="block"]{--bg:var(--surface);--fg:var(--surface-fg);--shadow:inset 0 0 0 1px var(--line);\n --shadow-hover:inset 0 0 0 1px var(--muted);flex-direction:column;align-items:stretch;gap:0;\n width:100%;max-width:420px;text-align:left;padding:16px;border-radius:var(--one-connect-radius,14px)}\n.b[data-variant="block"][data-full-width]{max-width:none}\n.stack{display:inline-flex;align-items:center;flex-shrink:0}\n.chip{width:var(--chip);height:var(--chip);border-radius:6px;display:grid;place-items:center;overflow:hidden;\n margin-left:-7px;position:relative;background:${k};color:${y};box-shadow:0 0 0 1.5px var(--bg);\n transition:margin-left .28s var(--ease)}\n.chip:first-child{margin-left:0}\n.b[data-variant="block"] .chip{box-shadow:0 0 0 1.5px var(--bg),0 0 0 2.5px var(--line)}\n.chip img{width:var(--logo);height:var(--logo);display:block;object-fit:contain}\n.chip.more,.chip.letter{font:500 9px/1 ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:-.02em}\n.chip.letter{font-size:10px;font-weight:600}\n.b:hover .chip{margin-left:-2px}.b:hover .chip:first-child{margin-left:0}\n.label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.icon{display:inline-flex;flex-shrink:0}\n.arrow{opacity:.55;transition:transform .2s var(--ease),opacity .2s var(--ease)}\n.b:hover .arrow{transform:translateX(2px);opacity:.85}\n.spinner{width:16px;height:16px;border-radius:50%;border:2px solid currentColor;border-top-color:transparent;\n opacity:.7;animation:spin .7s linear infinite;flex-shrink:0}\n@keyframes spin{to{transform:rotate(360deg)}}\n.top{display:flex;align-items:center;justify-content:space-between;gap:12px}\n.title{font-size:15px;font-weight:600;letter-spacing:-.01em}\n.sub{font-size:13px;line-height:1.5;margin-top:6px;font-weight:400;color:var(--muted)}\n.foot{margin-top:14px;padding-top:12px;display:flex;align-items:center;gap:6px;font-size:11px;font-weight:400;\n color:var(--muted);border-top:1px solid var(--line)}\n.lockup{display:inline-flex;color:var(--surface-fg)}\n.sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}\n@media (prefers-reduced-motion:reduce){.b,.chip,.arrow{transition:none}.spinner{animation-duration:1.6s}}\n@media (forced-colors:active){.b{border:1px solid ButtonText}.b:focus-visible{outline-color:Highlight}}\n`;let S=null;const L=(e,t,n)=>{const o=document.createElement(e);return t&&(o.className=t),void 0!==n&&(o.textContent=n),o},E=(e,t="icon")=>{const n=L("span",t);return n.innerHTML=e,n};function z(e){var t;const n=(null!=(o=null!==(t=e.logos)&&void 0!==t?t:e.platforms)?o:[]).map(m).filter(e=>null!==e);var o;if(0===n.length)return null;const i=L("span","stack");i.setAttribute("aria-hidden","true");for(const e of n.slice(0,3)){const t=L("span","chip");t.title=e.name;const n=L("img");n.alt="",n.decoding="async",n.src=e.imageUrl,n.addEventListener("error",()=>{n.remove(),t.classList.add("letter"),t.textContent=e.name.charAt(0).toUpperCase()}),t.appendChild(n),i.appendChild(t)}const a=n.length-3;return a>0&&i.appendChild(L("span","chip more",`+${a}`)),i}const F=(e,t)=>({authorizeUrl:e.authorizeUrl,connectTheme:e.connectTheme,...t});function M(e,t){var n;const o=null!==(n=e.shadowRoot)&&void 0!==n?n:e.attachShadow({mode:"open"});!function(e){if("undefined"!=typeof CSSStyleSheet&&"replaceSync"in CSSStyleSheet.prototype&&"adoptedStyleSheets"in e)try{return S||(S=new CSSStyleSheet,S.replaceSync(A)),void(e.adoptedStyleSheets=[S])}catch{}const t=document.createElement("style");t.textContent=A,e.appendChild(t)}(o);let i=t,a=!1,r=!1,l=null;const s=L("button","b");s.type="button",s.setAttribute("part","button");const c=L("span","sr");c.setAttribute("role","status"),c.setAttribute("aria-live","polite"),o.append(s,c);const d=()=>{return a?"connecting":void 0!==i.connected?i.connected?"connected":"idle":"success"===(null===(e=p())||void 0===e?void 0:e.status)?"connected":"idle";var e},u={onSuccess:()=>{var e,t;return null===(e=(t=i).onSuccess)||void 0===e?void 0:e.call(t)},onError:(e,t)=>{var n,o;return null===(n=(o=i).onError)||void 0===n?void 0:n.call(o,e,t)},onCancel:()=>{var e,t;a=!1,f(),null===(e=(t=i).onCancel)||void 0===e||e.call(t)}},C=h(F(i,u)),f=()=>{var e,t,n,o,a;if(r)return;const p=d(),u=null!==(e=i.variant)&&void 0!==e?e:"default",h="connecting"===p?"Connecting…":"connected"===p?null!==(t=i.connectedLabel)&&void 0!==t?t:"Connected":null!==(n=i.label)&&void 0!==n?n:"Connect your apps";s.dataset.variant=u,s.dataset.size=null!==(o=i.size)&&void 0!==o?o:"md",s.dataset.theme=null!==(a=i.theme)&&void 0!==a?a:"light",s.dataset.state=p,s.toggleAttribute("data-full-width",Boolean(i.fullWidth)),s.disabled=Boolean(i.disabled),s.setAttribute("aria-busy",String("connecting"===p)),"connecting"===p?s.setAttribute("aria-disabled","true"):s.removeAttribute("aria-disabled");const C="idle"===p?z(i):null,f="connecting"===p?L("span","spinner"):"connected"===p?E('<svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M3 8.5l3.5 3.5L13 5"/></svg>'):C;if(s.replaceChildren(),s.removeAttribute("aria-labelledby"),s.removeAttribute("aria-describedby"),"block"===u){const e=L("span","top"),t=L("span","title",h);if(t.id="one-connect-title",t.setAttribute("part","label"),e.appendChild(t),f&&e.appendChild(f),s.appendChild(e),s.setAttribute("aria-labelledby",t.id),i.description){const e=L("span","sub",i.description);e.id="one-connect-description",s.appendChild(e),s.setAttribute("aria-describedby",e.id)}const n=L("span","foot");n.setAttribute("aria-hidden","true"),n.append(L("span","","Secured by"),E('<svg viewBox="0 0 3152 990" width="35" height="11" fill="none" aria-hidden="true" focusable="false"><path d="M1698.02 793.203C1525.75 793.203 1401 666.834 1401 495.102C1401 323.909 1524.67 197 1698.02 197C1870.83 197 1996.12 323.909 1996.12 495.102C1996.12 666.834 1869.75 793.203 1698.02 793.203ZM1698.02 694.916C1801.71 694.916 1884.88 615.53 1884.88 495.102C1884.88 374.133 1801.71 295.827 1698.02 295.827C1594.87 295.827 1511.71 373.053 1511.71 495.102C1511.71 616.61 1595.41 694.916 1698.02 694.916Z" fill="currentColor"/><path d="M2326.71 197.54C2480.62 197.54 2565.95 289.887 2565.95 467.56V779.702H2455.24V468.64C2455.24 361.172 2411.5 292.587 2308.35 292.587C2217.63 292.587 2140.4 356.852 2140.4 484.841V779.702H2030.77V211.041H2140.4V272.065C2185.76 225.082 2248.41 197.54 2326.71 197.54Z" fill="currentColor"/><path d="M3151.98 493.481C3151.98 514.003 3150.36 520.483 3148.74 529.124H2700.51C2715.63 637.672 2794.47 686.815 2922.46 686.815C3031.01 686.815 3099.6 650.633 3116.88 643.072V747.84C3100.68 755.4 3023.45 793.203 2908.96 793.203C2699.97 793.203 2588.18 661.434 2588.18 497.802C2588.18 332.55 2702.67 197 2871.7 197C3031.55 197 3151.98 317.969 3151.98 493.481ZM2876.02 300.688C2784.75 300.688 2720.49 345.511 2702.67 434.617H3050.45C3034.79 344.971 2967.29 300.688 2876.02 300.688Z" fill="currentColor"/><path d="M537.494 782.175C641.011 827.7 767.922 858.83 880.501 839.875C983.155 822.599 1069.64 764.946 1094.39 659.271C1114.47 573.493 1088.54 481.273 1047.27 405.311C983.124 287.246 874.768 183.791 759.847 114.657C644.926 45.5225 507.181 -5.02605 372.102 0.398669C289.698 3.69665 205.938 26.536 146.544 85.6685C112.069 119.989 88.3818 171.231 83.1266 219.823C78.1642 265.64 84.3749 310.317 99.8478 354.007C168.243 547.14 354.009 701.467 537.51 782.191L537.494 782.175ZM751.956 818.053C583.05 796.2 415.7 707.108 292.472 593.004C222.536 528.246 159.366 444.979 125.985 355.471C102.961 293.734 96.3956 223.367 122.41 161.969C137.158 127.14 160.367 98.244 190.743 75.9133C275.581 13.5752 395.819 6.99464 495.977 26.8596C608.848 49.252 713.875 99.4615 806.712 166.515C907.085 239.025 999.537 339.922 1048.42 454.627C1072.45 511.001 1083.99 570.103 1075.64 630.869C1067.38 690.957 1034.57 742.353 983.987 775.379C917.626 818.715 830.861 828.255 751.972 818.053H751.956Z" fill="currentColor"/><path d="M1103.27 661.228C1086.68 755.313 1024.9 818.622 934.021 848.69C821.751 885.846 685.146 860.263 576.251 818.915C452.515 771.942 340.336 699.91 245.157 607.813C209.002 572.83 177.255 534.456 148.837 493.031C100.384 422.402 61.7024 335.19 65.8326 248.071C68.2213 197.769 83.987 159.241 111.403 116.938C45.8289 171.308 31.404 262.511 47.1543 342.002C53.4728 373.841 62.9815 403.23 76.528 432.958C100.338 485.202 130.914 532.992 167.747 577.238C255.452 682.573 367.83 765.13 491.073 824.124C614.317 883.118 769.307 920.691 900.471 889.128C985.788 868.601 1061.47 816.095 1090.83 730.856C1098.18 708.71 1104.61 686.564 1103.25 661.244L1103.27 661.228Z" fill="currentColor"/><path d="M883.297 963.502C923.15 947.074 960.877 926.022 988.309 893.967C954.265 917.839 920.931 934.807 882.403 944.993C751.747 979.53 595.123 942.589 474.731 886.57C422.102 862.082 372.617 834.018 325.181 800.591C205.128 715.984 89.4825 597.996 36.7762 458.756C20.2092 414.973 11.7793 370.404 11.5327 323.739C11.4249 302.641 15.4627 283.747 19.0226 263.004C-2.52219 310.486 -3.66265 380.915 5.21419 431.617C32.0605 584.881 147.151 721.146 266.988 813.983C343.443 873.224 436.403 924.913 528.424 954.672C620.444 984.431 713.851 999.426 808.491 983.598C834.459 979.252 858.362 973.781 883.297 963.502Z" fill="currentColor"/><path d="M1045.09 830.737C1053.55 816.158 1061.75 802.95 1066.99 787.061C1043.75 824.541 1013.3 854.408 974.29 874.982C947.752 888.991 920.228 899.27 890.577 905.219C864.578 910.428 839.673 914.481 812.781 914.851C739.716 915.852 668.717 903.092 599.459 880.854C418.686 822.8 238.422 697.6 127.985 543.165C94.8819 496.87 68.8679 447.847 50.7135 394.031C28.1978 324.45 25.7782 258.69 53.4104 189.078C36.1345 211.825 26.9956 237.793 20.4151 264.916C18.3654 282.732 14.713 299.345 15.0828 317.561C15.9613 360.774 23.5436 402.692 38.477 443.562C73.1522 538.464 134.936 621.869 207.368 691.913C307.34 788.587 426.762 862.268 558.127 907.993C689.491 953.718 871.975 973.768 992.614 885.446C1013.28 870.312 1029.39 851.773 1045.07 830.752L1045.09 830.737Z" fill="currentColor"/><path d="M552.552 745.664C671.079 797.831 835.825 835.526 954.768 769.12C999.137 744.354 1031.99 705.626 1047.99 657.312C1086.75 540.264 1020.28 405.817 947.124 315.631C855.536 202.745 729.688 114.516 592.76 66.0323C506.349 35.4412 418.968 22.0797 328.211 37.46C262.313 48.6177 195.29 81.7054 157.563 138.234C118.912 196.133 115.891 270.785 136.758 335.882C176.519 459.926 276.769 570.763 381.01 646.277C434.995 685.391 491.662 718.864 552.567 745.664H552.552ZM210.162 422.955C199.898 402.381 189.141 382.701 184.733 360.385C182.267 347.918 184.625 333.477 184.564 320.64C184.44 293.223 194.072 269.059 209.992 247.93C219.609 235.17 229.456 224.844 243.018 215.906C341.218 151.179 476.051 175.991 576.763 223.904C661.971 264.435 737.394 321.534 796.11 395.862C836.919 447.52 871.193 513.634 880.502 579.501C888.238 634.272 873.243 695.485 826.763 729.189C807.853 742.905 785.045 751.721 761.728 755.974C721.921 763.217 688.802 758.008 649.565 748.916C594.27 736.094 542.488 715.212 492.279 688.889C441.977 662.521 396.745 631.483 353.008 595.436C314.372 563.597 280.252 537.845 248.458 498.007L248.274 497.837L221.504 461.945L211.379 445.84C194.103 418.408 177.398 391.346 165.238 361.202C151.291 326.604 142.676 291.852 143.678 254.279C146.19 160.564 203.766 96.7467 290.238 67.82C434.394 19.5985 611.561 79.4246 735.298 157.636C825.099 214.411 904.435 286.581 963.321 375.134C989.767 414.894 1010.42 456.998 1023.78 502.646C1049.84 591.66 1036.79 685.884 957.404 742.659C890.257 790.68 785.6 793.146 707.295 776.486C680.403 769.736 654.065 766.007 629.222 754.818C732.107 783.93 882.397 797.723 963.938 715.35C990.599 688.412 1007.55 656.218 1013.75 618.537C1020.87 575.232 1016.12 531.634 1002.62 489.931C985.498 437.071 956.34 384.026 922.405 340.289C876.911 281.665 823.188 230.531 762.468 187.981C681.112 130.975 588.783 88.887 490.799 71.0872C425.595 59.2514 349.463 60.4072 287.557 85.0959C256.441 97.5019 228.501 114.5 205.924 138.85C158.303 190.2 147.176 256.036 161.539 323.383C166.856 348.334 175.456 371.296 185.596 394.737C194.488 415.295 222.676 461.883 236.022 477.649L226.729 456.196L210.162 423.001V422.955ZM832.342 286.936C756.904 211.544 666.44 154.076 564.896 120.249C526.553 107.473 487.948 99.4899 447.648 96.084C401.26 92.1696 356.167 96.7313 312.215 111.341C222.337 141.208 169.399 217.277 175.255 312.333C177.567 324.847 179.555 335.774 180.603 348.503C152.971 264.944 174.454 175.236 251.356 125.581C310.797 87.2072 387.39 78.2071 456.694 86.7603C503.714 92.5549 555.387 106.656 599.078 124.317C706.016 167.546 800.764 234.615 876.741 321.395C912.002 361.664 942.085 405.756 963.876 454.532C996.779 528.166 1011.85 610.046 965.895 681.369C952.379 702.359 935.427 718.818 914.283 731.871C884.432 747.421 852.947 758.671 818.872 761.06C839.523 755.959 859.404 750.981 878.637 740.424C929.186 717.061 964.601 671.567 974.818 616.488C987.671 547.245 964.693 475.429 930.881 415.357C903.834 367.305 871.471 326.049 832.311 286.905L832.342 286.936ZM890.673 420.18C861.623 370.387 825.515 327.621 783.288 287.999C721.659 230.161 650.028 185.345 570.598 156.033C513.623 135.013 454.506 124.394 393.786 128.108C353.316 130.59 315.728 139.867 280.498 159.516C245.268 179.166 216.819 204.918 201.023 240.394L188.617 268.242C204.583 180.445 278.325 132.054 361.931 119.355C412.757 111.634 462.658 116.643 512.421 129.048C596.905 150.116 674.1 189.923 743.45 242.028C816.607 296.999 885.526 373.531 924.578 456.982C949.713 510.675 965.094 571.61 949.837 630.234C939.018 671.768 912.511 706.566 875.308 727.987C847.013 744.292 816.191 754.679 783.242 758.101C825.915 745.926 863.75 731.917 895.327 698.799C913.512 679.72 926.535 657.62 933.054 631.714C951.347 558.989 927.49 483.274 890.642 420.134L890.673 420.18ZM726.19 279.369C625.678 198.799 493.404 141.917 362.655 156.973C343.854 159.131 326.547 164.17 308.639 169.195C301.18 171.29 295.201 177.732 286.493 176.253C378.313 130.081 492.063 149.545 583.143 188.119C684.102 230.87 775.952 302.825 840.664 391.069C871.794 433.527 895.805 479.652 909.506 530.386C918.382 563.273 920.232 596.654 911.941 629.294C905.622 654.153 895.481 677.778 875.786 694.9C893.987 666.327 905.452 637.693 907.086 604.128C908.72 570.562 903.141 536.565 891.567 503.57C861.392 417.53 797.066 336.19 726.205 279.384L726.19 279.369Z" fill="currentColor"/></svg>',"lockup")),s.appendChild(n)}else{f&&s.appendChild(f);const e=L("span","label",h);e.setAttribute("part","label"),s.appendChild(e),"idle"===p&&s.appendChild(E('<svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M6 3l5 5-5 5"/></svg>',"icon arrow"))}var b,g;b=p,null!==l?b!==l&&(l=b,c.textContent="connecting"===b?"Connecting to One…":"connected"===b?null!==(g=i.connectedLabel)&&void 0!==g?g:"Connected":""):l=b};return s.addEventListener("click",()=>{r||i.disabled||a||(a=!0,f(),C.open())}),f(),{update:e=>{i=e,C.update(F(i,u)),f()},destroy:()=>{r=!0,C.destroy(),o.replaceChildren()}}}function $(e,t){const n=document.createElement("span");n.className="one-connect";const o=e=>{var t;n.setAttribute("data-variant",null!==(t=e.variant)&&void 0!==t?t:"default"),n.toggleAttribute("data-full-width",Boolean(e.fullWidth))};o(t),e.appendChild(n);const i=M(n,t);return{update:e=>{o(e),i.update(e)},destroy:()=>{i.destroy(),n.remove()}}}const T=["authorize-url","logos","platforms","connected","disabled","variant","size","full-width","theme","connect-theme","label","connected-label","description"];function U(e,t,n){const o=e.getAttribute(t);return o&&n.includes(o)?o:void 0}const Z=(e,t)=>e.hasAttribute(t)?"false"!==e.getAttribute(t):void 0;function B(){if("undefined"!=typeof window&&"undefined"!=typeof customElements&&!customElements.get("one-connect-button")){class e extends HTMLElement{constructor(...e){super(...e),C(this,"onSuccess",null),C(this,"onError",null),C(this,"onCancel",null),C(this,"handle",null)}connectedCallback(){this.sync()}disconnectedCallback(){var e;null===(e=this.handle)||void 0===e||e.destroy(),this.handle=null}attributeChangedCallback(){this.isConnected&&this.sync()}props(e){var t,n,o,i;return{authorizeUrl:e,logos:x(null!==(t=this.getAttribute("logos"))&&void 0!==t?t:this.getAttribute("platforms")),connected:Z(this,"connected"),disabled:Z(this,"disabled"),variant:U(this,"variant",["default","accent","block"]),size:U(this,"size",["sm","md","lg"]),fullWidth:Z(this,"full-width"),theme:U(this,"theme",["light","dark","auto"]),connectTheme:U(this,"connect-theme",["light","dark"]),label:null!==(n=this.getAttribute("label"))&&void 0!==n?n:void 0,connectedLabel:null!==(o=this.getAttribute("connected-label"))&&void 0!==o?o:void 0,description:null!==(i=this.getAttribute("description"))&&void 0!==i?i:void 0,onSuccess:()=>{var e;null===(e=this.onSuccess)||void 0===e||e.call(this),this.dispatchEvent(new CustomEvent("success"))},onError:(e,t)=>{var n;null===(n=this.onError)||void 0===n||n.call(this,e,t),this.dispatchEvent(new CustomEvent("error",{detail:{message:e,code:t}}))},onCancel:()=>{var e;null===(e=this.onCancel)||void 0===e||e.call(this),this.dispatchEvent(new CustomEvent("cancel"))}}}sync(){const e=this.getAttribute("authorize-url");var t;if(!e)return null===(t=this.handle)||void 0===t||t.destroy(),void(this.handle=null);const n=this.props(e);this.handle?this.handle.update(n):this.handle=M(this,n)}}C(e,"observedAttributes",[...T]),customElements.define("one-connect-button",e)}}B();export{h as createConnectFlow,$ as mountConnectButton,p as readConnectReturn,B as registerConnectButton,M as renderConnectButton};
package/dist/next.cjs.js CHANGED
@@ -83,6 +83,16 @@ function createOneConnectRoutes(oneConnect, options) {
83
83
  url: request.url,
84
84
  getCookie: name => readCookie(request, name)
85
85
  });
86
+ if (options.onComplete) {
87
+ try {
88
+ await options.onComplete({
89
+ userId: user,
90
+ result
91
+ });
92
+ } catch {
93
+ /* the app's own hook threw; the redirect still happens */
94
+ }
95
+ }
86
96
  return redirectWithCookies(result.redirectUrl, result.clearCookieName ? [expireCookie(result.clearCookieName, cookiePath())] : []);
87
97
  };
88
98
  return {
package/dist/next.d.ts CHANGED
@@ -14,7 +14,7 @@
14
14
  * That serves /api/one/authorize and /api/one/callback. Register
15
15
  * `https://yourapp.com/api/one/callback` as the app's redirect URI.
16
16
  */
17
- import type { OneConnectClient } from "./server";
17
+ import type { CompleteAuthorizationResult, OneConnectClient } from "./server";
18
18
  export interface OneConnectRoutesOptions {
19
19
  /** The app's own id for the signed-in user, or null when nobody is
20
20
  * signed in. The grant is stored under this id. */
@@ -24,6 +24,15 @@ export interface OneConnectRoutesOptions {
24
24
  /** Where to send the browser when nobody is signed in. Answers 401
25
25
  * when omitted. */
26
26
  signInUrl?: string;
27
+ /** Called after every callback, before the browser is redirected:
28
+ * `result.outcome` is "connected", "declined" or "failed", and
29
+ * `result.message` says why a flow failed. For your logs and metrics;
30
+ * never show the message to the user. An error it throws is ignored,
31
+ * so the user still lands back in the app. */
32
+ onComplete?: (event: {
33
+ userId: string;
34
+ result: CompleteAuthorizationResult;
35
+ }) => void | Promise<void>;
27
36
  }
28
37
  export interface OneConnectRoutes {
29
38
  GET: (request: Request) => Promise<Response>;
package/dist/next.esm.js CHANGED
@@ -81,6 +81,16 @@ function createOneConnectRoutes(oneConnect, options) {
81
81
  url: request.url,
82
82
  getCookie: name => readCookie(request, name)
83
83
  });
84
+ if (options.onComplete) {
85
+ try {
86
+ await options.onComplete({
87
+ userId: user,
88
+ result
89
+ });
90
+ } catch {
91
+ /* the app's own hook threw; the redirect still happens */
92
+ }
93
+ }
84
94
  return redirectWithCookies(result.redirectUrl, result.clearCookieName ? [expireCookie(result.clearCookieName, cookiePath())] : []);
85
95
  };
86
96
  return {
package/dist/node.cjs.js CHANGED
@@ -44,21 +44,25 @@ async function send(response, web) {
44
44
  }
45
45
  function createOneConnectHandlers(oneConnect, options) {
46
46
  // The web adapter receives a Request; the Node callbacks want the
47
- // original IncomingMessage, so it is carried alongside by closure.
48
- let current = null;
49
- const routeOptions = {
50
- identifyUser: () => options.identifyUser(current),
51
- loginHintFor: options.loginHintFor ? () => options.loginHintFor(current) : undefined,
52
- signInUrl: options.signInUrl
47
+ // original IncomingMessage. Each Request maps to its own message, so
48
+ // concurrent requests never read each other's session or login hint.
49
+ const origin = new WeakMap();
50
+ const nodeRequestFor = request => {
51
+ const message = origin.get(request);
52
+ if (!message) throw new Error("@withone/connect/node: unknown request");
53
+ return message;
53
54
  };
54
- const routes = next.createOneConnectRoutes(oneConnect, routeOptions);
55
+ const loginHintFor = options.loginHintFor;
56
+ const routes = next.createOneConnectRoutes(oneConnect, {
57
+ identifyUser: request => options.identifyUser(nodeRequestFor(request)),
58
+ loginHintFor: loginHintFor ? request => loginHintFor(nodeRequestFor(request)) : undefined,
59
+ signInUrl: options.signInUrl,
60
+ onComplete: options.onComplete
61
+ });
55
62
  const handle = async (request, response) => {
56
- current = request;
57
- try {
58
- await send(response, await routes.GET(toWebRequest(request)));
59
- } finally {
60
- current = null;
61
- }
63
+ const web = toWebRequest(request);
64
+ origin.set(web, request);
65
+ await send(response, await routes.GET(web));
62
66
  };
63
67
  return {
64
68
  authorize: handle,
package/dist/node.d.ts CHANGED
@@ -15,6 +15,7 @@
15
15
  * app.get("/api/one/callback", callback);
16
16
  */
17
17
  import type { IncomingMessage, ServerResponse } from "node:http";
18
+ import { type OneConnectRoutesOptions } from "@withone/connect/next";
18
19
  import type { OneConnectClient } from "./server";
19
20
  export interface OneConnectNodeOptions {
20
21
  /** The app's own id for the signed-in user, or null when nobody is
@@ -22,8 +23,12 @@ export interface OneConnectNodeOptions {
22
23
  identifyUser: (request: IncomingMessage) => Promise<string | null> | string | null;
23
24
  /** Pre-fills the sign-in email on One's page for this user. */
24
25
  loginHintFor?: (request: IncomingMessage) => Promise<string | null> | string | null;
25
- /** Where to send the browser when nobody is signed in. */
26
+ /** Where to send the browser when nobody is signed in. Answers 401
27
+ * when omitted. */
26
28
  signInUrl?: string;
29
+ /** Called after every callback with how it ended; see
30
+ * `OneConnectRoutesOptions.onComplete`. */
31
+ onComplete?: OneConnectRoutesOptions["onComplete"];
27
32
  }
28
33
  export type NodeHandler = (request: IncomingMessage, response: ServerResponse) => Promise<void>;
29
34
  export interface OneConnectHandlers {
package/dist/node.esm.js CHANGED
@@ -42,21 +42,25 @@ async function send(response, web) {
42
42
  }
43
43
  function createOneConnectHandlers(oneConnect, options) {
44
44
  // The web adapter receives a Request; the Node callbacks want the
45
- // original IncomingMessage, so it is carried alongside by closure.
46
- let current = null;
47
- const routeOptions = {
48
- identifyUser: () => options.identifyUser(current),
49
- loginHintFor: options.loginHintFor ? () => options.loginHintFor(current) : undefined,
50
- signInUrl: options.signInUrl
45
+ // original IncomingMessage. Each Request maps to its own message, so
46
+ // concurrent requests never read each other's session or login hint.
47
+ const origin = new WeakMap();
48
+ const nodeRequestFor = request => {
49
+ const message = origin.get(request);
50
+ if (!message) throw new Error("@withone/connect/node: unknown request");
51
+ return message;
51
52
  };
52
- const routes = createOneConnectRoutes(oneConnect, routeOptions);
53
+ const loginHintFor = options.loginHintFor;
54
+ const routes = createOneConnectRoutes(oneConnect, {
55
+ identifyUser: request => options.identifyUser(nodeRequestFor(request)),
56
+ loginHintFor: loginHintFor ? request => loginHintFor(nodeRequestFor(request)) : undefined,
57
+ signInUrl: options.signInUrl,
58
+ onComplete: options.onComplete
59
+ });
53
60
  const handle = async (request, response) => {
54
- current = request;
55
- try {
56
- await send(response, await routes.GET(toWebRequest(request)));
57
- } finally {
58
- current = null;
59
- }
61
+ const web = toWebRequest(request);
62
+ origin.set(web, request);
63
+ await send(response, await routes.GET(web));
60
64
  };
61
65
  return {
62
66
  authorize: handle,
@@ -113,7 +113,7 @@ export interface OneConnectBaseConfig {
113
113
  export interface OneConnectKeyConfig extends OneConnectBaseConfig {
114
114
  mode?: "key";
115
115
  /** The app's connect key, minted on the app's page in the dashboard.
116
- * Server only. One key per environment. */
116
+ * Server only. Connect keys work in Production. */
117
117
  connectKey: string;
118
118
  userStore: OneConnectUserStore;
119
119
  tokenStore?: never;
package/dist/types.d.ts CHANGED
@@ -69,9 +69,9 @@ export interface ConnectButtonLogo {
69
69
  name: string;
70
70
  imageUrl: string;
71
71
  }
72
- /** @deprecated Renamed to `ConnectButtonLogoInput`; removed in the next minor. */
72
+ /** @deprecated Renamed to `ConnectButtonLogoInput`; removed in 0.17.0. */
73
73
  export type ConnectButtonPlatformInput = ConnectButtonLogoInput;
74
- /** @deprecated Renamed to `ConnectButtonLogo`; removed in the next minor. */
74
+ /** @deprecated Renamed to `ConnectButtonLogo`; removed in 0.17.0. */
75
75
  export type ConnectButtonPlatform = ConnectButtonLogo;
76
76
  export type ConnectButtonVariant = "default" | "accent" | "block";
77
77
  export type ConnectButtonSize = "sm" | "md" | "lg";
@@ -86,7 +86,7 @@ export interface ConnectButtonProps {
86
86
  * into a "+N" chip. Decoration only; the permission set decides what
87
87
  * One asks for. */
88
88
  logos?: ConnectButtonLogoInput[];
89
- /** @deprecated Renamed to `logos`; removed in the next minor. */
89
+ /** @deprecated Renamed to `logos`; removed in 0.17.0. */
90
90
  platforms?: ConnectButtonLogoInput[];
91
91
  /** Whether this user has a live grant, from your server. When set, it
92
92
  * decides the Connected state. When omitted, the button shows
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@withone/connect",
3
- "version": "0.15.0",
3
+ "version": "0.16.0",
4
4
  "description": "One Connect for your app: the button your users press, the two backend routes as one import, and a server client that calls One with the grant. Users keep their connections in One; your app holds only what they granted.",
5
5
  "files": [
6
6
  "dist",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: one-connect
3
- description: Add One Connect to an application so its users can grant the app scoped, revocable access to their own One-connected tools (Gmail, Slack, Notion, Stripe and 500 more). Use when wiring @withone/connect into an app - the button, the two backend routes, the connect key, and calling One with the grant.
3
+ description: Add One Connect to an application so its users can grant the app scoped, revocable access to their own One-connected tools (Gmail, Slack, Notion, Stripe and 900+ more). Use when wiring @withone/connect into an app - choosing key or token mode, the two backend routes, the Connect button or the app's own button, and calling One with the grant.
4
4
  ---
5
5
 
6
6
  # One Connect
@@ -13,19 +13,31 @@ you wire three things: a button, two routes, and the calls made with the grant.
13
13
  Browser Your backend One
14
14
  <ConnectButton> ------> GET /api/one/authorize ---302---> hosted page: sign in, pick tools, set access
15
15
  GET /api/one/callback <--302---- ?code&state
16
- saves one id for the user, redirects home
16
+ saves the grant for the user, redirects home
17
17
  <------ onSuccess fires
18
18
  Later: oneConnect.runAction(userId, ...) -> One, grant enforced
19
19
  ```
20
20
 
21
- Use **key mode**, described in sections 1 to 7: the app holds one connect
22
- key and saves one id per user, and nothing is refreshed. Token mode
23
- (section 9) is the other way to hold the grant; use it only when the human
24
- asks for it, or when the app already passes a `tokenStore`.
25
-
26
21
  The client secret and the connect key stay on the server.
27
22
 
28
- ## 1 - Ask the human for these
23
+ ## 1 - Choose the mode
24
+
25
+ The routes, the button and the calls are the same in both modes. Only what
26
+ the server keeps differs.
27
+
28
+ | | Key mode (default) | Token mode |
29
+ |---|---|---|
30
+ | Server keeps | one connect key for the app, one id per user | an access and a refresh token per user |
31
+ | Expires | nothing | yes; the app runs a daily refresh job |
32
+ | User revoked | next call throws `reconnect_required` | next refresh throws `refresh_failed` |
33
+ | Call outside the grant | `403`, `blockedByGrant: true` | `403`, `blockedByGrant` stays `false` |
34
+
35
+ Use **key mode** unless the human asks for token mode, the app needs the
36
+ bearer token itself, or the app already passes a `tokenStore`. Do not switch
37
+ an existing app from one mode to the other unless asked. Sections 2 to 9 are
38
+ key mode; section 10 lists what changes for token mode.
39
+
40
+ ## 2 - Ask the human for these
29
41
 
30
42
  They create the app in the One dashboard: Developers -> Connect -> New app.
31
43
 
@@ -33,14 +45,14 @@ They create the app in the One dashboard: Developers -> Connect -> New app.
33
45
  |---|---|
34
46
  | `ONE_CLIENT_ID` | From the app. |
35
47
  | `ONE_CLIENT_SECRET` | Starts with `one_secret_`. Shown once. |
36
- | `ONE_CONNECT_KEY` | On the app's page: Credentials -> Connect keys -> Create key, with the dashboard on Production. Shown once. |
48
+ | `ONE_CONNECT_KEY` | Key mode. On the app's page: Credentials -> Connect keys -> Create key, with the dashboard on Production. Shown once. |
37
49
  | Redirect URI | Registered on the app. Must match the callback route exactly, e.g. `http://localhost:3000/api/one/callback`. |
38
- | `ONE_PERMISSION_SET` | Optional. The tools and access levels to ask for. |
50
+ | `ONE_PERMISSION_SET` | Optional. The app's Permission set ID: the tools and access levels to ask for. Without it, the consent page lists the user's connections and they choose. |
39
51
 
40
52
  Never ask the human to paste the secret or the connect key into the chat.
41
53
  Tell them which environment variable to set and read it from there.
42
54
 
43
- ## 2 - Environment (server only)
55
+ ## 3 - Environment (server only)
44
56
 
45
57
  ```bash
46
58
  ONE_CLIENT_ID=...
@@ -50,7 +62,7 @@ ONE_REDIRECT_URI=https://yourapp.com/api/one/callback
50
62
  ONE_PERMISSION_SET=... # optional
51
63
  ```
52
64
 
53
- ## 3 - Install and create the client
65
+ ## 4 - Install and create the client
54
66
 
55
67
  ```bash
56
68
  npm install @withone/connect
@@ -67,9 +79,9 @@ export const oneConnect = createOneConnect({
67
79
  permissionSet: process.env.ONE_PERMISSION_SET,
68
80
  connectKey: process.env.ONE_CONNECT_KEY!,
69
81
  userStore: {
70
- saveUser: (userId, reference) => /* save the string on the app's user row */,
71
- loadUser: (userId) => /* read it; null when never connected */,
72
- clearUser: (userId) => /* set it to null */,
82
+ saveUser: async (userId, reference) => { /* save the string on the app's user row */ },
83
+ loadUser: async (userId) => /* read it; null when never connected */,
84
+ clearUser: async (userId) => { /* set it to null */ },
73
85
  },
74
86
  });
75
87
  ```
@@ -83,7 +95,10 @@ identifier, not a secret, so it needs no encryption and no lock. The
83
95
  package writes it in the callback and reads it on every call; the app
84
96
  never passes it anywhere.
85
97
 
86
- ## 4 - The two routes
98
+ Optional settings: `returnTo` (where the callback sends the browser, `/` by
99
+ default) and `oneApiUrl` (One's API origin, production by default).
100
+
101
+ ## 5 - The two routes
87
102
 
88
103
  Next.js App Router (also Remix, SvelteKit, Hono, Bun):
89
104
 
@@ -94,16 +109,23 @@ import { oneConnect } from "@/lib/one";
94
109
 
95
110
  export const { GET } = createOneConnectRoutes(oneConnect, {
96
111
  identifyUser: async (request) => /* the signed-in user's id, or null */,
112
+ signInUrl: "/login", // where signed-out users go; 401 when omitted
97
113
  loginHintFor: async (request) => /* their email, optional */,
98
- signInUrl: "/login",
114
+ onComplete: ({ userId, result }) => { /* log result.outcome and, on failure, result.message */ },
99
115
  });
100
116
  ```
101
117
 
102
- Express or plain Node: `createOneConnectHandlers(oneConnect, { identifyUser })`
103
- from `@withone/connect/node`, mounted at `/api/one/authorize` and
104
- `/api/one/callback`.
118
+ Express, Fastify, Koa or plain Node: `createOneConnectHandlers(oneConnect,
119
+ options)` from `@withone/connect/node` takes the same options and returns
120
+ `{ authorize, callback }`, mounted at `/api/one/authorize` and
121
+ `/api/one/callback`. Both routes must share that directory: the state
122
+ cookie is scoped to it.
123
+
124
+ ## 6 - The button
105
125
 
106
- ## 5 - The button
126
+ Pick by what the app already has. Each option uses the routes above.
127
+
128
+ **The ready-made button** (default):
107
129
 
108
130
  ```tsx
109
131
  import { ConnectButton } from "@withone/connect/react";
@@ -118,20 +140,48 @@ import { ConnectButton } from "@withone/connect/react";
118
140
  ```
119
141
 
120
142
  Optional props: `variant` ("default" | "accent" | "block"), `size` ("sm" |
121
- "md" | "lg"), `fullWidth`, `theme` ("light" | "dark" | "auto"), `label`,
122
- `description`, `disabled`. The accent variant's colours come from the host's
123
- `--one-connect-accent` and `--one-connect-accent-fg` CSS variables.
143
+ "md" | "lg"), `fullWidth`, `theme` ("light" | "dark" | "auto"),
144
+ `connectTheme` ("light" | "dark", One's page), `label`, `connectedLabel`,
145
+ `description`, `disabled`, `onCancel`. The accent variant's colours come
146
+ from the host's `--one-connect-accent` and `--one-connect-accent-fg` CSS
147
+ variables.
124
148
 
125
149
  Vue: `@withone/connect/vue`, same props. Svelte: `use:connectButton` from
126
150
  `@withone/connect/svelte`. Anything else: `import "@withone/connect"` and use
127
151
  `<one-connect-button authorize-url="/api/one/authorize" logos="gmail, stripe">`.
128
- A custom button in React: `useOneConnect({ authorizeUrl })` returns `{ open, status }`.
129
152
 
130
- ## 6 - Calling One with the grant
153
+ **The app's own button.** When the app has its own design system button,
154
+ keep it and wire the flow to it instead of adding a second style:
155
+
156
+ - React: `useOneConnect` from `@withone/connect/react`.
131
157
 
132
- The same four steps the One CLI takes: find the action, read its knowledge,
133
- run it. Always read the knowledge before running an action for the first
134
- time; it names the required fields, the encoding and any header.
158
+ ```tsx
159
+ const { open, status, error } = useOneConnect({ authorizeUrl: "/api/one/authorize", onSuccess: refetch });
160
+ <Button onClick={open} disabled={status === "connecting"}>Connect your tools</Button>
161
+ ```
162
+
163
+ - Any other framework, or none: `createConnectFlow` from `@withone/connect`.
164
+ Create it once where the button lives (Vue `onMounted`, Svelte `onMount`),
165
+ call `flow.open()` on click, and `flow.destroy()` when the button goes.
166
+
167
+ ```ts
168
+ const flow = createConnectFlow({ authorizeUrl: "/api/one/authorize", onSuccess, onError, onCancel });
169
+ button.addEventListener("click", () => flow.open());
170
+ ```
171
+
172
+ - No SDK in the browser (server-rendered pages): a plain link,
173
+ `<a href="/api/one/authorize">`. The user returns with
174
+ `?one_connect=success`, or `?one_connect=error&one_connect_error=` with
175
+ `declined`, `expired` or `failed`. Show the app's own text per code, never
176
+ text from the URL, and remove the parameters after reading them.
177
+
178
+ Do not build a completion page; the callback redirect is the completion.
179
+
180
+ ## 7 - Calling One with the grant
181
+
182
+ The same four steps the One CLI takes: list, find the action, read its
183
+ knowledge, run it. Always read the knowledge before running an action for
184
+ the first time; it names the required fields, the encoding and any header.
135
185
 
136
186
  ```ts
137
187
  const connections = await oneConnect.listConnections(userId); // [{ key, platform, access }]
@@ -150,14 +200,19 @@ const reply = await oneConnect.runAction(userId, {
150
200
  // { status, ok, blockedByGrant, data }
151
201
  ```
152
202
 
203
+ Each connection's `access` is `{ policy: "full" }`, `{ policy: "methods",
204
+ methods }` or `{ policy: "actions", actions }`; plan from it before calling.
153
205
  `runAction` takes the method and path from the action, fills the path's
154
206
  placeholders, puts the connection key in the body of an action One serves
155
207
  itself (tag `custom`), and encodes the body as asked. `listActions(userId,
156
- platform)` lists a whole catalog when search is not enough.
208
+ platform)` lists a whole catalog when search is not enough;
209
+ `oneConnect.fetch(userId, path, init)` reaches any other `/v1` endpoint.
157
210
 
158
211
  Do not set any auth header. The package adds the connect key and the
159
212
  user's id to every call it makes.
160
213
 
214
+ ## 8 - Errors
215
+
161
216
  A `403` reply with `blockedByGrant: true` means the call is outside what
162
217
  the user granted. Do not retry it.
163
218
 
@@ -166,18 +221,19 @@ Errors are `OneConnectError` with a `code`. Handle them where the app calls One:
166
221
  | `code` | Meaning | Do |
167
222
  |---|---|---|
168
223
  | `not_connected` | Nothing is stored for this user. | Show the Connect button. |
169
- | `reconnect_required` | One will not act for this user: they revoked access, or the app is deactivated. The stored value is kept. | Ask the user to connect again. |
224
+ | `reconnect_required` | Key mode: One will not act for this user; they revoked access, or the app is deactivated. The stored value is kept. | Ask the user to connect again. |
225
+ | `refresh_failed` | Token mode: the grant is gone. The tokens are cleared. | Ask the user to connect again. |
170
226
  | `request_failed` | One answered with an error or could not be reached. Nothing stored changed. | Retry later. |
171
227
 
172
228
  ```ts
173
229
  import { OneConnectError } from "@withone/connect/server";
174
230
 
175
231
  try {
176
- await oneConnect.runAction(userId, action);
232
+ await oneConnect.runAction(userId, input);
177
233
  } catch (error) {
178
234
  if (
179
235
  error instanceof OneConnectError &&
180
- ["not_connected", "reconnect_required"].includes(error.code)
236
+ ["not_connected", "reconnect_required", "refresh_failed"].includes(error.code)
181
237
  ) {
182
238
  // show the Connect button again
183
239
  } else {
@@ -187,10 +243,11 @@ try {
187
243
  ```
188
244
 
189
245
  `isConnected(userId)` says the user has connected before. One confirms the
190
- consent on each call, so a user who revoked is found by the next call
191
- throwing `reconnect_required`.
246
+ consent on each call, so a user who revoked is found by the next call.
247
+
248
+ ## 9 - Rules and done
192
249
 
193
- ## 7 - Rules
250
+ Rules:
194
251
 
195
252
  - Never put the client secret or the connect key in browser code, logs,
196
253
  error reports, source files or prompts. Environment variables only.
@@ -198,14 +255,14 @@ throwing `reconnect_required`.
198
255
  the dashboard on Production.
199
256
  - Store the per-user string as given.
200
257
  - The registered redirect URI and `ONE_REDIRECT_URI` must be identical.
201
- - Do not build a completion page; the callback redirect is the completion.
202
258
  - Do not write OAuth steps or One request headers by hand; use the package.
203
- - Do not switch an existing app from one mode to the other unless asked.
259
+ - Never show `result.message` or any URL text to users; log it.
204
260
 
205
- ## 8 - Done when
261
+ Done when:
206
262
 
207
263
  1. The button leads to One's page; after signing in and authorizing, the user
208
- lands back in the app and `onSuccess` fires.
264
+ lands back in the app and `onSuccess` fires (or the app reads
265
+ `?one_connect=success`).
209
266
  2. One string is saved for the user.
210
267
  3. `listConnections` returns only the granted connections.
211
268
  4. `runAction` works for an action inside the grant and returns `403` with
@@ -213,11 +270,10 @@ throwing `reconnect_required`.
213
270
  5. After the user revokes the app in their One dashboard, the next call
214
271
  fails with `reconnect_required` and the app asks them to connect again.
215
272
 
216
- ## 9 - Token mode (only when asked)
273
+ ## 10 - Token mode (only when chosen in section 1)
217
274
 
218
- The other way to hold the grant: the app stores an access token and a
219
- refresh token per user, as a standard OAuth client. The routes, the button
220
- and the calls are the same. No `ONE_CONNECT_KEY` is needed.
275
+ The app stores an access token and a refresh token per user, as a standard
276
+ OAuth client. No `ONE_CONNECT_KEY` is needed; everything else above holds.
221
277
 
222
278
  ```ts
223
279
  export const oneConnect = createOneConnect({
@@ -226,11 +282,13 @@ export const oneConnect = createOneConnect({
226
282
  redirectUri: process.env.ONE_REDIRECT_URI!,
227
283
  permissionSet: process.env.ONE_PERMISSION_SET,
228
284
  tokenStore: {
229
- saveTokens: (userId, tokens) => /* save in the app's database, encrypted */,
230
- loadTokens: (userId) => /* read; null when never connected */,
231
- clearTokens: (userId) => /* delete */,
285
+ saveTokens: async (userId, tokens) => { /* save in the app's database, encrypted */ },
286
+ loadTokens: async (userId) => /* read; null when never connected */,
287
+ clearTokens: async (userId) => { /* delete */ },
232
288
  },
233
289
  });
290
+
291
+ const accessToken = await oneConnect.getAccessToken(userId); // when the app needs the bearer token itself
234
292
  ```
235
293
 
236
294
  - Store tokens encrypted, keyed by the app's user.
@@ -263,6 +321,3 @@ the pair. The access token lives as long as the app's Token lifetime says
263
321
  (30 days unless changed under Advanced when creating the app); keep the
264
322
  window shorter than that, or every run refreshes. In token mode, "done"
265
323
  also means the daily job exists and runs for every connected user.
266
-
267
- The mode is whichever credential `createOneConnect` is given: `connectKey`
268
- and `userStore` for key mode, `tokenStore` for token mode.