@crownpeak/dqm-react-component 1.1.0 → 1.2.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/CHANGELOG.md +16 -0
- package/README.md +52 -24
- package/dist/DQMSidebar.d.ts.map +1 -1
- package/dist/ErrorBoundary.d.ts.map +1 -1
- package/dist/__tests__/setup.d.ts +1 -0
- package/dist/__tests__/setup.d.ts.map +1 -0
- package/dist/__tests__/utils.d.ts +145 -0
- package/dist/__tests__/utils.d.ts.map +1 -0
- package/dist/auth-ui/assets/index-YKFZYENy.js +158 -0
- package/dist/auth-ui/index.html +1 -1
- package/dist/components/auth/DQMLogin.d.ts.map +1 -1
- package/dist/components/auth/index.d.ts +0 -1
- package/dist/components/auth/index.d.ts.map +1 -1
- package/dist/components/cards/AISummaryCard.d.ts +2 -0
- package/dist/components/cards/AISummaryCard.d.ts.map +1 -0
- package/dist/components/cards/index.d.ts +1 -0
- package/dist/components/cards/index.d.ts.map +1 -1
- package/dist/components/common/LanguageSwitch.d.ts +5 -0
- package/dist/components/common/LanguageSwitch.d.ts.map +1 -0
- package/dist/components/common/LanguageSwitchBase.d.ts +16 -0
- package/dist/components/common/LanguageSwitchBase.d.ts.map +1 -0
- package/dist/components/common/index.d.ts +1 -0
- package/dist/components/common/index.d.ts.map +1 -1
- package/dist/components/modals/AISettingsDialog.d.ts +61 -0
- package/dist/components/modals/AISettingsDialog.d.ts.map +1 -0
- package/dist/components/modals/HighlightModal.d.ts +45 -0
- package/dist/components/modals/HighlightModal.d.ts.map +1 -0
- package/dist/components/modals/LoginOverlay.d.ts +22 -0
- package/dist/components/modals/LoginOverlay.d.ts.map +1 -0
- package/dist/components/modals/index.d.ts +9 -0
- package/dist/components/modals/index.d.ts.map +1 -0
- package/dist/components/renderers/BrowserViewRenderer.d.ts.map +1 -1
- package/dist/components/renderers/ShadowDOMRenderer.d.ts.map +1 -1
- package/dist/components/sidebar/index.d.ts +1 -0
- package/dist/components/sidebar/index.d.ts.map +1 -1
- package/dist/context/ai/AIContext.d.ts +13 -0
- package/dist/context/ai/AIContext.d.ts.map +1 -0
- package/dist/context/ai/index.d.ts +12 -0
- package/dist/context/ai/index.d.ts.map +1 -0
- package/dist/context/ai/types.d.ts +161 -0
- package/dist/context/ai/types.d.ts.map +1 -0
- package/dist/context/ai/useAIEngine.d.ts +10 -0
- package/dist/context/ai/useAIEngine.d.ts.map +1 -0
- package/dist/context/ai/useAISummary.d.ts +10 -0
- package/dist/context/ai/useAISummary.d.ts.map +1 -0
- package/dist/context/ai/useAITranslation.d.ts +10 -0
- package/dist/context/ai/useAITranslation.d.ts.map +1 -0
- package/dist/context/ai/useTranslationCache.d.ts +9 -0
- package/dist/context/ai/useTranslationCache.d.ts.map +1 -0
- package/dist/dqm-widget.esm.js +394 -264
- package/dist/dqm-widget.iife.js +76 -25
- package/dist/hooks/index.d.ts +10 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/useAnalysis.d.ts +43 -0
- package/dist/hooks/useAnalysis.d.ts.map +1 -0
- package/dist/hooks/useAuthentication.d.ts +49 -0
- package/dist/hooks/useAuthentication.d.ts.map +1 -0
- package/dist/hooks/useHighlightActions.d.ts +37 -0
- package/dist/hooks/useHighlightActions.d.ts.map +1 -0
- package/dist/hooks/useHighlights.d.ts +72 -0
- package/dist/hooks/useHighlights.d.ts.map +1 -0
- package/dist/html-pages/DQMWidget.d.ts.map +1 -1
- package/dist/html-pages/index.d.ts.map +1 -1
- package/dist/i18n/auth/de.d.ts +25 -0
- package/dist/i18n/auth/de.d.ts.map +1 -0
- package/dist/i18n/auth/en.d.ts +26 -0
- package/dist/i18n/auth/en.d.ts.map +1 -0
- package/dist/i18n/auth/es.d.ts +25 -0
- package/dist/i18n/auth/es.d.ts.map +1 -0
- package/dist/i18n/auth/index.d.ts +8 -0
- package/dist/i18n/auth/index.d.ts.map +1 -0
- package/dist/i18n/common/de.d.ts +18 -0
- package/dist/i18n/common/de.d.ts.map +1 -0
- package/dist/i18n/common/en.d.ts +19 -0
- package/dist/i18n/common/en.d.ts.map +1 -0
- package/dist/i18n/common/es.d.ts +18 -0
- package/dist/i18n/common/es.d.ts.map +1 -0
- package/dist/i18n/common/index.d.ts +8 -0
- package/dist/i18n/common/index.d.ts.map +1 -0
- package/dist/i18n/demo/de.d.ts +104 -0
- package/dist/i18n/demo/de.d.ts.map +1 -0
- package/dist/i18n/demo/en.d.ts +105 -0
- package/dist/i18n/demo/en.d.ts.map +1 -0
- package/dist/i18n/demo/es.d.ts +104 -0
- package/dist/i18n/demo/es.d.ts.map +1 -0
- package/dist/i18n/demo/index.d.ts +8 -0
- package/dist/i18n/demo/index.d.ts.map +1 -0
- package/dist/i18n/index.d.ts +673 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/sidebar/de.d.ts +89 -0
- package/dist/i18n/sidebar/de.d.ts.map +1 -0
- package/dist/i18n/sidebar/en.d.ts +90 -0
- package/dist/i18n/sidebar/en.d.ts.map +1 -0
- package/dist/i18n/sidebar/es.d.ts +89 -0
- package/dist/i18n/sidebar/es.d.ts.map +1 -0
- package/dist/i18n/sidebar/index.d.ts +8 -0
- package/dist/i18n/sidebar/index.d.ts.map +1 -0
- package/dist/i18n.d.ts +8 -0
- package/dist/i18n.d.ts.map +1 -0
- package/dist/index.cjs +61 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.html +3 -3
- package/dist/index.js +17795 -7252
- package/dist/index.js.map +1 -1
- package/dist/locale.d.ts +25 -0
- package/dist/locale.d.ts.map +1 -0
- package/dist/mocks/browser.d.ts +23 -0
- package/dist/mocks/browser.d.ts.map +1 -0
- package/dist/mocks/handlers.d.ts +32 -0
- package/dist/mocks/handlers.d.ts.map +1 -0
- package/dist/mocks/index.d.ts +7 -0
- package/dist/mocks/index.d.ts.map +1 -0
- package/dist/mocks/server.d.ts +24 -0
- package/dist/mocks/server.d.ts.map +1 -0
- package/dist/server/routes/auth.js +0 -10
- package/dist/server/routes/auth.js.map +1 -1
- package/dist/store/api/dqmApi.d.ts +1793 -0
- package/dist/store/api/dqmApi.d.ts.map +1 -0
- package/dist/store/api/index.d.ts +6 -0
- package/dist/store/api/index.d.ts.map +1 -0
- package/dist/store/index.d.ts +57 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/localeSlice.d.ts +6 -0
- package/dist/store/localeSlice.d.ts.map +1 -0
- package/dist/store/slices/aiSlice.d.ts +134 -0
- package/dist/store/slices/aiSlice.d.ts.map +1 -0
- package/dist/store/slices/analysisSlice.d.ts +54 -0
- package/dist/store/slices/analysisSlice.d.ts.map +1 -0
- package/dist/store/slices/authSlice.d.ts +170 -0
- package/dist/store/slices/authSlice.d.ts.map +1 -0
- package/dist/store/slices/highlightSlice.d.ts +188 -0
- package/dist/store/slices/highlightSlice.d.ts.map +1 -0
- package/dist/store/slices/index.d.ts +12 -0
- package/dist/store/slices/index.d.ts.map +1 -0
- package/dist/types.d.ts +27 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/aiJsonClient.d.ts +23 -0
- package/dist/utils/aiJsonClient.d.ts.map +1 -0
- package/dist/utils/colors/GenerateCategoryColors.d.ts.map +1 -1
- package/dist/utils/logger.d.ts +107 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/openaiJsonClient.d.ts +8 -0
- package/dist/utils/openaiJsonClient.d.ts.map +1 -0
- package/dist/utils/sanitizeHtmlDocument.d.ts +4 -0
- package/dist/utils/sanitizeHtmlDocument.d.ts.map +1 -0
- package/dist/utils/secureStorage.d.ts +95 -0
- package/dist/utils/secureStorage.d.ts.map +1 -0
- package/dist/utils/storage.d.ts.map +1 -1
- package/dist/utils/translationCache.d.ts +45 -0
- package/dist/utils/translationCache.d.ts.map +1 -0
- package/dist/utils/translationUtils.d.ts +52 -0
- package/dist/utils/translationUtils.d.ts.map +1 -0
- package/package.json +48 -10
- package/AUTHENTICATION.md +0 -281
- package/BACKEND-API.md +0 -1829
- package/DEVELOPMENT.md +0 -374
- package/EXAMPLES.md +0 -381
- package/QUICKSTART.md +0 -207
- package/dist/auth-ui/assets/index-CczTRrba.js +0 -158
- package/dist/components/auth/OAuth2CallbackHandler.d.ts +0 -15
- package/dist/components/auth/OAuth2CallbackHandler.d.ts.map +0 -1
package/DEVELOPMENT.md
DELETED
|
@@ -1,374 +0,0 @@
|
|
|
1
|
-
# Development Guide
|
|
2
|
-
|
|
3
|
-
## Running the Complete Stack
|
|
4
|
-
|
|
5
|
-
### Start Development (Frontend + Backend)
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm run dev
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
This runs both servers concurrently:
|
|
12
|
-
- **Frontend (Vite)**: http://localhost:5173
|
|
13
|
-
- **Backend (Express)**: http://localhost:3001
|
|
14
|
-
|
|
15
|
-
### Start Individual Servers
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
# Frontend only
|
|
19
|
-
npm run dev:client
|
|
20
|
-
|
|
21
|
-
# Backend only
|
|
22
|
-
npm run dev:server
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
## Project Structure
|
|
26
|
-
|
|
27
|
-
```
|
|
28
|
-
crownpeak-dqm-react-component/
|
|
29
|
-
├── src/ # React component source
|
|
30
|
-
│ ├── components/
|
|
31
|
-
│ │ ├── auth/ # Authentication components
|
|
32
|
-
│ │ ├── sidebar/ # Sidebar UI components
|
|
33
|
-
│ │ ├── cards/ # Analysis result cards
|
|
34
|
-
│ │ ├── renderers/ # HTML rendering
|
|
35
|
-
│ │ └── common/ # Shared components
|
|
36
|
-
│ ├── utils/ # Utilities
|
|
37
|
-
│ ├── types.ts # TypeScript types
|
|
38
|
-
│ ├── DQMSidebar.tsx # Main component
|
|
39
|
-
│ ├── index.ts # Library entry point
|
|
40
|
-
│ ├── App.tsx # Dev test harness
|
|
41
|
-
│ └── main.tsx # Dev app entry
|
|
42
|
-
│ ├── html-pages/ # Widget entrypoint, loaders, declarations
|
|
43
|
-
│
|
|
44
|
-
├── server/ # Backend API
|
|
45
|
-
│ ├── routes/ # API endpoints
|
|
46
|
-
│ │ ├── auth.ts # Authentication
|
|
47
|
-
│ │ └── dqm.ts # DQM proxy
|
|
48
|
-
│ ├── services/ # Business logic
|
|
49
|
-
│ │ ├── sessionStore.ts # Session management
|
|
50
|
-
│ │ └── dqmClient.ts # DQM API client
|
|
51
|
-
│ ├── middleware/ # Express middleware
|
|
52
|
-
│ ├── config.ts # Configuration
|
|
53
|
-
│ ├── types.ts # TypeScript types
|
|
54
|
-
│ └── index.ts # Express app
|
|
55
|
-
│
|
|
56
|
-
├── dist/ # Build output
|
|
57
|
-
│ ├── index.js # Library ESM
|
|
58
|
-
│ ├── index.cjs # Library CommonJS
|
|
59
|
-
│ ├── index.d.ts # Library type declarations
|
|
60
|
-
│ ├── dqm-widget.esm.js # Widget bundle (ESM)
|
|
61
|
-
│ ├── dqm-widget.iife.js # Widget bundle (IIFE)
|
|
62
|
-
│ └── dqm-widget.d.ts # Widget type declarations
|
|
63
|
-
│ └── server/ # Compiled server code
|
|
64
|
-
│
|
|
65
|
-
├── test/ # Demo pages for widget bundles
|
|
66
|
-
├── public/ # Landing page for demos
|
|
67
|
-
├── vite.config.ts # Vite configuration
|
|
68
|
-
├── tsconfig.json # TypeScript base config
|
|
69
|
-
├── tsconfig.lib.json # Library build config
|
|
70
|
-
├── tsconfig.server.json # Server build config
|
|
71
|
-
└── package.json # Dependencies & scripts
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
## Authentication Modes
|
|
75
|
-
|
|
76
|
-
The component supports two modes:
|
|
77
|
-
|
|
78
|
-
### 1. Backend Mode (Recommended for Production)
|
|
79
|
-
|
|
80
|
-
```tsx
|
|
81
|
-
<DQMSidebar
|
|
82
|
-
config={{
|
|
83
|
-
authBackendUrl: 'http://localhost:3001',
|
|
84
|
-
useLocalStorage: true,
|
|
85
|
-
}}
|
|
86
|
-
/>
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
- All API calls proxied through backend
|
|
90
|
-
- Session token stored in localStorage
|
|
91
|
-
- Real credentials never exposed to client
|
|
92
|
-
|
|
93
|
-
### 2. Direct Mode (Development/Staging)
|
|
94
|
-
|
|
95
|
-
```tsx
|
|
96
|
-
<DQMSidebar
|
|
97
|
-
config={{
|
|
98
|
-
apiKey: 'YOUR_API_KEY',
|
|
99
|
-
websiteId: 'YOUR_WEBSITE_ID',
|
|
100
|
-
}}
|
|
101
|
-
/>
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
- Direct communication with Crownpeak DQM API
|
|
105
|
-
- Credentials in props or localStorage
|
|
106
|
-
- No backend required
|
|
107
|
-
|
|
108
|
-
## Testing Both Modes
|
|
109
|
-
|
|
110
|
-
### Test Backend Mode
|
|
111
|
-
|
|
112
|
-
1. Start both servers: `npm run dev`
|
|
113
|
-
2. Open http://localhost:5173
|
|
114
|
-
3. Click "Login" and enter credentials
|
|
115
|
-
4. Backend validates and issues session token
|
|
116
|
-
5. All API calls go through http://localhost:3001
|
|
117
|
-
|
|
118
|
-
### Test Direct Mode
|
|
119
|
-
|
|
120
|
-
1. Update `src/App.tsx`:
|
|
121
|
-
```tsx
|
|
122
|
-
<DQMSidebar
|
|
123
|
-
config={{
|
|
124
|
-
apiKey: 'YOUR_API_KEY',
|
|
125
|
-
websiteId: 'YOUR_WEBSITE_ID',
|
|
126
|
-
}}
|
|
127
|
-
/>
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
2. Start frontend only: `npm run dev:client`
|
|
131
|
-
3. No backend needed, direct API calls
|
|
132
|
-
|
|
133
|
-
## Building for Production
|
|
134
|
-
|
|
135
|
-
### Build Library
|
|
136
|
-
|
|
137
|
-
```bash
|
|
138
|
-
npm run build:lib
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
Output: `dist/index.{js,cjs,d.ts}`
|
|
142
|
-
|
|
143
|
-
### Build Widget Bundle
|
|
144
|
-
|
|
145
|
-
```bash
|
|
146
|
-
npm run build:widget
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
Output: `dist/dqm-widget.{esm.js,iife.js,d.ts}` (fully bundled, Shadow DOM-safe)
|
|
150
|
-
|
|
151
|
-
### Build Server
|
|
152
|
-
|
|
153
|
-
```bash
|
|
154
|
-
npm run build:server
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
Output: `dist/server/`
|
|
158
|
-
|
|
159
|
-
### Build Everything
|
|
160
|
-
|
|
161
|
-
```bash
|
|
162
|
-
npm run build
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
Runs library + widget + backend + auth UI builds.
|
|
166
|
-
|
|
167
|
-
### Test Library Build
|
|
168
|
-
|
|
169
|
-
```bash
|
|
170
|
-
npm pack
|
|
171
|
-
# Creates: crownpeak-dqm-react-component-1.0.0.tgz
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
### Preview Widget Bundle Locally
|
|
175
|
-
|
|
176
|
-
```bash
|
|
177
|
-
npm run build:widget
|
|
178
|
-
npm run serve:widget
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
Serves `dist/` plus demo pages via `serve.json` rewrites:
|
|
182
|
-
- `/test/demo-iife.html` for IIFE bundle
|
|
183
|
-
- `/test/demo-esm.html` for ESM bundle
|
|
184
|
-
- `/test/demo-dynamic.html` for lazy loading
|
|
185
|
-
- `/test/widget-standalone.html` for full standalone demo
|
|
186
|
-
|
|
187
|
-
## Environment Configuration
|
|
188
|
-
|
|
189
|
-
### Frontend (.env)
|
|
190
|
-
|
|
191
|
-
```env
|
|
192
|
-
VITE_BACKEND_URL=http://localhost:3001
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
### Backend (.env)
|
|
196
|
-
|
|
197
|
-
```env
|
|
198
|
-
PORT=3001
|
|
199
|
-
CORS_ORIGINS=http://localhost:5173,http://localhost:3000
|
|
200
|
-
DQM_API_BASE_URL=https://api.crownpeak.net/dqm-cms/v1
|
|
201
|
-
JWT_SECRET=your-secret-key
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
## API Testing with cURL
|
|
205
|
-
|
|
206
|
-
### Login
|
|
207
|
-
|
|
208
|
-
```bash
|
|
209
|
-
curl -X POST http://localhost:3001/auth/login \
|
|
210
|
-
-H "Content-Type: application/json" \
|
|
211
|
-
-d '{
|
|
212
|
-
"apiKey": "YOUR_API_KEY",
|
|
213
|
-
"websiteId": "YOUR_WEBSITE_ID"
|
|
214
|
-
}'
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
Response:
|
|
218
|
-
```json
|
|
219
|
-
{
|
|
220
|
-
"sessionToken": "abc123...",
|
|
221
|
-
"websiteId": "YOUR_WEBSITE_ID"
|
|
222
|
-
}
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
### Start Analysis
|
|
226
|
-
|
|
227
|
-
```bash
|
|
228
|
-
curl -X POST http://localhost:3001/dqm/assets \
|
|
229
|
-
-H "Authorization: Bearer YOUR_SESSION_TOKEN" \
|
|
230
|
-
-H "Content-Type: application/json" \
|
|
231
|
-
-d '{
|
|
232
|
-
"html": "<html><body><h1>Test</h1></body></html>",
|
|
233
|
-
"url": "https://example.com"
|
|
234
|
-
}'
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
### Get Results
|
|
238
|
-
|
|
239
|
-
```bash
|
|
240
|
-
curl -X GET http://localhost:3001/dqm/assets/ASSET_ID \
|
|
241
|
-
-H "Authorization: Bearer YOUR_SESSION_TOKEN"
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
## Debugging
|
|
245
|
-
|
|
246
|
-
### Enable Verbose Logging
|
|
247
|
-
|
|
248
|
-
Backend logs all requests automatically. Check terminal output:
|
|
249
|
-
|
|
250
|
-
```
|
|
251
|
-
[2025-10-31T10:00:00.000Z] POST /auth/login
|
|
252
|
-
[Auth] User logged in successfully (websiteId: test_id)
|
|
253
|
-
[SessionStore] Created session: abc12345... (expires in 1440 minutes)
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
### Check Session Status
|
|
257
|
-
|
|
258
|
-
```bash
|
|
259
|
-
curl -X GET http://localhost:3001/auth/session \
|
|
260
|
-
-H "Authorization: Bearer YOUR_SESSION_TOKEN"
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
### View Active Sessions (Dev Only)
|
|
264
|
-
|
|
265
|
-
Add to `server/routes/auth.ts`:
|
|
266
|
-
|
|
267
|
-
```typescript
|
|
268
|
-
authRouter.get('/sessions/count', (req, res) => {
|
|
269
|
-
res.json({ count: sessionStore.count() });
|
|
270
|
-
});
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
## Common Issues
|
|
274
|
-
|
|
275
|
-
### CORS Errors
|
|
276
|
-
|
|
277
|
-
**Problem:** Frontend can't reach backend
|
|
278
|
-
|
|
279
|
-
**Solution:** Add frontend URL to `CORS_ORIGINS` in `.env`:
|
|
280
|
-
```env
|
|
281
|
-
CORS_ORIGINS=http://localhost:5173,http://localhost:3000
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
### Port Already in Use
|
|
285
|
-
|
|
286
|
-
**Problem:** `Error: listen EADDRINUSE: address already in use :::3001`
|
|
287
|
-
|
|
288
|
-
**Solution:** Kill process or change port:
|
|
289
|
-
```bash
|
|
290
|
-
lsof -ti:3001 | xargs kill -9
|
|
291
|
-
# or change PORT in .env
|
|
292
|
-
```
|
|
293
|
-
|
|
294
|
-
### Session Expired
|
|
295
|
-
|
|
296
|
-
**Problem:** 401 Unauthorized after some time
|
|
297
|
-
|
|
298
|
-
**Solution:** Session TTL is 24 hours. Login again or extend TTL in `server/config.ts`:
|
|
299
|
-
```typescript
|
|
300
|
-
session: {
|
|
301
|
-
ttl: 48 * 60 * 60 * 1000, // 48 hours
|
|
302
|
-
}
|
|
303
|
-
```
|
|
304
|
-
|
|
305
|
-
### TypeScript Errors
|
|
306
|
-
|
|
307
|
-
**Problem:** Type errors in server code
|
|
308
|
-
|
|
309
|
-
**Solution:** Ensure @types packages installed:
|
|
310
|
-
```bash
|
|
311
|
-
npm install --save-dev @types/express @types/cors @types/node
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
## Production Deployment
|
|
315
|
-
|
|
316
|
-
### Deploy Backend
|
|
317
|
-
|
|
318
|
-
1. Build server: `npm run build:server`
|
|
319
|
-
2. Copy `dist/server/` to production
|
|
320
|
-
3. Set environment variables
|
|
321
|
-
4. Install production dependencies only
|
|
322
|
-
5. Start: `node dist/server/index.js`
|
|
323
|
-
|
|
324
|
-
### Use Redis for Sessions
|
|
325
|
-
|
|
326
|
-
Replace `server/services/sessionStore.ts` with Redis:
|
|
327
|
-
|
|
328
|
-
```typescript
|
|
329
|
-
import { createClient } from 'redis';
|
|
330
|
-
|
|
331
|
-
const redis = createClient({
|
|
332
|
-
url: process.env.REDIS_URL
|
|
333
|
-
});
|
|
334
|
-
|
|
335
|
-
await redis.connect();
|
|
336
|
-
|
|
337
|
-
export const sessionStore = {
|
|
338
|
-
create: async (apiKey, websiteId) => {
|
|
339
|
-
const token = generateToken();
|
|
340
|
-
await redis.setEx(`session:${token}`, 86400, JSON.stringify({
|
|
341
|
-
apiKey, websiteId, createdAt: Date.now()
|
|
342
|
-
}));
|
|
343
|
-
return token;
|
|
344
|
-
},
|
|
345
|
-
get: async (token) => {
|
|
346
|
-
const data = await redis.get(`session:${token}`);
|
|
347
|
-
return data ? JSON.parse(data) : null;
|
|
348
|
-
},
|
|
349
|
-
delete: async (token) => {
|
|
350
|
-
await redis.del(`session:${token}`);
|
|
351
|
-
}
|
|
352
|
-
};
|
|
353
|
-
```
|
|
354
|
-
|
|
355
|
-
### Add Rate Limiting
|
|
356
|
-
|
|
357
|
-
```bash
|
|
358
|
-
npm install express-rate-limit
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
```typescript
|
|
362
|
-
import rateLimit from 'express-rate-limit';
|
|
363
|
-
|
|
364
|
-
const limiter = rateLimit({
|
|
365
|
-
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
366
|
-
max: 100 // limit each IP to 100 requests per windowMs
|
|
367
|
-
});
|
|
368
|
-
|
|
369
|
-
app.use('/auth/login', limiter);
|
|
370
|
-
```
|
|
371
|
-
|
|
372
|
-
## License
|
|
373
|
-
|
|
374
|
-
MIT
|