@juanito_boop/w-sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,663 @@
1
+ // src/http/auth.ts
2
+ function buildQueryString(params) {
3
+ const query = new URLSearchParams();
4
+ Object.entries(params).forEach(([key, value]) => {
5
+ if (value) query.append(key, value);
6
+ });
7
+ const str = query.toString();
8
+ return str ? `?${str}` : "";
9
+ }
10
+ function createAuthHttp(opts) {
11
+ const fetcher = opts.fetch ?? globalThis.fetch;
12
+ async function post(path, body) {
13
+ try {
14
+ const res = await fetcher(`${opts.baseUrl}${path}`, {
15
+ method: "POST",
16
+ headers: {
17
+ "Content-Type": "application/json",
18
+ ...opts.apiKey ? { "x-api-key": opts.apiKey } : {}
19
+ },
20
+ body: JSON.stringify(body)
21
+ });
22
+ const json = await res.json().catch(() => null);
23
+ if (!res.ok) {
24
+ return {
25
+ success: false,
26
+ error: {
27
+ message: json?.message ?? res.statusText,
28
+ code: json?.code,
29
+ statusCode: res.status,
30
+ details: json
31
+ }
32
+ };
33
+ }
34
+ return { success: true, data: json };
35
+ } catch (err) {
36
+ return {
37
+ success: false,
38
+ error: {
39
+ message: err instanceof Error ? err.message : "Network error",
40
+ code: "NETWORK_ERROR"
41
+ }
42
+ };
43
+ }
44
+ }
45
+ async function get(path) {
46
+ try {
47
+ const res = await fetcher(`${opts.baseUrl}${path}`, {
48
+ method: "GET",
49
+ headers: {
50
+ "Content-Type": "application/json",
51
+ ...opts.apiKey ? { "x-api-key": opts.apiKey } : {}
52
+ }
53
+ });
54
+ const json = await res.json().catch(() => null);
55
+ if (!res.ok) {
56
+ return {
57
+ success: false,
58
+ error: {
59
+ message: json?.message ?? res.statusText,
60
+ code: json?.code,
61
+ statusCode: res.status,
62
+ details: json
63
+ }
64
+ };
65
+ }
66
+ return { success: true, data: json };
67
+ } catch (err) {
68
+ return {
69
+ success: false,
70
+ error: {
71
+ message: err instanceof Error ? err.message : "Network error",
72
+ code: "NETWORK_ERROR"
73
+ }
74
+ };
75
+ }
76
+ }
77
+ async function del(path) {
78
+ try {
79
+ const res = await fetcher(`${opts.baseUrl}${path}`, {
80
+ method: "DELETE",
81
+ headers: {
82
+ "Content-Type": "application/json",
83
+ ...opts.apiKey ? { "x-api-key": opts.apiKey } : {}
84
+ }
85
+ });
86
+ const json = await res.json().catch(() => null);
87
+ if (!res.ok) {
88
+ return {
89
+ success: false,
90
+ error: {
91
+ message: json?.message ?? res.statusText,
92
+ code: json?.code,
93
+ statusCode: res.status,
94
+ details: json
95
+ }
96
+ };
97
+ }
98
+ return { success: true, data: json };
99
+ } catch (err) {
100
+ return {
101
+ success: false,
102
+ error: {
103
+ message: err instanceof Error ? err.message : "Network error",
104
+ code: "NETWORK_ERROR"
105
+ }
106
+ };
107
+ }
108
+ }
109
+ return {
110
+ register: (data) => post("/auth/register", data),
111
+ login: (data) => post("/auth/login", data),
112
+ logout: (data) => post("/auth/logout", data),
113
+ requestMagicLink: (data) => post("/auth/magic-link/request", data),
114
+ verifyMagicLink: (token) => post("/auth/magic-link/verify", { token }),
115
+ createApiKey: (data) => post("/auth/api-keys", data),
116
+ listApiKeys: (userId) => get(`/auth/api-keys/${userId}`),
117
+ revokeApiKey: (userId, keyId) => del(`/auth/api-keys/${userId}/${keyId}`),
118
+ validateSession: (token) => post("/auth/validate-session", { token }),
119
+ rollbackApiKey: (data) => {
120
+ const query = buildQueryString({
121
+ fromActivityId: data.fromActivityId,
122
+ fromTimestamp: data.fromTimestamp,
123
+ initiatedBy: data.initiatedBy
124
+ });
125
+ return post(
126
+ `/auth/api-keys/${data.keyId}/rollback${query}`,
127
+ {}
128
+ );
129
+ },
130
+ verifyMagicLinkWithQuery: (token) => get(`/auth/magic-link/verify?token=${token}`),
131
+ getSessions: (userId) => get(`/auth/sessions/${userId}`),
132
+ getLogs: () => get("/auth/logs"),
133
+ getUserLogs: (userId) => get(`/auth/logs/${userId}`),
134
+ getRollbackHistory: (keyId, limit = 50) => get(
135
+ `/auth/rollback-history${buildQueryString({ keyId, limit: String(limit) })}`
136
+ )
137
+ };
138
+ }
139
+
140
+ // src/ws/realtime.ts
141
+ import { io } from "socket.io-client";
142
+ async function toBytes(input) {
143
+ if (input instanceof Uint8Array) {
144
+ return Array.from(input);
145
+ }
146
+ if (input instanceof ArrayBuffer) {
147
+ return Array.from(new Uint8Array(input));
148
+ }
149
+ const arrayBuffer = await input.arrayBuffer();
150
+ return Array.from(new Uint8Array(arrayBuffer));
151
+ }
152
+ async function createWsImageFile(file, opts) {
153
+ if (file instanceof Blob) {
154
+ const detectedMime = opts?.mime ?? file.type;
155
+ const payload2 = {
156
+ filename: opts?.filename ?? file.name ?? "image.bin",
157
+ mime: detectedMime || "application/octet-stream",
158
+ buffer: await toBytes(file),
159
+ name: opts?.name,
160
+ expiration: opts?.expiration
161
+ };
162
+ return payload2;
163
+ }
164
+ const payload = {
165
+ filename: opts?.filename ?? "image.bin",
166
+ mime: opts?.mime ?? "application/octet-stream",
167
+ buffer: await toBytes(file),
168
+ name: opts?.name,
169
+ expiration: opts?.expiration
170
+ };
171
+ return payload;
172
+ }
173
+ function createRealtime(opts) {
174
+ let socket = null;
175
+ let apiKey = opts.apiKey;
176
+ const ACK_TIMEOUT_MS = 3e4;
177
+ function connect() {
178
+ return new Promise((resolve, reject) => {
179
+ if (socket?.connected) {
180
+ resolve();
181
+ return;
182
+ }
183
+ const auth = apiKey ? { apiKey } : void 0;
184
+ const extraHeaders = apiKey ? { "x-api-key": apiKey } : void 0;
185
+ let timeoutId;
186
+ socket = io(opts.baseUrl, {
187
+ path: "/ws",
188
+ transports: ["websocket", "polling"],
189
+ auth,
190
+ extraHeaders
191
+ });
192
+ const handleConnect = () => {
193
+ if (timeoutId) {
194
+ clearTimeout(timeoutId);
195
+ }
196
+ socket?.off("connect", handleConnect);
197
+ socket?.off("connect_error", handleError);
198
+ resolve();
199
+ };
200
+ const handleError = (error) => {
201
+ if (timeoutId) {
202
+ clearTimeout(timeoutId);
203
+ }
204
+ socket?.off("connect", handleConnect);
205
+ socket?.off("connect_error", handleError);
206
+ reject(error);
207
+ };
208
+ socket.on("connect", handleConnect);
209
+ socket.on("connect_error", handleError);
210
+ timeoutId = setTimeout(() => {
211
+ socket?.off("connect", handleConnect);
212
+ socket?.off("connect_error", handleError);
213
+ reject(new Error("Connection timeout"));
214
+ }, 5e3);
215
+ });
216
+ }
217
+ function disconnect() {
218
+ socket?.disconnect();
219
+ socket = null;
220
+ }
221
+ function setApiKey(key) {
222
+ apiKey = key;
223
+ if (socket) {
224
+ disconnect();
225
+ connect();
226
+ }
227
+ }
228
+ function emitAck(event, payload) {
229
+ if (!socket) {
230
+ return Promise.resolve({
231
+ success: false,
232
+ error: {
233
+ message: "Socket no conectado",
234
+ code: "SOCKET_NOT_CONNECTED"
235
+ }
236
+ });
237
+ }
238
+ return new Promise((resolve) => {
239
+ socket.timeout(ACK_TIMEOUT_MS).emit(event, payload, (err, res) => {
240
+ if (err) {
241
+ resolve({
242
+ success: false,
243
+ error: {
244
+ message: err.message ?? "Socket error",
245
+ code: err.code ?? "SOCKET_ERROR",
246
+ details: err
247
+ }
248
+ });
249
+ return;
250
+ }
251
+ if (res?.error) {
252
+ resolve({
253
+ success: false,
254
+ error: {
255
+ message: res.error.message,
256
+ code: res.error.code,
257
+ details: res.error
258
+ }
259
+ });
260
+ return;
261
+ }
262
+ resolve({ success: true, data: res });
263
+ });
264
+ });
265
+ }
266
+ return {
267
+ connect,
268
+ disconnect,
269
+ setApiKey,
270
+ getWines: () => emitAck("get_wines", void 0),
271
+ getWinesPage: (page = 1, perPage = 16) => emitAck("get_wines_page", { page, perPage }),
272
+ insertWine: (data) => emitAck("insert_wine", data),
273
+ insertBulkWines: (data) => emitAck("insert_bulk_wines", data),
274
+ editWine: (data) => emitAck("edit_wine", data)
275
+ };
276
+ }
277
+
278
+ // src/client.ts
279
+ var WineClient = class {
280
+ constructor(options) {
281
+ if (!options.baseUrl) {
282
+ throw new Error("baseUrl es requerido");
283
+ }
284
+ this.baseUrl = options.baseUrl;
285
+ this.apiKey = options.apiKey;
286
+ this.auth = createAuthHttp({
287
+ baseUrl: this.baseUrl,
288
+ apiKey: this.apiKey
289
+ });
290
+ this.realtime = createRealtime({
291
+ baseUrl: this.baseUrl,
292
+ apiKey: this.apiKey
293
+ });
294
+ }
295
+ setApiKey(apiKey) {
296
+ this.apiKey = apiKey;
297
+ this.realtime.setApiKey(apiKey);
298
+ }
299
+ async connectRealtime() {
300
+ await this.realtime.connect();
301
+ return this.realtime;
302
+ }
303
+ disconnectRealtime() {
304
+ this.realtime.disconnect();
305
+ }
306
+ };
307
+ function createClient(options) {
308
+ return new WineClient(options);
309
+ }
310
+
311
+ // src/types.ts
312
+ import { z } from "zod";
313
+
314
+ // src/types/_helpers.ts
315
+ function defineSchema(schema) {
316
+ return {
317
+ schema
318
+ };
319
+ }
320
+
321
+ // src/types.ts
322
+ var ClientOptionsDef = defineSchema(
323
+ z.object({
324
+ baseUrl: z.url("baseUrl debe ser una URL v\xE1lida"),
325
+ apiKey: z.string().optional()
326
+ })
327
+ );
328
+ var ApiErrorDef = defineSchema(
329
+ z.object({
330
+ message: z.string(),
331
+ code: z.string().optional(),
332
+ statusCode: z.number().optional(),
333
+ details: z.unknown().optional()
334
+ })
335
+ );
336
+ var LoginDataDef = defineSchema(
337
+ z.object({
338
+ email: z.email("Email inv\xE1lido"),
339
+ password: z.string().min(1, "Password es requerido")
340
+ })
341
+ );
342
+ var RegisterDataDef = defineSchema(
343
+ z.object({
344
+ email: z.email("Email inv\xE1lido"),
345
+ password: z.string().min(6, "Password debe tener al menos 6 caracteres"),
346
+ fullName: z.string().optional()
347
+ })
348
+ );
349
+ var LogoutDataDef = defineSchema(
350
+ z.object({
351
+ token: z.string(),
352
+ logoutAll: z.boolean().optional()
353
+ })
354
+ );
355
+ var MagicLinkRequestDataDef = defineSchema(
356
+ z.object({
357
+ email: z.email("Email inv\xE1lido"),
358
+ redirectUrl: z.url().optional()
359
+ })
360
+ );
361
+ var AuthResponseDef = defineSchema(
362
+ z.object({
363
+ token: z.string(),
364
+ user: z.object({
365
+ id: z.uuid(),
366
+ email: z.email(),
367
+ fullName: z.string().optional()
368
+ }),
369
+ apiKey: z.object({
370
+ id: z.uuid(),
371
+ key: z.string(),
372
+ name: z.string(),
373
+ expiresAt: z.iso.datetime()
374
+ }).optional()
375
+ })
376
+ );
377
+ var ApiKeyDef = defineSchema(
378
+ z.object({
379
+ id: z.uuid(),
380
+ key: z.string(),
381
+ name: z.string(),
382
+ expiresAt: z.iso.datetime().optional(),
383
+ createdAt: z.iso.datetime()
384
+ })
385
+ );
386
+ var MagicLinkResponseDef = defineSchema(
387
+ z.object({
388
+ success: z.boolean(),
389
+ message: z.string(),
390
+ email: z.email()
391
+ })
392
+ );
393
+ var CreateApiKeyDef = z.object({
394
+ userId: z.uuid(),
395
+ name: z.string(),
396
+ expiresAt: z.iso.datetime().optional(),
397
+ // ISO 8601
398
+ expiresIn: z.number().positive().optional()
399
+ // Segundos
400
+ });
401
+ var RollbackApiKeyDataDef = z.object({
402
+ keyId: z.uuid(),
403
+ fromActivityId: z.uuid().optional(),
404
+ fromTimestamp: z.iso.datetime().optional(),
405
+ initiatedBy: z.string().optional()
406
+ });
407
+ var RollbackResponseDef = z.object({
408
+ success: z.boolean(),
409
+ message: z.string(),
410
+ changesReverted: z.number(),
411
+ errors: z.array(z.string()),
412
+ rollbackSince: z.iso.datetime().optional()
413
+ });
414
+ var SessionDataDef = defineSchema(
415
+ z.object({
416
+ id: z.uuid(),
417
+ userId: z.uuid(),
418
+ token: z.string(),
419
+ ipAddress: z.string().nullable(),
420
+ userAgent: z.string().nullable(),
421
+ isActive: z.boolean(),
422
+ lastActivityAt: z.iso.datetime(),
423
+ createdAt: z.iso.datetime(),
424
+ expiresAt: z.iso.datetime().nullable()
425
+ })
426
+ );
427
+ var ValidateSessionResponseDef = defineSchema(
428
+ z.object({
429
+ valid: z.boolean(),
430
+ userId: z.uuid().optional(),
431
+ sessionId: z.uuid().optional()
432
+ })
433
+ );
434
+ var ActivityLogDef = defineSchema(
435
+ z.object({
436
+ id: z.uuid(),
437
+ userId: z.uuid().nullable().optional(),
438
+ apiKeyId: z.uuid().nullable().optional(),
439
+ action: z.string(),
440
+ ipAddress: z.string().nullable(),
441
+ userAgent: z.string().nullable(),
442
+ location: z.string().nullable(),
443
+ metadata: z.string().nullable(),
444
+ beforeState: z.string().nullable(),
445
+ afterState: z.string().nullable(),
446
+ tableName: z.string().nullable(),
447
+ recordId: z.uuid().nullable(),
448
+ timestamp: z.iso.datetime()
449
+ })
450
+ );
451
+ var RollbackLogDef = defineSchema(
452
+ z.object({
453
+ id: z.uuid(),
454
+ apiKeyId: z.uuid(),
455
+ initiatedBy: z.uuid().nullable().optional(),
456
+ status: z.string(),
457
+ changesReverted: z.string(),
458
+ errorMessage: z.string().nullable(),
459
+ createdAt: z.iso.datetime(),
460
+ completedAt: z.iso.datetime().nullable().optional()
461
+ })
462
+ );
463
+ var RealtimeOptionsDef = defineSchema(
464
+ z.object({
465
+ baseUrl: z.url(),
466
+ apiKey: z.string().optional()
467
+ })
468
+ );
469
+ var WineDataDef = defineSchema(
470
+ z.object({
471
+ id: z.uuid().optional()
472
+ }).strict()
473
+ );
474
+ var WineDetailsDef = defineSchema(
475
+ z.object({
476
+ id_detalle: z.uuid().nullable().optional(),
477
+ id_vino: z.uuid().nullable().optional(),
478
+ notas_cata: z.string().nullable().optional(),
479
+ tipo_crianza: z.string().nullable().optional(),
480
+ bodega: z.string().nullable().optional()
481
+ })
482
+ );
483
+ var WineDef = defineSchema(
484
+ z.object({
485
+ id_vino: z.uuid(),
486
+ nombre: z.string(),
487
+ precio: z.number(),
488
+ url_imagen: z.string(),
489
+ imgbb_delete_url: z.string().optional(),
490
+ image_hash: z.string().optional(),
491
+ descripcion: z.string(),
492
+ nivel_alcohol: z.number(),
493
+ variedades: z.array(z.string()),
494
+ pais_importacion: z.string(),
495
+ color_vino: z.string(),
496
+ stock: z.number(),
497
+ capacidad: z.number(),
498
+ wine_details: WineDetailsDef.schema.nullable().optional()
499
+ })
500
+ );
501
+ var EditWineDef = defineSchema(
502
+ WineDef.schema.omit({ wine_details: true }).partial().extend({
503
+ id_vino: z.uuid(),
504
+ wine_details: WineDetailsDef.schema.partial().optional(),
505
+ image_file: z.object({
506
+ filename: z.string().min(1),
507
+ mime: z.string().min(1),
508
+ buffer: z.union([
509
+ z.instanceof(Uint8Array),
510
+ z.array(z.number().int().min(0).max(255)),
511
+ z.object({
512
+ type: z.literal("Buffer"),
513
+ data: z.array(z.number().int().min(0).max(255))
514
+ })
515
+ ]),
516
+ name: z.string().optional(),
517
+ expiration: z.number().int().nonnegative().optional()
518
+ }).optional()
519
+ }).strict()
520
+ );
521
+ var CreateWineDef = defineSchema(
522
+ z.object({
523
+ nombre: z.string().min(1, 'El campo "nombre" es obligatorio'),
524
+ precio: z.number().positive("El precio debe ser positivo"),
525
+ url_imagen: z.string().optional(),
526
+ imgbb_delete_url: z.string().optional(),
527
+ image_hash: z.string().optional(),
528
+ descripcion: z.string().optional(),
529
+ nivel_alcohol: z.number().default(0),
530
+ variedades: z.array(z.string()).optional(),
531
+ pais_importacion: z.string().optional(),
532
+ color_vino: z.string().optional(),
533
+ stock: z.number().default(0),
534
+ capacidad: z.number().default(750),
535
+ notas_cata: z.string().optional(),
536
+ tipo_crianza: z.string().optional(),
537
+ bodega: z.string().optional(),
538
+ image_file: z.object({
539
+ filename: z.string().min(1),
540
+ mime: z.string().min(1),
541
+ buffer: z.union([
542
+ z.instanceof(Uint8Array),
543
+ z.array(z.number().int().min(0).max(255)),
544
+ z.object({
545
+ type: z.literal("Buffer"),
546
+ data: z.array(z.number().int().min(0).max(255))
547
+ })
548
+ ]),
549
+ name: z.string().optional(),
550
+ expiration: z.number().int().nonnegative().optional()
551
+ }).optional()
552
+ })
553
+ );
554
+ var BulkInsertWinesDef = defineSchema(z.array(CreateWineDef.schema));
555
+ var BulkInsertWinesResultDef = defineSchema(
556
+ z.object({
557
+ total: z.number(),
558
+ successful: z.number(),
559
+ failed: z.number(),
560
+ results: z.array(
561
+ z.object({
562
+ insertado_id: z.string().nullable(),
563
+ error: z.string().nullable()
564
+ })
565
+ )
566
+ })
567
+ );
568
+ var ReusedWineImageDef = defineSchema(
569
+ z.object({
570
+ url: z.string(),
571
+ delete_url: z.string()
572
+ })
573
+ );
574
+ var ImgbbAssetDef = defineSchema(
575
+ z.object({
576
+ filename: z.string(),
577
+ name: z.string(),
578
+ mime: z.string(),
579
+ extension: z.string(),
580
+ url: z.string()
581
+ })
582
+ );
583
+ var ImgbbUploadDataDef = defineSchema(
584
+ z.object({
585
+ id: z.string(),
586
+ title: z.string(),
587
+ url_viewer: z.string(),
588
+ url: z.string(),
589
+ display_url: z.string(),
590
+ width: z.string(),
591
+ height: z.string(),
592
+ size: z.string(),
593
+ time: z.string(),
594
+ expiration: z.string(),
595
+ image: ImgbbAssetDef.schema,
596
+ thumb: ImgbbAssetDef.schema,
597
+ medium: ImgbbAssetDef.schema,
598
+ delete_url: z.string()
599
+ })
600
+ );
601
+ var InsertWineResultDef = defineSchema(
602
+ z.object({
603
+ insertado_id: z.string().nullable(),
604
+ error: z.string().nullable(),
605
+ image: z.union([ImgbbUploadDataDef.schema, ReusedWineImageDef.schema]).optional(),
606
+ deduplicated: z.boolean().optional()
607
+ })
608
+ );
609
+
610
+ // src/index.ts
611
+ var ClientOptionsSchema = ClientOptionsDef.schema;
612
+ var ApiErrorSchema = ApiErrorDef.schema;
613
+ var LoginDataSchema = LoginDataDef.schema;
614
+ var RegisterDataSchema = RegisterDataDef.schema;
615
+ var MagicLinkRequestDataSchema = MagicLinkRequestDataDef.schema;
616
+ var AuthResponseSchema = AuthResponseDef.schema;
617
+ var ApiKeySchema = ApiKeyDef.schema;
618
+ var MagicLinkResponseSchema = MagicLinkResponseDef.schema;
619
+ var ValidateSessionResponseSchema = ValidateSessionResponseDef.schema;
620
+ var SessionDataSchema = SessionDataDef.schema;
621
+ var ActivityLogSchema = ActivityLogDef.schema;
622
+ var RollbackLogSchema = RollbackLogDef.schema;
623
+ var RealtimeOptionsSchema = RealtimeOptionsDef.schema;
624
+ var WineSchema = WineDef.schema;
625
+ var WineDetailsSchema = WineDetailsDef.schema;
626
+ var WineDataSchema = WineDataDef.schema;
627
+ var CreateWineSchema = CreateWineDef.schema;
628
+ var EditWineSchema = EditWineDef.schema;
629
+ var BulkInsertWinesSchema = BulkInsertWinesDef.schema;
630
+ var BulkInsertWinesResultSchema = BulkInsertWinesResultDef.schema;
631
+ var ReusedWineImageSchema = ReusedWineImageDef.schema;
632
+ var ImgbbAssetSchema = ImgbbAssetDef.schema;
633
+ var ImgbbUploadDataSchema = ImgbbUploadDataDef.schema;
634
+ var InsertWineResultSchema = InsertWineResultDef.schema;
635
+ export {
636
+ ActivityLogSchema,
637
+ ApiErrorSchema,
638
+ ApiKeySchema,
639
+ AuthResponseSchema,
640
+ BulkInsertWinesResultSchema,
641
+ BulkInsertWinesSchema,
642
+ ClientOptionsSchema,
643
+ CreateWineSchema,
644
+ EditWineSchema,
645
+ ImgbbAssetSchema,
646
+ ImgbbUploadDataSchema,
647
+ InsertWineResultSchema,
648
+ LoginDataSchema,
649
+ MagicLinkRequestDataSchema,
650
+ MagicLinkResponseSchema,
651
+ RealtimeOptionsSchema,
652
+ RegisterDataSchema,
653
+ ReusedWineImageSchema,
654
+ RollbackLogSchema,
655
+ SessionDataSchema,
656
+ ValidateSessionResponseSchema,
657
+ WineClient,
658
+ WineDataSchema,
659
+ WineDetailsSchema,
660
+ WineSchema,
661
+ createClient,
662
+ createWsImageFile
663
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,32 @@
1
+ import { WineClient } from './client';
2
+ const client = new WineClient({
3
+ baseUrl: 'http://localhost:3000',
4
+ });
5
+ async function main() {
6
+ const authResult = await client.auth.login({
7
+ email: 'juanitogaming2707@gmail.com',
8
+ password: 'Prom_2019',
9
+ });
10
+ if (!authResult.success) {
11
+ console.error(authResult.error.message, authResult.error.code, authResult.error.statusCode);
12
+ return;
13
+ }
14
+ const apiKey = authResult.data.apiKey?.key;
15
+ if (apiKey) {
16
+ client.setApiKey(apiKey);
17
+ console.log('✅ ApiKey configurada');
18
+ }
19
+ await client.connectRealtime();
20
+ console.log('✅ Socket conectado');
21
+ const wines = await client.realtime.getWines();
22
+ if (!wines.success) {
23
+ console.error(wines.error.message, wines.error.code, wines.error.statusCode);
24
+ return;
25
+ }
26
+ console.log(wines.data);
27
+ console.log('✅ Vinos obtenidos:', wines.data.length);
28
+ console.log('Primera entrada:', wines.data[0]);
29
+ }
30
+ main().catch(err => {
31
+ console.error('❌ Error inesperado:', err);
32
+ });
@@ -0,0 +1,5 @@
1
+ import { z } from 'zod';
2
+ export declare function defineSchema<S extends z.ZodTypeAny>(schema: S): {
3
+ schema: S;
4
+ type: z.infer<S>;
5
+ };
@@ -0,0 +1,5 @@
1
+ export function defineSchema(schema) {
2
+ return {
3
+ schema,
4
+ };
5
+ }