@central-ticket/queue-sdk 0.0.1 → 0.0.3

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.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export { C as CentralQ, a as CentralQClient, b as CentralQClientOptions, c as CentralQCreateOptions, d as CentralQOptions, E as ErrorDetail, e as ExpiredDetail, P as PassedDetail, f as PositionDetail, Q as QueueStatus, g as createCentralQClient } from './centralq-I9tdL_Xr.js';
2
- export { QueueTokenValidationResult, ValidateQueueTokenServerOptions, validateQueueTokenServer } from './server.js';
1
+ export { C as CentralQ, a as CentralQClient, b as CentralQClientOptions, c as CentralQCreateOptions, d as CentralQOptions, E as ErrorDetail, e as ExpiredDetail, P as PassedDetail, f as PositionDetail, Q as QueueStatus, g as createCentralQClient } from './centralq-C3ukDo0x.js';
2
+ export { CentralQServerClient, CentralQServerClientOptions, CentralQServerRequestError, CentralQServerRequestErrorCode, CompleteQueueAccessServerOptions, QueueAccessCompletionResult, QueueAccessValidationResult, QueueTokenValidationResult, ValidateQueueTokenServerOptions, VerifyQueueAccessServerOptions, completeQueueAccessServer, createCentralQServerClient, validateQueueTokenServer, verifyQueueAccessServer } from './server.js';
3
3
  import * as lit from 'lit';
4
4
  import { LitElement } from 'lit';
5
5
 
@@ -20,6 +20,31 @@ interface QueueInitResponse {
20
20
  queueInitToken: string;
21
21
  expiresAt: number;
22
22
  }
23
+ type AdmissionMode = "PUBLIC" | "MANAGED" | "TRUSTED";
24
+ interface QueueProtectionResponse {
25
+ eventId: string;
26
+ configured: boolean;
27
+ protected: boolean;
28
+ isActive: boolean;
29
+ admissionMode: AdmissionMode;
30
+ challengeRequired: boolean;
31
+ }
32
+ type AdmissionChallengeResponse = {
33
+ required: false;
34
+ } | {
35
+ required: true;
36
+ publicKey: string;
37
+ appearance: "interaction-only";
38
+ };
39
+ type QueueVerifyResponse = {
40
+ valid: true;
41
+ userId: string;
42
+ eventId: string;
43
+ expiresAt: string;
44
+ } | {
45
+ valid: false;
46
+ reason: string;
47
+ };
23
48
  declare const CENTRALQ_DEFAULT_API_URL = "http://localhost:3001";
24
49
  /** @internal — HTTP client usado internamente por CentralQ */
25
50
  declare class QueueHttpClient {
@@ -43,7 +68,10 @@ declare class QueueHttpClient {
43
68
  * Llamar al completar la compra o al salir voluntariamente.
44
69
  */
45
70
  leaveQueue(eventId: string, userId: string): Promise<void>;
46
- issueQueueInitToken(eventId: string, userId?: string): Promise<QueueInitResponse>;
71
+ issueQueueInitToken(eventId: string, userId?: string, admissionProof?: string): Promise<QueueInitResponse>;
72
+ getProtection(eventId: string): Promise<QueueProtectionResponse>;
73
+ getAdmissionChallenge(eventId: string): Promise<AdmissionChallengeResponse>;
74
+ verifyToken(eventId: string, token: string): Promise<QueueVerifyResponse>;
47
75
  }
48
76
 
49
77
  /**
@@ -61,4 +89,4 @@ declare class CentralQElement extends LitElement {
61
89
  render(): lit.TemplateResult<1>;
62
90
  }
63
91
 
64
- export { CENTRALQ_DEFAULT_API_URL, CentralQElement, QueueHttpClient, type QueueJoinResponse };
92
+ export { type AdmissionChallengeResponse, type AdmissionMode, CENTRALQ_DEFAULT_API_URL, CentralQElement, QueueHttpClient, type QueueJoinResponse, type QueueProtectionResponse, type QueueVerifyResponse };
package/dist/index.js CHANGED
@@ -149,9 +149,14 @@ __export(index_exports, {
149
149
  CENTRALQ_DEFAULT_API_URL: () => CENTRALQ_DEFAULT_API_URL,
150
150
  CentralQ: () => CentralQ,
151
151
  CentralQClient: () => CentralQClient,
152
+ CentralQServerClient: () => CentralQServerClient,
153
+ CentralQServerRequestError: () => CentralQServerRequestError,
152
154
  QueueHttpClient: () => QueueHttpClient,
155
+ completeQueueAccessServer: () => completeQueueAccessServer,
153
156
  createCentralQClient: () => createCentralQClient,
154
- validateQueueTokenServer: () => validateQueueTokenServer
157
+ createCentralQServerClient: () => createCentralQServerClient,
158
+ validateQueueTokenServer: () => validateQueueTokenServer,
159
+ verifyQueueAccessServer: () => verifyQueueAccessServer
155
160
  });
156
161
  module.exports = __toCommonJS(index_exports);
157
162
 
@@ -223,13 +228,13 @@ var QueueHttpClient = class {
223
228
  }
224
229
  );
225
230
  }
226
- async issueQueueInitToken(eventId, userId) {
231
+ async issueQueueInitToken(eventId, userId, admissionProof) {
227
232
  const res = await fetch(
228
233
  `${this.apiUrl}/api/queue/init/${encodeURIComponent(eventId)}`,
229
234
  {
230
235
  method: "POST",
231
236
  headers: this.headers,
232
- body: JSON.stringify({ userId })
237
+ body: JSON.stringify({ userId, admissionProof })
233
238
  }
234
239
  );
235
240
  const body = await res.json().catch(() => ({}));
@@ -248,8 +253,155 @@ var QueueHttpClient = class {
248
253
  expiresAt: body.expiresAt
249
254
  };
250
255
  }
256
+ async getProtection(eventId) {
257
+ const res = await fetch(
258
+ `${this.apiUrl}/api/queue/${encodeURIComponent(eventId)}/protection`,
259
+ { headers: this.headers }
260
+ );
261
+ const body = await res.json().catch(() => ({}));
262
+ if (!res.ok) {
263
+ throw new Error(
264
+ body.message ?? `Error ${res.status} al consultar protecci\xF3n`
265
+ );
266
+ }
267
+ return {
268
+ eventId: body.eventId ?? eventId,
269
+ configured: body.configured === true,
270
+ protected: body.protected === true,
271
+ isActive: body.isActive === true,
272
+ admissionMode: body.admissionMode ?? "PUBLIC",
273
+ challengeRequired: body.challengeRequired === true
274
+ };
275
+ }
276
+ async getAdmissionChallenge(eventId) {
277
+ const res = await fetch(
278
+ `${this.apiUrl}/api/queue/${encodeURIComponent(eventId)}/admission`,
279
+ { headers: this.headers }
280
+ );
281
+ const body = await res.json().catch(() => ({}));
282
+ if (!res.ok) {
283
+ throw new Error(
284
+ body.message ?? `Error ${res.status} al preparar la admisi\xF3n`
285
+ );
286
+ }
287
+ if (body.required !== true) return { required: false };
288
+ if (!("publicKey" in body) || !body.publicKey) {
289
+ throw new Error("Respuesta inv\xE1lida al preparar la admisi\xF3n");
290
+ }
291
+ return {
292
+ required: true,
293
+ publicKey: body.publicKey,
294
+ appearance: "interaction-only"
295
+ };
296
+ }
297
+ async verifyToken(eventId, token) {
298
+ const res = await fetch(
299
+ `${this.apiUrl}/api/queue/verify/${encodeURIComponent(eventId)}`,
300
+ {
301
+ method: "POST",
302
+ headers: this.headers,
303
+ body: JSON.stringify({ token })
304
+ }
305
+ );
306
+ const body = await res.json().catch(() => ({
307
+ valid: false,
308
+ reason: "Respuesta inv\xE1lida"
309
+ }));
310
+ if (body.valid === true && body.userId && body.eventId && body.expiresAt) {
311
+ return body;
312
+ }
313
+ if (body.valid === false) {
314
+ return { valid: false, reason: body.reason ?? "Token inv\xE1lido" };
315
+ }
316
+ if (!res.ok) {
317
+ return {
318
+ valid: false,
319
+ reason: body.message ?? `Error ${res.status} al validar token de cola`
320
+ };
321
+ }
322
+ return { valid: false, reason: "Respuesta inv\xE1lida" };
323
+ }
251
324
  };
252
325
 
326
+ // src/admission.ts
327
+ var turnstileScript = null;
328
+ function loadManagedAdmissionDriver() {
329
+ if (typeof window === "undefined" || typeof document === "undefined") {
330
+ return Promise.reject(
331
+ new Error("La admisi\xF3n administrada requiere un navegador")
332
+ );
333
+ }
334
+ if (window.turnstile) return Promise.resolve(window.turnstile);
335
+ if (turnstileScript) return turnstileScript;
336
+ turnstileScript = new Promise((resolve, reject) => {
337
+ const script = document.createElement("script");
338
+ script.src = "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit";
339
+ script.async = true;
340
+ script.defer = true;
341
+ script.onload = () => {
342
+ if (window.turnstile) resolve(window.turnstile);
343
+ else {
344
+ turnstileScript = null;
345
+ reject(new Error("No se pudo inicializar la admisi\xF3n administrada"));
346
+ }
347
+ };
348
+ script.onerror = () => {
349
+ turnstileScript = null;
350
+ reject(new Error("No se pudo cargar la admisi\xF3n administrada"));
351
+ };
352
+ document.head.appendChild(script);
353
+ });
354
+ return turnstileScript;
355
+ }
356
+ async function acquireManagedAdmissionProof(publicKey) {
357
+ const driver = await loadManagedAdmissionDriver();
358
+ const container = document.createElement("div");
359
+ container.style.position = "fixed";
360
+ container.style.inset = "0";
361
+ container.style.zIndex = "2147483647";
362
+ container.style.display = "grid";
363
+ container.style.placeItems = "center";
364
+ container.style.pointerEvents = "auto";
365
+ document.body.appendChild(container);
366
+ return new Promise((resolve, reject) => {
367
+ let widgetId = "";
368
+ let timeout;
369
+ const cleanup = () => {
370
+ clearTimeout(timeout);
371
+ if (widgetId) driver.remove(widgetId);
372
+ container.remove();
373
+ };
374
+ timeout = setTimeout(() => {
375
+ cleanup();
376
+ reject(new Error("La validaci\xF3n de admisi\xF3n agot\xF3 el tiempo de espera"));
377
+ }, 15e3);
378
+ try {
379
+ widgetId = driver.render(container, {
380
+ sitekey: publicKey,
381
+ appearance: "interaction-only",
382
+ execution: "execute",
383
+ action: "centralq_admission",
384
+ callback: (token) => {
385
+ cleanup();
386
+ resolve(token);
387
+ },
388
+ "error-callback": () => {
389
+ cleanup();
390
+ reject(new Error("La validaci\xF3n de admisi\xF3n fall\xF3"));
391
+ },
392
+ "expired-callback": () => {
393
+ cleanup();
394
+ reject(new Error("La validaci\xF3n de admisi\xF3n expir\xF3"));
395
+ }
396
+ });
397
+ driver.execute(widgetId);
398
+ } catch {
399
+ cleanup();
400
+ reject(new Error("No se pudo ejecutar la admisi\xF3n administrada"));
401
+ }
402
+ });
403
+ }
404
+
253
405
  // src/centralq.ts
254
406
  var CentralQ = class _CentralQ {
255
407
  constructor(options) {
@@ -454,7 +606,22 @@ var CentralQClient = class {
454
606
  this.defaults.apiUrl,
455
607
  this.defaults.apiKey
456
608
  );
457
- return client.issueQueueInitToken(eventId, userId);
609
+ return this.issueInitToken(client, eventId, userId);
610
+ }
611
+ async issueInitToken(client, eventId, userId) {
612
+ if (typeof window === "undefined") {
613
+ return client.issueQueueInitToken(eventId, userId);
614
+ }
615
+ const protection = await client.getProtection(eventId);
616
+ if (!protection.challengeRequired) {
617
+ return client.issueQueueInitToken(eventId, userId);
618
+ }
619
+ const challenge = await client.getAdmissionChallenge(eventId);
620
+ if (!challenge.required) {
621
+ throw new Error("El evento requiere admisi\xF3n administrada");
622
+ }
623
+ const proof = await acquireManagedAdmissionProof(challenge.publicKey);
624
+ return client.issueQueueInitToken(eventId, userId, proof);
458
625
  }
459
626
  createQueue(options) {
460
627
  return CentralQ.init({
@@ -476,34 +643,118 @@ function createCentralQClient(options) {
476
643
  }
477
644
 
478
645
  // src/server.ts
646
+ var DEFAULT_TIMEOUT_MS = 5e3;
647
+ var CentralQServerRequestError = class extends Error {
648
+ constructor(code, message, options) {
649
+ super(message, options);
650
+ this.name = "CentralQServerRequestError";
651
+ this.code = code;
652
+ }
653
+ };
479
654
  function normalizeApiUrl2(apiUrl) {
480
- return apiUrl.replace(/\/+$/, "");
655
+ const trimmed = apiUrl.trim().replace(/\/+$/, "");
656
+ return trimmed.endsWith("/api") ? trimmed.slice(0, -4) : trimmed;
481
657
  }
482
- async function validateQueueTokenServer(options) {
483
- const apiUrl = options.apiUrl ?? CENTRALQ_DEFAULT_API_URL;
484
- const response = await fetch(
485
- `${normalizeApiUrl2(apiUrl)}/api/verify/${encodeURIComponent(options.eventId)}`,
486
- {
487
- method: "POST",
488
- headers: {
489
- "Content-Type": "application/json",
490
- "x-api-key": options.secretKey
658
+ function validateOptions(options) {
659
+ if (!options.secretKey?.trim()) {
660
+ throw new TypeError("CentralQ secretKey es requerida");
661
+ }
662
+ if (options.timeoutMs !== void 0 && options.timeoutMs <= 0) {
663
+ throw new TypeError("CentralQ timeoutMs debe ser mayor a cero");
664
+ }
665
+ }
666
+ var CentralQServerClient = class {
667
+ constructor(options) {
668
+ validateOptions(options);
669
+ this.apiUrl = normalizeApiUrl2(options.apiUrl ?? CENTRALQ_DEFAULT_API_URL);
670
+ this.secretKey = options.secretKey.trim();
671
+ this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
672
+ this.fetchFn = options.fetch ?? globalThis.fetch;
673
+ }
674
+ validateToken(input) {
675
+ return this.post(
676
+ `/api/queue/verify/${encodeURIComponent(input.eventId)}`,
677
+ { token: input.token },
678
+ { valid: false, reason: "Respuesta inv\xE1lida" }
679
+ );
680
+ }
681
+ verifyAccess(input) {
682
+ return this.post(
683
+ `/api/queue/verify/${encodeURIComponent(input.eventId)}/access`,
684
+ { token: input.token ?? null },
685
+ {
686
+ allowed: false,
687
+ reason: "invalid_response",
688
+ message: "Respuesta inv\xE1lida"
689
+ }
690
+ );
691
+ }
692
+ completeAccess(input) {
693
+ return this.post(
694
+ `/api/queue/verify/${encodeURIComponent(input.eventId)}/complete`,
695
+ {
696
+ token: input.token,
697
+ completionId: input.completionId
491
698
  },
492
- body: JSON.stringify({ token: options.token })
699
+ { completed: false, reason: "invalid_response" }
700
+ );
701
+ }
702
+ async post(path, body, fallback) {
703
+ const controller = new AbortController();
704
+ const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
705
+ try {
706
+ const response = await this.fetchFn(`${this.apiUrl}${path}`, {
707
+ method: "POST",
708
+ headers: {
709
+ "Content-Type": "application/json",
710
+ "x-api-key": this.secretKey
711
+ },
712
+ body: JSON.stringify(body),
713
+ signal: controller.signal
714
+ });
715
+ const data = await response.json().catch(() => fallback);
716
+ return { status: response.status, data };
717
+ } catch (error) {
718
+ if (controller.signal.aborted) {
719
+ throw new CentralQServerRequestError(
720
+ "timeout",
721
+ `CentralQ no respondi\xF3 en ${this.timeoutMs}ms`,
722
+ { cause: error }
723
+ );
724
+ }
725
+ throw new CentralQServerRequestError(
726
+ "network_error",
727
+ "No se pudo conectar con CentralQ",
728
+ { cause: error }
729
+ );
730
+ } finally {
731
+ clearTimeout(timeout);
493
732
  }
494
- );
495
- const data = await response.json().catch(() => ({
496
- valid: false,
497
- reason: "Respuesta inv\xE1lida"
498
- }));
499
- return { status: response.status, data };
733
+ }
734
+ };
735
+ function createCentralQServerClient(options) {
736
+ return new CentralQServerClient(options);
737
+ }
738
+ function validateQueueTokenServer(options) {
739
+ return createCentralQServerClient(options).validateToken(options);
740
+ }
741
+ function verifyQueueAccessServer(options) {
742
+ return createCentralQServerClient(options).verifyAccess(options);
743
+ }
744
+ function completeQueueAccessServer(options) {
745
+ return createCentralQServerClient(options).completeAccess(options);
500
746
  }
501
747
  // Annotate the CommonJS export names for ESM import in node:
502
748
  0 && (module.exports = {
503
749
  CENTRALQ_DEFAULT_API_URL,
504
750
  CentralQ,
505
751
  CentralQClient,
752
+ CentralQServerClient,
753
+ CentralQServerRequestError,
506
754
  QueueHttpClient,
755
+ completeQueueAccessServer,
507
756
  createCentralQClient,
508
- validateQueueTokenServer
757
+ createCentralQServerClient,
758
+ validateQueueTokenServer,
759
+ verifyQueueAccessServer
509
760
  });
package/dist/index.mjs CHANGED
@@ -1,21 +1,31 @@
1
1
  import {
2
- validateQueueTokenServer
3
- } from "./chunk-JR7BCYB5.mjs";
2
+ CentralQServerClient,
3
+ CentralQServerRequestError,
4
+ completeQueueAccessServer,
5
+ createCentralQServerClient,
6
+ validateQueueTokenServer,
7
+ verifyQueueAccessServer
8
+ } from "./chunk-FAJWYFUK.mjs";
4
9
  import {
5
10
  CentralQ,
6
11
  CentralQClient,
7
12
  createCentralQClient
8
- } from "./chunk-A4HITWM4.mjs";
13
+ } from "./chunk-BVCZFNM3.mjs";
9
14
  import {
10
15
  CENTRALQ_DEFAULT_API_URL,
11
16
  QueueHttpClient
12
- } from "./chunk-42RGFZKP.mjs";
17
+ } from "./chunk-P73Q2ZIO.mjs";
13
18
  import "./chunk-XRJFNASX.mjs";
14
19
  export {
15
20
  CENTRALQ_DEFAULT_API_URL,
16
21
  CentralQ,
17
22
  CentralQClient,
23
+ CentralQServerClient,
24
+ CentralQServerRequestError,
18
25
  QueueHttpClient,
26
+ completeQueueAccessServer,
19
27
  createCentralQClient,
20
- validateQueueTokenServer
28
+ createCentralQServerClient,
29
+ validateQueueTokenServer,
30
+ verifyQueueAccessServer
21
31
  };
package/dist/react.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { C as CentralQ, c as CentralQCreateOptions, a as CentralQClient, Q as QueueStatus, d as CentralQOptions } from './centralq-I9tdL_Xr.mjs';
1
+ import { C as CentralQ, c as CentralQCreateOptions, a as CentralQClient, Q as QueueStatus, d as CentralQOptions } from './centralq-C3ukDo0x.mjs';
2
2
 
3
3
  interface UseCentralQReturn {
4
4
  /** Token JWT si el usuario fue admitido, null si no */
package/dist/react.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { C as CentralQ, c as CentralQCreateOptions, a as CentralQClient, Q as QueueStatus, d as CentralQOptions } from './centralq-I9tdL_Xr.js';
1
+ import { C as CentralQ, c as CentralQCreateOptions, a as CentralQClient, Q as QueueStatus, d as CentralQOptions } from './centralq-C3ukDo0x.js';
2
2
 
3
3
  interface UseCentralQReturn {
4
4
  /** Token JWT si el usuario fue admitido, null si no */
package/dist/react.js CHANGED
@@ -220,13 +220,13 @@ var QueueHttpClient = class {
220
220
  }
221
221
  );
222
222
  }
223
- async issueQueueInitToken(eventId, userId) {
223
+ async issueQueueInitToken(eventId, userId, admissionProof) {
224
224
  const res = await fetch(
225
225
  `${this.apiUrl}/api/queue/init/${encodeURIComponent(eventId)}`,
226
226
  {
227
227
  method: "POST",
228
228
  headers: this.headers,
229
- body: JSON.stringify({ userId })
229
+ body: JSON.stringify({ userId, admissionProof })
230
230
  }
231
231
  );
232
232
  const body = await res.json().catch(() => ({}));
@@ -245,6 +245,74 @@ var QueueHttpClient = class {
245
245
  expiresAt: body.expiresAt
246
246
  };
247
247
  }
248
+ async getProtection(eventId) {
249
+ const res = await fetch(
250
+ `${this.apiUrl}/api/queue/${encodeURIComponent(eventId)}/protection`,
251
+ { headers: this.headers }
252
+ );
253
+ const body = await res.json().catch(() => ({}));
254
+ if (!res.ok) {
255
+ throw new Error(
256
+ body.message ?? `Error ${res.status} al consultar protecci\xF3n`
257
+ );
258
+ }
259
+ return {
260
+ eventId: body.eventId ?? eventId,
261
+ configured: body.configured === true,
262
+ protected: body.protected === true,
263
+ isActive: body.isActive === true,
264
+ admissionMode: body.admissionMode ?? "PUBLIC",
265
+ challengeRequired: body.challengeRequired === true
266
+ };
267
+ }
268
+ async getAdmissionChallenge(eventId) {
269
+ const res = await fetch(
270
+ `${this.apiUrl}/api/queue/${encodeURIComponent(eventId)}/admission`,
271
+ { headers: this.headers }
272
+ );
273
+ const body = await res.json().catch(() => ({}));
274
+ if (!res.ok) {
275
+ throw new Error(
276
+ body.message ?? `Error ${res.status} al preparar la admisi\xF3n`
277
+ );
278
+ }
279
+ if (body.required !== true) return { required: false };
280
+ if (!("publicKey" in body) || !body.publicKey) {
281
+ throw new Error("Respuesta inv\xE1lida al preparar la admisi\xF3n");
282
+ }
283
+ return {
284
+ required: true,
285
+ publicKey: body.publicKey,
286
+ appearance: "interaction-only"
287
+ };
288
+ }
289
+ async verifyToken(eventId, token) {
290
+ const res = await fetch(
291
+ `${this.apiUrl}/api/queue/verify/${encodeURIComponent(eventId)}`,
292
+ {
293
+ method: "POST",
294
+ headers: this.headers,
295
+ body: JSON.stringify({ token })
296
+ }
297
+ );
298
+ const body = await res.json().catch(() => ({
299
+ valid: false,
300
+ reason: "Respuesta inv\xE1lida"
301
+ }));
302
+ if (body.valid === true && body.userId && body.eventId && body.expiresAt) {
303
+ return body;
304
+ }
305
+ if (body.valid === false) {
306
+ return { valid: false, reason: body.reason ?? "Token inv\xE1lido" };
307
+ }
308
+ if (!res.ok) {
309
+ return {
310
+ valid: false,
311
+ reason: body.message ?? `Error ${res.status} al validar token de cola`
312
+ };
313
+ }
314
+ return { valid: false, reason: "Respuesta inv\xE1lida" };
315
+ }
248
316
  };
249
317
 
250
318
  // src/centralq.ts
package/dist/react.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  CentralQ
3
- } from "./chunk-A4HITWM4.mjs";
4
- import "./chunk-42RGFZKP.mjs";
3
+ } from "./chunk-BVCZFNM3.mjs";
4
+ import "./chunk-P73Q2ZIO.mjs";
5
5
  import "./chunk-XRJFNASX.mjs";
6
6
 
7
7
  // src/react.ts
package/dist/server.d.mts CHANGED
@@ -1,6 +1,10 @@
1
- interface ValidateQueueTokenServerOptions {
1
+ interface CentralQServerClientOptions {
2
2
  apiUrl?: string;
3
3
  secretKey: string;
4
+ timeoutMs?: number;
5
+ fetch?: typeof fetch;
6
+ }
7
+ interface ValidateQueueTokenServerOptions extends CentralQServerClientOptions {
4
8
  eventId: string;
5
9
  token: string;
6
10
  }
@@ -13,9 +17,85 @@ type QueueTokenValidationResult = {
13
17
  valid: false;
14
18
  reason: string;
15
19
  };
20
+ interface VerifyQueueAccessServerOptions extends CentralQServerClientOptions {
21
+ eventId: string;
22
+ token?: string;
23
+ }
24
+ type QueueAccessValidationResult = {
25
+ allowed: true;
26
+ eventId: string;
27
+ protected: boolean;
28
+ reason?: string;
29
+ userId?: string;
30
+ expiresAt?: string;
31
+ } | {
32
+ allowed: false;
33
+ eventId?: string;
34
+ protected?: boolean;
35
+ reason?: string;
36
+ message?: string;
37
+ };
38
+ interface CompleteQueueAccessServerOptions extends CentralQServerClientOptions {
39
+ eventId: string;
40
+ token: string;
41
+ completionId: string;
42
+ }
43
+ type QueueAccessCompletionResult = {
44
+ completed: true;
45
+ alreadyCompleted: boolean;
46
+ } | {
47
+ completed: false;
48
+ reason: string;
49
+ };
50
+ type CentralQServerRequestErrorCode = "network_error" | "timeout";
51
+ declare class CentralQServerRequestError extends Error {
52
+ readonly code: CentralQServerRequestErrorCode;
53
+ constructor(code: CentralQServerRequestErrorCode, message: string, options?: {
54
+ cause?: unknown;
55
+ });
56
+ }
57
+ declare class CentralQServerClient {
58
+ private readonly apiUrl;
59
+ private readonly secretKey;
60
+ private readonly timeoutMs;
61
+ private readonly fetchFn;
62
+ constructor(options: CentralQServerClientOptions);
63
+ validateToken(input: {
64
+ eventId: string;
65
+ token: string;
66
+ }): Promise<{
67
+ status: number;
68
+ data: QueueTokenValidationResult;
69
+ }>;
70
+ verifyAccess(input: {
71
+ eventId: string;
72
+ token?: string;
73
+ }): Promise<{
74
+ status: number;
75
+ data: QueueAccessValidationResult;
76
+ }>;
77
+ completeAccess(input: {
78
+ eventId: string;
79
+ token: string;
80
+ completionId: string;
81
+ }): Promise<{
82
+ status: number;
83
+ data: QueueAccessCompletionResult;
84
+ }>;
85
+ private post;
86
+ }
87
+ declare function createCentralQServerClient(options: CentralQServerClientOptions): CentralQServerClient;
16
88
  declare function validateQueueTokenServer(options: ValidateQueueTokenServerOptions): Promise<{
17
89
  status: number;
18
90
  data: QueueTokenValidationResult;
19
91
  }>;
92
+ declare function verifyQueueAccessServer(options: VerifyQueueAccessServerOptions): Promise<{
93
+ status: number;
94
+ data: QueueAccessValidationResult;
95
+ }>;
96
+ declare function completeQueueAccessServer(options: CompleteQueueAccessServerOptions): Promise<{
97
+ status: number;
98
+ data: QueueAccessCompletionResult;
99
+ }>;
20
100
 
21
- export { type QueueTokenValidationResult, type ValidateQueueTokenServerOptions, validateQueueTokenServer };
101
+ export { CentralQServerClient, type CentralQServerClientOptions, CentralQServerRequestError, type CentralQServerRequestErrorCode, type CompleteQueueAccessServerOptions, type QueueAccessCompletionResult, type QueueAccessValidationResult, type QueueTokenValidationResult, type ValidateQueueTokenServerOptions, type VerifyQueueAccessServerOptions, completeQueueAccessServer, createCentralQServerClient, validateQueueTokenServer, verifyQueueAccessServer };