@javleds/vue-game-engine 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 (44) hide show
  1. package/LICENSE +21 -0
  2. package/README.es.md +169 -0
  3. package/README.md +177 -0
  4. package/dist/composables/useRoomConnectionLifecycle.d.ts +2 -0
  5. package/dist/composables/useRoomConnectionLifecycle.d.ts.map +1 -0
  6. package/dist/composables/useRoomConnectionLifecycle.js +18 -0
  7. package/dist/composables/useRoomConnectionLifecycle.js.map +1 -0
  8. package/dist/composables/useRoomRealtime.d.ts +14 -0
  9. package/dist/composables/useRoomRealtime.d.ts.map +1 -0
  10. package/dist/composables/useRoomRealtime.js +16 -0
  11. package/dist/composables/useRoomRealtime.js.map +1 -0
  12. package/dist/index.d.ts +10 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/index.js +8 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/realtime/realtimeClient.d.ts +11 -0
  17. package/dist/realtime/realtimeClient.d.ts.map +1 -0
  18. package/dist/realtime/realtimeClient.js +11 -0
  19. package/dist/realtime/realtimeClient.js.map +1 -0
  20. package/dist/repositories/chatRepository.d.ts +5 -0
  21. package/dist/repositories/chatRepository.d.ts.map +1 -0
  22. package/dist/repositories/chatRepository.js +10 -0
  23. package/dist/repositories/chatRepository.js.map +1 -0
  24. package/dist/repositories/http.d.ts +5 -0
  25. package/dist/repositories/http.d.ts.map +1 -0
  26. package/dist/repositories/http.js +13 -0
  27. package/dist/repositories/http.js.map +1 -0
  28. package/dist/repositories/roomsRepository.d.ts +9 -0
  29. package/dist/repositories/roomsRepository.d.ts.map +1 -0
  30. package/dist/repositories/roomsRepository.js +44 -0
  31. package/dist/repositories/roomsRepository.js.map +1 -0
  32. package/dist/stores/sessionStore.d.ts +28 -0
  33. package/dist/stores/sessionStore.d.ts.map +1 -0
  34. package/dist/stores/sessionStore.js +72 -0
  35. package/dist/stores/sessionStore.js.map +1 -0
  36. package/dist/types/chat.d.ts +10 -0
  37. package/dist/types/chat.d.ts.map +1 -0
  38. package/dist/types/chat.js +2 -0
  39. package/dist/types/chat.js.map +1 -0
  40. package/dist/types/room.d.ts +28 -0
  41. package/dist/types/room.d.ts.map +1 -0
  42. package/dist/types/room.js +2 -0
  43. package/dist/types/room.js.map +1 -0
  44. package/package.json +56 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Javleds
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.es.md ADDED
@@ -0,0 +1,169 @@
1
+ # Vue Game Engine
2
+
3
+ Paquete frontend reusable para juegos de mesa en linea por turnos usando Vue.
4
+
5
+ Este paquete contiene la capa cliente generica: repositorios HTTP de sala, repositorios de chat, almacenamiento de sesion del jugador, ciclo de conexion de sala y suscripciones realtime. No renderiza un tablero especifico y no contiene reglas de juego.
6
+
7
+ La documentacion principal en ingles esta en [README.md](README.md).
8
+
9
+ ## Enlaces de Repositorio
10
+
11
+ Repositorios oficiales:
12
+
13
+ - Paquete frontend Vue: https://github.com/javleds/vue-game-engine
14
+ - Paquete backend Laravel: https://github.com/javleds/laravel-game-engine
15
+
16
+ ## Relacion Backend / Frontend
17
+
18
+ `@javleds/vue-game-engine` es la mitad frontend del motor. `javleds/laravel-game-engine` es la mitad backend. El frontend consume endpoints HTTP, guarda la sesion local del jugador y escucha eventos realtime por sala. El backend mantiene el estado autoritativo.
19
+
20
+ ```plantuml
21
+ @startuml
22
+ skinparam componentStyle rectangle
23
+
24
+ package "Aplicacion Vue host" {
25
+ [Paginas del juego]
26
+ [Componentes UI]
27
+ [Repositorios de acciones]
28
+ [Setup de Echo]
29
+ }
30
+
31
+ package "@javleds/vue-game-engine" {
32
+ [Repositorio de sala]
33
+ [Repositorio de chat]
34
+ [Store de sesion]
35
+ [Composables realtime]
36
+ }
37
+
38
+ package "javleds/laravel-game-engine" {
39
+ [Servicios de sala]
40
+ [Servicios de chat]
41
+ [Command Runner]
42
+ [Broadcast events]
43
+ }
44
+
45
+ [Paginas del juego] --> [Repositorio de sala]
46
+ [Paginas del juego] --> [Store de sesion]
47
+ [Setup de Echo] --> [Composables realtime]
48
+ [Repositorio de sala] --> [Servicios de sala]
49
+ [Repositorio de chat] --> [Servicios de chat]
50
+ [Broadcast events] --> [Composables realtime]
51
+ @enduml
52
+ ```
53
+
54
+ ## Que Resuelve
55
+
56
+ El paquete frontend resuelve:
57
+
58
+ - Llamadas HTTP genericas para crear, unir, salir, iniciar, desconectar y consultar estado de sala.
59
+ - Llamadas HTTP genericas para listar y enviar mensajes de chat.
60
+ - Helper de bearer token para requests por jugador.
61
+ - Store Pinia para datos de reconexion.
62
+ - Suscripciones realtime por sala para cambios de estado y chat.
63
+ - Composable de ciclo de conexion/desconexion.
64
+ - Tipos TypeScript compartidos para sala y chat.
65
+
66
+ La aplicacion host sigue siendo responsable de:
67
+
68
+ - Paginas y componentes Vue.
69
+ - Repositorios de acciones especificas del juego.
70
+ - Tipos TypeScript del estado y comandos del juego.
71
+ - Configurar Laravel Echo u otro cliente realtime compatible.
72
+ - Estilos, rutas y comportamiento de UI.
73
+
74
+ ## Instalacion Local
75
+
76
+ Para desarrollo con repos hermanos:
77
+
78
+ ```json
79
+ {
80
+ "dependencies": {
81
+ "@javleds/vue-game-engine": "file:../vue-game-engine"
82
+ }
83
+ }
84
+ ```
85
+
86
+ Despues:
87
+
88
+ ```bash
89
+ npm install
90
+ ```
91
+
92
+ Cuando el paquete este publicado en npm, se podra reemplazar el `file:` por una version semantica.
93
+
94
+ ## Setup en la App Host
95
+
96
+ Configura el cliente realtime durante el arranque de la app. Laravel Echo es el cliente esperado por defecto:
97
+
98
+ ```ts
99
+ import Echo from 'laravel-echo'
100
+ import Pusher from 'pusher-js'
101
+ import { configureTurnEngineRealtime } from '@javleds/vue-game-engine'
102
+
103
+ window.Pusher = Pusher
104
+
105
+ const echo = new Echo({
106
+ broadcaster: 'reverb',
107
+ key: import.meta.env.VITE_REVERB_APP_KEY,
108
+ wsHost: import.meta.env.VITE_REVERB_HOST,
109
+ wsPort: Number(import.meta.env.VITE_REVERB_PORT ?? 80),
110
+ wssPort: Number(import.meta.env.VITE_REVERB_PORT ?? 443),
111
+ forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
112
+ enabledTransports: ['ws', 'wss'],
113
+ authEndpoint: '/broadcasting/auth',
114
+ })
115
+
116
+ configureTurnEngineRealtime(echo)
117
+ ```
118
+
119
+ Importa ese modulo antes de montar Vue:
120
+
121
+ ```ts
122
+ import './echo'
123
+ ```
124
+
125
+ Cuando uses paquetes locales enlazados, conserva symlinks para que TypeScript y Vite resuelvan las peer dependencies desde la app host:
126
+
127
+ ```json
128
+ {
129
+ "compilerOptions": {
130
+ "preserveSymlinks": true
131
+ }
132
+ }
133
+ ```
134
+
135
+ ```ts
136
+ export default defineConfig({
137
+ resolve: {
138
+ preserveSymlinks: true,
139
+ },
140
+ })
141
+ ```
142
+
143
+ ## Contrato Backend / Frontend
144
+
145
+ El paquete espera endpoints compatibles con estos flujos:
146
+
147
+ - Ciclo de sala: crear, unir, salir, iniciar, desconectar, reconectar/consultar estado.
148
+ - Chat: listar mensajes y enviar mensaje.
149
+ - Eventos realtime en canales `room.{roomId}`:
150
+ - `.room.state.changed`
151
+ - `.room.chat.message.created`
152
+
153
+ Los comandos especificos del juego quedan fuera del paquete. La app host debe crear su propio repositorio de acciones y puede reutilizar el cliente `http` y el helper `bearer` exportados.
154
+
155
+ ## Checklist Para Publicar
156
+
157
+ - Mantener `dist` generado por `npm run build` antes de publicar.
158
+ - Agregar CI para typecheck, build e instalacion de prueba.
159
+ - Crear tag semantico, por ejemplo `v0.1.0`.
160
+
161
+ ## Build
162
+
163
+ Este paquete publica JavaScript compilado y declaraciones desde `dist`.
164
+
165
+ ```bash
166
+ npm install
167
+ npm run build
168
+ npm pack --dry-run
169
+ ```
package/README.md ADDED
@@ -0,0 +1,177 @@
1
+ # Vue Game Engine
2
+
3
+ Reusable Vue client package for online turn-based board games.
4
+
5
+ This package owns the generic frontend client layer: room HTTP repositories, chat repositories, player session storage, room connection lifecycle, and realtime subscriptions. It does not render a specific game board and does not contain game rules.
6
+
7
+ Spanish documentation is available in [README.es.md](README.es.md).
8
+
9
+ ## Repository Links
10
+
11
+ Official repositories:
12
+
13
+ - Vue frontend package: https://github.com/javleds/vue-game-engine
14
+ - Laravel backend package: https://github.com/javleds/laravel-game-engine
15
+
16
+ ## Package Pair
17
+
18
+ This package is the frontend half of the engine. It is designed to work with the Laravel backend package, `javleds/laravel-game-engine`, through HTTP endpoints and realtime room events.
19
+
20
+ ```plantuml
21
+ @startuml
22
+ skinparam componentStyle rectangle
23
+
24
+ package "Host Vue app" {
25
+ [Game Pages]
26
+ [Game UI Components]
27
+ [Game Action Repositories]
28
+ [Echo Setup]
29
+ }
30
+
31
+ package "@javleds/vue-game-engine" {
32
+ [Room Repository]
33
+ [Chat Repository]
34
+ [Session Store]
35
+ [Realtime Composables]
36
+ }
37
+
38
+ package "javleds/laravel-game-engine" {
39
+ [Room Services]
40
+ [Chat Services]
41
+ [Command Runner]
42
+ [Broadcast Events]
43
+ }
44
+
45
+ [Game Pages] --> [Room Repository]
46
+ [Game Pages] --> [Session Store]
47
+ [Game Pages] --> [Realtime Composables]
48
+ [Game Action Repositories] --> [Command Runner]
49
+ [Echo Setup] --> [Realtime Composables]
50
+ [Room Repository] --> [Room Services]
51
+ [Chat Repository] --> [Chat Services]
52
+ [Broadcast Events] --> [Realtime Composables]
53
+ @enduml
54
+ ```
55
+
56
+ ## Responsibilities
57
+
58
+ The package provides:
59
+
60
+ - Generic room HTTP calls: create, join, leave, start, disconnect, and fetch state.
61
+ - Generic chat HTTP calls: list and send room messages.
62
+ - Bearer-token helper for room-scoped requests.
63
+ - Pinia session store for player reconnect data.
64
+ - Realtime room subscriptions for state and chat events.
65
+ - Connection lifecycle composable for disconnect keepalive behavior.
66
+ - Shared TypeScript types for room and chat API responses.
67
+
68
+ The host game provides:
69
+
70
+ - Vue pages and components.
71
+ - Game-specific action repositories.
72
+ - Game-specific TypeScript state and command payload types.
73
+ - Laravel Echo or another compatible realtime client.
74
+ - Styling, routing, and UI behavior.
75
+
76
+ ## Installation
77
+
78
+ For local development with a sibling checkout:
79
+
80
+ ```json
81
+ {
82
+ "dependencies": {
83
+ "@javleds/vue-game-engine": "file:../vue-game-engine"
84
+ }
85
+ }
86
+ ```
87
+
88
+ Then run:
89
+
90
+ ```bash
91
+ npm install
92
+ ```
93
+
94
+ For npm registry usage, replace the file dependency with the published package version once the repository is published.
95
+
96
+ ## Host App Setup
97
+
98
+ Configure the realtime client during app boot. Laravel Echo is the expected default client:
99
+
100
+ ```ts
101
+ import Echo from 'laravel-echo'
102
+ import Pusher from 'pusher-js'
103
+ import { configureTurnEngineRealtime } from '@javleds/vue-game-engine'
104
+
105
+ window.Pusher = Pusher
106
+
107
+ const echo = new Echo({
108
+ broadcaster: 'reverb',
109
+ key: import.meta.env.VITE_REVERB_APP_KEY,
110
+ wsHost: import.meta.env.VITE_REVERB_HOST,
111
+ wsPort: Number(import.meta.env.VITE_REVERB_PORT ?? 80),
112
+ wssPort: Number(import.meta.env.VITE_REVERB_PORT ?? 443),
113
+ forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
114
+ enabledTransports: ['ws', 'wss'],
115
+ authEndpoint: '/broadcasting/auth',
116
+ })
117
+
118
+ configureTurnEngineRealtime(echo)
119
+ ```
120
+
121
+ Import that setup module before mounting Vue.
122
+
123
+ ```ts
124
+ import './echo'
125
+ ```
126
+
127
+ When using local linked packages, preserve symlinks so TypeScript and Vite resolve peer dependencies from the host app:
128
+
129
+ ```json
130
+ {
131
+ "compilerOptions": {
132
+ "preserveSymlinks": true
133
+ }
134
+ }
135
+ ```
136
+
137
+ ```ts
138
+ export default defineConfig({
139
+ resolve: {
140
+ preserveSymlinks: true,
141
+ },
142
+ })
143
+ ```
144
+
145
+ ## Backend / Frontend Contract
146
+
147
+ The package expects host endpoints compatible with these flows:
148
+
149
+ - Room lifecycle: create, join, leave, start, disconnect, reconnect/state fetch.
150
+ - Chat lifecycle: list messages and send message.
151
+ - Realtime events on `room.{roomId}` channels:
152
+ - `.room.state.changed`
153
+ - `.room.chat.message.created`
154
+
155
+ Game-specific commands are intentionally outside this package. A game app should create its own action repository and can reuse the exported `http` client and `bearer` helper.
156
+
157
+ ## Publishing Checklist
158
+
159
+ Before publishing this package publicly:
160
+
161
+ - Keep `dist` generated by `npm run build` before publishing.
162
+ - Add CI for typecheck, package build, and install smoke tests.
163
+ - Tag a semantic version, for example `v0.1.0`.
164
+
165
+ ## Current Status
166
+
167
+ This package is extracted and usable as a local npm file package. It is not tied to the Giants game domain.
168
+
169
+ ## Build
170
+
171
+ This package publishes compiled JavaScript and declaration files from `dist`.
172
+
173
+ ```bash
174
+ npm install
175
+ npm run build
176
+ npm pack --dry-run
177
+ ```
@@ -0,0 +1,2 @@
1
+ export declare function useRoomConnectionLifecycle(roomId: string, token: () => string | null): void;
2
+ //# sourceMappingURL=useRoomConnectionLifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRoomConnectionLifecycle.d.ts","sourceRoot":"","sources":["../../src/composables/useRoomConnectionLifecycle.ts"],"names":[],"mappings":"AAIA,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,IAAI,CAkB3F"}
@@ -0,0 +1,18 @@
1
+ import { onMounted, onUnmounted } from 'vue';
2
+ import { disconnectRoomKeepalive } from '../repositories/roomsRepository';
3
+ export function useRoomConnectionLifecycle(roomId, token) {
4
+ function notifyDisconnect() {
5
+ const playerToken = token();
6
+ if (!playerToken) {
7
+ return;
8
+ }
9
+ disconnectRoomKeepalive(roomId, playerToken);
10
+ }
11
+ onMounted(() => {
12
+ window.addEventListener('pagehide', notifyDisconnect);
13
+ });
14
+ onUnmounted(() => {
15
+ window.removeEventListener('pagehide', notifyDisconnect);
16
+ });
17
+ }
18
+ //# sourceMappingURL=useRoomConnectionLifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRoomConnectionLifecycle.js","sourceRoot":"","sources":["../../src/composables/useRoomConnectionLifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,KAAK,CAAA;AAE5C,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAA;AAEzE,MAAM,UAAU,0BAA0B,CAAC,MAAc,EAAE,KAA0B;IACnF,SAAS,gBAAgB;QACvB,MAAM,WAAW,GAAG,KAAK,EAAE,CAAA;QAE3B,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAM;QACR,CAAC;QAED,uBAAuB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;IAC9C,CAAC;IAED,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAA;IACvD,CAAC,CAAC,CAAA;IAEF,WAAW,CAAC,GAAG,EAAE;QACf,MAAM,CAAC,mBAAmB,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAA;IAC1D,CAAC,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,14 @@
1
+ interface RoomStateChangedEvent {
2
+ roomId: string;
3
+ stateVersion: number;
4
+ }
5
+ interface RoomChatMessageCreatedEvent {
6
+ roomId: string;
7
+ messageId: string;
8
+ }
9
+ export declare function useRoomRealtime(roomId: string, handlers: {
10
+ onStateChanged?: (event: RoomStateChangedEvent) => void | Promise<void>;
11
+ onChatMessageCreated?: (event: RoomChatMessageCreatedEvent) => void | Promise<void>;
12
+ }): void;
13
+ export {};
14
+ //# sourceMappingURL=useRoomRealtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRoomRealtime.d.ts","sourceRoot":"","sources":["../../src/composables/useRoomRealtime.ts"],"names":[],"mappings":"AAIA,UAAU,qBAAqB;IAC7B,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,UAAU,2BAA2B;IACnC,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE;IACR,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACvE,oBAAoB,CAAC,EAAE,CAAC,KAAK,EAAE,2BAA2B,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACpF,GACA,IAAI,CAcN"}
@@ -0,0 +1,16 @@
1
+ import { onBeforeUnmount } from 'vue';
2
+ import { roomRealtimeClient } from '../realtime/realtimeClient';
3
+ export function useRoomRealtime(roomId, handlers) {
4
+ const echo = roomRealtimeClient();
5
+ const channel = echo.channel(`room.${roomId}`);
6
+ channel.listen('.room.state.changed', (event) => {
7
+ void handlers.onStateChanged?.(event);
8
+ });
9
+ channel.listen('.room.chat.message.created', (event) => {
10
+ void handlers.onChatMessageCreated?.(event);
11
+ });
12
+ onBeforeUnmount(() => {
13
+ echo.leave(`room.${roomId}`);
14
+ });
15
+ }
16
+ //# sourceMappingURL=useRoomRealtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRoomRealtime.js","sourceRoot":"","sources":["../../src/composables/useRoomRealtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,KAAK,CAAA;AAErC,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAA;AAY/D,MAAM,UAAU,eAAe,CAC7B,MAAc,EACd,QAGC;IAED,MAAM,IAAI,GAAG,kBAAkB,EAAE,CAAA;IACjC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,MAAM,EAAE,CAAC,CAAA;IAE9C,OAAO,CAAC,MAAM,CAAC,qBAAqB,EAAE,CAAC,KAA4B,EAAE,EAAE;QACrE,KAAK,QAAQ,CAAC,cAAc,EAAE,CAAC,KAAK,CAAC,CAAA;IACvC,CAAC,CAAC,CAAA;IACF,OAAO,CAAC,MAAM,CAAC,4BAA4B,EAAE,CAAC,KAAkC,EAAE,EAAE;QAClF,KAAK,QAAQ,CAAC,oBAAoB,EAAE,CAAC,KAAK,CAAC,CAAA;IAC7C,CAAC,CAAC,CAAA;IAEF,eAAe,CAAC,GAAG,EAAE;QACnB,IAAI,CAAC,KAAK,CAAC,QAAQ,MAAM,EAAE,CAAC,CAAA;IAC9B,CAAC,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,10 @@
1
+ export { useRoomConnectionLifecycle } from './composables/useRoomConnectionLifecycle';
2
+ export { useRoomRealtime } from './composables/useRoomRealtime';
3
+ export { configureTurnEngineRealtime } from './realtime/realtimeClient';
4
+ export { bearer, http } from './repositories/http';
5
+ export { createRoom, disconnectRoom, disconnectRoomKeepalive, getRoomState, joinRoom, leaveRoom, startRoomGame, } from './repositories/roomsRepository';
6
+ export { listChatMessages, sendChatMessage, type ChatMessageKind, } from './repositories/chatRepository';
7
+ export { useSessionStore } from './stores/sessionStore';
8
+ export type { ChatMessageView } from './types/chat';
9
+ export type { LobbyPlayer, RoomSessionResponse, RoomStateResponse, RoomSummary, } from './types/room';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,0CAA0C,CAAA;AACrF,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAA;AACvE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EACL,UAAU,EACV,cAAc,EACd,uBAAuB,EACvB,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,aAAa,GACd,MAAM,gCAAgC,CAAA;AACvC,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,KAAK,eAAe,GACrB,MAAM,+BAA+B,CAAA;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACvD,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACnD,YAAY,EACV,WAAW,EACX,mBAAmB,EACnB,iBAAiB,EACjB,WAAW,GACZ,MAAM,cAAc,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ export { useRoomConnectionLifecycle } from './composables/useRoomConnectionLifecycle';
2
+ export { useRoomRealtime } from './composables/useRoomRealtime';
3
+ export { configureTurnEngineRealtime } from './realtime/realtimeClient';
4
+ export { bearer, http } from './repositories/http';
5
+ export { createRoom, disconnectRoom, disconnectRoomKeepalive, getRoomState, joinRoom, leaveRoom, startRoomGame, } from './repositories/roomsRepository';
6
+ export { listChatMessages, sendChatMessage, } from './repositories/chatRepository';
7
+ export { useSessionStore } from './stores/sessionStore';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,0CAA0C,CAAA;AACrF,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAA;AACvE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EACL,UAAU,EACV,cAAc,EACd,uBAAuB,EACvB,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,aAAa,GACd,MAAM,gCAAgC,CAAA;AACvC,OAAO,EACL,gBAAgB,EAChB,eAAe,GAEhB,MAAM,+BAA+B,CAAA;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA"}
@@ -0,0 +1,11 @@
1
+ interface RoomChannel {
2
+ listen(event: string, callback: (payload: never) => void): RoomChannel;
3
+ }
4
+ interface RealtimeClient {
5
+ channel(name: string): RoomChannel;
6
+ leave(name: string): void;
7
+ }
8
+ export declare function configureTurnEngineRealtime(client: RealtimeClient): void;
9
+ export declare function roomRealtimeClient(): RealtimeClient;
10
+ export {};
11
+ //# sourceMappingURL=realtimeClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtimeClient.d.ts","sourceRoot":"","sources":["../../src/realtime/realtimeClient.ts"],"names":[],"mappings":"AAAA,UAAU,WAAW;IACnB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,KAAK,KAAK,IAAI,GAAG,WAAW,CAAA;CACvE;AAED,UAAU,cAAc;IACtB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAA;IAClC,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B;AAID,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAExE;AAED,wBAAgB,kBAAkB,IAAI,cAAc,CAMnD"}
@@ -0,0 +1,11 @@
1
+ let realtimeClient = null;
2
+ export function configureTurnEngineRealtime(client) {
3
+ realtimeClient = client;
4
+ }
5
+ export function roomRealtimeClient() {
6
+ if (!realtimeClient) {
7
+ throw new Error('Turn engine realtime client has not been configured.');
8
+ }
9
+ return realtimeClient;
10
+ }
11
+ //# sourceMappingURL=realtimeClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtimeClient.js","sourceRoot":"","sources":["../../src/realtime/realtimeClient.ts"],"names":[],"mappings":"AASA,IAAI,cAAc,GAA0B,IAAI,CAAA;AAEhD,MAAM,UAAU,2BAA2B,CAAC,MAAsB;IAChE,cAAc,GAAG,MAAM,CAAA;AACzB,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAA;IACzE,CAAC;IAED,OAAO,cAAc,CAAA;AACvB,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { ChatMessageView } from '../types/chat';
2
+ export type ChatMessageKind = ChatMessageView['kind'];
3
+ export declare function listChatMessages(roomId: string, token: string, kind?: ChatMessageKind): Promise<ChatMessageView[]>;
4
+ export declare function sendChatMessage(roomId: string, token: string, message: string): Promise<ChatMessageView>;
5
+ //# sourceMappingURL=chatRepository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chatRepository.d.ts","sourceRoot":"","sources":["../../src/repositories/chatRepository.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAEpD,MAAM,MAAM,eAAe,GAAG,eAAe,CAAC,MAAM,CAAC,CAAA;AAErD,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,eAAwB,GAC7B,OAAO,CAAC,eAAe,EAAE,CAAC,CAO5B;AAED,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,eAAe,CAAC,CAQ1B"}
@@ -0,0 +1,10 @@
1
+ import { bearer, http } from './http';
2
+ export async function listChatMessages(roomId, token, kind = 'chat') {
3
+ const response = await http.get(`/rooms/${roomId}/chat/messages`, { headers: bearer(token), params: { kind } });
4
+ return response.data.messages;
5
+ }
6
+ export async function sendChatMessage(roomId, token, message) {
7
+ const response = await http.post(`/rooms/${roomId}/chat/messages`, { message }, { headers: bearer(token) });
8
+ return response.data.message;
9
+ }
10
+ //# sourceMappingURL=chatRepository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chatRepository.js","sourceRoot":"","sources":["../../src/repositories/chatRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAKrC,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,MAAc,EACd,KAAa,EACb,OAAwB,MAAM;IAE9B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAC7B,UAAU,MAAM,gBAAgB,EAChC,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,CAC7C,CAAA;IAED,OAAO,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAA;AAC/B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAAc,EACd,KAAa,EACb,OAAe;IAEf,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAC9B,UAAU,MAAM,gBAAgB,EAChC,EAAE,OAAO,EAAE,EACX,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAC3B,CAAA;IAED,OAAO,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAA;AAC9B,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare const http: import("axios").AxiosInstance;
2
+ export declare function bearer(token: string): {
3
+ Authorization: string;
4
+ };
5
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/repositories/http.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,IAAI,+BAKf,CAAA;AAEF,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,CAI/D"}
@@ -0,0 +1,13 @@
1
+ import axios from 'axios';
2
+ export const http = axios.create({
3
+ baseURL: '/api',
4
+ headers: {
5
+ Accept: 'application/json',
6
+ },
7
+ });
8
+ export function bearer(token) {
9
+ return {
10
+ Authorization: `Bearer ${token}`,
11
+ };
12
+ }
13
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/repositories/http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,MAAM,CAAC,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC;IAC/B,OAAO,EAAE,MAAM;IACf,OAAO,EAAE;QACP,MAAM,EAAE,kBAAkB;KAC3B;CACF,CAAC,CAAA;AAEF,MAAM,UAAU,MAAM,CAAC,KAAa;IAClC,OAAO;QACL,aAAa,EAAE,UAAU,KAAK,EAAE;KACjC,CAAA;AACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { RoomSessionResponse, RoomStateResponse } from '../types/room';
2
+ export declare function createRoom(nickname: string): Promise<RoomSessionResponse>;
3
+ export declare function joinRoom(roomId: string, nickname: string): Promise<RoomSessionResponse>;
4
+ export declare function getRoomState<TState = unknown>(roomId: string, token: string): Promise<RoomStateResponse<TState>>;
5
+ export declare function startRoomGame(roomId: string, token: string): Promise<unknown>;
6
+ export declare function leaveRoom(roomId: string, token: string): Promise<unknown>;
7
+ export declare function disconnectRoom(roomId: string, token: string): Promise<unknown>;
8
+ export declare function disconnectRoomKeepalive(roomId: string, token: string): void;
9
+ //# sourceMappingURL=roomsRepository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roomsRepository.d.ts","sourceRoot":"","sources":["../../src/repositories/roomsRepository.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAE3E,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAI/E;AAED,wBAAsB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAI7F;AAED,wBAAsB,YAAY,CAAC,MAAM,GAAG,OAAO,EACjD,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAMpC;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAMnF;AAED,wBAAsB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAM/E;AAED,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAMpF;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAS3E"}
@@ -0,0 +1,44 @@
1
+ import { bearer, http } from './http';
2
+ export async function createRoom(nickname) {
3
+ const response = await http.post('/rooms', { nickname });
4
+ return response.data;
5
+ }
6
+ export async function joinRoom(roomId, nickname) {
7
+ const response = await http.post(`/rooms/${roomId}/join`, { nickname });
8
+ return response.data;
9
+ }
10
+ export async function getRoomState(roomId, token) {
11
+ const response = await http.get(`/rooms/${roomId}/state`, {
12
+ headers: bearer(token),
13
+ });
14
+ return response.data;
15
+ }
16
+ export async function startRoomGame(roomId, token) {
17
+ const response = await http.post(`/rooms/${roomId}/start`, {}, {
18
+ headers: bearer(token),
19
+ });
20
+ return response.data;
21
+ }
22
+ export async function leaveRoom(roomId, token) {
23
+ const response = await http.post(`/rooms/${roomId}/leave`, {}, {
24
+ headers: bearer(token),
25
+ });
26
+ return response.data;
27
+ }
28
+ export async function disconnectRoom(roomId, token) {
29
+ const response = await http.post(`/rooms/${roomId}/disconnect`, {}, {
30
+ headers: bearer(token),
31
+ });
32
+ return response.data;
33
+ }
34
+ export function disconnectRoomKeepalive(roomId, token) {
35
+ void fetch(`/api/rooms/${roomId}/disconnect`, {
36
+ method: 'POST',
37
+ headers: {
38
+ Accept: 'application/json',
39
+ Authorization: `Bearer ${token}`,
40
+ },
41
+ keepalive: true,
42
+ });
43
+ }
44
+ //# sourceMappingURL=roomsRepository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roomsRepository.js","sourceRoot":"","sources":["../../src/repositories/roomsRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAGrC,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAAgB;IAC/C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAsB,QAAQ,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAA;IAE7E,OAAO,QAAQ,CAAC,IAAI,CAAA;AACtB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,MAAc,EAAE,QAAgB;IAC7D,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAsB,UAAU,MAAM,OAAO,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAA;IAE5F,OAAO,QAAQ,CAAC,IAAI,CAAA;AACtB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAAc,EACd,KAAa;IAEb,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAA4B,UAAU,MAAM,QAAQ,EAAE;QACnF,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC;KACvB,CAAC,CAAA;IAEF,OAAO,QAAQ,CAAC,IAAI,CAAA;AACtB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAc,EAAE,KAAa;IAC/D,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAU,UAAU,MAAM,QAAQ,EAAE,EAAE,EAAE;QACtE,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC;KACvB,CAAC,CAAA;IAEF,OAAO,QAAQ,CAAC,IAAI,CAAA;AACtB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAAc,EAAE,KAAa;IAC3D,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAU,UAAU,MAAM,QAAQ,EAAE,EAAE,EAAE;QACtE,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC;KACvB,CAAC,CAAA;IAEF,OAAO,QAAQ,CAAC,IAAI,CAAA;AACtB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,MAAc,EAAE,KAAa;IAChE,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAU,UAAU,MAAM,aAAa,EAAE,EAAE,EAAE;QAC3E,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC;KACvB,CAAC,CAAA;IAEF,OAAO,QAAQ,CAAC,IAAI,CAAA;AACtB,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,MAAc,EAAE,KAAa;IACnE,KAAK,KAAK,CAAC,cAAc,MAAM,aAAa,EAAE;QAC5C,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,MAAM,EAAE,kBAAkB;YAC1B,aAAa,EAAE,UAAU,KAAK,EAAE;SACjC;QACD,SAAS,EAAE,IAAI;KAChB,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,28 @@
1
+ import type { RoomSessionResponse } from '../types/room';
2
+ interface SessionState {
3
+ roomId: string | null;
4
+ playerId: string | null;
5
+ playerToken: string | null;
6
+ publicInviteUrl: string | null;
7
+ privateReconnectUrl: string | null;
8
+ }
9
+ type StoredSessions = Record<string, SessionState>;
10
+ export declare const useSessionStore: import("pinia").StoreDefinition<"session", SessionState, {
11
+ hasSession: (state: {
12
+ roomId: string | null;
13
+ playerId: string | null;
14
+ playerToken: string | null;
15
+ publicInviteUrl: string | null;
16
+ privateReconnectUrl: string | null;
17
+ } & import("pinia").PiniaCustomStateProperties<SessionState>) => boolean;
18
+ }, {
19
+ restore(roomId: string): void;
20
+ save(session: RoomSessionResponse): void;
21
+ saveManual(session: SessionState): void;
22
+ clear(roomId?: string | null): void;
23
+ persistSession(session: SessionState): void;
24
+ storedSessions(): StoredSessions;
25
+ parseStoredSessions(): StoredSessions;
26
+ }>;
27
+ export {};
28
+ //# sourceMappingURL=sessionStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionStore.d.ts","sourceRoot":"","sources":["../../src/stores/sessionStore.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AAIxD,UAAU,YAAY;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAA;CACnC;AAED,KAAK,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;AAElD,eAAO,MAAM,eAAe;;gBATlB,MAAM,GAAG,IAAI;kBACX,MAAM,GAAG,IAAI;qBACV,MAAM,GAAG,IAAI;yBACT,MAAM,GAAG,IAAI;6BACT,MAAM,GAAG,IAAI;qEAcX,OAAO;;oBAGZ,MAAM,GAAG,IAAI;kBASf,mBAAmB,GAAG,IAAI;wBAWpB,YAAY,GAAG,IAAI;mBAGxB,MAAM,GAAG,IAAI,GAAG,IAAI;4BAcX,YAAY,GAAG,IAAI;sBAUzB,cAAc;2BAGT,cAAc;EAcvC,CAAA"}
@@ -0,0 +1,72 @@
1
+ import { defineStore } from 'pinia';
2
+ const STORAGE_KEY = 'turn-engine.sessions';
3
+ export const useSessionStore = defineStore('session', {
4
+ state: () => ({
5
+ roomId: null,
6
+ playerId: null,
7
+ playerToken: null,
8
+ publicInviteUrl: null,
9
+ privateReconnectUrl: null,
10
+ }),
11
+ getters: {
12
+ hasSession: (state) => Boolean(state.roomId && state.playerId && state.playerToken),
13
+ },
14
+ actions: {
15
+ restore(roomId) {
16
+ const session = this.storedSessions()[roomId];
17
+ if (!session) {
18
+ return;
19
+ }
20
+ this.$patch(session);
21
+ },
22
+ save(session) {
23
+ const state = {
24
+ roomId: session.roomId,
25
+ playerId: session.playerId,
26
+ playerToken: session.playerToken,
27
+ publicInviteUrl: session.publicInviteUrl,
28
+ privateReconnectUrl: session.privateReconnectUrl,
29
+ };
30
+ this.persistSession(state);
31
+ },
32
+ saveManual(session) {
33
+ this.persistSession(session);
34
+ },
35
+ clear(roomId) {
36
+ const targetRoomId = roomId ?? this.roomId;
37
+ if (targetRoomId) {
38
+ const sessions = this.storedSessions();
39
+ delete sessions[targetRoomId];
40
+ window.localStorage.setItem(STORAGE_KEY, JSON.stringify(sessions));
41
+ }
42
+ if (!targetRoomId || this.roomId === targetRoomId) {
43
+ this.$reset();
44
+ }
45
+ },
46
+ persistSession(session) {
47
+ if (!session.roomId) {
48
+ return;
49
+ }
50
+ const sessions = this.storedSessions();
51
+ sessions[session.roomId] = session;
52
+ this.$patch(session);
53
+ window.localStorage.setItem(STORAGE_KEY, JSON.stringify(sessions));
54
+ },
55
+ storedSessions() {
56
+ return this.parseStoredSessions();
57
+ },
58
+ parseStoredSessions() {
59
+ const raw = window.localStorage.getItem(STORAGE_KEY);
60
+ if (!raw) {
61
+ return {};
62
+ }
63
+ try {
64
+ return JSON.parse(raw);
65
+ }
66
+ catch {
67
+ return {};
68
+ }
69
+ },
70
+ },
71
+ });
72
+ //# sourceMappingURL=sessionStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionStore.js","sourceRoot":"","sources":["../../src/stores/sessionStore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export interface ChatMessageView {
2
+ id: string;
3
+ roomId: string;
4
+ playerId: string;
5
+ nickname: string;
6
+ kind: 'chat' | 'activity';
7
+ message: string;
8
+ createdAt: string;
9
+ }
10
+ //# sourceMappingURL=chat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/types/chat.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,GAAG,UAAU,CAAA;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;CAClB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=chat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat.js","sourceRoot":"","sources":["../../src/types/chat.ts"],"names":[],"mappings":""}
@@ -0,0 +1,28 @@
1
+ export interface RoomSessionResponse {
2
+ roomId: string;
3
+ roomStatus: string;
4
+ playerId: string;
5
+ playerToken: string;
6
+ publicInviteUrl: string;
7
+ privateReconnectUrl: string;
8
+ recovered?: boolean;
9
+ }
10
+ export interface RoomSummary {
11
+ id: string;
12
+ status: string;
13
+ hostPlayerId: string;
14
+ rulesetVersion: string;
15
+ }
16
+ export interface LobbyPlayer {
17
+ id: string;
18
+ nickname: string;
19
+ is_host: boolean;
20
+ turn_order_index: number | null;
21
+ connected: boolean;
22
+ }
23
+ export interface RoomStateResponse<TState = unknown> {
24
+ room: RoomSummary;
25
+ players: LobbyPlayer[];
26
+ state: TState | null;
27
+ }
28
+ //# sourceMappingURL=room.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"room.d.ts","sourceRoot":"","sources":["../../src/types/room.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,eAAe,EAAE,MAAM,CAAA;IACvB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,EAAE,MAAM,CAAA;IACpB,cAAc,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,OAAO,CAAA;IAChB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,SAAS,EAAE,OAAO,CAAA;CACnB;AAED,MAAM,WAAW,iBAAiB,CAAC,MAAM,GAAG,OAAO;IACjD,IAAI,EAAE,WAAW,CAAA;IACjB,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=room.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"room.js","sourceRoot":"","sources":["../../src/types/room.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@javleds/vue-game-engine",
3
+ "version": "0.1.0",
4
+ "private": false,
5
+ "type": "module",
6
+ "description": "Reusable Vue client utilities for online turn-based board games.",
7
+ "license": "MIT",
8
+ "keywords": [
9
+ "vue",
10
+ "board-game",
11
+ "turn-based",
12
+ "game-engine",
13
+ "realtime"
14
+ ],
15
+ "homepage": "https://github.com/javleds/vue-game-engine#readme",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/javleds/vue-game-engine.git"
19
+ },
20
+ "bugs": {
21
+ "url": "https://github.com/javleds/vue-game-engine/issues"
22
+ },
23
+ "files": [
24
+ "dist",
25
+ "README.md",
26
+ "README.es.md",
27
+ "LICENSE"
28
+ ],
29
+ "main": "./dist/index.js",
30
+ "module": "./dist/index.js",
31
+ "types": "./dist/index.d.ts",
32
+ "exports": {
33
+ ".": {
34
+ "types": "./dist/index.d.ts",
35
+ "import": "./dist/index.js"
36
+ }
37
+ },
38
+ "scripts": {
39
+ "build": "tsc -p tsconfig.json",
40
+ "typecheck": "tsc -p tsconfig.json --noEmit",
41
+ "prepack": "npm run build"
42
+ },
43
+ "peerDependencies": {
44
+ "axios": "^1.7.9",
45
+ "laravel-echo": "^2.0.2",
46
+ "pinia": "^2.3.0",
47
+ "vue": "^3.5.13"
48
+ },
49
+ "devDependencies": {
50
+ "axios": "^1.7.9",
51
+ "laravel-echo": "^2.0.2",
52
+ "pinia": "^2.3.0",
53
+ "typescript": "^5.7.2",
54
+ "vue": "^3.5.13"
55
+ }
56
+ }