@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.
- package/CHANGELOG.md +38 -0
- package/LICENSE +21 -0
- package/README.md +319 -0
- package/bin/openwa.js +11 -0
- package/favicon.ico +0 -0
- package/logo-long.png +0 -0
- package/logo-square.png +0 -0
- package/package.json +69 -0
- package/prisma/schema.prisma +182 -0
- package/server/config.js +29 -0
- package/server/database/client.js +11 -0
- package/server/database/init.js +28 -0
- package/server/express/create-app.js +349 -0
- package/server/express/openapi.js +853 -0
- package/server/index.js +163 -0
- package/server/services/api-key-service.js +131 -0
- package/server/services/auth-service.js +162 -0
- package/server/services/chat-service.js +1014 -0
- package/server/services/session-service.js +81 -0
- package/server/socket/register.js +127 -0
- package/server/utils/avatar.js +34 -0
- package/server/utils/paths.js +29 -0
- package/server/whatsapp/adapters/mock-adapter.js +47 -0
- package/server/whatsapp/adapters/wwebjs-adapter.js +263 -0
- package/server/whatsapp/session-manager.js +356 -0
- package/web/components/AppHead.js +14 -0
- package/web/components/AuthCard.js +170 -0
- package/web/components/BrandLogo.js +11 -0
- package/web/components/ChatWindow.js +875 -0
- package/web/components/ChatWindow.js.tmp +0 -0
- package/web/components/ContactList.js +97 -0
- package/web/components/ContactsPanel.js +90 -0
- package/web/components/EmojiPicker.js +108 -0
- package/web/components/MediaPreviewModal.js +146 -0
- package/web/components/MessageActionMenu.js +155 -0
- package/web/components/SessionSidebar.js +167 -0
- package/web/components/SettingsModal.js +266 -0
- package/web/components/Skeletons.js +73 -0
- package/web/jsconfig.json +10 -0
- package/web/lib/api.js +33 -0
- package/web/lib/socket.js +9 -0
- package/web/pages/_app.js +5 -0
- package/web/pages/dashboard.js +541 -0
- package/web/pages/index.js +62 -0
- package/web/postcss.config.js +10 -0
- package/web/public/favicon.ico +0 -0
- package/web/public/logo-long.png +0 -0
- package/web/public/logo-square.png +0 -0
- package/web/store/useAppStore.js +209 -0
- package/web/styles/globals.css +52 -0
- 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
package/favicon.ico
ADDED
|
Binary file
|
package/logo-long.png
ADDED
|
Binary file
|
package/logo-square.png
ADDED
|
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
|
+
}
|
package/server/config.js
ADDED
|
@@ -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 };
|