@krishp/one-auth 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,273 @@
1
+ <img src="https://assets.withone.ai/banners/auth.png" alt="One Auth — Connect your users to every app with a drop-in auth widget." style="border-radius: 5px;">
2
+
3
+ <h3 align="center">One Auth</h3>
4
+
5
+ <p align="center">
6
+ <a href="https://withone.ai"><strong>Website</strong></a>
7
+ &nbsp;·&nbsp;
8
+ <a href="https://withone.ai/docs/auth"><strong>Docs</strong></a>
9
+ &nbsp;·&nbsp;
10
+ <a href="https://app.withone.ai"><strong>Dashboard</strong></a>
11
+ &nbsp;·&nbsp;
12
+ <a href="https://withone.ai/changelog"><strong>Changelog</strong></a>
13
+ &nbsp;·&nbsp;
14
+ <a href="https://x.com/withoneai"><strong>X</strong></a>
15
+ &nbsp;·&nbsp;
16
+ <a href="https://linkedin.com/company/withoneai"><strong>LinkedIn</strong></a>
17
+ </p>
18
+
19
+ <p align="center">
20
+ <a href="https://npmjs.com/package/@withone/auth"><img src="https://img.shields.io/npm/v/%40withone%2Fauth" alt="npm version"></a>
21
+ </p>
22
+
23
+ One Auth is a pre-built, embeddable authentication UI that makes it easy for your users to securely connect their third-party accounts (Gmail, Slack, Salesforce, QuickBooks, etc.) directly within your application.
24
+
25
+ Fully compatible with popular frameworks such as React, Next.js, Vue, Svelte, and more.
26
+
27
+ ## Install
28
+
29
+ With npm:
30
+
31
+ ```bash
32
+ npm i @withone/auth
33
+ ```
34
+
35
+ With yarn:
36
+
37
+ ```bash
38
+ yarn add @withone/auth
39
+ ```
40
+
41
+ ## Getting Started with the Skill
42
+
43
+ The easiest way to integrate One Auth is by installing the skill for your AI coding agent. The skill provides step-by-step guidance for setting up the backend token endpoint, frontend component, and connection handling.
44
+
45
+ ```bash
46
+ npx skills add withoneai/auth
47
+ ```
48
+
49
+ Once installed, your AI coding agent will have full context on how to set up and work with One Auth in your project.
50
+
51
+ ## Using the Auth component
52
+
53
+ Replace the `token URL` with your backend token endpoint URL.
54
+
55
+ > ⚠️ **Must be a full URL** — relative paths like `/api/one-auth` won't work because the Auth widget runs in an iframe on a different domain. Use the complete URL (e.g., `https://your-domain.com/api/one-auth`).
56
+
57
+ ```tsx
58
+ "use client";
59
+
60
+ import { useOneAuth } from "@withone/auth";
61
+
62
+ const USER_ID = "your-user-uuid";
63
+
64
+ export function ConnectIntegrationButton() {
65
+ const { open } = useOneAuth({
66
+ token: {
67
+ url: "https://your-domain.com/api/one-auth",
68
+ headers: {
69
+ "x-user-id": USER_ID,
70
+ },
71
+ },
72
+ onSuccess: (connection) => {
73
+ console.log("Connection created:", connection);
74
+ },
75
+ onError: (error) => {
76
+ console.error("Connection failed:", error);
77
+ },
78
+ onClose: () => {
79
+ console.log("Auth modal closed");
80
+ },
81
+ });
82
+
83
+ return <button onClick={open}>Connect Integration</button>;
84
+ }
85
+ ```
86
+
87
+ ### Configuration Options
88
+
89
+ | Option | Type | Description |
90
+ |---|---|---|
91
+ | `token.url` | `string` | Full URL of your backend token endpoint |
92
+ | `token.headers` | `object` | Headers to send with the token request (e.g., user ID) |
93
+ | `selectedConnection` | `string` | Pre-select an integration by display name (e.g., `"Gmail"`) |
94
+ | `appTheme` | `"dark" \| "light"` | Theme for the Auth modal |
95
+ | `title` | `string` | Custom title for the modal |
96
+ | `imageUrl` | `string` | Custom logo URL to display in the modal |
97
+ | `companyName` | `string` | Your company name to display in the modal |
98
+ | `onSuccess` | `(connection) => void` | Callback when a connection is successfully created |
99
+ | `onError` | `(error) => void` | Callback when the connection fails |
100
+ | `onClose` | `() => void` | Callback when the modal is closed |
101
+
102
+ ## Backend Token Generation
103
+
104
+ To enable Auth connections, your backend needs an endpoint that generates a session token by calling the One API.
105
+
106
+ ### Environment Variables
107
+
108
+ ```env
109
+ ONE_SECRET_KEY=sk_test_your_secret_key_here
110
+ ```
111
+
112
+ | Variable | Description |
113
+ |---|---|
114
+ | `ONE_SECRET_KEY` | Your secret key from the [One dashboard](https://app.withone.ai/settings/api-keys) |
115
+
116
+ ### API Route — `POST /api/one-auth`
117
+
118
+ Your backend endpoint should:
119
+
120
+ 1. Extract the `x-user-id` header to identify the user
121
+ 2. Handle pagination — the Auth widget sends `page` and `limit` as query parameters
122
+ 3. Call `POST https://api.withone.ai/v1/authkit/token` with your secret key and the user's identity
123
+ 4. Return the token response to the client
124
+
125
+ **Request headers:**
126
+
127
+ | Header | Required | Description |
128
+ |---|---|---|
129
+ | `x-user-id` | Yes | Unique identifier for the user (e.g., UUID from your auth system) |
130
+
131
+ **Query parameters (sent automatically by the widget):**
132
+
133
+ | Parameter | Description |
134
+ |---|---|
135
+ | `page` | Current page number for paginated integration list |
136
+ | `limit` | Number of integrations per page |
137
+
138
+ **Example implementation (Next.js):**
139
+
140
+ ```typescript
141
+ import { NextRequest, NextResponse } from "next/server";
142
+
143
+ const corsHeaders = {
144
+ "Access-Control-Allow-Origin": "*",
145
+ "Access-Control-Allow-Methods": "POST, OPTIONS",
146
+ "Access-Control-Allow-Headers": "Content-Type, Authorization, x-user-id",
147
+ };
148
+
149
+ export async function OPTIONS() {
150
+ return NextResponse.json({}, { headers: corsHeaders });
151
+ }
152
+
153
+ export async function POST(req: NextRequest) {
154
+ try {
155
+ const userId = req.headers.get("x-user-id");
156
+
157
+ if (!userId) {
158
+ return NextResponse.json(
159
+ { error: "Unauthorized" },
160
+ { status: 401, headers: corsHeaders }
161
+ );
162
+ }
163
+
164
+ // The Auth widget sends pagination params as query parameters
165
+ const page = req.nextUrl.searchParams.get("page");
166
+ const limit = req.nextUrl.searchParams.get("limit");
167
+
168
+ const response = await fetch(
169
+ `https://api.withone.ai/v1/authkit/token?page=${page}&limit=${limit}`,
170
+ {
171
+ method: "POST",
172
+ headers: {
173
+ "Content-Type": "application/json",
174
+ "X-One-Secret": process.env.ONE_SECRET_KEY!,
175
+ },
176
+ body: JSON.stringify({
177
+ identity: userId,
178
+ identityType: "user", // "user" | "team" | "organization" | "project"
179
+ }),
180
+ }
181
+ );
182
+
183
+ if (!response.ok) {
184
+ return NextResponse.json(
185
+ { error: "Failed to generate token" },
186
+ { status: response.status, headers: corsHeaders }
187
+ );
188
+ }
189
+
190
+ const token = await response.json();
191
+ return NextResponse.json(token, { headers: corsHeaders });
192
+ } catch (error) {
193
+ return NextResponse.json(
194
+ { error: "Failed to generate token" },
195
+ { status: 500, headers: corsHeaders }
196
+ );
197
+ }
198
+ }
199
+ ```
200
+
201
+ **Success response (200):**
202
+
203
+ ```json
204
+ {
205
+ "rows": [
206
+ {
207
+ "id": 41596,
208
+ "connectionDefId": 34,
209
+ "type": "api",
210
+ "title": "ActiveCampaign",
211
+ "image": "https://assets.withone.ai/connectors/activecampaign.svg",
212
+ "environment": "test",
213
+ "tags": [],
214
+ "active": true
215
+ },
216
+ {
217
+ "id": 41524,
218
+ "connectionDefId": 109,
219
+ "type": "api",
220
+ "title": "Anthropic",
221
+ "image": "https://assets.withone.ai/connectors/anthropic.svg",
222
+ "environment": "test",
223
+ "tags": [],
224
+ "active": true
225
+ }
226
+ ],
227
+ "total": 247,
228
+ "pages": 3,
229
+ "page": 1,
230
+ "requestId": 110256
231
+ }
232
+ ```
233
+
234
+ The response includes a paginated list of available integrations. The widget handles pagination automatically by calling your token endpoint with different `page` values.
235
+
236
+ ## Configuration & Management
237
+
238
+ All configuration for the Auth component is managed via the **[One Dashboard](https://app.withone.ai/settings/authkit)**. From the dashboard, you can:
239
+
240
+ - **Choose which apps are visible** — Select which integrations appear in the Auth modal for your users
241
+ - **Configure OAuth credentials** — Use One's default client ID and client secret, or bring your own for any integration
242
+ - **Adjust scopes** — Customize the OAuth scopes requested for each integration
243
+
244
+ AuthKit configuration is scoped at the **project level**, enabling multi-tenant architecture. Each project in your One account can have its own set of visible apps, OAuth credentials, and scopes — allowing you to serve different configurations to different products or customer segments from a single account.
245
+
246
+ > **Dashboard link:** [app.withone.ai/settings/authkit](https://app.withone.ai/settings/authkit)
247
+
248
+ ## Diagram
249
+
250
+ ```mermaid
251
+ sequenceDiagram
252
+ participant User
253
+ participant YourApp as Your Application
254
+ participant YourBackend as Your Backend
255
+ participant One as One Auth
256
+ participant Integration as Third-party Integration
257
+
258
+ User->>YourApp: Clicks "Connect Integration"
259
+ YourApp->>One: Open Auth modal
260
+ One->>YourBackend: Request Auth token (page=1&limit=100)
261
+ YourBackend->>One: Generate token with user identity
262
+ One->>One: Display integrations list
263
+ User->>One: Select integration & authenticate
264
+ One->>Integration: OAuth handshake
265
+ Integration->>One: Access token
266
+ One->>One: Store encrypted credentials
267
+ One->>YourApp: Return connection details
268
+ YourApp->>User: Connection successful!
269
+ ```
270
+
271
+ ## License
272
+
273
+ This project is licensed under the GPL-3.0 license. See the [LICENSE](LICENSE) file for details.
@@ -0,0 +1 @@
1
+ export { useEventLink as useOneAuth } from './useEventLink';
@@ -0,0 +1 @@
1
+ function e(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 i=n.call(e,t);if("object"!=typeof i)return i;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}const t={oauthRedirect:!0},n="event-link";class i{constructor(t){e(this,"linkTokenEndpoint",void 0),e(this,"linkHeaders",void 0),e(this,"baseUrl",void 0),e(this,"onClose",void 0),e(this,"title",void 0),e(this,"imageUrl",void 0),e(this,"companyName",void 0),e(this,"selectedConnection",void 0),e(this,"showNameInput",void 0),e(this,"appTheme",void 0),e(this,"checkState",void 0),this.linkTokenEndpoint=t.token.url,this.linkHeaders=t.token.headers,this.baseUrl=t.baseUrl,this.onClose=t.onClose,this.title=t.title,this.imageUrl=t.imageUrl,this.companyName=t.companyName,this.selectedConnection=t.selectedConnection,this.showNameInput=t.showNameInput,this.appTheme=t.appTheme,this.checkState=t.checkState}_getBaseUrl(){return this.baseUrl?this.baseUrl:"https://auth.withone.ai"}_buildPayload(){return{linkTokenEndpoint:this.linkTokenEndpoint,linkHeaders:this.linkHeaders,title:this.title,imageUrl:this.imageUrl,companyName:this.companyName,selectedConnection:this.selectedConnection,showNameInput:this.showNameInput,appTheme:this.appTheme,capabilities:t,checkState:this.checkState}}openLink(){const e=document.getElementById(n);e&&e.remove();const t=document.createElement("iframe"),i=this._buildPayload(),o=JSON.stringify(i),s=btoa(o),a=new URLSearchParams({data:s}).toString(),r=`${this._getBaseUrl()}?${a}`;document.body.appendChild(t),t.style.height="100%",t.style.width="100%",t.style.position="fixed",t.style.display="hidden",t.style.visibility="hidden",t.style.zIndex="9999",t.style.backgroundColor="transparent",t.style.inset="0px",t.style.borderWidth="0px",t.id=n,t.style.overflow="hidden auto",t.src=r,t.onload=()=>{var e;setTimeout(()=>{t.style.display="block",t.style.visibility="visible"},100),null===(e=t.contentWindow)||void 0===e||e.postMessage(i,r)}}closeLink(){const e=document.getElementById(n);e&&e.remove()}}const o=new Set;let s=!1;const a="one_auth_state",r="one_auth_error";function l(e,t,n){const i=`${t}~${o=n,btoa(o).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}`;var o;try{const t=new URL(e);return t.searchParams.set("state",i),t.toString()}catch{return e.replace(`state=${encodeURIComponent(t)}`,`state=${encodeURIComponent(i)}`).replace(`state=${t}`,`state=${encodeURIComponent(i)}`)}}function c(){if("undefined"!=typeof window)try{const e=new URL(window.location.href);let t=!1;e.searchParams.has(a)&&(e.searchParams.delete(a),t=!0),e.searchParams.has(r)&&(e.searchParams.delete(r),t=!0),t&&window.history.replaceState({},document.title,e.toString())}catch{}}function d(e,t){const o=new i({...e,checkState:t});let a=!1,r=!1;const l=t=>{if("undefined"==typeof window)return;const i=document.getElementById(n);if(!i||t.source!==i.contentWindow)return;const d=t.data;if(null!=d&&d.messageType)if("LINK_SUCCESS"===d.messageType){if(!r){r=!0;try{var u;null===(u=e.onSuccess)||void 0===u||u.call(e,d.message)}catch{}c()}}else if("LINK_ERROR"===d.messageType){if(!r){r=!0;try{var h;null===(h=e.onError)||void 0===h||h.call(e,d.message)}catch{}c()}}else if("EXIT_EVENT_LINK"===d.messageType){if(!r)try{var m;null===(m=e.onClose)||void 0===m||m.call(e)}catch{}!function(){if(a)return;a=!0,"undefined"!=typeof window&&window.removeEventListener("message",l);o.closeLink(),c(),s=!1}()}};"undefined"!=typeof window&&window.addEventListener("message",l),o.openLink()}function u(e){if("undefined"==typeof window)return;if(s)return;let t;try{t=new URLSearchParams(window.location.search)}catch{return}const n=t.get(r),i=t.get(a);(n||i)&&(s=!0,n?function(e,t){setTimeout(()=>{try{var n;null===(n=e.onError)||void 0===n||n.call(e,t)}finally{c()}},0)}(e,n):i&&d(e,i))}const h=e=>{u(e);const t=(e=>new i(e))({...e});let s=null,a=!1;const r=i=>{var r,d,u,h,m;if("undefined"==typeof window)return;const p=document.getElementById(n);if(!p||"block"!==p.style.display)return;if(i.source!==p.contentWindow)return;const f=i.data;if(null==f||!f.messageType)return;const y=`${f.messageType}-${JSON.stringify(null!==(r=null!==(d=f.message)&&void 0!==d?d:f.url)&&void 0!==r?r:"")}`;if(!o.has(y))switch(o.add(y),setTimeout(()=>o.delete(y),5e3),f.messageType){case"EXIT_EVENT_LINK":null===(u=e.onClose)||void 0===u||u.call(e),setTimeout(()=>{c()},200);break;case"LINK_SUCCESS":null===(h=e.onSuccess)||void 0===h||h.call(e,f.message);break;case"LINK_ERROR":null===(m=e.onError)||void 0===m||m.call(e,f.message);break;case"OAUTH_REDIRECT":{const n=f.url,i=f.state;if(!n||!i){var w;null===(w=e.onError)||void 0===w||w.call(e,"Invalid OAuth redirect message");break}const o=l(n,i,window.location.href);s&&a&&(window.removeEventListener("message",s),a=!1,s=null),t.closeLink(),window.location.href=o;break}}},c=()=>{"undefined"!=typeof window&&s&&a&&(window.removeEventListener("message",s),a=!1,s=null);for(const e of o)e.startsWith("EXIT_EVENT_LINK")&&o.delete(e);t.closeLink()};return{open:()=>{s&&a&&window.removeEventListener("message",s),s=r,"undefined"!=typeof window&&(window.addEventListener("message",s),a=!0),t.openLink()},close:c}};export{h as useOneAuth};
@@ -0,0 +1 @@
1
+ "use strict";function e(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 i=n.call(e,t);if("object"!=typeof i)return i;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}const t={oauthRedirect:!0},n="event-link";class i{constructor(t){e(this,"linkTokenEndpoint",void 0),e(this,"linkHeaders",void 0),e(this,"baseUrl",void 0),e(this,"onClose",void 0),e(this,"title",void 0),e(this,"imageUrl",void 0),e(this,"companyName",void 0),e(this,"selectedConnection",void 0),e(this,"showNameInput",void 0),e(this,"appTheme",void 0),e(this,"checkState",void 0),this.linkTokenEndpoint=t.token.url,this.linkHeaders=t.token.headers,this.baseUrl=t.baseUrl,this.onClose=t.onClose,this.title=t.title,this.imageUrl=t.imageUrl,this.companyName=t.companyName,this.selectedConnection=t.selectedConnection,this.showNameInput=t.showNameInput,this.appTheme=t.appTheme,this.checkState=t.checkState}_getBaseUrl(){return this.baseUrl?this.baseUrl:"https://auth.withone.ai"}_buildPayload(){return{linkTokenEndpoint:this.linkTokenEndpoint,linkHeaders:this.linkHeaders,title:this.title,imageUrl:this.imageUrl,companyName:this.companyName,selectedConnection:this.selectedConnection,showNameInput:this.showNameInput,appTheme:this.appTheme,capabilities:t,checkState:this.checkState}}openLink(){const e=document.getElementById(n);e&&e.remove();const t=document.createElement("iframe"),i=this._buildPayload(),o=JSON.stringify(i),s=btoa(o),a=new URLSearchParams({data:s}).toString(),r=`${this._getBaseUrl()}?${a}`;document.body.appendChild(t),t.style.height="100%",t.style.width="100%",t.style.position="fixed",t.style.display="hidden",t.style.visibility="hidden",t.style.zIndex="9999",t.style.backgroundColor="transparent",t.style.inset="0px",t.style.borderWidth="0px",t.id=n,t.style.overflow="hidden auto",t.src=r,t.onload=()=>{var e;setTimeout(()=>{t.style.display="block",t.style.visibility="visible"},100),null===(e=t.contentWindow)||void 0===e||e.postMessage(i,r)}}closeLink(){const e=document.getElementById(n);e&&e.remove()}}const o=new Set;let s=!1;const a="one_auth_state",r="one_auth_error";function l(e,t,n){const i=`${t}~${o=n,btoa(o).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}`;var o;try{const t=new URL(e);return t.searchParams.set("state",i),t.toString()}catch{return e.replace(`state=${encodeURIComponent(t)}`,`state=${encodeURIComponent(i)}`).replace(`state=${t}`,`state=${encodeURIComponent(i)}`)}}function c(){if("undefined"!=typeof window)try{const e=new URL(window.location.href);let t=!1;e.searchParams.has(a)&&(e.searchParams.delete(a),t=!0),e.searchParams.has(r)&&(e.searchParams.delete(r),t=!0),t&&window.history.replaceState({},document.title,e.toString())}catch{}}function d(e,t){const o=new i({...e,checkState:t});let a=!1,r=!1;const l=t=>{if("undefined"==typeof window)return;const i=document.getElementById(n);if(!i||t.source!==i.contentWindow)return;const d=t.data;if(null!=d&&d.messageType)if("LINK_SUCCESS"===d.messageType){if(!r){r=!0;try{var u;null===(u=e.onSuccess)||void 0===u||u.call(e,d.message)}catch{}c()}}else if("LINK_ERROR"===d.messageType){if(!r){r=!0;try{var h;null===(h=e.onError)||void 0===h||h.call(e,d.message)}catch{}c()}}else if("EXIT_EVENT_LINK"===d.messageType){if(!r)try{var m;null===(m=e.onClose)||void 0===m||m.call(e)}catch{}!function(){if(a)return;a=!0,"undefined"!=typeof window&&window.removeEventListener("message",l);o.closeLink(),c(),s=!1}()}};"undefined"!=typeof window&&window.addEventListener("message",l),o.openLink()}function u(e){if("undefined"==typeof window)return;if(s)return;let t;try{t=new URLSearchParams(window.location.search)}catch{return}const n=t.get(r),i=t.get(a);(n||i)&&(s=!0,n?function(e,t){setTimeout(()=>{try{var n;null===(n=e.onError)||void 0===n||n.call(e,t)}finally{c()}},0)}(e,n):i&&d(e,i))}exports.useOneAuth=e=>{u(e);const t=(e=>new i(e))({...e});let s=null,a=!1;const r=i=>{var r,d,u,h,m;if("undefined"==typeof window)return;const p=document.getElementById(n);if(!p||"block"!==p.style.display)return;if(i.source!==p.contentWindow)return;const f=i.data;if(null==f||!f.messageType)return;const y=`${f.messageType}-${JSON.stringify(null!==(r=null!==(d=f.message)&&void 0!==d?d:f.url)&&void 0!==r?r:"")}`;if(!o.has(y))switch(o.add(y),setTimeout(()=>o.delete(y),5e3),f.messageType){case"EXIT_EVENT_LINK":null===(u=e.onClose)||void 0===u||u.call(e),setTimeout(()=>{c()},200);break;case"LINK_SUCCESS":null===(h=e.onSuccess)||void 0===h||h.call(e,f.message);break;case"LINK_ERROR":null===(m=e.onError)||void 0===m||m.call(e,f.message);break;case"OAUTH_REDIRECT":{const n=f.url,i=f.state;if(!n||!i){var w;null===(w=e.onError)||void 0===w||w.call(e,"Invalid OAuth redirect message");break}const o=l(n,i,window.location.href);s&&a&&(window.removeEventListener("message",s),a=!1,s=null),t.closeLink(),window.location.href=o;break}}},c=()=>{"undefined"!=typeof window&&s&&a&&(window.removeEventListener("message",s),a=!1,s=null);for(const e of o)e.startsWith("EXIT_EVENT_LINK")&&o.delete(e);t.closeLink()};return{open:()=>{s&&a&&window.removeEventListener("message",s),s=r,"undefined"!=typeof window&&(window.addEventListener("message",s),a=!0),t.openLink()},close:c}};
@@ -0,0 +1,80 @@
1
+ export interface EventLinkProps {
2
+ baseUrl?: string;
3
+ appTheme?: 'dark' | 'light';
4
+ title?: string;
5
+ imageUrl?: string;
6
+ companyName?: string;
7
+ onClose?: () => void;
8
+ onSuccess?: (connection: ConnectionRecord) => void;
9
+ onError?: (error: string) => void;
10
+ selectedConnection?: string;
11
+ showNameInput?: boolean;
12
+ token: {
13
+ url: string;
14
+ headers?: Record<string, unknown>;
15
+ }
16
+ }
17
+
18
+ // Internal type — extends EventLinkProps with implementation flags
19
+ // not part of the public API.
20
+ export interface EventLinkWindowProps {
21
+ baseUrl?: string;
22
+ appTheme?: 'dark' | 'light';
23
+ environment?: "sandbox" | "production";
24
+ title?: string;
25
+ imageUrl?: string;
26
+ companyName?: string;
27
+ onClose?: () => void;
28
+ selectedConnection?: string;
29
+ showNameInput?: boolean;
30
+ token: {
31
+ url: string;
32
+ headers?: Record<string, unknown>;
33
+ };
34
+ // Internal: when set, the iframe is opened in "check" mode and goes
35
+ // straight to polling /v1/connections/oauth/check?state=X. Used by
36
+ // the OAuth return flow after a same-window redirect.
37
+ checkState?: string;
38
+ }
39
+
40
+ export interface ConnectionRecord {
41
+ _id: string;
42
+ platformVersion: string;
43
+ connectionDefinitionId: string;
44
+ name: string;
45
+ key: string;
46
+ environment: string;
47
+ platform: string;
48
+ secretsServiceId: string;
49
+ identity?: string;
50
+ identityType?: 'user' | 'team' | 'organization' | 'project';
51
+ settings: {
52
+ parseWebhookBody: boolean;
53
+ showSecret: boolean;
54
+ allowCustomEvents: boolean;
55
+ oauth: boolean;
56
+ };
57
+ throughput: {
58
+ key: string;
59
+ limit: number;
60
+ };
61
+ createdAt: number;
62
+ updatedAt: number;
63
+ updated: boolean;
64
+ version: string;
65
+ lastModifiedBy: string;
66
+ deleted: boolean;
67
+ tags: string[];
68
+ active: boolean;
69
+ deprecated: boolean;
70
+ }
71
+
72
+ export interface EventProps {
73
+ data: {
74
+ messageType: string;
75
+ message: ConnectionRecord | string;
76
+ // Optional fields for OAUTH_REDIRECT messages
77
+ url?: string;
78
+ state?: string;
79
+ }
80
+ }
@@ -0,0 +1,5 @@
1
+ import { EventLinkProps } from "./types";
2
+ export declare const useEventLink: (props: EventLinkProps) => {
3
+ open: () => void;
4
+ close: () => void;
5
+ };
@@ -0,0 +1,21 @@
1
+ import { EventLinkWindowProps } from "../types";
2
+ export declare const VISIBLE_IFRAME_ID = "event-link";
3
+ export declare class EventLinkWindow {
4
+ private linkTokenEndpoint;
5
+ private linkHeaders?;
6
+ private baseUrl?;
7
+ private onClose?;
8
+ private title?;
9
+ private imageUrl?;
10
+ private companyName?;
11
+ private selectedConnection?;
12
+ private showNameInput?;
13
+ private appTheme?;
14
+ private checkState?;
15
+ constructor(props: EventLinkWindowProps);
16
+ private _getBaseUrl;
17
+ private _buildPayload;
18
+ openLink(): void;
19
+ closeLink(): void;
20
+ }
21
+ export declare const createWindow: (props: EventLinkWindowProps) => EventLinkWindow;
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@krishp/one-auth",
3
+ "version": "0.0.1",
4
+ "description": "Frontend bindings for One Auth, a drop-in authentication widget that lets your users connect their third-party apps to your application. Supports OAuth and non-OAuth integrations across 250+ platforms with project-level multi-tenant configuration.",
5
+ "files": [
6
+ "dist",
7
+ "src",
8
+ "README.md",
9
+ "LICENSE"
10
+ ],
11
+ "main": "dist/index.umd.js",
12
+ "module": "dist/index.esm.js",
13
+ "types": "dist/index.d.ts",
14
+ "devDependencies": {
15
+ "@babel/core": "^7.24.0",
16
+ "@babel/plugin-transform-class-properties": "^7.28.6",
17
+ "@babel/plugin-transform-nullish-coalescing-operator": "^7.28.6",
18
+ "@babel/plugin-transform-optional-chaining": "^7.28.6",
19
+ "@babel/preset-env": "^7.24.0",
20
+ "@babel/preset-typescript": "^7.28.5",
21
+ "@rollup/plugin-babel": "^6.0.4",
22
+ "@rollup/plugin-commonjs": "^25.0.7",
23
+ "@rollup/plugin-json": "^6.1.0",
24
+ "@rollup/plugin-node-resolve": "^15.2.3",
25
+ "@rollup/plugin-terser": "^0.4.4",
26
+ "@tsconfig/recommended": "^1.0.3",
27
+ "@typescript-eslint/eslint-plugin": "^7.0.0",
28
+ "@typescript-eslint/parser": "^7.0.0",
29
+ "axios": "^1.6.7",
30
+ "eslint": "^8.57.0",
31
+ "prettier": "^3.2.5",
32
+ "rollup": "^4.12.0",
33
+ "rollup-plugin-copy": "^3.5.0",
34
+ "rollup-plugin-typescript2": "^0.36.0",
35
+ "tslib": "^2.6.2",
36
+ "typescript": "^5.3.3"
37
+ },
38
+ "author": "@withoneai",
39
+ "publishConfig": {
40
+ "access": "public"
41
+ },
42
+ "scripts": {
43
+ "build": "rollup -c",
44
+ "lint": "eslint src --ext .ts,.tsx",
45
+ "format": "prettier --write \"src/**/*.{ts,tsx}\""
46
+ },
47
+ "repository": {
48
+ "type": "git",
49
+ "url": "git+https://github.com/withoneai/auth"
50
+ },
51
+ "keywords": [
52
+ "withone",
53
+ "integrations",
54
+ "multi-tenant"
55
+ ],
56
+ "license": "GPL-3.0",
57
+ "homepage": "https://withone.ai"
58
+ }
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export { useEventLink as useOneAuth } from './useEventLink';
@@ -0,0 +1,80 @@
1
+ export interface EventLinkProps {
2
+ baseUrl?: string;
3
+ appTheme?: 'dark' | 'light';
4
+ title?: string;
5
+ imageUrl?: string;
6
+ companyName?: string;
7
+ onClose?: () => void;
8
+ onSuccess?: (connection: ConnectionRecord) => void;
9
+ onError?: (error: string) => void;
10
+ selectedConnection?: string;
11
+ showNameInput?: boolean;
12
+ token: {
13
+ url: string;
14
+ headers?: Record<string, unknown>;
15
+ }
16
+ }
17
+
18
+ // Internal type — extends EventLinkProps with implementation flags
19
+ // not part of the public API.
20
+ export interface EventLinkWindowProps {
21
+ baseUrl?: string;
22
+ appTheme?: 'dark' | 'light';
23
+ environment?: "sandbox" | "production";
24
+ title?: string;
25
+ imageUrl?: string;
26
+ companyName?: string;
27
+ onClose?: () => void;
28
+ selectedConnection?: string;
29
+ showNameInput?: boolean;
30
+ token: {
31
+ url: string;
32
+ headers?: Record<string, unknown>;
33
+ };
34
+ // Internal: when set, the iframe is opened in "check" mode and goes
35
+ // straight to polling /v1/connections/oauth/check?state=X. Used by
36
+ // the OAuth return flow after a same-window redirect.
37
+ checkState?: string;
38
+ }
39
+
40
+ export interface ConnectionRecord {
41
+ _id: string;
42
+ platformVersion: string;
43
+ connectionDefinitionId: string;
44
+ name: string;
45
+ key: string;
46
+ environment: string;
47
+ platform: string;
48
+ secretsServiceId: string;
49
+ identity?: string;
50
+ identityType?: 'user' | 'team' | 'organization' | 'project';
51
+ settings: {
52
+ parseWebhookBody: boolean;
53
+ showSecret: boolean;
54
+ allowCustomEvents: boolean;
55
+ oauth: boolean;
56
+ };
57
+ throughput: {
58
+ key: string;
59
+ limit: number;
60
+ };
61
+ createdAt: number;
62
+ updatedAt: number;
63
+ updated: boolean;
64
+ version: string;
65
+ lastModifiedBy: string;
66
+ deleted: boolean;
67
+ tags: string[];
68
+ active: boolean;
69
+ deprecated: boolean;
70
+ }
71
+
72
+ export interface EventProps {
73
+ data: {
74
+ messageType: string;
75
+ message: ConnectionRecord | string;
76
+ // Optional fields for OAUTH_REDIRECT messages
77
+ url?: string;
78
+ state?: string;
79
+ }
80
+ }