nostr-arena 0.1.1

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 (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +188 -0
  3. package/dist/__tests__/callbacks.test.d.ts +28 -0
  4. package/dist/__tests__/callbacks.test.d.ts.map +1 -0
  5. package/dist/__tests__/callbacks.test.js +140 -0
  6. package/dist/__tests__/callbacks.test.js.map +1 -0
  7. package/dist/__tests__/config.test.d.ts +18 -0
  8. package/dist/__tests__/config.test.d.ts.map +1 -0
  9. package/dist/__tests__/config.test.js +43 -0
  10. package/dist/__tests__/config.test.js.map +1 -0
  11. package/dist/__tests__/error-handling.test.d.ts +14 -0
  12. package/dist/__tests__/error-handling.test.d.ts.map +1 -0
  13. package/dist/__tests__/error-handling.test.js +199 -0
  14. package/dist/__tests__/error-handling.test.js.map +1 -0
  15. package/dist/__tests__/protocol.test.d.ts +7 -0
  16. package/dist/__tests__/protocol.test.d.ts.map +1 -0
  17. package/dist/__tests__/protocol.test.js +257 -0
  18. package/dist/__tests__/protocol.test.js.map +1 -0
  19. package/dist/__tests__/state-flow.test.d.ts +37 -0
  20. package/dist/__tests__/state-flow.test.d.ts.map +1 -0
  21. package/dist/__tests__/state-flow.test.js +160 -0
  22. package/dist/__tests__/state-flow.test.js.map +1 -0
  23. package/dist/__tests__/timing.test.d.ts +20 -0
  24. package/dist/__tests__/timing.test.d.ts.map +1 -0
  25. package/dist/__tests__/timing.test.js +73 -0
  26. package/dist/__tests__/timing.test.js.map +1 -0
  27. package/dist/core/Arena.d.ts +164 -0
  28. package/dist/core/Arena.d.ts.map +1 -0
  29. package/dist/core/Arena.js +634 -0
  30. package/dist/core/Arena.js.map +1 -0
  31. package/dist/core/NostrClient.d.ts +108 -0
  32. package/dist/core/NostrClient.d.ts.map +1 -0
  33. package/dist/core/NostrClient.js +225 -0
  34. package/dist/core/NostrClient.js.map +1 -0
  35. package/dist/core/index.d.ts +8 -0
  36. package/dist/core/index.d.ts.map +1 -0
  37. package/dist/core/index.js +7 -0
  38. package/dist/core/index.js.map +1 -0
  39. package/dist/index.d.ts +35 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +37 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/proxy.d.ts +36 -0
  44. package/dist/proxy.d.ts.map +1 -0
  45. package/dist/proxy.js +98 -0
  46. package/dist/proxy.js.map +1 -0
  47. package/dist/react/index.d.ts +7 -0
  48. package/dist/react/index.d.ts.map +1 -0
  49. package/dist/react/index.js +6 -0
  50. package/dist/react/index.js.map +1 -0
  51. package/dist/react/useArena.d.ts +74 -0
  52. package/dist/react/useArena.d.ts.map +1 -0
  53. package/dist/react/useArena.js +224 -0
  54. package/dist/react/useArena.js.map +1 -0
  55. package/dist/retry.d.ts +54 -0
  56. package/dist/retry.d.ts.map +1 -0
  57. package/dist/retry.js +82 -0
  58. package/dist/retry.js.map +1 -0
  59. package/dist/testing/MockArena.d.ts +84 -0
  60. package/dist/testing/MockArena.d.ts.map +1 -0
  61. package/dist/testing/MockArena.js +156 -0
  62. package/dist/testing/MockArena.js.map +1 -0
  63. package/dist/testing/index.d.ts +6 -0
  64. package/dist/testing/index.d.ts.map +1 -0
  65. package/dist/testing/index.js +6 -0
  66. package/dist/testing/index.js.map +1 -0
  67. package/dist/types.d.ts +183 -0
  68. package/dist/types.d.ts.map +1 -0
  69. package/dist/types.js +55 -0
  70. package/dist/types.js.map +1 -0
  71. package/package.json +84 -0
@@ -0,0 +1,108 @@
1
+ /**
2
+ * nostr-battle-room - NostrClient
3
+ * Framework-agnostic Nostr connection management
4
+ */
5
+ import type { Filter } from 'nostr-tools';
6
+ import type { NostrEvent, Unsubscribe } from '../types';
7
+ import { type RetryOptions } from '../retry';
8
+ export type { Filter as NostrFilter } from 'nostr-tools';
9
+ /**
10
+ * Options for NostrClient
11
+ */
12
+ export interface NostrClientOptions {
13
+ /** Nostr relay URLs */
14
+ relays?: string[];
15
+ /** Storage key prefix for persisting keys */
16
+ storageKeyPrefix?: string;
17
+ /** Custom storage (defaults to localStorage) */
18
+ storage?: {
19
+ getItem: (key: string) => string | null;
20
+ setItem: (key: string, value: string) => void;
21
+ };
22
+ /** Retry options for publish operations */
23
+ publishRetry?: RetryOptions;
24
+ }
25
+ /**
26
+ * NostrClient - Manages Nostr connection, publishing, and subscriptions
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * const client = new NostrClient({ relays: ['wss://relay.damus.io'] });
31
+ * await client.connect();
32
+ *
33
+ * // Publish an event
34
+ * await client.publish({
35
+ * kind: 25000,
36
+ * tags: [['d', 'my-room']],
37
+ * content: JSON.stringify({ type: 'state', data: {} }),
38
+ * });
39
+ *
40
+ * // Subscribe to events
41
+ * const unsubscribe = client.subscribe(
42
+ * [{ kinds: [25000], '#d': ['my-room'] }],
43
+ * (event) => console.log('Received:', event)
44
+ * );
45
+ *
46
+ * // Later: cleanup
47
+ * unsubscribe();
48
+ * client.disconnect();
49
+ * ```
50
+ */
51
+ export declare class NostrClient {
52
+ private pool;
53
+ private secretKey;
54
+ private _publicKey;
55
+ private _isConnected;
56
+ private relays;
57
+ private storageKeyPrefix;
58
+ private storage;
59
+ private publishRetry;
60
+ constructor(options?: NostrClientOptions);
61
+ /**
62
+ * Whether the client is connected to relays
63
+ */
64
+ get isConnected(): boolean;
65
+ /**
66
+ * The public key of this client (Nostr identity)
67
+ */
68
+ get publicKey(): string;
69
+ /**
70
+ * Get the connection status of each relay
71
+ * @returns Map of relay URL to connection status (true = connected)
72
+ */
73
+ getRelayStatus(): Map<string, boolean>;
74
+ /**
75
+ * Check if at least one relay is connected
76
+ */
77
+ get hasConnectedRelay(): boolean;
78
+ /**
79
+ * Connect to Nostr relays
80
+ * Generates or retrieves a key pair from storage
81
+ */
82
+ connect(): void;
83
+ /**
84
+ * Safely set storage item, ignoring quota errors
85
+ */
86
+ private safeStorageSet;
87
+ /**
88
+ * Disconnect from all relays
89
+ */
90
+ disconnect(): void;
91
+ /**
92
+ * Publish an event to all relays with retry logic
93
+ *
94
+ * Retries with exponential backoff if all relays fail.
95
+ * Succeeds if at least one relay accepts the event.
96
+ */
97
+ publish(eventTemplate: Omit<NostrEvent, 'id' | 'pubkey' | 'created_at' | 'sig'>): Promise<void>;
98
+ /**
99
+ * Subscribe to events matching the given filters
100
+ * @returns Unsubscribe function
101
+ */
102
+ subscribe(filters: Filter[], onEvent: (event: NostrEvent) => void): Unsubscribe;
103
+ /**
104
+ * Fetch events matching the given filter (one-time query)
105
+ */
106
+ fetch(filter: Filter, timeoutMs?: number): Promise<NostrEvent[]>;
107
+ }
108
+ //# sourceMappingURL=NostrClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NostrClient.d.ts","sourceRoot":"","sources":["../../src/core/NostrClient.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAExD,OAAO,EAAa,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AAGxD,YAAY,EAAE,MAAM,IAAI,WAAW,EAAE,MAAM,aAAa,CAAC;AAEzD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,uBAAuB;IACvB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,6CAA6C;IAC7C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gDAAgD;IAChD,OAAO,CAAC,EAAE;QACR,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;QACxC,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;KAC/C,CAAC;IACF,2CAA2C;IAC3C,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,IAAI,CAA2B;IACvC,OAAO,CAAC,SAAS,CAA2B;IAC5C,OAAO,CAAC,UAAU,CAAc;IAChC,OAAO,CAAC,YAAY,CAAkB;IACtC,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,OAAO,CAA6C;IAC5D,OAAO,CAAC,YAAY,CAAe;gBAEvB,OAAO,GAAE,kBAAuB;IAc5C;;OAEG;IACH,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED;;OAEG;IACH,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED;;;OAGG;IACH,cAAc,IAAI,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAOtC;;OAEG;IACH,IAAI,iBAAiB,IAAI,OAAO,CAG/B;IAED;;;OAGG;IACH,OAAO,IAAI,IAAI;IA+Bf;;OAEG;IACH,OAAO,CAAC,cAAc;IAQtB;;OAEG;IACH,UAAU,IAAI,IAAI;IAQlB;;;;;OAKG;IACG,OAAO,CACX,aAAa,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,QAAQ,GAAG,YAAY,GAAG,KAAK,CAAC,GACtE,OAAO,CAAC,IAAI,CAAC;IAkBhB;;;OAGG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,WAAW;IAuB/E;;OAEG;IACG,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,GAAE,MAAa,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;CA2C7E"}
@@ -0,0 +1,225 @@
1
+ /**
2
+ * nostr-battle-room - NostrClient
3
+ * Framework-agnostic Nostr connection management
4
+ */
5
+ import { SimplePool, finalizeEvent, generateSecretKey, getPublicKey } from 'nostr-tools';
6
+ import { DEFAULT_CONFIG } from '../types';
7
+ import { withRetry } from '../retry';
8
+ /**
9
+ * NostrClient - Manages Nostr connection, publishing, and subscriptions
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * const client = new NostrClient({ relays: ['wss://relay.damus.io'] });
14
+ * await client.connect();
15
+ *
16
+ * // Publish an event
17
+ * await client.publish({
18
+ * kind: 25000,
19
+ * tags: [['d', 'my-room']],
20
+ * content: JSON.stringify({ type: 'state', data: {} }),
21
+ * });
22
+ *
23
+ * // Subscribe to events
24
+ * const unsubscribe = client.subscribe(
25
+ * [{ kinds: [25000], '#d': ['my-room'] }],
26
+ * (event) => console.log('Received:', event)
27
+ * );
28
+ *
29
+ * // Later: cleanup
30
+ * unsubscribe();
31
+ * client.disconnect();
32
+ * ```
33
+ */
34
+ export class NostrClient {
35
+ constructor(options = {}) {
36
+ this.pool = null;
37
+ this.secretKey = null;
38
+ this._publicKey = '';
39
+ this._isConnected = false;
40
+ this.relays = options.relays ?? DEFAULT_CONFIG.relays;
41
+ this.storageKeyPrefix = options.storageKeyPrefix ?? 'nostr-battle';
42
+ this.storage = options.storage ?? {
43
+ getItem: (key) => localStorage.getItem(key),
44
+ setItem: (key, value) => localStorage.setItem(key, value),
45
+ };
46
+ this.publishRetry = options.publishRetry ?? {
47
+ maxAttempts: 3,
48
+ initialDelay: 1000,
49
+ maxDelay: 5000,
50
+ };
51
+ }
52
+ /**
53
+ * Whether the client is connected to relays
54
+ */
55
+ get isConnected() {
56
+ return this._isConnected;
57
+ }
58
+ /**
59
+ * The public key of this client (Nostr identity)
60
+ */
61
+ get publicKey() {
62
+ return this._publicKey;
63
+ }
64
+ /**
65
+ * Get the connection status of each relay
66
+ * @returns Map of relay URL to connection status (true = connected)
67
+ */
68
+ getRelayStatus() {
69
+ if (!this.pool) {
70
+ return new Map();
71
+ }
72
+ return this.pool.listConnectionStatus();
73
+ }
74
+ /**
75
+ * Check if at least one relay is connected
76
+ */
77
+ get hasConnectedRelay() {
78
+ const status = this.getRelayStatus();
79
+ return Array.from(status.values()).some((connected) => connected);
80
+ }
81
+ /**
82
+ * Connect to Nostr relays
83
+ * Generates or retrieves a key pair from storage
84
+ */
85
+ connect() {
86
+ if (this._isConnected)
87
+ return;
88
+ // Generate or retrieve key pair
89
+ const storageKey = `${this.storageKeyPrefix}-key`;
90
+ try {
91
+ const storedKey = this.storage.getItem(storageKey);
92
+ if (storedKey) {
93
+ try {
94
+ this.secretKey = new Uint8Array(JSON.parse(storedKey));
95
+ }
96
+ catch {
97
+ // Invalid stored key, generate new one
98
+ this.secretKey = generateSecretKey();
99
+ this.safeStorageSet(storageKey, JSON.stringify(Array.from(this.secretKey)));
100
+ }
101
+ }
102
+ else {
103
+ this.secretKey = generateSecretKey();
104
+ this.safeStorageSet(storageKey, JSON.stringify(Array.from(this.secretKey)));
105
+ }
106
+ }
107
+ catch {
108
+ // Storage not available, generate ephemeral key
109
+ this.secretKey = generateSecretKey();
110
+ }
111
+ this._publicKey = getPublicKey(this.secretKey);
112
+ this.pool = new SimplePool();
113
+ this._isConnected = true;
114
+ }
115
+ /**
116
+ * Safely set storage item, ignoring quota errors
117
+ */
118
+ safeStorageSet(key, value) {
119
+ try {
120
+ this.storage.setItem(key, value);
121
+ }
122
+ catch {
123
+ // Ignore storage errors (quota exceeded, etc.)
124
+ }
125
+ }
126
+ /**
127
+ * Disconnect from all relays
128
+ */
129
+ disconnect() {
130
+ if (this.pool) {
131
+ this.pool.close(this.relays);
132
+ this.pool = null;
133
+ }
134
+ this._isConnected = false;
135
+ }
136
+ /**
137
+ * Publish an event to all relays with retry logic
138
+ *
139
+ * Retries with exponential backoff if all relays fail.
140
+ * Succeeds if at least one relay accepts the event.
141
+ */
142
+ async publish(eventTemplate) {
143
+ if (!this.pool || !this.secretKey) {
144
+ throw new Error('NostrClient not connected. Call connect() first.');
145
+ }
146
+ const event = finalizeEvent({
147
+ kind: eventTemplate.kind,
148
+ tags: eventTemplate.tags,
149
+ content: eventTemplate.content,
150
+ created_at: Math.floor(Date.now() / 1000),
151
+ }, this.secretKey);
152
+ await withRetry(() => Promise.any(this.pool.publish(this.relays, event)), this.publishRetry);
153
+ }
154
+ /**
155
+ * Subscribe to events matching the given filters
156
+ * @returns Unsubscribe function
157
+ */
158
+ subscribe(filters, onEvent) {
159
+ if (!this.pool) {
160
+ console.warn('NostrClient not connected. Call connect() first.');
161
+ return () => { };
162
+ }
163
+ try {
164
+ // nostr-tools types show Filter (singular) but implementation accepts Filter[]
165
+ const sub = this.pool.subscribeMany(this.relays, filters, {
166
+ onevent(event) {
167
+ onEvent(event);
168
+ },
169
+ });
170
+ return () => {
171
+ sub.close();
172
+ };
173
+ }
174
+ catch (error) {
175
+ console.error('Failed to subscribe:', error);
176
+ return () => { };
177
+ }
178
+ }
179
+ /**
180
+ * Fetch events matching the given filter (one-time query)
181
+ */
182
+ async fetch(filter, timeoutMs = 5000) {
183
+ if (!this.pool) {
184
+ throw new Error('NostrClient not connected. Call connect() first.');
185
+ }
186
+ return new Promise((resolve, reject) => {
187
+ const events = [];
188
+ let resolved = false;
189
+ const finish = (success, error) => {
190
+ if (resolved)
191
+ return;
192
+ resolved = true;
193
+ sub.close();
194
+ if (success) {
195
+ resolve(events);
196
+ }
197
+ else {
198
+ reject(error);
199
+ }
200
+ };
201
+ const sub = this.pool.subscribeManyEose(this.relays, filter, {
202
+ onevent: (event) => {
203
+ events.push(event);
204
+ },
205
+ onclose: (reasons) => {
206
+ // Check if at least one relay sent EOSE (successful response)
207
+ const hasEose = reasons.some((r) => r === 'EOSE');
208
+ if (hasEose) {
209
+ // Valid response (may have 0 events, but relay responded)
210
+ finish(true);
211
+ }
212
+ else {
213
+ // All relays failed without sending EOSE
214
+ finish(false, new Error('No relay response: ' + reasons.join(', ')));
215
+ }
216
+ },
217
+ });
218
+ // Timeout fallback
219
+ setTimeout(() => {
220
+ finish(false, new Error('No relay response: timeout'));
221
+ }, timeoutMs);
222
+ });
223
+ }
224
+ }
225
+ //# sourceMappingURL=NostrClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NostrClient.js","sourceRoot":"","sources":["../../src/core/NostrClient.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGzF,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAqB,MAAM,UAAU,CAAC;AAsBxD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,OAAO,WAAW;IAUtB,YAAY,UAA8B,EAAE;QATpC,SAAI,GAAsB,IAAI,CAAC;QAC/B,cAAS,GAAsB,IAAI,CAAC;QACpC,eAAU,GAAW,EAAE,CAAC;QACxB,iBAAY,GAAY,KAAK,CAAC;QAOpC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,cAAc,CAAC,MAAM,CAAC;QACtD,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,cAAc,CAAC;QACnE,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI;YAChC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC;YAC3C,OAAO,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC;SAC1D,CAAC;QACF,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI;YAC1C,WAAW,EAAE,CAAC;YACd,YAAY,EAAE,IAAI;YAClB,QAAQ,EAAE,IAAI;SACf,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED;;;OAGG;IACH,cAAc;QACZ,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,OAAO,IAAI,GAAG,EAAE,CAAC;QACnB,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,CAAC;IAC1C,CAAC;IAED;;OAEG;IACH,IAAI,iBAAiB;QACnB,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACrC,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC;IACpE,CAAC;IAED;;;OAGG;IACH,OAAO;QACL,IAAI,IAAI,CAAC,YAAY;YAAE,OAAO;QAE9B,gCAAgC;QAChC,MAAM,UAAU,GAAG,GAAG,IAAI,CAAC,gBAAgB,MAAM,CAAC;QAElD,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YAEnD,IAAI,SAAS,EAAE,CAAC;gBACd,IAAI,CAAC;oBACH,IAAI,CAAC,SAAS,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;gBACzD,CAAC;gBAAC,MAAM,CAAC;oBACP,uCAAuC;oBACvC,IAAI,CAAC,SAAS,GAAG,iBAAiB,EAAE,CAAC;oBACrC,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;gBAC9E,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,SAAS,GAAG,iBAAiB,EAAE,CAAC;gBACrC,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YAC9E,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,gDAAgD;YAChD,IAAI,CAAC,SAAS,GAAG,iBAAiB,EAAE,CAAC;QACvC,CAAC;QAED,IAAI,CAAC,UAAU,GAAG,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/C,IAAI,CAAC,IAAI,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;IAC3B,CAAC;IAED;;OAEG;IACK,cAAc,CAAC,GAAW,EAAE,KAAa;QAC/C,IAAI,CAAC;YACH,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC;YACP,+CAA+C;QACjD,CAAC;IACH,CAAC;IAED;;OAEG;IACH,UAAU;QACR,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC7B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACnB,CAAC;QACD,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;IAC5B,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,OAAO,CACX,aAAuE;QAEvE,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;QACtE,CAAC;QAED,MAAM,KAAK,GAAG,aAAa,CACzB;YACE,IAAI,EAAE,aAAa,CAAC,IAAI;YACxB,IAAI,EAAE,aAAa,CAAC,IAAI;YACxB,OAAO,EAAE,aAAa,CAAC,OAAO;YAC9B,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;SAC1C,EACD,IAAI,CAAC,SAAS,CACf,CAAC;QAEF,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;IAChG,CAAC;IAED;;;OAGG;IACH,SAAS,CAAC,OAAiB,EAAE,OAAoC;QAC/D,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;YACjE,OAAO,GAAG,EAAE,GAAE,CAAC,CAAC;QAClB,CAAC;QAED,IAAI,CAAC;YACH,+EAA+E;YAC/E,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,OAA4B,EAAE;gBAC7E,OAAO,CAAC,KAAK;oBACX,OAAO,CAAC,KAAmB,CAAC,CAAC;gBAC/B,CAAC;aACF,CAAC,CAAC;YAEH,OAAO,GAAG,EAAE;gBACV,GAAG,CAAC,KAAK,EAAE,CAAC;YACd,CAAC,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC;YAC7C,OAAO,GAAG,EAAE,GAAE,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,KAAK,CAAC,MAAc,EAAE,YAAoB,IAAI;QAClD,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;QACtE,CAAC;QAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,MAAM,MAAM,GAAiB,EAAE,CAAC;YAChC,IAAI,QAAQ,GAAG,KAAK,CAAC;YAErB,MAAM,MAAM,GAAG,CAAC,OAAgB,EAAE,KAAa,EAAE,EAAE;gBACjD,IAAI,QAAQ;oBAAE,OAAO;gBACrB,QAAQ,GAAG,IAAI,CAAC;gBAChB,GAAG,CAAC,KAAK,EAAE,CAAC;gBACZ,IAAI,OAAO,EAAE,CAAC;oBACZ,OAAO,CAAC,MAAM,CAAC,CAAC;gBAClB,CAAC;qBAAM,CAAC;oBACN,MAAM,CAAC,KAAK,CAAC,CAAC;gBAChB,CAAC;YACH,CAAC,CAAC;YAEF,MAAM,GAAG,GAAG,IAAI,CAAC,IAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,EAAE,MAA2B,EAAE;gBACjF,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;oBACjB,MAAM,CAAC,IAAI,CAAC,KAAmB,CAAC,CAAC;gBACnC,CAAC;gBACD,OAAO,EAAE,CAAC,OAAO,EAAE,EAAE;oBACnB,8DAA8D;oBAC9D,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC;oBAClD,IAAI,OAAO,EAAE,CAAC;wBACZ,0DAA0D;wBAC1D,MAAM,CAAC,IAAI,CAAC,CAAC;oBACf,CAAC;yBAAM,CAAC;wBACN,yCAAyC;wBACzC,MAAM,CAAC,KAAK,EAAE,IAAI,KAAK,CAAC,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;oBACvE,CAAC;gBACH,CAAC;aACF,CAAC,CAAC;YAEH,mBAAmB;YACnB,UAAU,CAAC,GAAG,EAAE;gBACd,MAAM,CAAC,KAAK,EAAE,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC,CAAC;YACzD,CAAC,EAAE,SAAS,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * nostr-battle-room - Core exports
3
+ * Framework-agnostic classes for Nostr battle rooms
4
+ */
5
+ export { NostrClient } from './NostrClient';
6
+ export type { NostrClientOptions } from './NostrClient';
7
+ export { Arena } from './Arena';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAExD,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * nostr-battle-room - Core exports
3
+ * Framework-agnostic classes for Nostr battle rooms
4
+ */
5
+ export { NostrClient } from './NostrClient';
6
+ export { Arena } from './Arena';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG5C,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * nostr-battle-room
3
+ * Nostr-based real-time battle room for multiplayer games
4
+ *
5
+ * @example
6
+ * ```typescript
7
+ * // Using the core Arena class (framework-agnostic)
8
+ * import { Arena } from 'nostr-battle-room';
9
+ *
10
+ * const room = new Arena<MyGameState>({ gameId: 'my-game' });
11
+ * room.onOpponentState((state) => console.log(state));
12
+ * await room.create();
13
+ * ```
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * // Using the React hook
18
+ * import { useArena } from 'nostr-battle-room/react';
19
+ *
20
+ * function Game() {
21
+ * const { roomState, opponent, createRoom } = useArena<MyGameState>({
22
+ * gameId: 'my-game',
23
+ * });
24
+ * // ...
25
+ * }
26
+ * ```
27
+ */
28
+ export { Arena } from './core/Arena';
29
+ export { NostrClient } from './core/NostrClient';
30
+ export type { NostrClientOptions, NostrFilter } from './core/NostrClient';
31
+ export type { ArenaConfig, ArenaCallbacks, ArenaEventName, RoomState, RoomStatus, OpponentBase, OpponentState, NostrEvent, StoredRoomData, Unsubscribe, RoomEventContent, JoinEventContent, StateEventContent, GameOverEventContent, RematchEventContent, HeartbeatEventContent, BattleEventContent, } from './types';
32
+ export { DEFAULT_CONFIG, INITIAL_ROOM_STATE, NOSTR_KINDS, createRoomTag, generateSeed, generateRoomId, } from './types';
33
+ export { configureProxy, resetProxyConfiguration } from './proxy';
34
+ export { withRetry, withTimeout, timeout, type RetryOptions } from './retry';
35
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,YAAY,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAG1E,YAAY,EACV,WAAW,EACX,cAAc,EACd,cAAc,EACd,SAAS,EACT,UAAU,EACV,YAAY,EACZ,aAAa,EACb,UAAU,EACV,cAAc,EACd,WAAW,EAEX,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,YAAY,EACZ,cAAc,GACf,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAC;AAGlE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,37 @@
1
+ /**
2
+ * nostr-battle-room
3
+ * Nostr-based real-time battle room for multiplayer games
4
+ *
5
+ * @example
6
+ * ```typescript
7
+ * // Using the core Arena class (framework-agnostic)
8
+ * import { Arena } from 'nostr-battle-room';
9
+ *
10
+ * const room = new Arena<MyGameState>({ gameId: 'my-game' });
11
+ * room.onOpponentState((state) => console.log(state));
12
+ * await room.create();
13
+ * ```
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * // Using the React hook
18
+ * import { useArena } from 'nostr-battle-room/react';
19
+ *
20
+ * function Game() {
21
+ * const { roomState, opponent, createRoom } = useArena<MyGameState>({
22
+ * gameId: 'my-game',
23
+ * });
24
+ * // ...
25
+ * }
26
+ * ```
27
+ */
28
+ // Core exports
29
+ export { Arena } from './core/Arena';
30
+ export { NostrClient } from './core/NostrClient';
31
+ // Constants and utilities
32
+ export { DEFAULT_CONFIG, INITIAL_ROOM_STATE, NOSTR_KINDS, createRoomTag, generateSeed, generateRoomId, } from './types';
33
+ // Proxy support (Node.js)
34
+ export { configureProxy, resetProxyConfiguration } from './proxy';
35
+ // Retry utilities
36
+ export { withRetry, withTimeout, timeout } from './retry';
37
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,eAAe;AACf,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAyBjD,0BAA0B;AAC1B,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,YAAY,EACZ,cAAc,GACf,MAAM,SAAS,CAAC;AAEjB,0BAA0B;AAC1B,OAAO,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAC;AAElE,kBAAkB;AAClB,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,OAAO,EAAqB,MAAM,SAAS,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * nostr-battle-room - Proxy Support
3
+ * Configure WebSocket to work through HTTP/HTTPS proxies
4
+ *
5
+ * Call configureProxy() before creating any Arena instances.
6
+ * Reads proxy URL from environment variables:
7
+ * - HTTPS_PROXY
8
+ * - HTTP_PROXY
9
+ * - ALL_PROXY
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * import { configureProxy } from 'nostr-battle-room';
14
+ *
15
+ * // Call once at startup (Node.js only)
16
+ * configureProxy();
17
+ *
18
+ * // Now create rooms as usual
19
+ * const room = new Arena({ gameId: 'my-game' });
20
+ * ```
21
+ */
22
+ /**
23
+ * Configure WebSocket to use proxy from environment variables.
24
+ * Must be called before connecting to any relays.
25
+ *
26
+ * In Node.js: Sets up proxy-aware WebSocket if HTTPS_PROXY/HTTP_PROXY is set
27
+ * In browser: No-op (browsers handle proxies at OS/network level)
28
+ *
29
+ * @returns true if proxy was configured, false otherwise
30
+ */
31
+ export declare function configureProxy(): boolean;
32
+ /**
33
+ * Reset proxy configuration (mainly for testing)
34
+ */
35
+ export declare function resetProxyConfiguration(): void;
36
+ //# sourceMappingURL=proxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAyBH;;;;;;;;GAQG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAmDxC;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C"}
package/dist/proxy.js ADDED
@@ -0,0 +1,98 @@
1
+ /**
2
+ * nostr-battle-room - Proxy Support
3
+ * Configure WebSocket to work through HTTP/HTTPS proxies
4
+ *
5
+ * Call configureProxy() before creating any Arena instances.
6
+ * Reads proxy URL from environment variables:
7
+ * - HTTPS_PROXY
8
+ * - HTTP_PROXY
9
+ * - ALL_PROXY
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * import { configureProxy } from 'nostr-battle-room';
14
+ *
15
+ * // Call once at startup (Node.js only)
16
+ * configureProxy();
17
+ *
18
+ * // Now create rooms as usual
19
+ * const room = new Arena({ gameId: 'my-game' });
20
+ * ```
21
+ */
22
+ import { useWebSocketImplementation } from 'nostr-tools/pool';
23
+ let proxyConfigured = false;
24
+ /**
25
+ * Get proxy URL from environment variables
26
+ */
27
+ function getProxyUrl() {
28
+ if (typeof process === 'undefined' || !process.env) {
29
+ return undefined;
30
+ }
31
+ return process.env.HTTPS_PROXY || process.env.HTTP_PROXY || process.env.ALL_PROXY;
32
+ }
33
+ /**
34
+ * Check if running in Node.js environment
35
+ */
36
+ function isNode() {
37
+ return (typeof process !== 'undefined' && process.versions != null && process.versions.node != null);
38
+ }
39
+ /**
40
+ * Configure WebSocket to use proxy from environment variables.
41
+ * Must be called before connecting to any relays.
42
+ *
43
+ * In Node.js: Sets up proxy-aware WebSocket if HTTPS_PROXY/HTTP_PROXY is set
44
+ * In browser: No-op (browsers handle proxies at OS/network level)
45
+ *
46
+ * @returns true if proxy was configured, false otherwise
47
+ */
48
+ export function configureProxy() {
49
+ if (proxyConfigured) {
50
+ return false;
51
+ }
52
+ if (!isNode()) {
53
+ // Browser environment - no action needed
54
+ proxyConfigured = true;
55
+ return false;
56
+ }
57
+ const proxyUrl = getProxyUrl();
58
+ // Always configure ws for Node.js, even without proxy
59
+ // This ensures WebSocket works in Node.js environment
60
+ try {
61
+ // Dynamic import to avoid bundling issues in browser
62
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
63
+ const WebSocket = require('ws');
64
+ if (proxyUrl) {
65
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
66
+ const { HttpsProxyAgent } = require('https-proxy-agent');
67
+ const agent = new HttpsProxyAgent(proxyUrl);
68
+ // Create a WebSocket class that uses the proxy agent
69
+ class ProxyWebSocket extends WebSocket {
70
+ constructor(url, protocols) {
71
+ super(url, protocols, { agent });
72
+ }
73
+ }
74
+ useWebSocketImplementation(ProxyWebSocket);
75
+ proxyConfigured = true;
76
+ return true;
77
+ }
78
+ else {
79
+ // No proxy, but still need ws for Node.js
80
+ useWebSocketImplementation(WebSocket);
81
+ proxyConfigured = true;
82
+ return false;
83
+ }
84
+ }
85
+ catch {
86
+ // ws or https-proxy-agent not installed
87
+ console.warn('nostr-battle-room: Could not configure WebSocket for Node.js.', 'Install "ws" package for Node.js support.', proxyUrl ? 'Install "https-proxy-agent" for proxy support.' : '');
88
+ proxyConfigured = true;
89
+ return false;
90
+ }
91
+ }
92
+ /**
93
+ * Reset proxy configuration (mainly for testing)
94
+ */
95
+ export function resetProxyConfiguration() {
96
+ proxyConfigured = false;
97
+ }
98
+ //# sourceMappingURL=proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAE9D,IAAI,eAAe,GAAG,KAAK,CAAC;AAE5B;;GAEG;AACH,SAAS,WAAW;IAClB,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QACnD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;AACpF,CAAC;AAED;;GAEG;AACH,SAAS,MAAM;IACb,OAAO,CACL,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,QAAQ,IAAI,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,IAAI,IAAI,CAC5F,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc;IAC5B,IAAI,eAAe,EAAE,CAAC;QACpB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;QACd,yCAAyC;QACzC,eAAe,GAAG,IAAI,CAAC;QACvB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAE/B,sDAAsD;IACtD,sDAAsD;IACtD,IAAI,CAAC;QACH,qDAAqD;QACrD,iEAAiE;QACjE,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAEhC,IAAI,QAAQ,EAAE,CAAC;YACb,iEAAiE;YACjE,MAAM,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;YACzD,MAAM,KAAK,GAAG,IAAI,eAAe,CAAC,QAAQ,CAAC,CAAC;YAE5C,qDAAqD;YACrD,MAAM,cAAe,SAAQ,SAAS;gBACpC,YAAY,GAAW,EAAE,SAA6B;oBACpD,KAAK,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;gBACnC,CAAC;aACF;YAED,0BAA0B,CAAC,cAAc,CAAC,CAAC;YAC3C,eAAe,GAAG,IAAI,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;aAAM,CAAC;YACN,0CAA0C;YAC1C,0BAA0B,CAAC,SAAS,CAAC,CAAC;YACtC,eAAe,GAAG,IAAI,CAAC;YACvB,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,wCAAwC;QACxC,OAAO,CAAC,IAAI,CACV,+DAA+D,EAC/D,2CAA2C,EAC3C,QAAQ,CAAC,CAAC,CAAC,gDAAgD,CAAC,CAAC,CAAC,EAAE,CACjE,CAAC;QACF,eAAe,GAAG,IAAI,CAAC;QACvB,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB;IACrC,eAAe,GAAG,KAAK,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * nostr-battle-room - React exports
3
+ * React hooks for Nostr battle rooms
4
+ */
5
+ export { useArena } from './useArena';
6
+ export type { UseArenaReturn, OpponentState } from './useArena';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * nostr-battle-room - React exports
3
+ * React hooks for Nostr battle rooms
4
+ */
5
+ export { useArena } from './useArena';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}