@kaikybrofc/omnizap-system 2.2.3 → 2.2.5

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 (55) hide show
  1. package/.env.example +13 -0
  2. package/README.md +29 -85
  3. package/app/controllers/messageController.js +133 -1
  4. package/app/modules/stickerPackModule/catalogHandlers/catalogAdminHttp.js +68 -0
  5. package/app/modules/stickerPackModule/catalogHandlers/catalogAuthHttp.js +34 -0
  6. package/app/modules/stickerPackModule/catalogHandlers/catalogPublicHttp.js +179 -0
  7. package/app/modules/stickerPackModule/catalogHandlers/catalogUploadHttp.js +92 -0
  8. package/app/modules/stickerPackModule/catalogRouter.js +79 -0
  9. package/app/modules/stickerPackModule/domainEventOutboxRepository.js +243 -0
  10. package/app/modules/stickerPackModule/domainEvents.js +61 -0
  11. package/app/modules/stickerPackModule/stickerAssetClassificationRepository.js +21 -0
  12. package/app/modules/stickerPackModule/stickerAssetRepository.js +19 -0
  13. package/app/modules/stickerPackModule/stickerClassificationBackgroundRuntime.js +55 -15
  14. package/app/modules/stickerPackModule/stickerDedicatedTaskWorkerRuntime.js +238 -0
  15. package/app/modules/stickerPackModule/stickerDomainEventBus.js +71 -0
  16. package/app/modules/stickerPackModule/stickerDomainEventConsumerRuntime.js +198 -0
  17. package/app/modules/stickerPackModule/stickerObjectStorageService.js +285 -0
  18. package/app/modules/stickerPackModule/stickerPackCatalogHttp.js +1090 -659
  19. package/app/modules/stickerPackModule/stickerPackCommandHandlers.js +19 -1
  20. package/app/modules/stickerPackModule/stickerPackEngagementRepository.js +44 -0
  21. package/app/modules/stickerPackModule/stickerPackItemRepository.js +18 -0
  22. package/app/modules/stickerPackModule/stickerPackRepository.js +51 -0
  23. package/app/modules/stickerPackModule/stickerPackScoreSnapshotRepository.js +191 -0
  24. package/app/modules/stickerPackModule/stickerPackScoreSnapshotRuntime.js +301 -0
  25. package/app/modules/stickerPackModule/stickerStorageService.js +111 -10
  26. package/app/modules/stickerPackModule/stickerWorkerPipelineRuntime.js +21 -0
  27. package/app/modules/stickerPackModule/stickerWorkerTaskQueueRepository.js +59 -7
  28. package/app/observability/metrics.js +169 -0
  29. package/app/services/featureFlagService.js +137 -0
  30. package/app/services/lidMapService.js +4 -1
  31. package/app/services/whatsappLoginLinkService.js +232 -0
  32. package/database/index.js +5 -0
  33. package/database/migrations/20260228_0021_sticker_web_google_owner_phone.sql +83 -0
  34. package/database/migrations/20260228_0022_sticker_scale_indexes.sql +16 -0
  35. package/database/migrations/20260228_0023_sticker_pack_score_snapshot.sql +25 -0
  36. package/database/migrations/20260228_0024_domain_event_outbox.sql +42 -0
  37. package/database/migrations/20260228_0025_sticker_worker_task_idempotency_dlq.sql +23 -0
  38. package/database/migrations/20260228_0026_feature_flags.sql +21 -0
  39. package/ecosystem.prod.config.cjs +70 -9
  40. package/index.js +26 -0
  41. package/package.json +5 -1
  42. package/public/index.html +128 -10
  43. package/public/js/apps/createPackApp.js +59 -272
  44. package/public/js/apps/homeApp.js +106 -0
  45. package/public/js/apps/loginApp.js +459 -0
  46. package/public/js/apps/stickersApp.js +34 -37
  47. package/public/js/apps/userApp.js +244 -0
  48. package/public/js/runtime/react-runtime.js +1 -0
  49. package/public/login/index.html +333 -0
  50. package/public/stickers/create/index.html +2 -1
  51. package/public/stickers/index.html +2 -1
  52. package/public/user/index.html +367 -0
  53. package/scripts/cache-bust.mjs +65 -11
  54. package/scripts/sticker-catalog-loadtest.mjs +208 -0
  55. package/scripts/sticker-worker-task.mjs +122 -0
@@ -2,6 +2,21 @@ require('dotenv').config();
2
2
 
3
3
  const appName = process.env.PM2_APP_NAME || 'omnizap-system';
4
4
 
5
+ const baseEnv = {
6
+ NODE_ENV: 'production',
7
+ COMMAND_PREFIX: '/',
8
+ LOG_LEVEL: 'info',
9
+ DB_LOG_EVERY_QUERY: 'false',
10
+ DB_MONITOR_ENABLED: 'false',
11
+ LID_BACKFILL_ON_START: 'false',
12
+ STICKER_CLASSIFICATION_BACKGROUND_ENABLED: 'true',
13
+ STICKER_REPROCESS_QUEUE_ENABLED: 'true',
14
+ STICKER_AUTO_PACK_BY_TAGS_ENABLED: 'true',
15
+ STICKER_WORKER_PIPELINE_ENABLED: 'true',
16
+ STICKER_WORKER_PIPELINE_INLINE_POLLER_ENABLED: 'true',
17
+ STICKER_DEDICATED_WORKERS_ENABLED: 'true',
18
+ };
19
+
5
20
  module.exports = {
6
21
  apps: [
7
22
  {
@@ -17,19 +32,65 @@ module.exports = {
17
32
  out_file: `logs/${appName}-out.log`,
18
33
  error_file: `logs/${appName}-error.log`,
19
34
  env: {
20
- NODE_ENV: 'production',
21
- COMMAND_PREFIX: '/',
22
- LOG_LEVEL: 'info',
23
- DB_LOG_EVERY_QUERY: 'false',
24
- DB_MONITOR_ENABLED: 'false',
25
- LID_BACKFILL_ON_START: 'false',
26
- STICKER_CLASSIFICATION_BACKGROUND_ENABLED: 'true',
27
- STICKER_REPROCESS_QUEUE_ENABLED: 'true',
28
- STICKER_AUTO_PACK_BY_TAGS_ENABLED: 'true',
35
+ ...baseEnv,
29
36
  },
30
37
  wait_ready: true,
31
38
  listen_timeout: 10000,
32
39
  kill_timeout: 5000,
33
40
  },
41
+ {
42
+ name: `${appName}-worker-classification`,
43
+ script: './scripts/sticker-worker-task.mjs',
44
+ args: '--task-type classification_cycle',
45
+ cwd: __dirname,
46
+ exec_mode: 'fork',
47
+ instances: 1,
48
+ autorestart: true,
49
+ watch: false,
50
+ max_memory_restart: '2G',
51
+ log_date_format: 'YYYY-MM-DD HH:mm:ss',
52
+ out_file: `logs/${appName}-worker-classification-out.log`,
53
+ error_file: `logs/${appName}-worker-classification-error.log`,
54
+ env: {
55
+ ...baseEnv,
56
+ },
57
+ kill_timeout: 5000,
58
+ },
59
+ {
60
+ name: `${appName}-worker-curation`,
61
+ script: './scripts/sticker-worker-task.mjs',
62
+ args: '--task-type curation_cycle',
63
+ cwd: __dirname,
64
+ exec_mode: 'fork',
65
+ instances: 1,
66
+ autorestart: true,
67
+ watch: false,
68
+ max_memory_restart: '2G',
69
+ log_date_format: 'YYYY-MM-DD HH:mm:ss',
70
+ out_file: `logs/${appName}-worker-curation-out.log`,
71
+ error_file: `logs/${appName}-worker-curation-error.log`,
72
+ env: {
73
+ ...baseEnv,
74
+ },
75
+ kill_timeout: 5000,
76
+ },
77
+ {
78
+ name: `${appName}-worker-rebuild`,
79
+ script: './scripts/sticker-worker-task.mjs',
80
+ args: '--task-type rebuild_cycle',
81
+ cwd: __dirname,
82
+ exec_mode: 'fork',
83
+ instances: 1,
84
+ autorestart: true,
85
+ watch: false,
86
+ max_memory_restart: '2G',
87
+ log_date_format: 'YYYY-MM-DD HH:mm:ss',
88
+ out_file: `logs/${appName}-worker-rebuild-out.log`,
89
+ error_file: `logs/${appName}-worker-rebuild-error.log`,
90
+ env: {
91
+ ...baseEnv,
92
+ },
93
+ kill_timeout: 5000,
94
+ },
34
95
  ],
35
96
  };
package/index.js CHANGED
@@ -39,6 +39,14 @@ import {
39
39
  startStickerWorkerPipeline,
40
40
  stopStickerWorkerPipeline,
41
41
  } from './app/modules/stickerPackModule/stickerWorkerPipelineRuntime.js';
42
+ import {
43
+ startStickerPackScoreSnapshotRuntime,
44
+ stopStickerPackScoreSnapshotRuntime,
45
+ } from './app/modules/stickerPackModule/stickerPackScoreSnapshotRuntime.js';
46
+ import {
47
+ startStickerDomainEventConsumer,
48
+ stopStickerDomainEventConsumer,
49
+ } from './app/modules/stickerPackModule/stickerDomainEventConsumerRuntime.js';
42
50
 
43
51
  /**
44
52
  * Timeout máximo para inicialização do banco (criar/verificar DB + tabelas).
@@ -216,6 +224,8 @@ async function startApp() {
216
224
  startStickerClassificationBackground();
217
225
  startStickerAutoPackByTagsBackground();
218
226
  }
227
+ startStickerPackScoreSnapshotRuntime();
228
+ startStickerDomainEventConsumer();
219
229
 
220
230
  // Backfill é opcional, rodando em background.
221
231
  const shouldBackfill = process.env.LID_BACKFILL_ON_START !== 'false';
@@ -363,6 +373,22 @@ async function shutdown(signal, error) {
363
373
  });
364
374
  }
365
375
 
376
+ try {
377
+ stopStickerPackScoreSnapshotRuntime();
378
+ } catch (snapshotError) {
379
+ logger.warn('Falha ao encerrar runtime de snapshot de score dos packs.', {
380
+ error: snapshotError?.message,
381
+ });
382
+ }
383
+
384
+ try {
385
+ stopStickerDomainEventConsumer();
386
+ } catch (consumerError) {
387
+ logger.warn('Falha ao encerrar consumidor interno de eventos de domínio.', {
388
+ error: consumerError?.message,
389
+ });
390
+ }
391
+
366
392
  // 5) Encerrar MySQL pool
367
393
  await closeDatabasePool();
368
394
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaikybrofc/omnizap-system",
3
- "version": "2.2.3",
3
+ "version": "2.2.5",
4
4
  "description": "Sistema profissional de automação WhatsApp com tecnologia Baileys",
5
5
  "main": "index.js",
6
6
  "publishConfig": {
@@ -59,6 +59,10 @@
59
59
  "deploy": "bash ./scripts/deploy.sh",
60
60
  "deploy:dry-run": "DEPLOY_DRY_RUN=1 bash ./scripts/deploy.sh",
61
61
  "readme:sync-snapshot": "node ./scripts/sync-readme-snapshot.mjs",
62
+ "loadtest:stickers": "node ./scripts/sticker-catalog-loadtest.mjs",
63
+ "worker:sticker:classification": "node ./scripts/sticker-worker-task.mjs --task-type classification_cycle",
64
+ "worker:sticker:curation": "node ./scripts/sticker-worker-task.mjs --task-type curation_cycle",
65
+ "worker:sticker:rebuild": "node ./scripts/sticker-worker-task.mjs --task-type rebuild_cycle",
62
66
  "release": "bash ./scripts/release.sh",
63
67
  "release:minor": "RELEASE_TYPE=minor bash ./scripts/release.sh",
64
68
  "release:major": "RELEASE_TYPE=major bash ./scripts/release.sh",
package/public/index.html CHANGED
@@ -138,8 +138,63 @@
138
138
 
139
139
  .nav { display: flex; gap: 10px; flex-wrap: wrap; }
140
140
 
141
- .nav-toggle {
142
- display: none;
141
+ .nav-user-chip {
142
+ display: inline-flex;
143
+ align-items: center;
144
+ gap: 8px;
145
+ padding: 6px 10px 6px 6px;
146
+ max-width: 270px;
147
+ border-color: #3f5f8f;
148
+ background: linear-gradient(120deg, #132544d6, #10203ad6);
149
+ }
150
+
151
+ .nav-user-avatar-bubble {
152
+ display: inline-flex;
153
+ width: 30px;
154
+ height: 30px;
155
+ border-radius: 999px;
156
+ border: 1px solid #4a6fa4;
157
+ background: #132340;
158
+ box-shadow: 0 0 0 2px #1a2e4b, 0 0 16px #6aaaf236;
159
+ overflow: hidden;
160
+ flex: 0 0 auto;
161
+ }
162
+
163
+ .nav-user-photo {
164
+ width: 100%;
165
+ height: 100%;
166
+ object-fit: cover;
167
+ display: block;
168
+ }
169
+
170
+ .nav-user-name-bubble {
171
+ display: inline-flex;
172
+ align-items: center;
173
+ gap: 6px;
174
+ min-width: 0;
175
+ padding: 4px 8px;
176
+ border-radius: 999px;
177
+ border: 1px solid #34547f;
178
+ background: #12213ac9;
179
+ }
180
+
181
+ .nav-user-icon {
182
+ font-size: 12px;
183
+ color: #9bc6f5;
184
+ flex: 0 0 auto;
185
+ }
186
+
187
+ .nav-user-name {
188
+ font-size: 12px;
189
+ font-weight: 700;
190
+ color: #dbe8fb;
191
+ white-space: nowrap;
192
+ overflow: hidden;
193
+ text-overflow: ellipsis;
194
+ }
195
+
196
+ .nav-toggle {
197
+ display: none;
143
198
  width: 42px;
144
199
  height: 42px;
145
200
  border-radius: 10px;
@@ -178,12 +233,12 @@
178
233
 
179
234
  .btn:hover { transform: translateY(-1px); border-color: #3f567f; }
180
235
 
181
- .btn.primary {
182
- color: #042511;
183
- border-color: transparent;
184
- background: linear-gradient(90deg, var(--primary), #16a34a);
185
- box-shadow: 0 8px 22px #22c55e33;
186
- }
236
+ .btn.primary {
237
+ color: #042511;
238
+ border-color: transparent;
239
+ background: linear-gradient(90deg, var(--primary), #16a34a);
240
+ box-shadow: 0 8px 22px #22c55e33;
241
+ }
187
242
 
188
243
  @media (max-width: 860px) {
189
244
  .top-inner {
@@ -221,6 +276,33 @@
221
276
  display: grid;
222
277
  }
223
278
 
279
+ body.home-authenticated .top-inner {
280
+ flex-direction: row;
281
+ align-items: center;
282
+ justify-content: space-between;
283
+ gap: 10px;
284
+ }
285
+
286
+ body.home-authenticated .top-head {
287
+ flex: 1 1 auto;
288
+ }
289
+
290
+ body.home-authenticated #nav-toggle {
291
+ display: none;
292
+ }
293
+
294
+ body.home-authenticated #main-nav {
295
+ display: flex;
296
+ width: auto;
297
+ grid-template-columns: none;
298
+ gap: 8px;
299
+ flex-wrap: nowrap;
300
+ }
301
+
302
+ body.home-authenticated #main-nav .btn:not(#nav-auth-link) {
303
+ display: none;
304
+ }
305
+
224
306
  .btn {
225
307
  width: 100%;
226
308
  text-align: center;
@@ -228,6 +310,38 @@
228
310
  border-radius: 10px;
229
311
  }
230
312
 
313
+ .nav-user-chip {
314
+ justify-content: flex-start;
315
+ }
316
+
317
+ body.home-authenticated #main-nav #nav-auth-link.nav-user-chip {
318
+ width: 44px;
319
+ min-width: 44px;
320
+ max-width: 44px;
321
+ height: 44px;
322
+ padding: 4px;
323
+ border-radius: 999px;
324
+ justify-content: center;
325
+ justify-self: auto;
326
+ align-self: auto;
327
+ background: linear-gradient(120deg, #132544f0, #10203af0);
328
+ }
329
+
330
+ body.home-authenticated #main-nav #nav-auth-link.nav-user-chip .nav-user-name-bubble {
331
+ display: none;
332
+ }
333
+
334
+ body.home-authenticated #main-nav #nav-auth-link.nav-user-chip .nav-user-avatar-bubble {
335
+ width: 34px;
336
+ height: 34px;
337
+ border: 1px solid #4a6fa4;
338
+ box-shadow: 0 0 0 1px #1a2e4b, 0 0 12px #6aaaf236;
339
+ }
340
+
341
+ body.home-authenticated #main-nav #nav-scheduler-link {
342
+ display: none;
343
+ }
344
+
231
345
  }
232
346
 
233
347
  @media (max-width: 420px) {
@@ -1057,7 +1171,8 @@
1057
1171
  >☰</button>
1058
1172
  </div>
1059
1173
  <nav id="main-nav" class="nav">
1060
- <a class="btn" href="/api-docs/"><i class="fa-solid fa-code icon-inline" aria-hidden="true"></i>API</a>
1174
+ <a id="nav-scheduler-link" class="btn" href="/api-docs/"><i class="fa-solid fa-code icon-inline" aria-hidden="true"></i>API</a>
1175
+ <a id="nav-auth-link" class="btn" href="/login/"><i class="fa-solid fa-right-to-bracket icon-inline" aria-hidden="true"></i>Login</a>
1061
1176
  <a class="btn" href="https://github.com/Kaikygr/omnizap-system" target="_blank" rel="noreferrer noopener"><i class="fa-brands fa-github icon-inline" aria-hidden="true"></i>GitHub</a>
1062
1177
  </nav>
1063
1178
  </div>
@@ -1072,6 +1187,8 @@
1072
1187
  <div class="hero-cta">
1073
1188
  <a class="btn primary" href="https://github.com/Kaikygr/omnizap-system" target="_blank" rel="noreferrer noopener"><i class="fa-brands fa-github icon-inline" aria-hidden="true"></i>Ver no GitHub</a>
1074
1189
  <a class="btn" href="/api-docs/"><i class="fa-solid fa-book icon-inline" aria-hidden="true"></i>Documentação da API</a>
1190
+ <a id="hero-login-cta" class="btn" href="/login/"><i class="fa-solid fa-right-to-bracket icon-inline" aria-hidden="true"></i>Login</a>
1191
+ <a class="btn" href="/stickers/"><i class="fa-solid fa-icons icon-inline" aria-hidden="true"></i>Ir para Stickers</a>
1075
1192
  <a class="btn" href="#infra-arquitetura"><i class="fa-solid fa-diagram-project icon-inline" aria-hidden="true"></i>Ver Arquitetura</a>
1076
1193
  </div>
1077
1194
  <section class="hero-proof">
@@ -1269,6 +1386,7 @@ curl -sS https://omnizap.shop/api/sticker-packs/system-summary | jq</code></pre>
1269
1386
  <div class="foot-col">
1270
1387
  <h4><i class="fa-solid fa-cube icon-inline" aria-hidden="true"></i>Produto</h4>
1271
1388
  <a href="/"><i class="fa-solid fa-house icon-inline" aria-hidden="true"></i>Home</a>
1389
+ <a href="/login/"><i class="fa-solid fa-right-to-bracket icon-inline" aria-hidden="true"></i>Login</a>
1272
1390
  <a href="/stickers/"><i class="fa-solid fa-icons icon-inline" aria-hidden="true"></i>Stickers</a>
1273
1391
  <a href="/stickers/create/"><i class="fa-solid fa-plus icon-inline" aria-hidden="true"></i>Criar Pack</a>
1274
1392
  <a href="/api-docs/"><i class="fa-solid fa-book icon-inline" aria-hidden="true"></i>API Docs</a>
@@ -1305,7 +1423,7 @@ curl -sS https://omnizap.shop/api/sticker-packs/system-summary | jq</code></pre>
1305
1423
  ><i class="fa-brands fa-whatsapp" aria-hidden="true"></i></a>
1306
1424
 
1307
1425
  <div id="home-react-root" hidden></div>
1308
- <script type="module" src="/js/apps/homeApp.js?v=20260227c"></script>
1426
+ <script type="module" src="/js/apps/homeApp.js?v=20260228-mobile-user-bubble3"></script>
1309
1427
  <script type="module" src="/js/github-panel/index.js?v=20260226a"></script>
1310
1428
  </body>
1311
1429
  </html>