@bridge-ai-dev/ecom-chat 1.0.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/README.md +178 -0
- package/bin/cli.js +174 -0
- package/dist/ChatComponent.d.ts +35 -0
- package/dist/ChatComponent.d.ts.map +1 -0
- package/dist/ChatComponent.js +159 -0
- package/dist/ChatComponent.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +108 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/package.json +49 -0
- package/templates/route.ts.template +25 -0
package/README.md
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# @bridge-ai-dev/ecom-chat
|
|
2
|
+
|
|
3
|
+
Bridge E-commerce Chat widget integration for Next.js with Litium authentication.
|
|
4
|
+
|
|
5
|
+
## Why This Package?
|
|
6
|
+
|
|
7
|
+
When integrating a chat widget with Litium e-commerce, you often need access to authentication cookies like `.AspNetCore.Identity.Application`. However, these cookies are typically `HttpOnly`, meaning they **cannot be accessed from client-side JavaScript** for security reasons.
|
|
8
|
+
|
|
9
|
+
This package solves this problem by:
|
|
10
|
+
|
|
11
|
+
1. **Creating a secure API route** that runs on the server and can access HttpOnly cookies
|
|
12
|
+
2. **Providing a React component** that fetches these cookies via the API and passes them to the chat widget
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
### Step 1: Run the Setup Command
|
|
17
|
+
|
|
18
|
+
In your Next.js project root, run:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npx @bridge-ai-dev/create-ecom-chat
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
This will create the API route at `app/api/bridge-auth/route.ts`.
|
|
25
|
+
|
|
26
|
+
### Step 2: Install the Package
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install @bridge-ai-dev/ecom-chat
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
### Basic Usage
|
|
35
|
+
|
|
36
|
+
Add the `ChatComponent` to your layout:
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
// app/layout.tsx
|
|
40
|
+
import { ChatComponent } from '@bridge-ai-dev/ecom-chat';
|
|
41
|
+
|
|
42
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
43
|
+
return (
|
|
44
|
+
<html>
|
|
45
|
+
<body>
|
|
46
|
+
{children}
|
|
47
|
+
<ChatComponent
|
|
48
|
+
tenantId="your-tenant-uuid"
|
|
49
|
+
widgetScriptUrl="http://localhost:5173/chat-widget.js"
|
|
50
|
+
/>
|
|
51
|
+
</body>
|
|
52
|
+
</html>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### With Full Widget Configuration
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
<ChatComponent
|
|
61
|
+
tenantId="your-tenant-uuid"
|
|
62
|
+
widgetScriptUrl="http://localhost:5173/chat-widget.js"
|
|
63
|
+
accessToken="optional-access-token"
|
|
64
|
+
position="bottom-right"
|
|
65
|
+
backgroundColor="#6366f1"
|
|
66
|
+
foregroundColor="#ffffff"
|
|
67
|
+
size="medium"
|
|
68
|
+
borderWidth={2}
|
|
69
|
+
borderColor="#4f46e5"
|
|
70
|
+
autoPopup={false}
|
|
71
|
+
onAuthSuccess={(authData) => {
|
|
72
|
+
console.log('Auth successful, cart context:', authData.cart_context);
|
|
73
|
+
}}
|
|
74
|
+
onAuthError={(error) => {
|
|
75
|
+
console.error('Auth failed:', error.message);
|
|
76
|
+
}}
|
|
77
|
+
/>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Custom API Endpoint
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
<ChatComponent
|
|
84
|
+
tenantId="your-tenant-uuid"
|
|
85
|
+
bridgeAuthEndpoint="/api/custom-bridge-auth" // Custom API route path
|
|
86
|
+
containerId="my-chat-container" // Custom container ID
|
|
87
|
+
/>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## API Reference
|
|
91
|
+
|
|
92
|
+
### ChatComponent Props
|
|
93
|
+
|
|
94
|
+
| Prop | Type | Required | Default | Description |
|
|
95
|
+
|------|------|----------|---------|-------------|
|
|
96
|
+
| `tenantId` | `string` | ✅ | - | Your Bridge Chat tenant identifier |
|
|
97
|
+
| `widgetScriptUrl` | `string` | ❌ | - | URL to the chat widget script (loads dynamically) |
|
|
98
|
+
| `accessToken` | `string` | ❌ | - | Optional access token for authenticated requests |
|
|
99
|
+
| `position` | `'bottom-right' \| 'bottom-left' \| 'top-right' \| 'top-left'` | ❌ | `'bottom-right'` | Widget position on screen |
|
|
100
|
+
| `backgroundColor` | `string` | ❌ | `'#6366f1'` | Widget background color |
|
|
101
|
+
| `foregroundColor` | `string` | ❌ | `'#ffffff'` | Widget foreground/text color |
|
|
102
|
+
| `size` | `'small' \| 'medium' \| 'large'` | ❌ | `'medium'` | Widget size |
|
|
103
|
+
| `borderWidth` | `number` | ❌ | `2` | Widget border width in pixels |
|
|
104
|
+
| `borderColor` | `string` | ❌ | `'#4f46e5'` | Widget border color |
|
|
105
|
+
| `autoPopup` | `boolean` | ❌ | `false` | Auto popup the chat widget on load |
|
|
106
|
+
| `onAuthSuccess` | `(authData: BridgeAuthResponse) => void` | ❌ | - | Callback when auth bridge succeeds |
|
|
107
|
+
| `onAuthError` | `(error: Error) => void` | ❌ | - | Callback when auth bridge fails |
|
|
108
|
+
| `bridgeAuthEndpoint` | `string` | ❌ | `/api/bridge-auth` | Custom API endpoint path |
|
|
109
|
+
| `containerId` | `string` | ❌ | `bgc-chat-container` | Container element ID |
|
|
110
|
+
|
|
111
|
+
### BridgeAuthResponse
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
interface BridgeAuthResponse {
|
|
115
|
+
cart_context: string | null;
|
|
116
|
+
identity: string | null;
|
|
117
|
+
raw?: string | null;
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## How It Works
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
|
|
125
|
+
│ ChatComponent │ ──▶ │ /api/bridge-auth │ ──▶ │ Chat Widget │
|
|
126
|
+
│ (Client) │ │ (Server) │ │ (BridgeChat) │
|
|
127
|
+
└─────────────────┘ └──────────────────┘ └─────────────────┘
|
|
128
|
+
│ │ │
|
|
129
|
+
│ 1. Fetch cookies │ │
|
|
130
|
+
│ ──────────────────────▶│ │
|
|
131
|
+
│ │ Server can read │
|
|
132
|
+
│ │ HttpOnly cookies │
|
|
133
|
+
│ │ │
|
|
134
|
+
│ 2. Return JSON │ │
|
|
135
|
+
│ ◀──────────────────────│ │
|
|
136
|
+
│ │ │
|
|
137
|
+
│ 3. Initialize with cookies + config │
|
|
138
|
+
│ ────────────────────────────────────────────────▶│
|
|
139
|
+
│ │ │
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## What Gets Passed to BridgeChat.init()
|
|
143
|
+
|
|
144
|
+
When the component initializes, it calls `BridgeChat.init()` with:
|
|
145
|
+
|
|
146
|
+
```javascript
|
|
147
|
+
BridgeChat.init({
|
|
148
|
+
tenantId: 'your-tenant-uuid',
|
|
149
|
+
accessToken: 'optional-access-token',
|
|
150
|
+
cookies: {
|
|
151
|
+
cart_context: 'value-from-cookie',
|
|
152
|
+
identity: 'value-from-identity-cookie'
|
|
153
|
+
},
|
|
154
|
+
container: 'bgc-chat-container',
|
|
155
|
+
position: 'bottom-right',
|
|
156
|
+
backgroundColor: '#6366f1',
|
|
157
|
+
foregroundColor: '#ffffff',
|
|
158
|
+
size: 'medium',
|
|
159
|
+
borderWidth: 2,
|
|
160
|
+
borderColor: '#4f46e5',
|
|
161
|
+
autoPopup: false
|
|
162
|
+
});
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Security
|
|
166
|
+
|
|
167
|
+
- The API route runs **server-side**, allowing access to `HttpOnly` cookies
|
|
168
|
+
- Cookies are passed to the chat widget via JavaScript, not exposed to third parties
|
|
169
|
+
- The component uses `credentials: 'include'` to ensure cookies are sent with the request
|
|
170
|
+
|
|
171
|
+
## Requirements
|
|
172
|
+
|
|
173
|
+
- Next.js 13+ with App Router
|
|
174
|
+
- React 17+
|
|
175
|
+
|
|
176
|
+
## License
|
|
177
|
+
|
|
178
|
+
MIT
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
// ANSI color codes for terminal output
|
|
7
|
+
const colors = {
|
|
8
|
+
green: '\x1b[32m',
|
|
9
|
+
yellow: '\x1b[33m',
|
|
10
|
+
blue: '\x1b[34m',
|
|
11
|
+
red: '\x1b[31m',
|
|
12
|
+
reset: '\x1b[0m',
|
|
13
|
+
bold: '\x1b[1m'
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const log = {
|
|
17
|
+
success: (msg) => console.log(`${colors.green}✅ ${msg}${colors.reset}`),
|
|
18
|
+
info: (msg) => console.log(`${colors.blue}ℹ️ ${msg}${colors.reset}`),
|
|
19
|
+
warning: (msg) => console.log(`${colors.yellow}⚠️ ${msg}${colors.reset}`),
|
|
20
|
+
error: (msg) => console.log(`${colors.red}❌ ${msg}${colors.reset}`),
|
|
21
|
+
step: (msg) => console.log(`${colors.bold}🚀 ${msg}${colors.reset}`)
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// The API route content that will be created
|
|
25
|
+
const apiRouteContent = `import { NextRequest, NextResponse } from "next/server";
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Bridge Auth API Route
|
|
29
|
+
*
|
|
30
|
+
* This route acts as a secure bridge to retrieve HttpOnly cookies
|
|
31
|
+
* that cannot be accessed from client-side JavaScript.
|
|
32
|
+
*
|
|
33
|
+
* The ChatComponent uses this route to get authentication context
|
|
34
|
+
* before initializing the chat widget.
|
|
35
|
+
*/
|
|
36
|
+
export const GET = async (request: NextRequest) => {
|
|
37
|
+
const cookies = request.cookies;
|
|
38
|
+
|
|
39
|
+
// Retrieve the secure cookies
|
|
40
|
+
const cartContext = cookies.get("cart-context")?.value;
|
|
41
|
+
const identity = cookies.get(".AspNetCore.Identity.Application")?.value;
|
|
42
|
+
|
|
43
|
+
return NextResponse.json({
|
|
44
|
+
cart_context: cartContext || null,
|
|
45
|
+
identity: identity || null,
|
|
46
|
+
// Optional: Include the raw cookie string if your backend needs it
|
|
47
|
+
raw: request.headers.get("cookie")
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
`;
|
|
51
|
+
|
|
52
|
+
function isNextJsProject(cwd) {
|
|
53
|
+
// Check for Next.js indicators
|
|
54
|
+
const indicators = [
|
|
55
|
+
'next.config.js',
|
|
56
|
+
'next.config.mjs',
|
|
57
|
+
'next.config.ts',
|
|
58
|
+
path.join('app', 'layout.tsx'),
|
|
59
|
+
path.join('app', 'layout.js'),
|
|
60
|
+
path.join('app', 'page.tsx'),
|
|
61
|
+
path.join('app', 'page.js')
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
for (const indicator of indicators) {
|
|
65
|
+
if (fs.existsSync(path.join(cwd, indicator))) {
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Check package.json for next dependency
|
|
71
|
+
const packageJsonPath = path.join(cwd, 'package.json');
|
|
72
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
73
|
+
try {
|
|
74
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
75
|
+
const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
76
|
+
if (deps.next) {
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
} catch (e) {
|
|
80
|
+
// Ignore parse errors
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function hasAppDirectory(cwd) {
|
|
88
|
+
return fs.existsSync(path.join(cwd, 'app'));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function setup() {
|
|
92
|
+
const cwd = process.cwd();
|
|
93
|
+
|
|
94
|
+
console.log('\n');
|
|
95
|
+
console.log(`${colors.bold}╔════════════════════════════════════════════╗${colors.reset}`);
|
|
96
|
+
console.log(`${colors.bold}║ Bridge E-com Chat Setup for Next.js ║${colors.reset}`);
|
|
97
|
+
console.log(`${colors.bold}╚════════════════════════════════════════════╝${colors.reset}`);
|
|
98
|
+
console.log('\n');
|
|
99
|
+
|
|
100
|
+
// Check if this is a Next.js project
|
|
101
|
+
if (!isNextJsProject(cwd)) {
|
|
102
|
+
log.warning('This does not appear to be a Next.js project.');
|
|
103
|
+
log.info('The bridge-auth route requires Next.js App Router.');
|
|
104
|
+
console.log('\n');
|
|
105
|
+
|
|
106
|
+
const readline = require('readline');
|
|
107
|
+
const rl = readline.createInterface({
|
|
108
|
+
input: process.stdin,
|
|
109
|
+
output: process.stdout
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
rl.question('Continue anyway? (y/N): ', (answer) => {
|
|
113
|
+
rl.close();
|
|
114
|
+
if (answer.toLowerCase() !== 'y') {
|
|
115
|
+
log.info('Setup cancelled.');
|
|
116
|
+
process.exit(0);
|
|
117
|
+
}
|
|
118
|
+
createFiles(cwd);
|
|
119
|
+
});
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Check for app directory
|
|
124
|
+
if (!hasAppDirectory(cwd)) {
|
|
125
|
+
log.error('No "app" directory found.');
|
|
126
|
+
log.info('Please ensure you are using Next.js 13+ with the App Router.');
|
|
127
|
+
log.info('Create an "app" directory and try again.');
|
|
128
|
+
process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
createFiles(cwd);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function createFiles(cwd) {
|
|
135
|
+
const targetDir = path.join(cwd, 'app', 'api', 'bridge-auth');
|
|
136
|
+
const targetFile = path.join(targetDir, 'route.ts');
|
|
137
|
+
|
|
138
|
+
// Check if file already exists
|
|
139
|
+
if (fs.existsSync(targetFile)) {
|
|
140
|
+
log.warning('API route already exists at: app/api/bridge-auth/route.ts');
|
|
141
|
+
log.info('Skipping file creation to avoid overwriting.');
|
|
142
|
+
} else {
|
|
143
|
+
// Create directory structure
|
|
144
|
+
if (!fs.existsSync(targetDir)) {
|
|
145
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
146
|
+
log.success('Created directory: app/api/bridge-auth/');
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Write the API route file
|
|
150
|
+
fs.writeFileSync(targetFile, apiRouteContent, 'utf8');
|
|
151
|
+
log.success('Created API route: app/api/bridge-auth/route.ts');
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
console.log('\n');
|
|
155
|
+
log.step('Next Steps:');
|
|
156
|
+
console.log('\n');
|
|
157
|
+
console.log(' 1. Install the package (if not already):');
|
|
158
|
+
console.log(` ${colors.yellow}npm install @bridge-ai-dev/ecom-chat${colors.reset}`);
|
|
159
|
+
console.log('\n');
|
|
160
|
+
console.log(' 2. Add the ChatComponent to your layout.tsx:');
|
|
161
|
+
console.log(` ${colors.yellow}import { ChatComponent } from '@bridge-ai-dev/ecom-chat';${colors.reset}`);
|
|
162
|
+
console.log('\n');
|
|
163
|
+
console.log(' 3. Include it in your layout:');
|
|
164
|
+
console.log(` ${colors.yellow}<ChatComponent tenantId="your-tenant-uuid" />${colors.reset}`);
|
|
165
|
+
console.log('\n');
|
|
166
|
+
console.log(' 4. Add your chat widget script to the layout:');
|
|
167
|
+
console.log(` ${colors.yellow}<script src="https://your-cdn.com/chat-widget.js" async />${colors.reset}`);
|
|
168
|
+
console.log('\n');
|
|
169
|
+
log.success('Setup complete! 🎉');
|
|
170
|
+
console.log('\n');
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Run the setup
|
|
174
|
+
setup();
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ChatComponentProps } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* ChatComponent - Bridge Chat Widget Integration for Next.js
|
|
5
|
+
*
|
|
6
|
+
* This component handles the secure handshake between your Next.js application
|
|
7
|
+
* and the Bridge Chat widget. It retrieves HttpOnly cookies via a server-side
|
|
8
|
+
* API route and initializes the chat widget with the authenticated context.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* import { ChatComponent } from '@bridge-ai-dev/ecom-chat';
|
|
13
|
+
*
|
|
14
|
+
* export default function RootLayout({ children }) {
|
|
15
|
+
* return (
|
|
16
|
+
* <html>
|
|
17
|
+
* <body>
|
|
18
|
+
* {children}
|
|
19
|
+
* <ChatComponent
|
|
20
|
+
* tenantId="your-tenant-uuid"
|
|
21
|
+
* widgetScriptUrl="http://localhost:5173/chat-widget.js"
|
|
22
|
+
* position="bottom-right"
|
|
23
|
+
* backgroundColor="#6366f1"
|
|
24
|
+
* foregroundColor="#ffffff"
|
|
25
|
+
* size="medium"
|
|
26
|
+
* />
|
|
27
|
+
* </body>
|
|
28
|
+
* </html>
|
|
29
|
+
* );
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare const ChatComponent: React.FC<ChatComponentProps>;
|
|
34
|
+
export default ChatComponent;
|
|
35
|
+
//# sourceMappingURL=ChatComponent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatComponent.d.ts","sourceRoot":"","sources":["../src/ChatComponent.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA2C,MAAM,OAAO,CAAC;AAChE,OAAO,KAAK,EAAE,kBAAkB,EAAsB,MAAM,SAAS,CAAC;AAEtE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA2JtD,CAAC;AAEF,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useState, useCallback } from 'react';
|
|
4
|
+
/**
|
|
5
|
+
* ChatComponent - Bridge Chat Widget Integration for Next.js
|
|
6
|
+
*
|
|
7
|
+
* This component handles the secure handshake between your Next.js application
|
|
8
|
+
* and the Bridge Chat widget. It retrieves HttpOnly cookies via a server-side
|
|
9
|
+
* API route and initializes the chat widget with the authenticated context.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* import { ChatComponent } from '@bridge-ai-dev/ecom-chat';
|
|
14
|
+
*
|
|
15
|
+
* export default function RootLayout({ children }) {
|
|
16
|
+
* return (
|
|
17
|
+
* <html>
|
|
18
|
+
* <body>
|
|
19
|
+
* {children}
|
|
20
|
+
* <ChatComponent
|
|
21
|
+
* tenantId="your-tenant-uuid"
|
|
22
|
+
* widgetScriptUrl="http://localhost:5173/chat-widget.js"
|
|
23
|
+
* position="bottom-right"
|
|
24
|
+
* backgroundColor="#6366f1"
|
|
25
|
+
* foregroundColor="#ffffff"
|
|
26
|
+
* size="medium"
|
|
27
|
+
* />
|
|
28
|
+
* </body>
|
|
29
|
+
* </html>
|
|
30
|
+
* );
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export const ChatComponent = ({ tenantId, onAuthSuccess, onAuthError, bridgeAuthEndpoint = '/api/bridge-auth', containerId = 'bgc-chat-container',
|
|
35
|
+
// Widget configuration options
|
|
36
|
+
position = 'bottom-right', backgroundColor = '#6366f1', foregroundColor = '#ffffff', size = 'medium', borderWidth = 2, borderColor = '#4f46e5', autoPopup = false, widgetScriptUrl }) => {
|
|
37
|
+
const [isInitialized, setIsInitialized] = useState(false);
|
|
38
|
+
const [error, setError] = useState(null);
|
|
39
|
+
const [scriptLoaded, setScriptLoaded] = useState(false);
|
|
40
|
+
// Load widget script dynamically if URL is provided
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
if (!widgetScriptUrl) {
|
|
43
|
+
// Script should already be loaded externally
|
|
44
|
+
setScriptLoaded(true);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
// Check if script already exists
|
|
48
|
+
const existingScript = document.querySelector(`script[src="${widgetScriptUrl}"]`);
|
|
49
|
+
if (existingScript) {
|
|
50
|
+
setScriptLoaded(true);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
// Load the script dynamically
|
|
54
|
+
const script = document.createElement('script');
|
|
55
|
+
script.src = widgetScriptUrl;
|
|
56
|
+
script.async = true;
|
|
57
|
+
script.onload = () => setScriptLoaded(true);
|
|
58
|
+
script.onerror = () => {
|
|
59
|
+
const err = new Error(`Failed to load chat widget script from: ${widgetScriptUrl}`);
|
|
60
|
+
setError(err);
|
|
61
|
+
onAuthError?.(err);
|
|
62
|
+
};
|
|
63
|
+
document.body.appendChild(script);
|
|
64
|
+
return () => {
|
|
65
|
+
// Cleanup on unmount if needed
|
|
66
|
+
};
|
|
67
|
+
}, [widgetScriptUrl, onAuthError]);
|
|
68
|
+
const initChat = useCallback(async () => {
|
|
69
|
+
// Prevent re-initialization
|
|
70
|
+
if (isInitialized)
|
|
71
|
+
return;
|
|
72
|
+
if (!scriptLoaded)
|
|
73
|
+
return;
|
|
74
|
+
try {
|
|
75
|
+
// 1. Call our local Next.js bridge route to get secure cookies
|
|
76
|
+
const authRes = await fetch(bridgeAuthEndpoint, {
|
|
77
|
+
method: 'GET',
|
|
78
|
+
credentials: 'include', // Important: include cookies in the request
|
|
79
|
+
});
|
|
80
|
+
if (!authRes.ok) {
|
|
81
|
+
throw new Error(`Bridge auth failed: ${authRes.status} ${authRes.statusText}`);
|
|
82
|
+
}
|
|
83
|
+
const authData = await authRes.json();
|
|
84
|
+
// 2. Wait for BridgeChat to be available (with timeout)
|
|
85
|
+
const waitForBridgeChat = () => {
|
|
86
|
+
return new Promise((resolve, reject) => {
|
|
87
|
+
let attempts = 0;
|
|
88
|
+
const maxAttempts = 50; // 5 seconds max wait
|
|
89
|
+
const check = () => {
|
|
90
|
+
if (window.BridgeChat) {
|
|
91
|
+
resolve();
|
|
92
|
+
}
|
|
93
|
+
else if (attempts >= maxAttempts) {
|
|
94
|
+
reject(new Error('BridgeChat widget not found. Make sure the widget script is loaded.'));
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
attempts++;
|
|
98
|
+
setTimeout(check, 100);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
check();
|
|
102
|
+
});
|
|
103
|
+
};
|
|
104
|
+
await waitForBridgeChat();
|
|
105
|
+
// 3. Initialize the Chat Widget with all configuration options
|
|
106
|
+
if (window.BridgeChat) {
|
|
107
|
+
window.BridgeChat.init({
|
|
108
|
+
tenantId: tenantId,
|
|
109
|
+
cookies: {
|
|
110
|
+
cart_context: authData.cart_context,
|
|
111
|
+
identity: authData.identity
|
|
112
|
+
},
|
|
113
|
+
container: containerId,
|
|
114
|
+
position: position,
|
|
115
|
+
backgroundColor: backgroundColor,
|
|
116
|
+
foregroundColor: foregroundColor,
|
|
117
|
+
size: size,
|
|
118
|
+
borderWidth: borderWidth,
|
|
119
|
+
borderColor: borderColor,
|
|
120
|
+
autoPopup: autoPopup
|
|
121
|
+
});
|
|
122
|
+
setIsInitialized(true);
|
|
123
|
+
onAuthSuccess?.(authData);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
const error = err instanceof Error ? err : new Error('Unknown error during chat initialization');
|
|
128
|
+
console.error('Failed to bridge Litium context:', error);
|
|
129
|
+
setError(error);
|
|
130
|
+
onAuthError?.(error);
|
|
131
|
+
}
|
|
132
|
+
}, [
|
|
133
|
+
tenantId,
|
|
134
|
+
bridgeAuthEndpoint,
|
|
135
|
+
isInitialized,
|
|
136
|
+
scriptLoaded,
|
|
137
|
+
containerId,
|
|
138
|
+
position,
|
|
139
|
+
backgroundColor,
|
|
140
|
+
foregroundColor,
|
|
141
|
+
size,
|
|
142
|
+
borderWidth,
|
|
143
|
+
borderColor,
|
|
144
|
+
autoPopup,
|
|
145
|
+
onAuthSuccess,
|
|
146
|
+
onAuthError
|
|
147
|
+
]);
|
|
148
|
+
useEffect(() => {
|
|
149
|
+
initChat();
|
|
150
|
+
}, [initChat]);
|
|
151
|
+
// Render a container for the chat widget
|
|
152
|
+
// The actual widget will be mounted here by BridgeChat.init()
|
|
153
|
+
return (_jsx("div", { id: containerId, "data-tenant-id": tenantId, "data-initialized": isInitialized, "data-error": error?.message, style: {
|
|
154
|
+
// The widget will control its own positioning
|
|
155
|
+
// This container is just a mount point
|
|
156
|
+
} }));
|
|
157
|
+
};
|
|
158
|
+
export default ChatComponent;
|
|
159
|
+
//# sourceMappingURL=ChatComponent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatComponent.js","sourceRoot":"","sources":["../src/ChatComponent.tsx"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @bridge-ai-dev/ecom-chat
|
|
3
|
+
*
|
|
4
|
+
* Bridge E-commerce Chat widget integration for Next.js with Litium authentication.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
export { ChatComponent, default } from './ChatComponent';
|
|
9
|
+
export type { ChatComponentProps, BridgeAuthResponse, BridgeChatInitConfig, BridgeChatGlobal, WidgetPosition, WidgetSize } from './types';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAGzD,YAAY,EACR,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAChB,cAAc,EACd,UAAU,EACb,MAAM,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @bridge-ai-dev/ecom-chat
|
|
3
|
+
*
|
|
4
|
+
* Bridge E-commerce Chat widget integration for Next.js with Litium authentication.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
// Export the main component
|
|
9
|
+
export { ChatComponent, default } from './ChatComponent';
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,4BAA4B;AAC5B,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript type definitions for Bridge Chat React
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Widget position options
|
|
6
|
+
*/
|
|
7
|
+
export type WidgetPosition = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
|
|
8
|
+
/**
|
|
9
|
+
* Widget size options
|
|
10
|
+
*/
|
|
11
|
+
export type WidgetSize = 'small' | 'medium' | 'large';
|
|
12
|
+
/**
|
|
13
|
+
* Props for the ChatComponent
|
|
14
|
+
*/
|
|
15
|
+
export interface ChatComponentProps {
|
|
16
|
+
/** The unique tenant identifier for your Bridge Chat instance */
|
|
17
|
+
tenantId: string;
|
|
18
|
+
/** Optional callback when authentication bridge completes successfully */
|
|
19
|
+
onAuthSuccess?: (authData: BridgeAuthResponse) => void;
|
|
20
|
+
/** Optional callback when authentication bridge fails */
|
|
21
|
+
onAuthError?: (error: Error) => void;
|
|
22
|
+
/** Optional custom API endpoint for the bridge auth route (default: /api/bridge-auth) */
|
|
23
|
+
bridgeAuthEndpoint?: string;
|
|
24
|
+
/** Optional custom container ID for the chat widget (default: bgc-chat-container) */
|
|
25
|
+
containerId?: string;
|
|
26
|
+
/** Widget position on screen (default: 'bottom-right') */
|
|
27
|
+
position?: WidgetPosition;
|
|
28
|
+
/** Widget background color (default: '#6366f1') */
|
|
29
|
+
backgroundColor?: string;
|
|
30
|
+
/** Widget foreground/text color (default: '#ffffff') */
|
|
31
|
+
foregroundColor?: string;
|
|
32
|
+
/** Widget size (default: 'medium') */
|
|
33
|
+
size?: WidgetSize;
|
|
34
|
+
/** Widget border width in pixels (default: 2) */
|
|
35
|
+
borderWidth?: number;
|
|
36
|
+
/** Widget border color (default: '#4f46e5') */
|
|
37
|
+
borderColor?: string;
|
|
38
|
+
/** Auto popup the chat widget on load (default: false) */
|
|
39
|
+
autoPopup?: boolean;
|
|
40
|
+
/** URL to the chat widget script (if not already loaded) */
|
|
41
|
+
widgetScriptUrl?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Response from the bridge-auth API route
|
|
45
|
+
*/
|
|
46
|
+
export interface BridgeAuthResponse {
|
|
47
|
+
/** The cart context cookie value */
|
|
48
|
+
cart_context: string | null;
|
|
49
|
+
/** The ASP.NET Core Identity cookie value */
|
|
50
|
+
identity: string | null;
|
|
51
|
+
/** Raw cookie header string (optional, for debugging) */
|
|
52
|
+
raw?: string | null;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Configuration for BridgeChat.init()
|
|
56
|
+
*/
|
|
57
|
+
export interface BridgeChatInitConfig {
|
|
58
|
+
/** The tenant identifier */
|
|
59
|
+
tenantId: string;
|
|
60
|
+
/** Cookie values retrieved from the bridge */
|
|
61
|
+
cookies: {
|
|
62
|
+
cart_context: string | null;
|
|
63
|
+
identity: string | null;
|
|
64
|
+
};
|
|
65
|
+
/** Container element ID for the widget */
|
|
66
|
+
container?: string;
|
|
67
|
+
/** Widget position on screen */
|
|
68
|
+
position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
|
|
69
|
+
/** Widget background color */
|
|
70
|
+
backgroundColor?: string;
|
|
71
|
+
/** Widget foreground/text color */
|
|
72
|
+
foregroundColor?: string;
|
|
73
|
+
/** Widget size */
|
|
74
|
+
size?: 'small' | 'medium' | 'large';
|
|
75
|
+
/** Widget border width in pixels */
|
|
76
|
+
borderWidth?: number;
|
|
77
|
+
/** Widget border color */
|
|
78
|
+
borderColor?: string;
|
|
79
|
+
/** Auto popup the chat widget on load */
|
|
80
|
+
autoPopup?: boolean;
|
|
81
|
+
/** Optional additional configuration */
|
|
82
|
+
[key: string]: unknown;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Global BridgeChat interface
|
|
86
|
+
*/
|
|
87
|
+
export interface BridgeChatGlobal {
|
|
88
|
+
/** Initialize the chat widget with configuration */
|
|
89
|
+
init: (config: BridgeChatInitConfig) => void;
|
|
90
|
+
/** Optional: Open the chat widget */
|
|
91
|
+
open?: () => void;
|
|
92
|
+
/** Optional: Close the chat widget */
|
|
93
|
+
close?: () => void;
|
|
94
|
+
/** Optional: Toggle the chat widget visibility */
|
|
95
|
+
toggle?: () => void;
|
|
96
|
+
/** Optional: Destroy/cleanup the chat widget */
|
|
97
|
+
destroy?: () => void;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Extend the Window interface to include BridgeChat
|
|
101
|
+
*/
|
|
102
|
+
declare global {
|
|
103
|
+
interface Window {
|
|
104
|
+
BridgeChat?: BridgeChatGlobal;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
export {};
|
|
108
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bridge-ai-dev/ecom-chat",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Bridge E-commerce Chat widget integration for Next.js with Litium authentication",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.mjs",
|
|
11
|
+
"require": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"bin": {
|
|
16
|
+
"create-ecom-chat": "./bin/cli.js"
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc && tsc -p tsconfig.esm.json",
|
|
20
|
+
"prepublishOnly": "npm run build"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"bridge-chat",
|
|
24
|
+
"litium",
|
|
25
|
+
"nextjs",
|
|
26
|
+
"react",
|
|
27
|
+
"authentication",
|
|
28
|
+
"chat-widget"
|
|
29
|
+
],
|
|
30
|
+
"author": "Bridge Delivery",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"react": ">=17.0.0"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@types/node": "^20.0.0",
|
|
37
|
+
"@types/react": "^18.0.0",
|
|
38
|
+
"typescript": "^5.0.0"
|
|
39
|
+
},
|
|
40
|
+
"files": [
|
|
41
|
+
"dist",
|
|
42
|
+
"bin",
|
|
43
|
+
"templates"
|
|
44
|
+
],
|
|
45
|
+
"repository": {
|
|
46
|
+
"type": "git",
|
|
47
|
+
"url": "https://github.com/bridge-ai/ecom-chat.git"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from "next/server";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Bridge Auth API Route
|
|
5
|
+
*
|
|
6
|
+
* This route acts as a secure bridge to retrieve HttpOnly cookies
|
|
7
|
+
* that cannot be accessed from client-side JavaScript.
|
|
8
|
+
*
|
|
9
|
+
* The ChatComponent uses this route to get authentication context
|
|
10
|
+
* before initializing the chat widget.
|
|
11
|
+
*/
|
|
12
|
+
export const GET = async (request: NextRequest) => {
|
|
13
|
+
const cookies = request.cookies;
|
|
14
|
+
|
|
15
|
+
// Retrieve the secure cookies
|
|
16
|
+
const cartContext = cookies.get("cart-context")?.value;
|
|
17
|
+
const identity = cookies.get(".AspNetCore.Identity.Application")?.value;
|
|
18
|
+
|
|
19
|
+
return NextResponse.json({
|
|
20
|
+
cart_context: cartContext || null,
|
|
21
|
+
identity: identity || null,
|
|
22
|
+
// Optional: Include the raw cookie string if your backend needs it
|
|
23
|
+
raw: request.headers.get("cookie")
|
|
24
|
+
});
|
|
25
|
+
};
|