@trillboards/api-client 3.1.15 → 3.2.5

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 CHANGED
@@ -1,5 +1,8 @@
1
- import { __require } from './chunk-X2AIWEHJ.mjs';
2
- export { generatedTypes } from './chunk-X2AIWEHJ.mjs';
1
+ import { __require } from './chunk-A5ESPUCN.mjs';
2
+ export { generatedTypes } from './chunk-A5ESPUCN.mjs';
3
+ import { createParser } from 'eventsource-parser';
4
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
5
+ import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
3
6
  import { createHmac, timingSafeEqual } from 'crypto';
4
7
 
5
8
  // src/error.ts
@@ -72,7 +75,7 @@ var TrillboardsError = class _TrillboardsError extends Error {
72
75
  };
73
76
 
74
77
  // src/version.ts
75
- var VERSION = "3.1.15";
78
+ var VERSION = "3.2.5";
76
79
 
77
80
  // src/http.ts
78
81
  var PUBLIC_PATHS = ["/v1/errors", "/v1/changelog", "/api/discover", "/v1/health"];
@@ -122,6 +125,13 @@ var HttpClient = class {
122
125
  this.config = config;
123
126
  }
124
127
  async request(method, path2, options) {
128
+ const response = await this.requestResponse(method, path2, options);
129
+ if (response.status === 204) return void 0;
130
+ const json = await this.readJson(response);
131
+ if (!response.ok) throw TrillboardsError.fromResponse(json, response);
132
+ return json;
133
+ }
134
+ async requestResponse(method, path2, options) {
125
135
  const url = this.buildUrl(path2, options?.params);
126
136
  const headers = {
127
137
  "Content-Type": "application/json",
@@ -144,13 +154,12 @@ var HttpClient = class {
144
154
  if (options?.body !== void 0 && options.body !== null) {
145
155
  fetchOptions.body = JSON.stringify(options.body);
146
156
  }
147
- const response = await fetch(url, fetchOptions);
148
- if (response.status === 204) {
149
- return void 0;
150
- }
151
- let json;
157
+ fetchOptions.signal = options?.signal;
158
+ return fetch(url, fetchOptions);
159
+ }
160
+ async readJson(response) {
152
161
  try {
153
- json = await response.json();
162
+ return await response.json();
154
163
  } catch {
155
164
  throw new TrillboardsError({
156
165
  type: "api_error",
@@ -159,10 +168,24 @@ var HttpClient = class {
159
168
  statusCode: response.status
160
169
  });
161
170
  }
162
- if (!response.ok) {
163
- throw TrillboardsError.fromResponse(json, response);
171
+ }
172
+ /** Open one authenticated live tail. The native endpoint has no replay cursor. */
173
+ async openStream(path2, options) {
174
+ const response = await this.requestResponse("GET", path2, {
175
+ ...options,
176
+ headers: { Accept: "text/event-stream", ...options?.headers }
177
+ });
178
+ if (!response.ok) throw TrillboardsError.fromResponse(await this.readJson(response), response);
179
+ if (!/^text\/event-stream(?:;|$)/i.test(response.headers.get("content-type") || "") || !response.body) {
180
+ await response.body?.cancel();
181
+ throw new TrillboardsError({
182
+ type: "api_error",
183
+ code: "invalid_response",
184
+ message: "Expected a text/event-stream response with a body.",
185
+ statusCode: response.status
186
+ });
164
187
  }
165
- return json;
188
+ return response;
166
189
  }
167
190
  get(path2, opts) {
168
191
  return this.request("GET", path2, { params: opts?.params });
@@ -413,6 +436,63 @@ var AudienceClient = class {
413
436
  return this.http.get("/v1/partner/audience/stats", { params });
414
437
  }
415
438
  };
439
+ async function* readEventStream(http, path2, params, options) {
440
+ const controller = new AbortController();
441
+ const abort = () => controller.abort(options.signal?.reason);
442
+ if (options.signal?.aborted) abort();
443
+ else options.signal?.addEventListener("abort", abort, { once: true });
444
+ let reader;
445
+ try {
446
+ const response = await http.openStream(path2, { params, signal: controller.signal });
447
+ reader = response.body.getReader();
448
+ const decoder = new TextDecoder(), events = [];
449
+ let retry;
450
+ const parser = createParser({
451
+ onRetry: (value) => {
452
+ retry = value;
453
+ },
454
+ onEvent: (frame) => {
455
+ let data;
456
+ try {
457
+ data = JSON.parse(frame.data);
458
+ } catch {
459
+ throw new TrillboardsError({
460
+ type: "api_error",
461
+ code: "invalid_response",
462
+ message: "Expected JSON data in an SSE event.",
463
+ statusCode: response.status
464
+ });
465
+ }
466
+ events.push({
467
+ event: frame.event || "message",
468
+ data,
469
+ ...frame.id === void 0 ? {} : { id: frame.id },
470
+ ...retry === void 0 ? {} : { retry }
471
+ });
472
+ retry = void 0;
473
+ }
474
+ });
475
+ while (true) {
476
+ const chunk = await reader.read();
477
+ if (chunk.done) break;
478
+ parser.feed(decoder.decode(chunk.value, { stream: true }));
479
+ while (events.length) {
480
+ if (controller.signal.aborted) throw controller.signal.reason;
481
+ yield events.shift();
482
+ }
483
+ }
484
+ parser.feed(decoder.decode());
485
+ while (events.length) yield events.shift();
486
+ } finally {
487
+ options.signal?.removeEventListener("abort", abort);
488
+ controller.abort();
489
+ try {
490
+ await reader?.cancel();
491
+ } catch {
492
+ }
493
+ reader?.releaseLock();
494
+ }
495
+ }
416
496
 
417
497
  // src/resources/data.ts
418
498
  var DataClient = class {
@@ -420,13 +500,29 @@ var DataClient = class {
420
500
  this.http = http;
421
501
  }
422
502
  /** Get venue intelligence data for a screen. */
423
- async getVenueIntelligence(screenId) {
424
- return this.http.get(`/v1/partner/venue/${screenId}`);
503
+ getVenueIntelligence(screenId) {
504
+ return this.http.get("/v1/partner/venue/" + encodeURIComponent(screenId));
425
505
  }
426
506
  /** Get API usage summary. */
427
- async getUsage(params) {
507
+ getUsage(params) {
428
508
  return this.http.get("/v1/partner/usage", { params });
429
509
  }
510
+ listScreens(query = {}) {
511
+ return this.http.get("/v1/data/screens", { params: query });
512
+ }
513
+ getHistory(screenId, query = {}) {
514
+ return this.http.get("/v1/data/screens/" + encodeURIComponent(screenId) + "/history", { params: query });
515
+ }
516
+ getAudience(screenId) {
517
+ return this.http.get("/v1/data/screens/" + encodeURIComponent(screenId) + "/audience");
518
+ }
519
+ query(body) {
520
+ return this.http.post("/v1/data/query", body);
521
+ }
522
+ /** One live tail; reconnect explicitly and recover history through bounded reads. */
523
+ stream(query = {}, options = {}) {
524
+ return readEventStream(this.http, "/v1/data/stream", query, options);
525
+ }
430
526
  };
431
527
 
432
528
  // src/resources/billing.ts
@@ -434,6 +530,19 @@ var BillingClient = class {
434
530
  constructor(http) {
435
531
  this.http = http;
436
532
  }
533
+ setup(body) {
534
+ return this.http.post("/v1/partner/billing/setup", body);
535
+ }
536
+ createCreditCheckout(body, options) {
537
+ return this.http.post("/v1/partner/billing/credits/checkout", body, { headers: { "Idempotency-Key": options.idempotencyKey } });
538
+ }
539
+ purchaseCredits(body, options) {
540
+ return this.http.post("/v1/partner/billing/credits", body, { headers: { "Idempotency-Key": options.idempotencyKey } });
541
+ }
542
+ /** Read the committed shared credit ledger after Stripe payment completes. */
543
+ getUsageSummary() {
544
+ return this.http.get("/v1/partner/billing/usage-summary");
545
+ }
437
546
  /** Get current billing info (plan, credits, usage). */
438
547
  async get() {
439
548
  return this.http.get("/v1/partner/billing");
@@ -514,6 +623,96 @@ var CreativeExperimentsClient = class {
514
623
  return this.http.post(path(id) + "/stop", body);
515
624
  }
516
625
  };
626
+ var McpToolError = class extends Error {
627
+ constructor(tool, result) {
628
+ super("Native MCP tool failed: " + tool);
629
+ this.tool = tool;
630
+ this.result = result;
631
+ this.name = "McpToolError";
632
+ }
633
+ };
634
+ var MediaBuysClient = class {
635
+ constructor(config) {
636
+ this.config = config;
637
+ }
638
+ connection() {
639
+ if (!this.connecting) {
640
+ const client = new Client({ name: "trillboards-typescript", version: VERSION });
641
+ const transport = new StreamableHTTPClientTransport(new URL(this.config.baseUrl + "/mcp"), {
642
+ requestInit: { headers: {
643
+ Authorization: "Bearer " + this.config.apiKey,
644
+ "X-Trillboards-Client": "typescript-sdk/" + VERSION,
645
+ "User-Agent": "trillboards-typescript/" + VERSION,
646
+ ...this.config.version ? { "Trillboards-Version": this.config.version } : {}
647
+ } }
648
+ });
649
+ this.client = client;
650
+ this.transport = transport;
651
+ this.connecting = client.connect(transport).then(() => client).catch(async (error) => {
652
+ await client.close();
653
+ this.client = void 0;
654
+ this.transport = void 0;
655
+ this.connecting = void 0;
656
+ throw error;
657
+ });
658
+ }
659
+ return this.connecting;
660
+ }
661
+ async call(name, args) {
662
+ const client = await this.connection();
663
+ const result = await client.callTool({ name, arguments: args });
664
+ if (result.isError) throw new McpToolError(name, result);
665
+ if (result.structuredContent) return result.structuredContent;
666
+ for (const block of result.content) {
667
+ if (block.type !== "text") continue;
668
+ try {
669
+ return JSON.parse(block.text);
670
+ } catch {
671
+ }
672
+ }
673
+ throw new McpToolError(name, result);
674
+ }
675
+ getProducts(args = {}) {
676
+ return this.call("get_products", args);
677
+ }
678
+ listAccounts(args = {}) {
679
+ return this.call("list_accounts", args);
680
+ }
681
+ syncAccounts(args) {
682
+ return this.call("sync_accounts", args);
683
+ }
684
+ create(args) {
685
+ return this.call("create_media_buy", args);
686
+ }
687
+ list(args = {}) {
688
+ return this.call("get_media_buys", args);
689
+ }
690
+ update(args) {
691
+ return this.call("update_media_buy", args);
692
+ }
693
+ getDelivery(args) {
694
+ return this.call("get_media_buy_delivery", args);
695
+ }
696
+ syncCreatives(args) {
697
+ return this.call("sync_creatives", args);
698
+ }
699
+ discoverInventory(args = {}) {
700
+ return this.call("discover_inventory", args);
701
+ }
702
+ /** Release MCP streams and terminate an optional server session. */
703
+ async close() {
704
+ await this.connecting?.catch(() => void 0);
705
+ const client = this.client, transport = this.transport;
706
+ this.client = void 0;
707
+ this.transport = void 0;
708
+ this.connecting = void 0;
709
+ try {
710
+ if (transport?.sessionId) await transport.terminateSession();
711
+ } finally {
712
+ await client?.close();
713
+ }
714
+ }
715
+ };
517
716
 
518
717
  // src/client.ts
519
718
  var DEFAULT_BASE_URL = "https://api.trillboards.com";
@@ -543,6 +742,7 @@ var TrillboardsClient = class {
543
742
  this.billing = new BillingClient(this._http);
544
743
  this.routes = new RoutesClient(this._http);
545
744
  this.creativeExperiments = new CreativeExperimentsClient(this._http);
745
+ this.mediaBuys = new MediaBuysClient({ apiKey: options.apiKey, baseUrl, version: options.version });
546
746
  }
547
747
  };
548
748
  var DEFAULT_TOLERANCE_SECONDS = 300;
@@ -838,6 +1038,6 @@ var Webhooks = {
838
1038
  verifyAdcpWebhook
839
1039
  };
840
1040
 
841
- export { ADCP_WEBHOOK_SIGNING_TAG, AnalyticsClient, AudienceClient, BillingClient, CreativeExperimentsClient, DataClient, DevicesClient, EarningsClient, ErrorsClient, FleetClient, ImpressionsClient, RoutesClient, ScreensClient, TrillboardsClient, TrillboardsError, VERSION, Webhooks, WebhooksClient, constructEvent, constructEventLegacy, parseSignatureHeader, retryWithBackoff, verifyAdcpWebhook };
1041
+ export { ADCP_WEBHOOK_SIGNING_TAG, AnalyticsClient, AudienceClient, BillingClient, CreativeExperimentsClient, DataClient, DevicesClient, EarningsClient, ErrorsClient, FleetClient, ImpressionsClient, McpToolError, MediaBuysClient, RoutesClient, ScreensClient, TrillboardsClient, TrillboardsError, VERSION, Webhooks, WebhooksClient, constructEvent, constructEventLegacy, parseSignatureHeader, retryWithBackoff, verifyAdcpWebhook };
842
1042
  //# sourceMappingURL=index.mjs.map
843
1043
  //# sourceMappingURL=index.mjs.map