@trillboards/ads-sdk 2.0.0 → 2.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/server.d.mts CHANGED
@@ -205,8 +205,43 @@ declare class CreativeClient {
205
205
  }
206
206
 
207
207
  interface PartnerClientConfig {
208
- apiKey: string;
208
+ apiKey?: string;
209
209
  apiBase?: string;
210
+ debug?: boolean;
211
+ }
212
+ interface QuickStartResult {
213
+ partner: {
214
+ partner_id: string;
215
+ name: string;
216
+ slug: string;
217
+ status: string;
218
+ revenue_share_percent: number;
219
+ };
220
+ credentials: {
221
+ api_key: string;
222
+ api_key_prefix: string;
223
+ warning: string;
224
+ };
225
+ device: {
226
+ device_id: string;
227
+ external_device_id: string;
228
+ fingerprint: string;
229
+ screen_id: string;
230
+ name: string;
231
+ status: string;
232
+ embed_url: string;
233
+ };
234
+ integration: {
235
+ sdk_snippet: string;
236
+ iframe_snippet: string;
237
+ embed_url: string;
238
+ api_base: string;
239
+ sdk_url: string;
240
+ docs_url: string;
241
+ };
242
+ sdk_config: Record<string, unknown>;
243
+ next_steps: string[];
244
+ client: PartnerClient;
210
245
  }
211
246
  declare class PartnerClient {
212
247
  private apiKey;
@@ -216,7 +251,22 @@ declare class PartnerClient {
216
251
  readonly analytics: AnalyticsClient;
217
252
  readonly auctions: AuctionClient;
218
253
  readonly creatives: CreativeClient;
219
- constructor(config: PartnerClientConfig);
254
+ constructor(config?: PartnerClientConfig);
255
+ /** Returns `true` if the API key is a test key (`trb_test_*`). */
256
+ get isTestMode(): boolean;
257
+ /**
258
+ * One-call onboarding: register a partner, create the first device,
259
+ * and return a pre-authenticated `PartnerClient` instance ready to use.
260
+ *
261
+ * This calls `POST /v1/partner/quick-start` (public, no auth required).
262
+ */
263
+ static quickStart(options: {
264
+ companyName: string;
265
+ email: string;
266
+ deviceName?: string;
267
+ apiBase?: string;
268
+ debug?: boolean;
269
+ }): Promise<QuickStartResult>;
220
270
  createVastTagBuilder(): VastTagBuilder;
221
271
  createTrackingBatch(): TrackingBatch;
222
272
  protected fetch(path: string, options?: RequestInit): Promise<any>;
@@ -231,8 +281,60 @@ declare class PartnerClient {
231
281
  * the caller provides their own `signal`.
232
282
  * - Always sends `Authorization: Bearer <key>` and
233
283
  * `Content-Type: application/json`.
234
- * - Throws on non-2xx responses.
284
+ * - Throws structured `TrillboardsError` subclasses on non-2xx responses.
285
+ * - Logs requests and responses when debug logging is active.
235
286
  */
236
287
  declare function createAuthenticatedFetch(apiKey: string, apiBase: string): (path: string, options?: RequestInit) => Promise<any>;
237
288
 
238
- export { AnalyticsClient, AuctionClient, type AuctionResult, AudienceClient, type AudiencePrediction, type BuildTagOptions, CreativeClient, type CreativeReview, type CreativeStats, type EarningsData, type ImpressionReport, type LiveAudience, type LookalikeScreen, PartnerClient, type PartnerClientConfig, type ScreenDailyAnalytics, TrackingBatch, type TrackingBatchConfig, type TrackingResult, VastTagBuilder, type VastTagBuilderConfig, type VastTagResult, createAuthenticatedFetch };
289
+ /**
290
+ * Base error class for all Trillboards SDK errors.
291
+ * Mirrors the API error response shape: `{ type, code, message, param, help }`.
292
+ */
293
+ declare class TrillboardsError extends Error {
294
+ readonly type: string;
295
+ readonly code: string;
296
+ readonly statusCode: number;
297
+ readonly help?: string;
298
+ readonly param?: string;
299
+ constructor(message: string, options?: {
300
+ type?: string;
301
+ code?: string;
302
+ statusCode?: number;
303
+ help?: string;
304
+ param?: string;
305
+ });
306
+ }
307
+ /** Thrown on HTTP 401 — invalid or missing API key. */
308
+ declare class TrillboardsAuthenticationError extends TrillboardsError {
309
+ constructor(message?: string);
310
+ }
311
+ /** Thrown on HTTP 429 — rate limit exceeded. */
312
+ declare class TrillboardsRateLimitError extends TrillboardsError {
313
+ readonly retryAfter: number;
314
+ constructor(retryAfter: number, message?: string);
315
+ }
316
+ /** Thrown on HTTP 404 — resource not found. */
317
+ declare class TrillboardsNotFoundError extends TrillboardsError {
318
+ constructor(message?: string);
319
+ }
320
+ /** Thrown on HTTP 400 — validation / bad request. */
321
+ declare class TrillboardsValidationError extends TrillboardsError {
322
+ constructor(message?: string, param?: string);
323
+ }
324
+
325
+ type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'none';
326
+ declare class Logger {
327
+ private level;
328
+ setLevel(level: LogLevel): void;
329
+ getLevel(): LogLevel;
330
+ debug(message: string, data?: unknown): void;
331
+ info(message: string, data?: unknown): void;
332
+ warn(message: string, data?: unknown): void;
333
+ error(message: string, data?: unknown): void;
334
+ }
335
+ /** Singleton logger instance shared across the SDK. */
336
+ declare const logger: Logger;
337
+ /** Set the global log level for the SDK. */
338
+ declare function setLogLevel(level: LogLevel): void;
339
+
340
+ export { AnalyticsClient, AuctionClient, type AuctionResult, AudienceClient, type AudiencePrediction, type BuildTagOptions, CreativeClient, type CreativeReview, type CreativeStats, type EarningsData, type ImpressionReport, type LiveAudience, type LogLevel, type LookalikeScreen, PartnerClient, type PartnerClientConfig, type QuickStartResult, type ScreenDailyAnalytics, TrackingBatch, type TrackingBatchConfig, type TrackingResult, TrillboardsAuthenticationError, TrillboardsError, TrillboardsNotFoundError, TrillboardsRateLimitError, TrillboardsValidationError, VastTagBuilder, type VastTagBuilderConfig, type VastTagResult, createAuthenticatedFetch, logger, setLogLevel };
package/dist/server.d.ts CHANGED
@@ -205,8 +205,43 @@ declare class CreativeClient {
205
205
  }
206
206
 
207
207
  interface PartnerClientConfig {
208
- apiKey: string;
208
+ apiKey?: string;
209
209
  apiBase?: string;
210
+ debug?: boolean;
211
+ }
212
+ interface QuickStartResult {
213
+ partner: {
214
+ partner_id: string;
215
+ name: string;
216
+ slug: string;
217
+ status: string;
218
+ revenue_share_percent: number;
219
+ };
220
+ credentials: {
221
+ api_key: string;
222
+ api_key_prefix: string;
223
+ warning: string;
224
+ };
225
+ device: {
226
+ device_id: string;
227
+ external_device_id: string;
228
+ fingerprint: string;
229
+ screen_id: string;
230
+ name: string;
231
+ status: string;
232
+ embed_url: string;
233
+ };
234
+ integration: {
235
+ sdk_snippet: string;
236
+ iframe_snippet: string;
237
+ embed_url: string;
238
+ api_base: string;
239
+ sdk_url: string;
240
+ docs_url: string;
241
+ };
242
+ sdk_config: Record<string, unknown>;
243
+ next_steps: string[];
244
+ client: PartnerClient;
210
245
  }
211
246
  declare class PartnerClient {
212
247
  private apiKey;
@@ -216,7 +251,22 @@ declare class PartnerClient {
216
251
  readonly analytics: AnalyticsClient;
217
252
  readonly auctions: AuctionClient;
218
253
  readonly creatives: CreativeClient;
219
- constructor(config: PartnerClientConfig);
254
+ constructor(config?: PartnerClientConfig);
255
+ /** Returns `true` if the API key is a test key (`trb_test_*`). */
256
+ get isTestMode(): boolean;
257
+ /**
258
+ * One-call onboarding: register a partner, create the first device,
259
+ * and return a pre-authenticated `PartnerClient` instance ready to use.
260
+ *
261
+ * This calls `POST /v1/partner/quick-start` (public, no auth required).
262
+ */
263
+ static quickStart(options: {
264
+ companyName: string;
265
+ email: string;
266
+ deviceName?: string;
267
+ apiBase?: string;
268
+ debug?: boolean;
269
+ }): Promise<QuickStartResult>;
220
270
  createVastTagBuilder(): VastTagBuilder;
221
271
  createTrackingBatch(): TrackingBatch;
222
272
  protected fetch(path: string, options?: RequestInit): Promise<any>;
@@ -231,8 +281,60 @@ declare class PartnerClient {
231
281
  * the caller provides their own `signal`.
232
282
  * - Always sends `Authorization: Bearer <key>` and
233
283
  * `Content-Type: application/json`.
234
- * - Throws on non-2xx responses.
284
+ * - Throws structured `TrillboardsError` subclasses on non-2xx responses.
285
+ * - Logs requests and responses when debug logging is active.
235
286
  */
236
287
  declare function createAuthenticatedFetch(apiKey: string, apiBase: string): (path: string, options?: RequestInit) => Promise<any>;
237
288
 
238
- export { AnalyticsClient, AuctionClient, type AuctionResult, AudienceClient, type AudiencePrediction, type BuildTagOptions, CreativeClient, type CreativeReview, type CreativeStats, type EarningsData, type ImpressionReport, type LiveAudience, type LookalikeScreen, PartnerClient, type PartnerClientConfig, type ScreenDailyAnalytics, TrackingBatch, type TrackingBatchConfig, type TrackingResult, VastTagBuilder, type VastTagBuilderConfig, type VastTagResult, createAuthenticatedFetch };
289
+ /**
290
+ * Base error class for all Trillboards SDK errors.
291
+ * Mirrors the API error response shape: `{ type, code, message, param, help }`.
292
+ */
293
+ declare class TrillboardsError extends Error {
294
+ readonly type: string;
295
+ readonly code: string;
296
+ readonly statusCode: number;
297
+ readonly help?: string;
298
+ readonly param?: string;
299
+ constructor(message: string, options?: {
300
+ type?: string;
301
+ code?: string;
302
+ statusCode?: number;
303
+ help?: string;
304
+ param?: string;
305
+ });
306
+ }
307
+ /** Thrown on HTTP 401 — invalid or missing API key. */
308
+ declare class TrillboardsAuthenticationError extends TrillboardsError {
309
+ constructor(message?: string);
310
+ }
311
+ /** Thrown on HTTP 429 — rate limit exceeded. */
312
+ declare class TrillboardsRateLimitError extends TrillboardsError {
313
+ readonly retryAfter: number;
314
+ constructor(retryAfter: number, message?: string);
315
+ }
316
+ /** Thrown on HTTP 404 — resource not found. */
317
+ declare class TrillboardsNotFoundError extends TrillboardsError {
318
+ constructor(message?: string);
319
+ }
320
+ /** Thrown on HTTP 400 — validation / bad request. */
321
+ declare class TrillboardsValidationError extends TrillboardsError {
322
+ constructor(message?: string, param?: string);
323
+ }
324
+
325
+ type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'none';
326
+ declare class Logger {
327
+ private level;
328
+ setLevel(level: LogLevel): void;
329
+ getLevel(): LogLevel;
330
+ debug(message: string, data?: unknown): void;
331
+ info(message: string, data?: unknown): void;
332
+ warn(message: string, data?: unknown): void;
333
+ error(message: string, data?: unknown): void;
334
+ }
335
+ /** Singleton logger instance shared across the SDK. */
336
+ declare const logger: Logger;
337
+ /** Set the global log level for the SDK. */
338
+ declare function setLogLevel(level: LogLevel): void;
339
+
340
+ export { AnalyticsClient, AuctionClient, type AuctionResult, AudienceClient, type AudiencePrediction, type BuildTagOptions, CreativeClient, type CreativeReview, type CreativeStats, type EarningsData, type ImpressionReport, type LiveAudience, type LogLevel, type LookalikeScreen, PartnerClient, type PartnerClientConfig, type QuickStartResult, type ScreenDailyAnalytics, TrackingBatch, type TrackingBatchConfig, type TrackingResult, TrillboardsAuthenticationError, TrillboardsError, TrillboardsNotFoundError, TrillboardsRateLimitError, TrillboardsValidationError, VastTagBuilder, type VastTagBuilderConfig, type VastTagResult, createAuthenticatedFetch, logger, setLogLevel };
package/dist/server.js CHANGED
@@ -1,9 +1,172 @@
1
1
  'use strict';
2
2
 
3
+ // src/errors.ts
4
+ var TrillboardsError = class extends Error {
5
+ constructor(message, options = {}) {
6
+ super(message);
7
+ this.name = "TrillboardsError";
8
+ this.type = options.type ?? "api_error";
9
+ this.code = options.code ?? "unknown_error";
10
+ this.statusCode = options.statusCode ?? 500;
11
+ this.help = options.help;
12
+ this.param = options.param;
13
+ }
14
+ };
15
+ var TrillboardsAuthenticationError = class extends TrillboardsError {
16
+ constructor(message) {
17
+ super(
18
+ message ?? "Invalid API key. Check your key at https://trillboards.com/developers",
19
+ {
20
+ type: "authentication_error",
21
+ code: "invalid_api_key",
22
+ statusCode: 401,
23
+ help: "https://trillboards.com/developers"
24
+ }
25
+ );
26
+ this.name = "TrillboardsAuthenticationError";
27
+ }
28
+ };
29
+ var TrillboardsRateLimitError = class extends TrillboardsError {
30
+ constructor(retryAfter, message) {
31
+ super(
32
+ message ?? `Rate limit exceeded. Retry after ${retryAfter} seconds.`,
33
+ {
34
+ type: "rate_limit_error",
35
+ code: "rate_limited",
36
+ statusCode: 429
37
+ }
38
+ );
39
+ this.name = "TrillboardsRateLimitError";
40
+ this.retryAfter = retryAfter;
41
+ }
42
+ };
43
+ var TrillboardsNotFoundError = class extends TrillboardsError {
44
+ constructor(message) {
45
+ super(
46
+ message ?? "The requested resource was not found.",
47
+ {
48
+ type: "not_found_error",
49
+ code: "resource_not_found",
50
+ statusCode: 404,
51
+ help: "Verify the ID is correct and belongs to your account."
52
+ }
53
+ );
54
+ this.name = "TrillboardsNotFoundError";
55
+ }
56
+ };
57
+ var TrillboardsValidationError = class extends TrillboardsError {
58
+ constructor(message, param) {
59
+ super(
60
+ message ?? "The request was invalid.",
61
+ {
62
+ type: "validation_error",
63
+ code: "invalid_request",
64
+ statusCode: 400,
65
+ param
66
+ }
67
+ );
68
+ this.name = "TrillboardsValidationError";
69
+ }
70
+ };
71
+
72
+ // src/logger.ts
73
+ var LEVEL_PRIORITY = {
74
+ debug: 0,
75
+ info: 1,
76
+ warn: 2,
77
+ error: 3,
78
+ none: 4
79
+ };
80
+ var PREFIX = "[Trillboards]";
81
+ var Logger = class {
82
+ constructor() {
83
+ this.level = "none";
84
+ }
85
+ setLevel(level) {
86
+ this.level = level;
87
+ }
88
+ getLevel() {
89
+ return this.level;
90
+ }
91
+ debug(message, data) {
92
+ if (LEVEL_PRIORITY[this.level] <= LEVEL_PRIORITY.debug) {
93
+ if (data !== void 0) {
94
+ console.debug(PREFIX, message, data);
95
+ } else {
96
+ console.debug(PREFIX, message);
97
+ }
98
+ }
99
+ }
100
+ info(message, data) {
101
+ if (LEVEL_PRIORITY[this.level] <= LEVEL_PRIORITY.info) {
102
+ if (data !== void 0) {
103
+ console.info(PREFIX, message, data);
104
+ } else {
105
+ console.info(PREFIX, message);
106
+ }
107
+ }
108
+ }
109
+ warn(message, data) {
110
+ if (LEVEL_PRIORITY[this.level] <= LEVEL_PRIORITY.warn) {
111
+ if (data !== void 0) {
112
+ console.warn(PREFIX, message, data);
113
+ } else {
114
+ console.warn(PREFIX, message);
115
+ }
116
+ }
117
+ }
118
+ error(message, data) {
119
+ if (LEVEL_PRIORITY[this.level] <= LEVEL_PRIORITY.error) {
120
+ if (data !== void 0) {
121
+ console.error(PREFIX, message, data);
122
+ } else {
123
+ console.error(PREFIX, message);
124
+ }
125
+ }
126
+ }
127
+ };
128
+ var logger = new Logger();
129
+ function setLogLevel(level) {
130
+ logger.setLevel(level);
131
+ }
132
+
3
133
  // src/server/fetchWithAuth.ts
134
+ async function errorFromResponse(response, path) {
135
+ let body;
136
+ try {
137
+ body = await response.json();
138
+ } catch {
139
+ }
140
+ const apiError = body?.error ?? body;
141
+ const msg = apiError?.message ?? `API error: HTTP ${response.status}`;
142
+ switch (response.status) {
143
+ case 401:
144
+ return new TrillboardsAuthenticationError(msg);
145
+ case 429: {
146
+ const retryHeader = response.headers.get("retry-after");
147
+ const retryAfter = retryHeader ? parseInt(retryHeader, 10) : 60;
148
+ return new TrillboardsRateLimitError(isNaN(retryAfter) ? 60 : retryAfter, msg);
149
+ }
150
+ case 404:
151
+ return new TrillboardsNotFoundError(msg);
152
+ case 400:
153
+ return new TrillboardsValidationError(msg, apiError?.param);
154
+ default:
155
+ return new TrillboardsError(msg, {
156
+ type: apiError?.type,
157
+ code: apiError?.code,
158
+ statusCode: response.status,
159
+ help: apiError?.help,
160
+ param: apiError?.param
161
+ });
162
+ }
163
+ }
4
164
  function createAuthenticatedFetch(apiKey, apiBase) {
5
165
  const base = apiBase.replace(/\/+$/, "");
6
166
  return async (path, options) => {
167
+ const method = options?.method ?? "GET";
168
+ const start = Date.now();
169
+ logger.debug(`${method} ${path}`, { base });
7
170
  const response = await globalThis.fetch(`${base}${path}`, {
8
171
  ...options,
9
172
  signal: options?.signal ?? AbortSignal.timeout(1e4),
@@ -13,9 +176,13 @@ function createAuthenticatedFetch(apiKey, apiBase) {
13
176
  ...options?.headers ?? {}
14
177
  }
15
178
  });
179
+ const ms = Date.now() - start;
16
180
  if (!response.ok) {
17
- throw new Error(`API error: HTTP ${response.status}`);
181
+ const error = await errorFromResponse(response);
182
+ logger.debug(`${method} ${path} -> ${response.status} (${ms}ms) ERROR`);
183
+ throw error;
18
184
  }
185
+ logger.debug(`${method} ${path} -> ${response.status} (${ms}ms)`);
19
186
  return response.json();
20
187
  };
21
188
  }
@@ -176,15 +343,87 @@ var CreativeClient = class {
176
343
  };
177
344
 
178
345
  // src/server/PartnerClient.ts
179
- var PartnerClient = class {
180
- constructor(config) {
181
- this.apiKey = config.apiKey;
346
+ var PartnerClient = class _PartnerClient {
347
+ constructor(config = {}) {
348
+ const debug = config.debug ?? (typeof process !== "undefined" && process.env?.TRILLBOARDS_DEBUG === "true");
349
+ if (debug) {
350
+ setLogLevel("debug");
351
+ }
352
+ const resolvedKey = config.apiKey ?? (typeof process !== "undefined" ? process.env?.TRILLBOARDS_API_KEY : void 0);
353
+ if (!resolvedKey) {
354
+ throw new TrillboardsAuthenticationError(
355
+ "No API key provided. Pass apiKey in config or set TRILLBOARDS_API_KEY environment variable."
356
+ );
357
+ }
358
+ this.apiKey = resolvedKey;
182
359
  this.apiBase = config.apiBase ?? "https://api.trillboards.com/v1";
183
360
  this.authFetch = createAuthenticatedFetch(this.apiKey, this.apiBase);
184
361
  this.audience = new AudienceClient(this.apiKey, this.apiBase);
185
362
  this.analytics = new AnalyticsClient(this.apiKey, this.apiBase);
186
363
  this.auctions = new AuctionClient(this.apiKey, this.apiBase);
187
364
  this.creatives = new CreativeClient(this.apiKey, this.apiBase);
365
+ if (this.isTestMode) {
366
+ logger.info("Test mode active");
367
+ }
368
+ logger.debug("PartnerClient initialized", {
369
+ apiBase: this.apiBase,
370
+ testMode: this.isTestMode
371
+ });
372
+ }
373
+ /** Returns `true` if the API key is a test key (`trb_test_*`). */
374
+ get isTestMode() {
375
+ return this.apiKey.startsWith("trb_test_");
376
+ }
377
+ /**
378
+ * One-call onboarding: register a partner, create the first device,
379
+ * and return a pre-authenticated `PartnerClient` instance ready to use.
380
+ *
381
+ * This calls `POST /v1/partner/quick-start` (public, no auth required).
382
+ */
383
+ static async quickStart(options) {
384
+ const base = (options.apiBase ?? "https://api.trillboards.com/v1").replace(/\/+$/, "");
385
+ if (options.debug) {
386
+ setLogLevel("debug");
387
+ }
388
+ logger.debug("QuickStart: registering partner", {
389
+ company: options.companyName,
390
+ email: options.email
391
+ });
392
+ const response = await globalThis.fetch(`${base}/partner/quick-start`, {
393
+ method: "POST",
394
+ headers: { "Content-Type": "application/json" },
395
+ body: JSON.stringify({
396
+ company_name: options.companyName,
397
+ email: options.email,
398
+ device_name: options.deviceName
399
+ }),
400
+ signal: AbortSignal.timeout(3e4)
401
+ });
402
+ if (!response.ok) {
403
+ let errorMsg = `Quick start failed: HTTP ${response.status}`;
404
+ let errorCode = "quick_start_failed";
405
+ try {
406
+ const body = await response.json();
407
+ errorMsg = body?.error?.message ?? body?.message ?? errorMsg;
408
+ errorCode = body?.error?.code ?? errorCode;
409
+ } catch {
410
+ }
411
+ if (response.status === 400) {
412
+ throw new TrillboardsValidationError(errorMsg);
413
+ }
414
+ throw new TrillboardsError(errorMsg, {
415
+ code: errorCode,
416
+ statusCode: response.status
417
+ });
418
+ }
419
+ const json = await response.json();
420
+ const data = json.data;
421
+ const client = new _PartnerClient({
422
+ apiKey: data.credentials.api_key,
423
+ apiBase: options.apiBase,
424
+ debug: options.debug
425
+ });
426
+ return { ...data, client };
188
427
  }
189
428
  createVastTagBuilder() {
190
429
  return new VastTagBuilder({ apiKey: this.apiKey, apiBase: this.apiBase });
@@ -203,7 +442,14 @@ exports.AudienceClient = AudienceClient;
203
442
  exports.CreativeClient = CreativeClient;
204
443
  exports.PartnerClient = PartnerClient;
205
444
  exports.TrackingBatch = TrackingBatch;
445
+ exports.TrillboardsAuthenticationError = TrillboardsAuthenticationError;
446
+ exports.TrillboardsError = TrillboardsError;
447
+ exports.TrillboardsNotFoundError = TrillboardsNotFoundError;
448
+ exports.TrillboardsRateLimitError = TrillboardsRateLimitError;
449
+ exports.TrillboardsValidationError = TrillboardsValidationError;
206
450
  exports.VastTagBuilder = VastTagBuilder;
207
451
  exports.createAuthenticatedFetch = createAuthenticatedFetch;
452
+ exports.logger = logger;
453
+ exports.setLogLevel = setLogLevel;
208
454
  //# sourceMappingURL=server.js.map
209
455
  //# sourceMappingURL=server.js.map