diff --git a/package.json b/package.json index 2b975b0..e33d3ea 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "husky": "^8.0.3", "nx": "21.5.2", "oxlint": "^1.16.0", - "prettier": "^3.4.2" + "prettier": "^3.4.2", + "typescript": "^5.3.3" } } diff --git a/packages/nylas-connect/app.js b/packages/nylas-connect/app.js new file mode 100644 index 0000000..78b2041 --- /dev/null +++ b/packages/nylas-connect/app.js @@ -0,0 +1,104 @@ +import { auth } from "./auth-instance.js"; + +const connectButton = document.getElementById("connectButton"); +const resultContainer = document.getElementById("resultContainer"); +const resultContent = document.getElementById("resultContent"); + +connectButton.addEventListener("click", async () => { + // Disable button and show loading state + connectButton.disabled = true; + connectButton.textContent = "Connecting..."; + resultContainer.classList.remove("show"); + resultContent.innerHTML = + '

Opening authentication window...

'; + + try { + const result = await auth.connect({ method: "popup" }); + + // Display the result + displayResult(result); + } catch (error) { + // Display error + displayError(error); + } finally { + // Re-enable button + connectButton.disabled = false; + connectButton.textContent = "Connect your inbox"; + } +}); + +function displayResult(result) { + const expiresAt = new Date(result.expiresAt); + const expiresIn = Math.floor((result.expiresAt - Date.now()) / 1000 / 60); + + let html = '✓ Authentication Successful'; + html += "

Connection Details

"; + + // Access Token + html += '
'; + html += '
Access Token
'; + html += `
${escapeHtml(result.accessToken)}
`; + html += "
"; + + // Grant ID + html += '
'; + html += '
Grant ID
'; + html += `
${escapeHtml(result.grantId)}
`; + html += "
"; + + // Grant Info (if available) + if (result.grantInfo) { + if (result.grantInfo.email) { + html += '
'; + html += '
Email
'; + html += `
${escapeHtml(result.grantInfo.email)}
`; + html += "
"; + } + + if (result.grantInfo.provider) { + html += '
'; + html += '
Provider
'; + html += `
${escapeHtml(result.grantInfo.provider)}
`; + html += "
"; + } + + if (result.grantInfo.name) { + html += '
'; + html += '
Name
'; + html += `
${escapeHtml(result.grantInfo.name)}
`; + html += "
"; + } + } + + // Scopes + html += '
'; + html += '
Granted Scopes
'; + html += `
${escapeHtml(result.scope)}
`; + html += "
"; + + // Expiration + html += '
'; + html += '
Expires
'; + html += `
${expiresAt.toLocaleString()} (in ${expiresIn} minutes)
`; + html += "
"; + + resultContent.innerHTML = html; + resultContainer.classList.add("show"); +} + +function displayError(error) { + const errorMessage = error instanceof Error ? error.message : String(error); + resultContent.innerHTML = ` +
+ Authentication Error:
+ ${escapeHtml(errorMessage)} +
+ `; + resultContainer.classList.add("show"); +} + +function escapeHtml(text) { + const div = document.createElement("div"); + div.textContent = text; + return div.innerHTML; +} diff --git a/packages/nylas-connect/auth-instance.js b/packages/nylas-connect/auth-instance.js index 7111985..eaf21f8 100644 --- a/packages/nylas-connect/auth-instance.js +++ b/packages/nylas-connect/auth-instance.js @@ -2,8 +2,8 @@ import { NylasConnect } from "./src/index.ts"; // Shared auth configuration export const auth = new NylasConnect({ - clientId: "3531f8b3-3d7f-4412-a073-2d4aa397508f", - apiUrl: "https://api-staging.us.nylas.com/v3", + clientId: "09e06084-b8a4-483c-92e2-07985e0d0489", + apiUrl: "https://api.us.nylas.com/v3", redirectUri: (globalThis.window?.location?.origin || "http://localhost:3000") + "/callback.html", diff --git a/packages/nylas-connect/index.html b/packages/nylas-connect/index.html index c70b2f2..952f968 100644 --- a/packages/nylas-connect/index.html +++ b/packages/nylas-connect/index.html @@ -4,28 +4,21 @@ Nylas Auth - Development - + -

Open the console to see the output

- +
+

Nylas Connect Demo

+

+ Click the button below to connect your inbox using Nylas Hosted Auth. +

+ +
+
+
+
+ diff --git a/packages/nylas-connect/package.json b/packages/nylas-connect/package.json index 27d2ab6..9218b07 100644 --- a/packages/nylas-connect/package.json +++ b/packages/nylas-connect/package.json @@ -18,9 +18,9 @@ ], "scripts": { "dev": "vite", - "build": "tsc && vite build", + "build": "../../node_modules/.bin/tsc && vite build", "preview": "vite preview", - "typecheck": "tsc --noEmit", + "typecheck": "../../node_modules/.bin/tsc --noEmit", "format": "pnpm --workspace-root prettier --write packages/nylas-connect/", "format:check": "pnpm --workspace-root prettier --check packages/nylas-connect/", "lint": "oxlint --fix . && exit 0", diff --git a/packages/nylas-connect/styles.css b/packages/nylas-connect/styles.css new file mode 100644 index 0000000..3066a86 --- /dev/null +++ b/packages/nylas-connect/styles.css @@ -0,0 +1,124 @@ +body { + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; + margin: 0; + padding: 0; + background: #f8f9fa; + min-height: 100vh; +} + +.demo-container { + max-width: 800px; + margin: 0 auto; + padding: 2rem; +} + +h1 { + color: #333; + margin-bottom: 0.5rem; + font-size: 2rem; +} + +.demo-description { + color: #64748b; + margin-bottom: 2rem; + font-size: 1rem; +} + +.connect-button { + background: #0066ff; + color: white; + border: none; + padding: 0.75rem 1.5rem; + font-size: 1rem; + font-weight: 500; + border-radius: 6px; + cursor: pointer; + transition: background 0.2s; + margin-bottom: 2rem; +} + +.connect-button:hover:not(:disabled) { + background: #0052cc; +} + +.connect-button:disabled { + background: #94a3b8; + cursor: not-allowed; +} + +.result-container { + display: none; + background: white; + border-radius: 8px; + padding: 1.5rem; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + margin-top: 2rem; +} + +.result-container.show { + display: block; +} + +.result-container h2 { + margin-top: 0; + color: #333; + font-size: 1.25rem; +} + +.result-section { + margin-bottom: 1.5rem; +} + +.result-section:last-child { + margin-bottom: 0; +} + +.result-label { + font-weight: 600; + color: #64748b; + font-size: 0.875rem; + text-transform: uppercase; + letter-spacing: 0.05em; + margin-bottom: 0.5rem; +} + +.result-value { + color: #1e293b; + word-break: break-all; + font-family: "Monaco", "Menlo", "Ubuntu Mono", monospace; + font-size: 0.875rem; + background: #f1f5f9; + padding: 0.75rem; + border-radius: 4px; + border: 1px solid #e2e8f0; +} + +.token-value { + font-size: 0.75rem; + line-height: 1.6; +} + +.error-message { + background: #fee2e2; + color: #991b1b; + padding: 1rem; + border-radius: 6px; + border: 1px solid #fecaca; +} + +.success-badge { + display: inline-block; + background: #d1fae5; + color: #065f46; + padding: 0.25rem 0.75rem; + border-radius: 4px; + font-size: 0.875rem; + font-weight: 500; + margin-bottom: 1rem; +} + +.loading { + color: #64748b; + font-style: italic; +} diff --git a/packages/react/package.json b/packages/react/package.json index 54cdbbe..421ec6b 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -4,7 +4,7 @@ "description": "React components and hooks for Nylas API integration", "type": "module", "scripts": { - "build": "tsc && vite build", + "build": "../../node_modules/.bin/tsc && vite build", "test": "vitest run", "test:watch": "vitest", "format": "pnpm --workspace-root prettier --write packages/react/", @@ -13,7 +13,7 @@ "lint:check": "oxlint .", "clean": "rm -rf dist", "dev": "vite build --watch --emptyOutDir=false", - "typecheck": "tsc --noEmit", + "typecheck": "../../node_modules/.bin/tsc --noEmit", "preview": "vite preview", "coverage": "vitest run --coverage", "docs": "typedoc" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d5ded98..24c4d62 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,6 +23,9 @@ importers: prettier: specifier: ^3.4.2 version: 3.6.2 + typescript: + specifier: ^5.3.3 + version: 5.9.2 packages/nylas-connect: devDependencies: