trucoshi 12.1.1 → 12.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/README.md CHANGED
@@ -30,9 +30,11 @@ Proba la demo actual en [Trucoshi](https://trucoshi.com)
30
30
 
31
31
  Run the three-repo local stack from this repo with:
32
32
 
33
- `yarn dev:all:sudo-docker`
33
+ `yarn dev:all`
34
34
 
35
- Do not prefix the command with `sudo`. The script only uses sudo for Docker commands, and running Yarn itself as root can corrupt local links and generated Prisma files.
35
+ If your user cannot run Docker directly, use `yarn dev:all:sudo-docker`. Do not prefix either command with `sudo`; that mode only elevates Docker commands, so Yarn, Vite, generated Prisma files, and local links remain owned by your user.
36
+
37
+ The launcher keeps the local stack in development mode: Lightning Accounts, Trucoshi, and the Vite client. Its interactive control panel can show one service's logs at a time, display stack status, restart a service, and optionally build and host a client snapshot at `http://10.10.1.106:2993`. The snapshot is off by default, so it never slows Vite's hot-reload loop. Set `DEV_ALL_PUBLIC_HOST`, `DEV_ALL_CLIENT_HOST_PORT`, or `DEV_ALL_LOG_DIR` if you need different defaults.
36
38
 
37
39
  # Test
38
40
 
package/dist/events.d.ts CHANGED
@@ -68,6 +68,7 @@ export declare enum EClientEvent {
68
68
  PAUSE_MATCH = "PAUSE_MATCH",
69
69
  PLAY_AGAIN = "PLAY_AGAIN",
70
70
  JOIN_QUEUE = "JOIN_QUEUE",
71
+ FETCH_QUEUE_STATUS = "FETCH_QUEUE_STATUS",
71
72
  LEAVE_QUEUE = "LEAVE_QUEUE",
72
73
  CONFIRM_QUEUE_MATCH = "CONFIRM_QUEUE_MATCH",
73
74
  DECLINE_QUEUE_MATCH = "DECLINE_QUEUE_MATCH",
@@ -137,6 +138,9 @@ export interface ClientToServerEvents {
137
138
  [EClientEvent.JOIN_QUEUE]: (options: IJoinQueueOptions, callback: IEventCallback<{
138
139
  status?: IQueueStatus;
139
140
  }>) => void;
141
+ [EClientEvent.FETCH_QUEUE_STATUS]: (callback: IEventCallback<{
142
+ status?: IQueueStatus;
143
+ }>) => void;
140
144
  [EClientEvent.LEAVE_QUEUE]: (callback?: IEventCallback<{}>) => void;
141
145
  [EClientEvent.CONFIRM_QUEUE_MATCH]: (proposalId: string, callback?: IEventCallback<{
142
146
  update?: IQueueReadyUpdate;
package/dist/events.js CHANGED
@@ -40,6 +40,7 @@ export var EClientEvent;
40
40
  EClientEvent["PAUSE_MATCH"] = "PAUSE_MATCH";
41
41
  EClientEvent["PLAY_AGAIN"] = "PLAY_AGAIN";
42
42
  EClientEvent["JOIN_QUEUE"] = "JOIN_QUEUE";
43
+ EClientEvent["FETCH_QUEUE_STATUS"] = "FETCH_QUEUE_STATUS";
43
44
  EClientEvent["LEAVE_QUEUE"] = "LEAVE_QUEUE";
44
45
  EClientEvent["CONFIRM_QUEUE_MATCH"] = "CONFIRM_QUEUE_MATCH";
45
46
  EClientEvent["DECLINE_QUEUE_MATCH"] = "DECLINE_QUEUE_MATCH";
@@ -19,49 +19,86 @@
19
19
  "messages": [
20
20
  {
21
21
  "trigger": "hand_start",
22
- "text": "Bienvenido. Ganas el partido llegando a 9 puntos antes que el Profe."
22
+ "text": "El partido se gana llegando a 9 buenas. Primero llenas malas; despues empiezan buenas."
23
23
  },
24
24
  {
25
25
  "trigger": "before_human_turn",
26
26
  "roundIdx": 1,
27
- "text": "La ronda se gana con la carta mas fuerte. El ancho de espada es la mejor."
27
+ "text": "Arranca con el ancho de espada. Es la mas fuerte y te deja bien parado."
28
28
  },
29
29
  {
30
30
  "trigger": "after_human_action",
31
+ "roundIdx": 1,
31
32
  "actionValue": "1e",
32
- "text": "Esa manda. Despues vienen ancho de basto, 7 de espada y 7 de oro."
33
+ "text": "Ahora falta que responda el Profe."
34
+ },
35
+ {
36
+ "trigger": "after_bot_action",
37
+ "roundIdx": 1,
38
+ "actionValue": "3c",
39
+ "text": "{{roundResult}} El que gana la ronda sale en la siguiente."
40
+ },
41
+ {
42
+ "trigger": "before_human_turn",
43
+ "roundIdx": 2,
44
+ "state": "WAITING_PLAY",
45
+ "roundCardCount": 0,
46
+ "requiresHandCards": ["4c", "7e"],
47
+ "text": "{{previousRoundScore}} Ahora abris: proba con el 4 y guarda el 7."
33
48
  },
34
49
  {
35
50
  "trigger": "before_human_turn",
36
51
  "roundIdx": 2,
37
- "text": "Ahora cerra la mano usando otra carta fuerte cuando haga falta."
52
+ "state": "WAITING_PLAY",
53
+ "roundCardCount": 1,
54
+ "requiresRoundCards": ["6b"],
55
+ "requiresHandCards": ["7e"],
56
+ "text": "El Profe tiro el 6 de basto. El 7 de espada lo mata."
57
+ },
58
+ {
59
+ "trigger": "after_bot_action",
60
+ "roundIdx": 2,
61
+ "actionValue": "6b",
62
+ "text": "Orden de las mas fuertes: ancho de espada, ancho de basto, 7 de espada y 7 de oro."
38
63
  },
39
64
  {
40
65
  "trigger": "before_human_turn",
41
66
  "roundIdx": 3,
42
67
  "state": "WAITING_PLAY",
43
- "text": "Si hace falta otra ronda, elegi la carta que mejor cierre la mano."
68
+ "text": "{{previousRoundScore}} Esta tercera define la mano."
44
69
  },
45
70
  {
46
71
  "trigger": "hand_end",
47
- "text": "Perfecto. En truco se gana al mejor de tres rondas."
72
+ "text": "Base lista: cada mano se juega al mejor de 3 rondas."
48
73
  }
49
74
  ],
50
75
  "botActions": [
51
76
  {
52
77
  "trigger": "before_bot_action",
53
78
  "roundIdx": 1,
54
- "action": { "type": "card", "value": "3c" }
79
+ "state": "WAITING_PLAY",
80
+ "action": {
81
+ "type": "card",
82
+ "value": "3c"
83
+ }
55
84
  },
56
85
  {
57
86
  "trigger": "before_bot_action",
58
87
  "roundIdx": 2,
59
- "action": { "type": "card", "value": "6b" }
88
+ "state": "WAITING_PLAY",
89
+ "action": {
90
+ "type": "card",
91
+ "value": "6b"
92
+ }
60
93
  },
61
94
  {
62
95
  "trigger": "before_bot_action",
63
96
  "roundIdx": 3,
64
- "action": { "type": "card", "value": "5o" }
97
+ "state": "WAITING_PLAY",
98
+ "action": {
99
+ "type": "card",
100
+ "value": "5o"
101
+ }
65
102
  }
66
103
  ]
67
104
  },
@@ -74,54 +111,141 @@
74
111
  "messages": [
75
112
  {
76
113
  "trigger": "hand_start",
77
- "text": "No siempre conviene tirar lo mejor de entrada. Guardar poder tambien gana manos."
114
+ "text": "No siempre conviene tirar lo mejor de entrada. Guardar cartas altas tambien gana manos."
78
115
  },
79
116
  {
80
117
  "trigger": "before_bot_action",
81
118
  "roundIdx": 1,
82
- "text": "Ahora arranca el Profe. Mira que carta tira antes de gastar una fuerte."
119
+ "state": "WAITING_PLAY",
120
+ "text": "Ahora sale el Profe. Mira que tira antes de gastar una carta fuerte."
83
121
  },
84
122
  {
85
123
  "trigger": "before_human_turn",
86
124
  "roundIdx": 1,
87
- "text": "Podes probar con el 4 de basto y guardar dos cartas bravas."
125
+ "text": "Podes tirar el 4 de basto y guardar las dos cartas fuertes."
88
126
  },
89
127
  {
90
128
  "trigger": "after_bot_action",
91
129
  "roundIdx": 2,
92
130
  "actionValue": "3o",
93
- "text": "Si perdes una ronda, tranqui. Usa una fuerte para recuperar control."
131
+ "roundComplete": false,
132
+ "requiresHandCards": ["7o", "1b"],
133
+ "requiresRoundCards": ["3o"],
134
+ "text": "El Profe tiro un 3. El 7 de oro lo mata; no hace falta gastar el ancho."
94
135
  },
95
136
  {
96
137
  "trigger": "before_human_turn",
97
138
  "roundIdx": 2,
98
- "text": "El ancho de basto es enorme. Usalo si necesitas ganar esta ronda."
139
+ "state": "WAITING_PLAY",
140
+ "roundCardCount": 1,
141
+ "requiresHandCards": ["7o", "1b"],
142
+ "requiresRoundCards": ["3o"],
143
+ "text": "Tira el 7 de oro: es la menor carta que gana."
144
+ },
145
+ {
146
+ "trigger": "after_human_action",
147
+ "roundIdx": 2,
148
+ "actionValue": "7o",
149
+ "roundComplete": true,
150
+ "requiresRoundCards": ["3o", "7o"],
151
+ "text": "Bien: el 7 de oro mata al 3. Esa es la menor carta alta que alcanza."
99
152
  },
100
153
  {
101
154
  "trigger": "before_human_turn",
102
155
  "roundIdx": 3,
103
- "text": "Te queda el 7 de oro. Muy buena carta para definir."
156
+ "text": "Tercera ronda: juga tu ultima carta. La mano se define con lo que queda."
157
+ }
158
+ ],
159
+ "botActions": [
160
+ {
161
+ "trigger": "before_bot_action",
162
+ "roundIdx": 1,
163
+ "state": "WAITING_PLAY",
164
+ "action": {
165
+ "type": "card",
166
+ "value": "5c"
167
+ }
168
+ },
169
+ {
170
+ "trigger": "before_bot_action",
171
+ "roundIdx": 2,
172
+ "state": "WAITING_PLAY",
173
+ "action": {
174
+ "type": "card",
175
+ "value": "3o"
176
+ }
177
+ },
178
+ {
179
+ "trigger": "before_bot_action",
180
+ "roundIdx": 3,
181
+ "state": "WAITING_PLAY",
182
+ "action": {
183
+ "type": "card",
184
+ "value": "2e"
185
+ }
186
+ }
187
+ ]
188
+ },
189
+ {
190
+ "goal": "Entender la parda y como se define una mano empatada.",
191
+ "cardsByPlayerIdx": {
192
+ "0": ["3e", "7b", "4o"],
193
+ "1": ["3o", "4c", "5b"]
194
+ },
195
+ "messages": [
196
+ {
197
+ "trigger": "hand_start",
198
+ "text": "Si dos cartas valen igual, la ronda queda parda. La siguiente pesa mucho mas."
199
+ },
200
+ {
201
+ "trigger": "before_human_turn",
202
+ "roundIdx": 1,
203
+ "text": "Juga el 3 de espada. Vale lo mismo que cualquier otro 3 para el truco."
204
+ },
205
+ {
206
+ "trigger": "after_human_action",
207
+ "roundIdx": 1,
208
+ "actionValue": "3e",
209
+ "text": "Ahora falta que responda el Profe. Si tira otro 3, queda parda."
210
+ },
211
+ {
212
+ "trigger": "after_bot_action",
213
+ "roundIdx": 1,
214
+ "actionValue": "3o",
215
+ "text": "{{roundResult}} Si fue parda, la segunda puede definir la mano."
104
216
  },
105
217
  {
106
218
  "trigger": "hand_end",
107
- "text": "Linda remontada. A veces perder barato la primera te deja mejor parado."
219
+ "text": "La primera fue parda; ganaste la segunda y por eso te llevaste la mano."
108
220
  }
109
221
  ],
110
222
  "botActions": [
111
223
  {
112
224
  "trigger": "before_bot_action",
113
225
  "roundIdx": 1,
114
- "action": { "type": "card", "value": "5c" }
226
+ "state": "WAITING_PLAY",
227
+ "action": {
228
+ "type": "card",
229
+ "value": "3o"
230
+ }
115
231
  },
116
232
  {
117
233
  "trigger": "before_bot_action",
118
234
  "roundIdx": 2,
119
- "action": { "type": "card", "value": "3o" }
235
+ "state": "WAITING_PLAY",
236
+ "action": {
237
+ "type": "card",
238
+ "value": "4c"
239
+ }
120
240
  },
121
241
  {
122
242
  "trigger": "before_bot_action",
123
243
  "roundIdx": 3,
124
- "action": { "type": "card", "value": "2e" }
244
+ "state": "WAITING_PLAY",
245
+ "action": {
246
+ "type": "card",
247
+ "value": "5b"
248
+ }
125
249
  }
126
250
  ]
127
251
  },
@@ -134,81 +258,194 @@
134
258
  "messages": [
135
259
  {
136
260
  "trigger": "hand_start",
137
- "text": "Tenes 33 de envido: 7 y 6 de copa suman 20 + 13. Cantalo antes de jugar."
261
+ "text": "Tenes 33 de envido: 20 de base por copa, mas 7 y 6. Cantalo antes de jugar."
138
262
  },
139
263
  {
140
264
  "trigger": "before_human_turn",
141
265
  "roundIdx": 1,
142
- "text": "Toca ENVIDO ahora. El envido se resuelve antes de seguir con las cartas."
266
+ "text": "Antes de tirar carta, toca ENVIDO. Tenes 33 y se canta antes de jugar las cartas."
143
267
  },
144
268
  {
145
269
  "trigger": "before_bot_action",
146
270
  "state": "WAITING_ENVIDO_ANSWER",
147
- "text": "El Profe puede aceptar con QUIERO o achicarse con NO QUIERO."
271
+ "text": "El Profe puede decir QUIERO o achicarse con NO QUIERO."
148
272
  },
149
273
  {
150
274
  "trigger": "after_bot_action",
151
275
  "actionValue": "QUIERO",
152
- "text": "El Profe quiso. Ahora declara tus 33 para comparar tantos."
276
+ "text": "El Profe quiso. Ahora canta tus 33 para comparar los tantos."
153
277
  },
154
278
  {
155
279
  "trigger": "before_human_turn",
156
280
  "state": "WAITING_ENVIDO_POINTS_ANSWER",
157
- "text": "Deci 33. Ese tanto obliga al Profe a superar tu envido."
281
+ "text": "Deci 33. El Profe necesita mas que eso para ganarte el envido."
158
282
  },
159
283
  {
160
- "trigger": "after_bot_action",
161
- "actionValue": 29,
162
- "text": "El Profe dijo 29. Tus 33 ganan el envido."
284
+ "trigger": "after_human_action",
285
+ "state": "WAITING_ENVIDO_POINTS_ANSWER",
286
+ "actionValue": 33,
287
+ "text": "Bien: declaraste 33. Es el puntaje mas alto."
163
288
  },
164
289
  {
165
- "trigger": "before_human_turn",
166
- "roundIdx": 1,
167
- "state": "WAITING_PLAY",
168
- "text": "Ahora segui la mano. El envido suma aparte del juego de cartas."
290
+ "trigger": "after_bot_action",
291
+ "actionValue": 29,
292
+ "text": "El Profe dijo 29. El tanto mas alto se lleva el envido; ahora segui con cartas."
169
293
  },
170
294
  {
171
295
  "trigger": "before_human_turn",
172
296
  "roundIdx": 2,
173
297
  "state": "WAITING_PLAY",
174
- "text": "Ahora segui jugando tus cartas. Busca ganar la ronda sin regalar de mas."
298
+ "text": "Ahora cartas: el envido ya paso, no gastes una fuerte sin necesidad."
175
299
  },
176
300
  {
177
301
  "trigger": "before_human_turn",
178
302
  "roundIdx": 3,
179
303
  "state": "WAITING_PLAY",
180
- "text": "Ya conoces la idea: elegi la mejor carta para esta ronda."
304
+ "text": "{{previousRoundScore}} Juga la carta que queda."
181
305
  },
182
306
  {
183
307
  "trigger": "hand_end",
184
- "text": "Clave: si tenes buen tanto, canta antes de mostrar cartas."
308
+ "text": "Clave: si tenes buen tanto, cantalo antes de mostrar cartas."
185
309
  }
186
310
  ],
187
311
  "botActions": [
188
312
  {
189
313
  "trigger": "before_bot_action",
190
314
  "state": "WAITING_ENVIDO_ANSWER",
191
- "action": { "type": "command", "value": "QUIERO" }
315
+ "action": {
316
+ "type": "command",
317
+ "value": "QUIERO"
318
+ }
192
319
  },
193
320
  {
194
321
  "trigger": "before_bot_action",
195
322
  "state": "WAITING_ENVIDO_POINTS_ANSWER",
196
- "action": { "type": "command", "value": 29 }
323
+ "action": {
324
+ "type": "command",
325
+ "value": 29
326
+ }
327
+ },
328
+ {
329
+ "trigger": "before_bot_action",
330
+ "roundIdx": 1,
331
+ "state": "WAITING_PLAY",
332
+ "action": {
333
+ "type": "card",
334
+ "value": "re"
335
+ }
336
+ },
337
+ {
338
+ "trigger": "before_bot_action",
339
+ "roundIdx": 2,
340
+ "state": "WAITING_PLAY",
341
+ "action": {
342
+ "type": "card",
343
+ "value": "5b"
344
+ }
345
+ },
346
+ {
347
+ "trigger": "before_bot_action",
348
+ "roundIdx": 3,
349
+ "state": "WAITING_PLAY",
350
+ "action": {
351
+ "type": "card",
352
+ "value": "4b"
353
+ }
354
+ }
355
+ ]
356
+ },
357
+ {
358
+ "goal": "Aprender cuando rechazar Envido con poco tanto.",
359
+ "cardsByPlayerIdx": {
360
+ "0": ["7e", "6b", "4c"],
361
+ "1": ["6o", "5o", "4b"]
362
+ },
363
+ "messages": [
364
+ {
365
+ "trigger": "hand_start",
366
+ "text": "Tambien hay que saber decir que no. Esta vez tenes poco envido: solo 7."
367
+ },
368
+ {
369
+ "trigger": "before_bot_action",
370
+ "roundIdx": 1,
371
+ "state": "WAITING_PLAY",
372
+ "text": "Como el Profe todavia no tiro carta, puede probar con ENVIDO."
373
+ },
374
+ {
375
+ "trigger": "after_bot_action",
376
+ "actionValue": "ENVIDO",
377
+ "text": "Con tan poco envido, NO QUIERO limita el dano: das 1 punto y la mano sigue."
378
+ },
379
+ {
380
+ "trigger": "before_human_turn",
381
+ "state": "WAITING_ENVIDO_ANSWER",
382
+ "text": "Toca NO QUIERO. No hace falta pelear todos los tantos."
383
+ },
384
+ {
385
+ "trigger": "after_human_action",
386
+ "state": "WAITING_ENVIDO_ANSWER",
387
+ "actionValue": "NO_QUIERO",
388
+ "text": "Bien. Diste 1 punto, pero evitaste jugar por 2 con un tanto muy bajo."
389
+ },
390
+ {
391
+ "trigger": "before_human_turn",
392
+ "roundIdx": 1,
393
+ "state": "WAITING_PLAY",
394
+ "text": "Con 7 de tanto, mejor no cantes. Tira el 7 de espada y juga la mano."
395
+ },
396
+ {
397
+ "trigger": "before_human_turn",
398
+ "roundIdx": 2,
399
+ "state": "WAITING_PLAY",
400
+ "text": "Una cosa es el envido y otra la mano: podes rechazar uno y ganar la otra."
401
+ },
402
+ {
403
+ "trigger": "before_human_turn",
404
+ "roundIdx": 3,
405
+ "state": "WAITING_PLAY",
406
+ "text": "Si llega a tercera, juga lo que queda. Lo importante fue no regalar el envido."
197
407
  },
408
+ {
409
+ "trigger": "hand_end",
410
+ "text": "Recorda: no regalar puntos tambien es jugar bien."
411
+ }
412
+ ],
413
+ "botActions": [
198
414
  {
199
415
  "trigger": "before_bot_action",
200
416
  "roundIdx": 1,
201
- "action": { "type": "card", "value": "re" }
417
+ "state": "WAITING_PLAY",
418
+ "action": {
419
+ "type": "command",
420
+ "value": "ENVIDO"
421
+ }
422
+ },
423
+ {
424
+ "trigger": "before_bot_action",
425
+ "roundIdx": 1,
426
+ "state": "WAITING_PLAY",
427
+ "action": {
428
+ "type": "card",
429
+ "value": "6o"
430
+ }
202
431
  },
203
432
  {
204
433
  "trigger": "before_bot_action",
205
434
  "roundIdx": 2,
206
- "action": { "type": "card", "value": "5b" }
435
+ "state": "WAITING_PLAY",
436
+ "action": {
437
+ "type": "card",
438
+ "value": "5o"
439
+ }
207
440
  },
208
441
  {
209
442
  "trigger": "before_bot_action",
210
443
  "roundIdx": 3,
211
- "action": { "type": "card", "value": "4b" }
444
+ "state": "WAITING_PLAY",
445
+ "action": {
446
+ "type": "card",
447
+ "value": "4b"
448
+ }
212
449
  }
213
450
  ]
214
451
  },
@@ -221,22 +458,29 @@
221
458
  "messages": [
222
459
  {
223
460
  "trigger": "hand_start",
224
- "text": "El Truco sube la apuesta de la mano. Aceptar puede pagar, pero duele perder."
461
+ "text": "El Truco sube la apuesta de la mano. Si aceptas, podes ganar mas o perder mas."
225
462
  },
226
463
  {
227
- "trigger": "before_bot_action",
464
+ "trigger": "before_human_turn",
228
465
  "roundIdx": 1,
229
- "text": "Ahora empieza el Profe. No aceptes presion sin mirar tu mano."
466
+ "roundCardCount": 1,
467
+ "requiresRoundCards": ["2b"],
468
+ "requiresHandCards": ["7b", "3e", "1c"],
469
+ "text": "El Profe tiro el 2 de basto. Perde barato con el 7 y guarda mejores."
230
470
  },
231
471
  {
232
- "trigger": "before_human_turn",
472
+ "trigger": "after_human_action",
233
473
  "roundIdx": 1,
234
- "text": "Responde con el 7 de basto. No es fuerte, pero guardas dos cartas decentes."
474
+ "actionValue": "7b",
475
+ "roundComplete": true,
476
+ "requiresRoundCards": ["2b", "7b"],
477
+ "text": "El 2 de basto le gana al 7. Perdiste barato y guardaste fuerza."
235
478
  },
236
479
  {
237
480
  "trigger": "before_bot_action",
238
481
  "roundIdx": 2,
239
- "text": "Ojo, el Profe te va a apretar con TRUCO."
482
+ "state": "WAITING_PLAY",
483
+ "text": "Ojo: el Profe te va a apretar con TRUCO."
240
484
  },
241
485
  {
242
486
  "trigger": "after_bot_action",
@@ -246,45 +490,173 @@
246
490
  {
247
491
  "trigger": "before_human_turn",
248
492
  "state": "WAITING_FOR_TRUCO_ANSWER",
249
- "text": "Aca acepta con QUIERO: tenes cartas para pelear y aprender el riesgo."
493
+ "text": "Aca podes decir QUIERO si ves chances de pelear la mano."
250
494
  },
251
495
  {
252
496
  "trigger": "before_human_turn",
253
497
  "roundIdx": 2,
254
498
  "state": "WAITING_PLAY",
255
- "text": "Ahora juga tu mejor carta disponible para pelear el Truco."
499
+ "roundCardCount": 1,
500
+ "requiresRoundCards": ["1e"],
501
+ "text": "El Profe tiro el ancho de espada. Ahora cuida lo que todavia sirve."
256
502
  },
257
503
  {
258
504
  "trigger": "before_human_turn",
259
505
  "roundIdx": 3,
260
506
  "state": "WAITING_PLAY",
261
- "text": "Si queda una ronda, mira que carta te queda y busca cerrarla."
507
+ "text": "{{previousRoundScore}} Juga la carta que queda."
262
508
  },
263
509
  {
264
510
  "trigger": "hand_end",
265
- "text": "A veces se pierde un Truco querido. La clave es medir riesgo y mano."
511
+ "text": "A veces se pierde un Truco querido. La clave es medir el riesgo."
266
512
  }
267
513
  ],
268
514
  "botActions": [
269
515
  {
270
516
  "trigger": "before_bot_action",
271
517
  "roundIdx": 1,
272
- "action": { "type": "card", "value": "4o" }
518
+ "state": "WAITING_PLAY",
519
+ "action": {
520
+ "type": "card",
521
+ "value": "2b"
522
+ }
273
523
  },
274
524
  {
275
525
  "trigger": "before_bot_action",
276
526
  "roundIdx": 2,
277
- "action": { "type": "command", "value": "TRUCO" }
527
+ "state": "WAITING_PLAY",
528
+ "action": {
529
+ "type": "command",
530
+ "value": "TRUCO"
531
+ }
278
532
  },
279
533
  {
280
534
  "trigger": "before_bot_action",
281
535
  "roundIdx": 2,
282
- "action": { "type": "card", "value": "1e" }
536
+ "state": "WAITING_PLAY",
537
+ "action": {
538
+ "type": "card",
539
+ "value": "1e"
540
+ }
283
541
  },
284
542
  {
285
543
  "trigger": "before_bot_action",
286
544
  "roundIdx": 3,
287
- "action": { "type": "card", "value": "2b" }
545
+ "state": "WAITING_PLAY",
546
+ "action": {
547
+ "type": "card",
548
+ "value": "4o"
549
+ }
550
+ }
551
+ ]
552
+ },
553
+ {
554
+ "goal": "Subir una apuesta de Truco con Re-Truco.",
555
+ "cardsByPlayerIdx": {
556
+ "0": ["1b", "7o", "3e"],
557
+ "1": ["3c", "2c", "4e"]
558
+ },
559
+ "messages": [
560
+ {
561
+ "trigger": "hand_start",
562
+ "text": "Si te cantan Truco y tenes buena mano, tambien podes subir la apuesta."
563
+ },
564
+ {
565
+ "trigger": "before_human_turn",
566
+ "roundIdx": 1,
567
+ "state": "WAITING_PLAY",
568
+ "requiresHandCards": ["1b", "7o", "3e"],
569
+ "text": "Tenes buena mano. Abri con el ancho de basto y preparate para subir."
570
+ },
571
+ {
572
+ "trigger": "before_bot_action",
573
+ "roundIdx": 1,
574
+ "state": "WAITING_PLAY",
575
+ "text": "Despues de tu primera carta, el Profe va a cantar TRUCO."
576
+ },
577
+ {
578
+ "trigger": "after_bot_action",
579
+ "actionValue": "TRUCO",
580
+ "requiresHandCards": ["7o", "3e"],
581
+ "text": "Te quedan 7 de oro y 3 de espada: podes retrucar y jugar por 3."
582
+ },
583
+ {
584
+ "trigger": "before_human_turn",
585
+ "state": "WAITING_FOR_TRUCO_ANSWER",
586
+ "text": "Toca RE-TRUCO. Subis la apuesta y despues el Profe decide si acepta."
587
+ },
588
+ {
589
+ "trigger": "after_human_action",
590
+ "state": "WAITING_FOR_TRUCO_ANSWER",
591
+ "actionValue": "RE_TRUCO",
592
+ "text": "Buen retruco. Si el Profe quiere, se juega por 3; si no, cobras 2."
593
+ },
594
+ {
595
+ "trigger": "after_bot_action",
596
+ "actionValue": "QUIERO",
597
+ "requiresHandCards": ["7o", "3e"],
598
+ "text": "Aceptado. Todavia tenes 7 de oro y 3 de espada para pelear."
599
+ },
600
+ {
601
+ "trigger": "after_bot_action",
602
+ "actionValue": "3c",
603
+ "text": "{{roundResult}} Con la apuesta subida, cada ronda pesa mas."
604
+ },
605
+ {
606
+ "trigger": "before_human_turn",
607
+ "roundIdx": 2,
608
+ "state": "WAITING_PLAY",
609
+ "text": "En segunda, mira quien gano la primera y no regales la apuesta subida."
610
+ },
611
+ {
612
+ "trigger": "hand_end",
613
+ "text": "El TRUCO vale 2, RE-TRUCO 3 y VALE CUATRO 4."
614
+ }
615
+ ],
616
+ "botActions": [
617
+ {
618
+ "trigger": "before_bot_action",
619
+ "roundIdx": 1,
620
+ "state": "WAITING_PLAY",
621
+ "action": {
622
+ "type": "command",
623
+ "value": "TRUCO"
624
+ }
625
+ },
626
+ {
627
+ "trigger": "before_bot_action",
628
+ "state": "WAITING_FOR_TRUCO_ANSWER",
629
+ "action": {
630
+ "type": "command",
631
+ "value": "QUIERO"
632
+ }
633
+ },
634
+ {
635
+ "trigger": "before_bot_action",
636
+ "roundIdx": 1,
637
+ "state": "WAITING_PLAY",
638
+ "action": {
639
+ "type": "card",
640
+ "value": "3c"
641
+ }
642
+ },
643
+ {
644
+ "trigger": "before_bot_action",
645
+ "roundIdx": 2,
646
+ "state": "WAITING_PLAY",
647
+ "action": {
648
+ "type": "card",
649
+ "value": "2c"
650
+ }
651
+ },
652
+ {
653
+ "trigger": "before_bot_action",
654
+ "roundIdx": 3,
655
+ "state": "WAITING_PLAY",
656
+ "action": {
657
+ "type": "card",
658
+ "value": "4e"
659
+ }
288
660
  }
289
661
  ]
290
662
  },
@@ -302,56 +674,64 @@
302
674
  {
303
675
  "trigger": "before_human_turn",
304
676
  "roundIdx": 1,
305
- "text": "Toca FLOR. Con flor activa, vale mas que pensar en envido."
677
+ "text": "Toca FLOR antes de tirar carta. Tres del mismo palo se cantan enseguida."
306
678
  },
307
679
  {
308
680
  "trigger": "after_human_action",
309
- "actionValue": "FLOR",
310
- "text": "Flor cantada. Ahora segui jugando la mano de cartas."
311
- },
312
- {
313
- "trigger": "before_human_turn",
314
681
  "roundIdx": 1,
315
682
  "state": "WAITING_PLAY",
316
- "text": "Tu 7 de oro es muy fuerte. Usalo para marcar la cancha."
683
+ "actionValue": "FLOR",
684
+ "text": "Flor cantada. Ahora tira el 7 de oro para marcar la cancha."
317
685
  },
318
686
  {
319
687
  "trigger": "before_human_turn",
320
688
  "roundIdx": 2,
321
689
  "state": "WAITING_PLAY",
322
- "text": "Ahora segui jugando tus cartas. La Flor ya sumo, falta la mano."
690
+ "text": "Si cantaste Flor, ya sumo. Ahora la mano sigue con cartas."
323
691
  },
324
692
  {
325
693
  "trigger": "before_human_turn",
326
694
  "roundIdx": 3,
327
695
  "state": "WAITING_PLAY",
328
- "text": "Ya conoces la idea: elegi la mejor carta para esta ronda."
696
+ "text": "{{previousRoundScore}} Juga la carta que queda."
329
697
  },
330
698
  {
331
699
  "trigger": "hand_end",
332
- "text": "Bien ahi. Si ves tres del mismo palo, primero mira la Flor."
700
+ "text": "Si ves tres cartas del mismo palo, primero mira si tenes Flor."
333
701
  }
334
702
  ],
335
703
  "botActions": [
336
704
  {
337
705
  "trigger": "before_bot_action",
338
706
  "roundIdx": 1,
339
- "action": { "type": "card", "value": "4e" }
707
+ "state": "WAITING_PLAY",
708
+ "action": {
709
+ "type": "card",
710
+ "value": "4e"
711
+ }
340
712
  },
341
713
  {
342
714
  "trigger": "before_bot_action",
343
715
  "roundIdx": 2,
344
- "action": { "type": "card", "value": "5b" }
716
+ "state": "WAITING_PLAY",
717
+ "action": {
718
+ "type": "card",
719
+ "value": "5b"
720
+ }
345
721
  },
346
722
  {
347
723
  "trigger": "before_bot_action",
348
724
  "roundIdx": 3,
349
- "action": { "type": "card", "value": "rc" }
725
+ "state": "WAITING_PLAY",
726
+ "action": {
727
+ "type": "card",
728
+ "value": "rc"
729
+ }
350
730
  }
351
731
  ]
352
732
  },
353
733
  {
354
- "goal": "Aprender cuando irse al mazo para perder menos.",
734
+ "goal": "Aprender cuando rechazar Truco para perder menos.",
355
735
  "cardsByPlayerIdx": {
356
736
  "0": ["4c", "5o", "6b"],
357
737
  "1": ["1e", "7e", "3b"]
@@ -361,46 +741,64 @@
361
741
  "trigger": "hand_start",
362
742
  "text": "Mano flojita: sin envido fuerte y sin cartas altas. No todo se pelea."
363
743
  },
744
+ {
745
+ "trigger": "before_human_turn",
746
+ "roundIdx": 1,
747
+ "state": "WAITING_PLAY",
748
+ "text": "Arranca con el 4 de copa. La mano es debil, asi que no inviertas de mas."
749
+ },
364
750
  {
365
751
  "trigger": "before_bot_action",
366
752
  "roundIdx": 1,
367
- "text": "El Profe huele debilidad y va a cantar TRUCO."
753
+ "state": "WAITING_PLAY",
754
+ "text": "El Profe ve debilidad y va a cantar TRUCO."
368
755
  },
369
756
  {
370
757
  "trigger": "after_bot_action",
371
758
  "actionValue": "TRUCO",
372
- "text": "Con esta mano, irte al MAZO es correcto: perdes poco y pasas a la proxima."
373
- },
374
- {
375
- "trigger": "before_human_turn",
376
- "state": "WAITING_FOR_TRUCO_ANSWER",
377
- "text": "Toca NO QUIERO. En truco, abandonar a tiempo tambien es jugar bien."
759
+ "text": "Con esta mano, rechazar el TRUCO esta bien: perdes poco y pasas a la proxima."
378
760
  },
379
761
  {
380
762
  "trigger": "hand_end",
381
- "text": "Excelente. Ahora intenta ganarme el resto del partido sin ayuda."
763
+ "text": "Frenar a tiempo tambien es jugar bien. Ahora intenta cerrar el partido sin ayuda."
382
764
  }
383
765
  ],
384
766
  "botActions": [
385
767
  {
386
768
  "trigger": "before_bot_action",
387
769
  "roundIdx": 1,
388
- "action": { "type": "command", "value": "TRUCO" }
770
+ "state": "WAITING_PLAY",
771
+ "action": {
772
+ "type": "command",
773
+ "value": "TRUCO"
774
+ }
389
775
  },
390
776
  {
391
777
  "trigger": "before_bot_action",
392
778
  "roundIdx": 1,
393
- "action": { "type": "card", "value": "1e" }
779
+ "state": "WAITING_PLAY",
780
+ "action": {
781
+ "type": "card",
782
+ "value": "1e"
783
+ }
394
784
  },
395
785
  {
396
786
  "trigger": "before_bot_action",
397
787
  "roundIdx": 2,
398
- "action": { "type": "card", "value": "7e" }
788
+ "state": "WAITING_PLAY",
789
+ "action": {
790
+ "type": "card",
791
+ "value": "7e"
792
+ }
399
793
  },
400
794
  {
401
795
  "trigger": "before_bot_action",
402
796
  "roundIdx": 3,
403
- "action": { "type": "card", "value": "3b" }
797
+ "state": "WAITING_PLAY",
798
+ "action": {
799
+ "type": "card",
800
+ "value": "3b"
801
+ }
404
802
  }
405
803
  ]
406
804
  }
@@ -1,5 +1,11 @@
1
- import { ITutorialScenario, TutorialScenarioId } from "../types";
1
+ import { IPlayedCard, ITutorialScenario, TutorialScenarioId } from "../types";
2
+ import type { IRound } from "../truco/Round";
2
3
  export declare const DEFAULT_TUTORIAL_SCENARIO_ID: TutorialScenarioId;
4
+ export declare const TUTORIAL_ROUND_RESULT_TOKEN = "{{roundResult}}";
5
+ export declare const TUTORIAL_PREVIOUS_ROUND_SCORE_TOKEN = "{{previousRoundScore}}";
6
+ export declare const renderTutorialRoundResult: (playedCards: IPlayedCard[]) => string | null;
7
+ export declare const renderTutorialPreviousRoundScore: (rounds: IRound[] | undefined) => string | null;
8
+ export declare const renderTutorialMessageText: (text: string, roundCards: IPlayedCard[] | undefined, previousRounds?: IRound[]) => string | null;
3
9
  export declare const validateTutorialScenario: (scenario: ITutorialScenario) => ITutorialScenario;
4
10
  export declare const TUTORIAL_SCENARIOS: Record<TutorialScenarioId, ITutorialScenario>;
5
11
  export declare const getTutorialScenario: (id?: TutorialScenarioId | null | undefined) => ITutorialScenario;
@@ -1,6 +1,111 @@
1
1
  import { CARDS, EAnswerCommand, EEnvidoAnswerCommand, EEnvidoCommand, EFlorCommand, EHandState, ESayCommand, ETrucoCommand, } from "../types";
2
2
  import basicTrucoV1 from "./basic-truco-v1.json";
3
3
  export const DEFAULT_TUTORIAL_SCENARIO_ID = "basic-truco-v1";
4
+ export const TUTORIAL_ROUND_RESULT_TOKEN = "{{roundResult}}";
5
+ export const TUTORIAL_PREVIOUS_ROUND_SCORE_TOKEN = "{{previousRoundScore}}";
6
+ const SUIT_NAMES = {
7
+ e: "espada",
8
+ b: "basto",
9
+ o: "oro",
10
+ c: "copa",
11
+ };
12
+ const CARD_NUMBER_NAMES = {
13
+ r: "12",
14
+ c: "11",
15
+ p: "10",
16
+ };
17
+ const getTutorialCardName = (card) => {
18
+ var _a, _b;
19
+ if (card === "1e") {
20
+ return "ancho de espada";
21
+ }
22
+ if (card === "1b") {
23
+ return "ancho de basto";
24
+ }
25
+ const suit = card.slice(-1);
26
+ const number = card.slice(0, -1);
27
+ const cardNumber = (_a = CARD_NUMBER_NAMES[number]) !== null && _a !== void 0 ? _a : number;
28
+ const suitName = (_b = SUIT_NAMES[suit]) !== null && _b !== void 0 ? _b : suit;
29
+ return `${cardNumber} de ${suitName}`;
30
+ };
31
+ export const renderTutorialRoundResult = (playedCards) => {
32
+ if (playedCards.length !== 2) {
33
+ return null;
34
+ }
35
+ const humanCard = playedCards.find((playedCard) => !playedCard.player.bot);
36
+ const botCard = playedCards.find((playedCard) => playedCard.player.bot);
37
+ if (!humanCard || !botCard) {
38
+ return null;
39
+ }
40
+ const humanValue = CARDS[humanCard.card];
41
+ const botValue = CARDS[botCard.card];
42
+ if (humanValue === undefined || botValue === undefined) {
43
+ return null;
44
+ }
45
+ const humanName = getTutorialCardName(humanCard.card);
46
+ const botName = getTutorialCardName(botCard.card);
47
+ if (humanValue > botValue) {
48
+ return `Ganaste la ronda: tu ${humanName} le gana al ${botName} del Profe.`;
49
+ }
50
+ if (botValue > humanValue) {
51
+ return `Gano el Profe: su ${botName} le gana a tu ${humanName}.`;
52
+ }
53
+ return `Parda: tu ${humanName} y el ${botName} tienen la misma fuerza.`;
54
+ };
55
+ export const renderTutorialPreviousRoundScore = (rounds) => {
56
+ const completedRounds = (rounds !== null && rounds !== void 0 ? rounds : []).filter((round) => round.cards.length >= 2);
57
+ if (!completedRounds.length) {
58
+ return null;
59
+ }
60
+ const score = completedRounds.reduce((current, round) => {
61
+ var _a;
62
+ if (round.tie) {
63
+ current.ties += 1;
64
+ return current;
65
+ }
66
+ if ((_a = round.winner) === null || _a === void 0 ? void 0 : _a.bot) {
67
+ current.bot += 1;
68
+ return current;
69
+ }
70
+ if (round.winner) {
71
+ current.human += 1;
72
+ }
73
+ return current;
74
+ }, { human: 0, bot: 0, ties: 0 });
75
+ if (score.human === 1 && score.bot === 1 && score.ties === 0) {
76
+ return "Van una ronda ganada cada uno.";
77
+ }
78
+ if (score.human === 1 && score.bot === 0 && score.ties === 0) {
79
+ return "Venis con una ronda ganada.";
80
+ }
81
+ if (score.bot === 1 && score.human === 0 && score.ties === 0) {
82
+ return "El Profe viene con una ronda ganada.";
83
+ }
84
+ if (score.ties === 1 && score.human === 0 && score.bot === 0) {
85
+ return "La primera fue parda.";
86
+ }
87
+ return "Las rondas anteriores dejaron la mano abierta.";
88
+ };
89
+ export const renderTutorialMessageText = (text, roundCards, previousRounds) => {
90
+ let renderedText = text;
91
+ if (renderedText.includes(TUTORIAL_ROUND_RESULT_TOKEN)) {
92
+ const roundResult = roundCards ? renderTutorialRoundResult(roundCards) : null;
93
+ if (!roundResult) {
94
+ return null;
95
+ }
96
+ renderedText = renderedText.split(TUTORIAL_ROUND_RESULT_TOKEN).join(roundResult);
97
+ }
98
+ if (renderedText.includes(TUTORIAL_PREVIOUS_ROUND_SCORE_TOKEN)) {
99
+ const previousRoundScore = renderTutorialPreviousRoundScore(previousRounds);
100
+ if (!previousRoundScore) {
101
+ return null;
102
+ }
103
+ renderedText = renderedText
104
+ .split(TUTORIAL_PREVIOUS_ROUND_SCORE_TOKEN)
105
+ .join(previousRoundScore);
106
+ }
107
+ return renderedText;
108
+ };
4
109
  const MESSAGE_TRIGGERS = [
5
110
  "hand_start",
6
111
  "before_human_turn",
@@ -29,6 +134,11 @@ const assertValidActionValue = (value, context) => {
29
134
  }
30
135
  throw new Error(`${context} has invalid action value: ${String(value)}`);
31
136
  };
137
+ const validateCardList = (value, context) => {
138
+ if (!Array.isArray(value) || value.some((card) => !isCard(card))) {
139
+ throw new Error(`${context} must be a list of valid card ids`);
140
+ }
141
+ };
32
142
  const validateMessage = (message, context) => {
33
143
  if (!MESSAGE_TRIGGERS.includes(message.trigger)) {
34
144
  throw new Error(`${context} has invalid trigger: ${message.trigger}`);
@@ -36,8 +146,8 @@ const validateMessage = (message, context) => {
36
146
  if (typeof message.text !== "string" || !message.text.trim()) {
37
147
  throw new Error(`${context} must contain text`);
38
148
  }
39
- if (message.text.length > 120) {
40
- throw new Error(`${context} text is longer than 120 characters`);
149
+ if (message.text.length > 155) {
150
+ throw new Error(`${context} text is longer than 155 characters`);
41
151
  }
42
152
  if (message.state && !HAND_STATES.has(message.state)) {
43
153
  throw new Error(`${context} has invalid state: ${message.state}`);
@@ -45,6 +155,19 @@ const validateMessage = (message, context) => {
45
155
  if (message.actionValue !== undefined) {
46
156
  assertValidActionValue(message.actionValue, context);
47
157
  }
158
+ if (message.roundComplete !== undefined && typeof message.roundComplete !== "boolean") {
159
+ throw new Error(`${context} has invalid roundComplete`);
160
+ }
161
+ if (message.roundCardCount !== undefined &&
162
+ (!Number.isInteger(message.roundCardCount) || message.roundCardCount < 0)) {
163
+ throw new Error(`${context} has invalid roundCardCount`);
164
+ }
165
+ if (message.requiresHandCards !== undefined) {
166
+ validateCardList(message.requiresHandCards, `${context} requiresHandCards`);
167
+ }
168
+ if (message.requiresRoundCards !== undefined) {
169
+ validateCardList(message.requiresRoundCards, `${context} requiresRoundCards`);
170
+ }
48
171
  };
49
172
  const validateBotAction = (botAction, context) => {
50
173
  var _a;
package/dist/types.d.ts CHANGED
@@ -55,6 +55,10 @@ export interface ITutorialMessage {
55
55
  state?: EHandState;
56
56
  playerIdx?: number;
57
57
  actionValue?: ECommand | ICard | number;
58
+ roundComplete?: boolean;
59
+ roundCardCount?: number;
60
+ requiresHandCards?: ICard[];
61
+ requiresRoundCards?: ICard[];
58
62
  }
59
63
  export interface ITutorialBotAction {
60
64
  trigger: Extract<ITutorialMessageTrigger, "before_bot_action">;
@@ -96,6 +100,7 @@ export interface IJoinQueueOptions {
96
100
  export interface IQueueStatus {
97
101
  requestId: string;
98
102
  maxPlayers: 0 | 2 | 4 | 6;
103
+ allowBots: boolean;
99
104
  queuedPlayers: number;
100
105
  requiredPlayers: number;
101
106
  position: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trucoshi",
3
- "version": "12.1.1",
3
+ "version": "12.2.0",
4
4
  "description": "Truco Game Server",
5
5
  "main": "dist/types.js",
6
6
  "license": "GPL-3.0",
@@ -36,11 +36,11 @@ exports.Prisma = Prisma
36
36
  exports.$Enums = {}
37
37
 
38
38
  /**
39
- * Prisma Client JS version: 6.19.2
39
+ * Prisma Client JS version: 6.19.3
40
40
  * Query Engine version: c2990dca591cba766e3b7ef5d9e8a84796e47ab7
41
41
  */
42
42
  Prisma.prismaVersion = {
43
- client: "6.19.2",
43
+ client: "6.19.3",
44
44
  engine: "c2990dca591cba766e3b7ef5d9e8a84796e47ab7"
45
45
  }
46
46
 
@@ -330,7 +330,7 @@ const config = {
330
330
  "schemaEnvPath": "../../.env"
331
331
  },
332
332
  "relativePath": "..",
333
- "clientVersion": "6.19.2",
333
+ "clientVersion": "6.19.3",
334
334
  "engineVersion": "c2990dca591cba766e3b7ef5d9e8a84796e47ab7",
335
335
  "datasourceNames": [
336
336
  "db"
@@ -21,11 +21,11 @@ exports.Prisma = Prisma
21
21
  exports.$Enums = {}
22
22
 
23
23
  /**
24
- * Prisma Client JS version: 6.19.2
24
+ * Prisma Client JS version: 6.19.3
25
25
  * Query Engine version: c2990dca591cba766e3b7ef5d9e8a84796e47ab7
26
26
  */
27
27
  Prisma.prismaVersion = {
28
- client: "6.19.2",
28
+ client: "6.19.3",
29
29
  engine: "c2990dca591cba766e3b7ef5d9e8a84796e47ab7"
30
30
  }
31
31
 
@@ -418,7 +418,7 @@ export namespace Prisma {
418
418
  export import Exact = $Public.Exact
419
419
 
420
420
  /**
421
- * Prisma Client JS version: 6.19.2
421
+ * Prisma Client JS version: 6.19.3
422
422
  * Query Engine version: c2990dca591cba766e3b7ef5d9e8a84796e47ab7
423
423
  */
424
424
  export type PrismaVersion = {
@@ -36,11 +36,11 @@ exports.Prisma = Prisma
36
36
  exports.$Enums = {}
37
37
 
38
38
  /**
39
- * Prisma Client JS version: 6.19.2
39
+ * Prisma Client JS version: 6.19.3
40
40
  * Query Engine version: c2990dca591cba766e3b7ef5d9e8a84796e47ab7
41
41
  */
42
42
  Prisma.prismaVersion = {
43
- client: "6.19.2",
43
+ client: "6.19.3",
44
44
  engine: "c2990dca591cba766e3b7ef5d9e8a84796e47ab7"
45
45
  }
46
46
 
@@ -331,7 +331,7 @@ const config = {
331
331
  "schemaEnvPath": "../../.env"
332
332
  },
333
333
  "relativePath": "..",
334
- "clientVersion": "6.19.2",
334
+ "clientVersion": "6.19.3",
335
335
  "engineVersion": "c2990dca591cba766e3b7ef5d9e8a84796e47ab7",
336
336
  "datasourceNames": [
337
337
  "db"
@@ -151,7 +151,7 @@
151
151
  },
152
152
  "./*": "./*"
153
153
  },
154
- "version": "6.19.2",
154
+ "version": "6.19.3",
155
155
  "sideEffects": false,
156
156
  "imports": {
157
157
  "#wasm-engine-loader": {
@@ -36,11 +36,11 @@ exports.Prisma = Prisma
36
36
  exports.$Enums = {}
37
37
 
38
38
  /**
39
- * Prisma Client JS version: 6.19.2
39
+ * Prisma Client JS version: 6.19.3
40
40
  * Query Engine version: c2990dca591cba766e3b7ef5d9e8a84796e47ab7
41
41
  */
42
42
  Prisma.prismaVersion = {
43
- client: "6.19.2",
43
+ client: "6.19.3",
44
44
  engine: "c2990dca591cba766e3b7ef5d9e8a84796e47ab7"
45
45
  }
46
46
 
@@ -330,7 +330,7 @@ const config = {
330
330
  "schemaEnvPath": "../../.env"
331
331
  },
332
332
  "relativePath": "..",
333
- "clientVersion": "6.19.2",
333
+ "clientVersion": "6.19.3",
334
334
  "engineVersion": "c2990dca591cba766e3b7ef5d9e8a84796e47ab7",
335
335
  "datasourceNames": [
336
336
  "db"