@adens/openwa 0.1.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.
Files changed (51) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/LICENSE +21 -0
  3. package/README.md +319 -0
  4. package/bin/openwa.js +11 -0
  5. package/favicon.ico +0 -0
  6. package/logo-long.png +0 -0
  7. package/logo-square.png +0 -0
  8. package/package.json +69 -0
  9. package/prisma/schema.prisma +182 -0
  10. package/server/config.js +29 -0
  11. package/server/database/client.js +11 -0
  12. package/server/database/init.js +28 -0
  13. package/server/express/create-app.js +349 -0
  14. package/server/express/openapi.js +853 -0
  15. package/server/index.js +163 -0
  16. package/server/services/api-key-service.js +131 -0
  17. package/server/services/auth-service.js +162 -0
  18. package/server/services/chat-service.js +1014 -0
  19. package/server/services/session-service.js +81 -0
  20. package/server/socket/register.js +127 -0
  21. package/server/utils/avatar.js +34 -0
  22. package/server/utils/paths.js +29 -0
  23. package/server/whatsapp/adapters/mock-adapter.js +47 -0
  24. package/server/whatsapp/adapters/wwebjs-adapter.js +263 -0
  25. package/server/whatsapp/session-manager.js +356 -0
  26. package/web/components/AppHead.js +14 -0
  27. package/web/components/AuthCard.js +170 -0
  28. package/web/components/BrandLogo.js +11 -0
  29. package/web/components/ChatWindow.js +875 -0
  30. package/web/components/ChatWindow.js.tmp +0 -0
  31. package/web/components/ContactList.js +97 -0
  32. package/web/components/ContactsPanel.js +90 -0
  33. package/web/components/EmojiPicker.js +108 -0
  34. package/web/components/MediaPreviewModal.js +146 -0
  35. package/web/components/MessageActionMenu.js +155 -0
  36. package/web/components/SessionSidebar.js +167 -0
  37. package/web/components/SettingsModal.js +266 -0
  38. package/web/components/Skeletons.js +73 -0
  39. package/web/jsconfig.json +10 -0
  40. package/web/lib/api.js +33 -0
  41. package/web/lib/socket.js +9 -0
  42. package/web/pages/_app.js +5 -0
  43. package/web/pages/dashboard.js +541 -0
  44. package/web/pages/index.js +62 -0
  45. package/web/postcss.config.js +10 -0
  46. package/web/public/favicon.ico +0 -0
  47. package/web/public/logo-long.png +0 -0
  48. package/web/public/logo-square.png +0 -0
  49. package/web/store/useAppStore.js +209 -0
  50. package/web/styles/globals.css +52 -0
  51. package/web/tailwind.config.js +36 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,38 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.0] - 2026-03-27
9
+
10
+ ### Added
11
+ - Initial release of OpenWA CLI package
12
+ - Self-hosted OpenWA dashboard running locally
13
+ - WhatsApp integration via whatsapp-web.js
14
+ - CLI command entry point (`openwa` command)
15
+ - Express.js backend server with Socket.IO real-time communication
16
+ - Next.js frontend dashboard with React UI
17
+ - Prisma ORM for database management
18
+ - User authentication with JWT and bcrypt password hashing
19
+ - QR code generation for WhatsApp authentication
20
+ - File upload support with Multer
21
+ - Tailwind CSS styling for responsive design
22
+ - Zustand state management
23
+ - MIT License
24
+
25
+ ### Features
26
+ - Local CLI-based dashboard deployment
27
+ - Real-time WhatsApp message handling
28
+ - Database schema management with Prisma
29
+ - Development and production modes
30
+ - Node.js 20+ compatibility
31
+
32
+ ### Documentation
33
+ - Comprehensive README with setup instructions
34
+ - API documentation and examples
35
+ - Contributing guidelines
36
+ - MIT license file
37
+
38
+ [0.1.0]: https://github.com/asepindrak/openwa/releases/tag/v0.1.0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 asepindrak
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,319 @@
1
+ <p align="center">
2
+ <img src="./logo-long.png" alt="OpenWA" width="320" />
3
+ </p>
4
+
5
+ # OpenWA
6
+
7
+ OpenWA is a self-hosted WhatsApp workspace that ships as a CLI package. It combines a Next.js dashboard, an Express API, Prisma-backed data access, Socket.IO realtime updates, media uploads, and runtime API documentation in a single local-first package.
8
+
9
+ OpenWA is also designed to be **AI-agent-ready**. The runtime exposes agent-friendly documentation, machine-readable OpenAPI output, and API key authentication so AI agents and automation tools can discover capabilities and interact with the workspace without reverse-engineering the app.
10
+
11
+ ## Disclaimer
12
+
13
+ OpenWA is an independent open source project. It is **not** an official WhatsApp product and is **not** affiliated with, endorsed by, or sponsored by Meta or WhatsApp.
14
+
15
+ If you use OpenWA with WhatsApp, make sure your usage complies with the terms, policies, and legal requirements that apply in your environment.
16
+
17
+ ## Features
18
+
19
+ - Dashboard authentication for register, login, and workspace access.
20
+ - Workspace bootstrap endpoint for loading the current user, sessions, chats, active chat, and initial messages.
21
+ - Multi-session WhatsApp management with session creation, connect, disconnect, and QR pairing.
22
+ - Contact and chat browsing with search and chat opening from contacts.
23
+ - Message APIs for listing, searching, sending, forwarding, and deleting messages.
24
+ - Multipart media upload flow with `mediaFileId` support for outbound media messages.
25
+ - Runtime docs endpoints for Swagger UI, OpenAPI JSON, agent README, health checks, and version metadata.
26
+ - Dual authentication model:
27
+ - JWT bearer auth for dashboard users.
28
+ - API key auth for agents and external integrations.
29
+
30
+ ## Tech stack
31
+
32
+ - Node.js 20+
33
+ - Next.js 15
34
+ - React 19
35
+ - Express
36
+ - Prisma
37
+ - Socket.IO
38
+ - `whatsapp-web.js`
39
+
40
+ ## Acknowledgements
41
+
42
+ Special thanks to [`whatsapp-web.js`](https://wwebjs.dev/). OpenWA builds on top of that excellent open source project for WhatsApp Web integration.
43
+
44
+ If you find this project useful, please also support and star the `whatsapp-web.js` project.
45
+
46
+ ## Getting started
47
+
48
+ Install OpenWA globally:
49
+
50
+ ```bash
51
+ npm i -g @adens/openwa
52
+ ```
53
+
54
+ Run OpenWA:
55
+
56
+ ```bash
57
+ openwa
58
+ ```
59
+
60
+ When OpenWA starts, it launches the local frontend and backend runtime and automatically opens your browser to the OpenWA frontend dashboard by default.
61
+
62
+ If you are working on this repository locally instead of using the published CLI package:
63
+
64
+ ```bash
65
+ npm install
66
+ npm run build
67
+ npm start
68
+ ```
69
+
70
+ ## Default runtime
71
+
72
+ By default, OpenWA starts two local services:
73
+
74
+ - Frontend dashboard: `http://localhost:55111`
75
+ - Backend API: `http://localhost:55222`
76
+
77
+ Important runtime endpoints such as docs, health, and version are also proxied through the frontend URL for convenience.
78
+
79
+ ## Environment configuration
80
+
81
+ OpenWA reads `.env` from the repository root. These are the runtime variables currently used by the app:
82
+
83
+ ```env
84
+ HOST=127.0.0.1
85
+ FE_PORT=55111
86
+ BE_PORT=55222
87
+ OPENWA_FRONTEND_URL=http://localhost:55111
88
+ OPENWA_BACKEND_URL=http://localhost:55222
89
+ OPENWA_JWT_SECRET=openwa-local-dev-secret
90
+ OPENWA_AUTO_OPEN=true
91
+ OPENWA_USE_WWEBJS=true
92
+ OPENWA_ALLOW_MOCK=false
93
+ ```
94
+
95
+ Notes:
96
+
97
+ - Set `OPENWA_AUTO_OPEN=false` to disable automatic browser opening.
98
+ - Set `OPENWA_USE_WWEBJS=false` to disable the WhatsApp Web adapter.
99
+ - Set `OPENWA_ALLOW_MOCK=true` to allow the mock adapter when needed.
100
+
101
+ ## Typical usage flow
102
+
103
+ 1. Start OpenWA.
104
+ 2. Open the dashboard at `http://localhost:55111`.
105
+ 3. Register the first user or log in.
106
+ 4. Create a new WhatsApp session from the dashboard.
107
+ 5. Connect the session to generate a QR code.
108
+ 6. Pair the device and wait for the workspace to sync chats and contacts.
109
+ 7. Send text or media from the dashboard or the HTTP API.
110
+ 8. Create an API key from **Settings → API Access** for agents or external integrations.
111
+
112
+ ## Runtime documentation
113
+
114
+ OpenWA exposes runtime documentation directly from the app:
115
+
116
+ - Swagger UI: `GET /docs`
117
+ - OpenAPI JSON: `GET /docs/json`
118
+ - Agent guide markdown: `GET /docs/readme`
119
+ - Health check: `GET /health`
120
+ - Version: `GET /version`
121
+ - Backend health alias: `GET /api/health`
122
+
123
+ If you are building an agent or automation client, prefer the frontend URL as the base URL because the main runtime metadata endpoints are already proxied there.
124
+
125
+ This makes OpenWA a strong fit for AI agents: an agent can read `/docs/readme`, fetch `/docs/json`, authenticate with an API key, and immediately start working with chats, contacts, sessions, and messages through a documented API surface.
126
+
127
+ ## API summary
128
+
129
+ ### Auth
130
+
131
+ - `POST /api/auth/register`
132
+ - `POST /api/auth/login`
133
+ - `GET /api/auth/me`
134
+
135
+ These endpoints are intended for dashboard users. External agents that already have an API key normally do not need to use dashboard login flows.
136
+
137
+ ### API keys
138
+
139
+ - `GET /api/api-keys`
140
+ - `POST /api/api-keys`
141
+ - `DELETE /api/api-keys/{apiKeyId}`
142
+
143
+ API key management requires dashboard JWT authentication.
144
+
145
+ ### Workspace
146
+
147
+ - `GET /api/bootstrap`
148
+
149
+ Returns the initial workspace payload, including the current user, sessions, chats, active chat, initial message batch, and pagination metadata.
150
+
151
+ ### Sessions
152
+
153
+ - `GET /api/sessions`
154
+ - `POST /api/sessions`
155
+ - `POST /api/sessions/{sessionId}/connect`
156
+ - `POST /api/sessions/{sessionId}/disconnect`
157
+
158
+ ### Chats and contacts
159
+
160
+ - `GET /api/chats`
161
+ - `GET /api/contacts`
162
+ - `POST /api/contacts/{contactId}/open`
163
+
164
+ `/api/chats` and `/api/contacts` support `sessionId` and `q` query filters.
165
+
166
+ ### Messages
167
+
168
+ - `GET /api/chats/{chatId}/messages`
169
+ - `POST /api/chats/{chatId}/messages/send`
170
+ - `DELETE /api/messages/{messageId}`
171
+ - `POST /api/messages/{messageId}/forward`
172
+
173
+ `GET /api/chats/{chatId}/messages` supports:
174
+
175
+ - `take`
176
+ - `before`
177
+ - `search`
178
+
179
+ ### Media
180
+
181
+ - `POST /api/media`
182
+
183
+ Upload a file first, then use the returned `mediaFileId` when calling the send message endpoint.
184
+
185
+ ## API authentication
186
+
187
+ OpenWA supports two main authentication modes.
188
+
189
+ ### JWT bearer
190
+
191
+ ```http
192
+ Authorization: Bearer <jwt-token>
193
+ ```
194
+
195
+ Used by the dashboard after login or registration.
196
+
197
+ ### API key
198
+
199
+ ```http
200
+ X-API-Key: <api-key>
201
+ ```
202
+
203
+ or:
204
+
205
+ ```http
206
+ Authorization: Bearer <api-key>
207
+ ```
208
+
209
+ Recommended for agents, automation, and external integrations.
210
+
211
+ ## API examples
212
+
213
+ List chats:
214
+
215
+ ```bash
216
+ curl -H "X-API-Key: <api-key>" http://localhost:55111/api/chats
217
+ ```
218
+
219
+ Read messages for a chat:
220
+
221
+ ```bash
222
+ curl -H "X-API-Key: <api-key>" http://localhost:55111/api/chats/<chatId>/messages
223
+ ```
224
+
225
+ Send a text message:
226
+
227
+ ```bash
228
+ curl -X POST http://localhost:55111/api/chats/<chatId>/messages/send \
229
+ -H "Content-Type: application/json" \
230
+ -H "X-API-Key: <api-key>" \
231
+ -d "{\"body\":\"Hello from OpenWA\",\"type\":\"text\"}"
232
+ ```
233
+
234
+ Upload media:
235
+
236
+ ```bash
237
+ curl -X POST http://localhost:55111/api/media \
238
+ -H "X-API-Key: <api-key>" \
239
+ -F "file=@./example.png"
240
+ ```
241
+
242
+ ## Project structure
243
+
244
+ - `bin/` - CLI entrypoint
245
+ - `server/` - backend runtime, OpenAPI docs, auth, sessions, chats, media, and sockets
246
+ - `web/` - Next.js dashboard
247
+ - `prisma/` - database schema
248
+ - `storage/` - runtime storage and generated files
249
+
250
+ ## Development
251
+
252
+ For repository-based local development:
253
+
254
+ 1. Install dependencies with `npm install`.
255
+ 2. Configure `.env` if you need non-default ports or runtime behavior.
256
+ 3. Run `npm run dev` for development mode.
257
+ 4. Run `npm run build` before shipping production changes.
258
+
259
+ If you are working on API-facing features, validate them against:
260
+
261
+ - `server/express/openapi.js`
262
+ - `/docs`
263
+ - `/docs/json`
264
+ - `/docs/readme`
265
+
266
+ ## Contributing
267
+
268
+ Contributions are welcome.
269
+
270
+ If you want to contribute:
271
+
272
+ 1. Fork the repository.
273
+ 2. Create a feature branch.
274
+ 3. Make focused changes.
275
+ 4. Test your changes locally.
276
+ 5. Open a pull request with a clear description of what changed and why.
277
+
278
+ Good contribution areas include:
279
+
280
+ - WhatsApp session reliability
281
+ - Dashboard UX
282
+ - API ergonomics
283
+ - Documentation improvements
284
+ - Tests and validation
285
+ - Developer experience
286
+
287
+ ## Issues and bug reports
288
+
289
+ If you find a bug or want to request a feature, please open an issue with:
290
+
291
+ - what you expected
292
+ - what happened
293
+ - steps to reproduce
294
+ - logs or screenshots if relevant
295
+ - environment details such as Node.js version and runtime mode
296
+
297
+ ## Security and responsible use
298
+
299
+ Please do not use this project for spam, abuse, or policy-violating automation.
300
+
301
+ If you discover a security issue, report it responsibly and avoid posting sensitive details publicly before maintainers have a chance to assess it.
302
+
303
+ ## License
304
+
305
+ This project is released under the MIT license. See `package.json` for the current license declaration.
306
+
307
+ ## For agents and integrations
308
+
309
+ Recommended call order:
310
+
311
+ 1. `GET /health`
312
+ 2. `GET /version`
313
+ 3. `GET /docs/json`
314
+ 4. `GET /api/chats` or `GET /api/contacts`
315
+ 5. `POST /api/contacts/{contactId}/open`
316
+ 6. `GET /api/chats/{chatId}/messages`
317
+ 7. `POST /api/chats/{chatId}/messages/send`
318
+
319
+ If you need an agent-oriented markdown guide directly from the runtime, use `GET /docs/readme`.
package/bin/openwa.js ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { startOpenWA } = require("../server");
4
+
5
+ const dev = process.argv.includes("--dev");
6
+
7
+ startOpenWA({ dev }).catch((error) => {
8
+ console.error("Failed to start OpenWA.");
9
+ console.error(error);
10
+ process.exit(1);
11
+ });
package/favicon.ico ADDED
Binary file
package/logo-long.png ADDED
Binary file
Binary file
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "@adens/openwa",
3
+ "version": "0.1.0",
4
+ "description": "Self-hosted WhatsApp workspace with multi-session management, REST API, JWT & API key authentication, real-time messaging via Socket.IO, media upload, Swagger documentation, and AI-agent integration support.",
5
+ "license": "MIT",
6
+ "author": "asepindrak <asepindrakurniawan@gmail.com>",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/asepindrak/openwa.git"
10
+ },
11
+ "homepage": "https://github.com/asepindrak/openwa#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/asepindrak/openwa/issues"
14
+ },
15
+ "preferGlobal": true,
16
+ "keywords": [
17
+ "openwa",
18
+ "cli",
19
+ "whatsapp",
20
+ "express",
21
+ "nextjs",
22
+ "socket.io",
23
+ "prisma"
24
+ ],
25
+ "bin": {
26
+ "openwa": "bin/openwa.js"
27
+ },
28
+ "scripts": {
29
+ "dev": "node bin/openwa.js --dev",
30
+ "start": "node bin/openwa.js",
31
+ "build": "node ./node_modules/prisma/build/index.js generate --schema prisma/schema.prisma && npm run build:web",
32
+ "build:web": "node ./node_modules/next/dist/bin/next build web",
33
+ "prisma:generate": "node ./node_modules/prisma/build/index.js generate --schema prisma/schema.prisma",
34
+ "prisma:push": "node ./node_modules/prisma/build/index.js db push --schema prisma/schema.prisma",
35
+ "publish": "npm run build && npm publish --access=public",
36
+ "prepublishOnly": "npm run build"
37
+ },
38
+ "engines": {
39
+ "node": ">=20"
40
+ },
41
+ "dependencies": {
42
+ "@prisma/client": "^6.6.0",
43
+ "bcryptjs": "^2.4.3",
44
+ "cookie": "^1.0.2",
45
+ "dotenv": "^16.4.7",
46
+ "express": "^4.21.2",
47
+ "jsonwebtoken": "^9.0.2",
48
+ "multer": "^1.4.5-lts.2",
49
+ "next": "^15.2.4",
50
+ "open": "^10.1.0",
51
+ "prisma": "^6.6.0",
52
+ "qrcode": "^1.5.4",
53
+ "react": "^19.0.0",
54
+ "react-dom": "^19.0.0",
55
+ "react-icons": "^5.6.0",
56
+ "socket.io": "^4.8.1",
57
+ "socket.io-client": "^4.8.1",
58
+ "whatsapp-web.js": "^1.34.6",
59
+ "zustand": "^5.0.3"
60
+ },
61
+ "devDependencies": {
62
+ "autoprefixer": "^10.4.20",
63
+ "postcss": "^8.5.3",
64
+ "tailwindcss": "^3.4.17"
65
+ },
66
+ "publishConfig": {
67
+ "access": "public"
68
+ }
69
+ }
@@ -0,0 +1,182 @@
1
+ generator client {
2
+ provider = "prisma-client-js"
3
+ }
4
+
5
+ datasource db {
6
+ provider = "sqlite"
7
+ url = "file:../storage/database/openwa.db"
8
+ }
9
+
10
+ enum SessionState {
11
+ connecting
12
+ ready
13
+ disconnected
14
+ error
15
+ }
16
+
17
+ enum TransportType {
18
+ mock
19
+ wwebjs
20
+ }
21
+
22
+ enum MessageType {
23
+ text
24
+ image
25
+ video
26
+ audio
27
+ document
28
+ sticker
29
+ }
30
+
31
+ enum DeliveryStatus {
32
+ sent
33
+ delivered
34
+ read
35
+ }
36
+
37
+ enum MessageDirection {
38
+ inbound
39
+ outbound
40
+ }
41
+
42
+ model User {
43
+ id String @id @default(cuid())
44
+ name String
45
+ email String @unique
46
+ passwordHash String
47
+ createdAt DateTime @default(now())
48
+ updatedAt DateTime @updatedAt
49
+ contacts Contact[]
50
+ chats Chat[]
51
+ sessions WhatsappSession[]
52
+ mediaFiles MediaFile[]
53
+ apiKeys ApiKey[]
54
+
55
+ @@map("users")
56
+ }
57
+
58
+ model ApiKey {
59
+ id String @id @default(cuid())
60
+ userId String
61
+ name String
62
+ keyHash String @unique
63
+ keyPrefix String
64
+ last4 String
65
+ lastUsedAt DateTime?
66
+ createdAt DateTime @default(now())
67
+ updatedAt DateTime @updatedAt
68
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
69
+
70
+ @@index([userId, createdAt])
71
+ @@map("api_keys")
72
+ }
73
+
74
+ model WhatsappSession {
75
+ id String @id @default(cuid())
76
+ userId String
77
+ name String
78
+ phoneNumber String?
79
+ status SessionState @default(disconnected)
80
+ qrCode String?
81
+ transportType TransportType @default(mock)
82
+ lastError String?
83
+ createdAt DateTime @default(now())
84
+ updatedAt DateTime @updatedAt
85
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
86
+ chats Chat[]
87
+ messages Message[]
88
+ contacts Contact[]
89
+
90
+ @@index([userId])
91
+ @@map("whatsapp_sessions")
92
+ }
93
+
94
+ model Contact {
95
+ id String @id @default(cuid())
96
+ userId String
97
+ sessionId String?
98
+ externalId String
99
+ displayName String
100
+ avatarUrl String?
101
+ lastMessagePreview String?
102
+ lastMessageAt DateTime?
103
+ unreadCount Int @default(0)
104
+ createdAt DateTime @default(now())
105
+ updatedAt DateTime @updatedAt
106
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
107
+ session WhatsappSession? @relation(fields: [sessionId], references: [id], onDelete: SetNull)
108
+ chats Chat[]
109
+
110
+ @@unique([userId, externalId])
111
+ @@map("contacts")
112
+ }
113
+
114
+ model Chat {
115
+ id String @id @default(cuid())
116
+ userId String
117
+ sessionId String?
118
+ contactId String
119
+ title String
120
+ createdAt DateTime @default(now())
121
+ updatedAt DateTime @updatedAt
122
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
123
+ session WhatsappSession? @relation(fields: [sessionId], references: [id], onDelete: SetNull)
124
+ contact Contact @relation(fields: [contactId], references: [id], onDelete: Cascade)
125
+ messages Message[]
126
+
127
+ @@unique([userId, contactId])
128
+ @@index([userId, updatedAt])
129
+ @@map("chats")
130
+ }
131
+
132
+ model MediaFile {
133
+ id String @id @default(cuid())
134
+ userId String
135
+ fileName String
136
+ originalName String
137
+ mimeType String
138
+ size Int
139
+ relativePath String
140
+ createdAt DateTime @default(now())
141
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
142
+ messages Message[]
143
+
144
+ @@index([userId])
145
+ @@map("media_files")
146
+ }
147
+
148
+ model Message {
149
+ id String @id @default(cuid())
150
+ chatId String
151
+ sessionId String?
152
+ mediaFileId String?
153
+ replyToId String?
154
+ externalMessageId String?
155
+ sender String
156
+ receiver String
157
+ body String?
158
+ type MessageType @default(text)
159
+ direction MessageDirection
160
+ createdAt DateTime @default(now())
161
+ updatedAt DateTime @updatedAt
162
+ chat Chat @relation(fields: [chatId], references: [id], onDelete: Cascade)
163
+ session WhatsappSession? @relation(fields: [sessionId], references: [id], onDelete: SetNull)
164
+ mediaFile MediaFile? @relation(fields: [mediaFileId], references: [id], onDelete: SetNull)
165
+ replyTo Message? @relation("MessageReplies", fields: [replyToId], references: [id], onDelete: SetNull)
166
+ replies Message[] @relation("MessageReplies")
167
+ statuses MessageStatus[]
168
+
169
+ @@index([chatId, createdAt])
170
+ @@map("messages")
171
+ }
172
+
173
+ model MessageStatus {
174
+ id String @id @default(cuid())
175
+ messageId String
176
+ status DeliveryStatus
177
+ createdAt DateTime @default(now())
178
+ message Message @relation(fields: [messageId], references: [id], onDelete: Cascade)
179
+
180
+ @@index([messageId, createdAt])
181
+ @@map("message_status")
182
+ }
@@ -0,0 +1,29 @@
1
+ const path = require("path");
2
+ const dotenv = require("dotenv");
3
+ const { rootDir } = require("./utils/paths");
4
+
5
+ dotenv.config({ path: path.join(rootDir, ".env") });
6
+
7
+ function getConfig({ dev = false } = {}) {
8
+ const host = process.env.HOST || "127.0.0.1";
9
+ const frontendPort = Number(process.env.FE_PORT || process.env.FRONTEND_PORT || 55111);
10
+ const backendPort = Number(process.env.BE_PORT || process.env.BACKEND_PORT || 55222);
11
+ const frontendUrl = process.env.OPENWA_FRONTEND_URL || `http://localhost:${frontendPort}`;
12
+ const backendUrl = process.env.OPENWA_BACKEND_URL || `http://localhost:${backendPort}`;
13
+
14
+ return {
15
+ dev,
16
+ host,
17
+ frontendPort,
18
+ backendPort,
19
+ frontendUrl,
20
+ backendUrl,
21
+ appUrl: frontendUrl,
22
+ jwtSecret: process.env.OPENWA_JWT_SECRET || "openwa-local-dev-secret",
23
+ autoOpenBrowser: process.env.OPENWA_AUTO_OPEN !== "false",
24
+ useWwebjs: process.env.OPENWA_USE_WWEBJS !== "false",
25
+ allowMockAdapter: process.env.OPENWA_ALLOW_MOCK === "true"
26
+ };
27
+ }
28
+
29
+ module.exports = { getConfig };
@@ -0,0 +1,11 @@
1
+ const { PrismaClient } = require("@prisma/client");
2
+
3
+ const globalKey = "__openwa_prisma__";
4
+
5
+ if (!global[globalKey]) {
6
+ global[globalKey] = new PrismaClient();
7
+ }
8
+
9
+ module.exports = {
10
+ prisma: global[globalKey]
11
+ };