@pindownai/client-js 0.0.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.
@@ -0,0 +1,544 @@
1
+ /**
2
+ * API Types for Pindown
3
+ */
4
+ interface ApiResponse<T = any> {
5
+ success: boolean;
6
+ data: T;
7
+ error?: {
8
+ code: string;
9
+ message: string;
10
+ details?: any;
11
+ };
12
+ }
13
+ interface PaginatedResponse<T> {
14
+ data: T[];
15
+ pagination: {
16
+ total: number;
17
+ limit: number;
18
+ offset: number;
19
+ hasMore: boolean;
20
+ };
21
+ }
22
+ type PinDataType = 'markdown' | 'json' | 'text' | 'pin-card';
23
+ type PinCardType = 'stat-cards' | 'line-chart' | 'flexible-table' | 'embed' | 'markdown' | 'image' | 'score-gauge' | 'indicator-table' | 'alert-action' | 'bottom-detector' | 'long-short-pie';
24
+ interface Pin {
25
+ id: string;
26
+ user_id: string;
27
+ owner_id: string;
28
+ data_type: PinDataType;
29
+ pin_card_type?: PinCardType;
30
+ content: any;
31
+ metadata?: {
32
+ name?: string;
33
+ description?: string;
34
+ tags?: string[];
35
+ [key: string]: any;
36
+ };
37
+ is_public: boolean;
38
+ allow_edit: boolean;
39
+ require_sign_in: boolean;
40
+ allow_comments: boolean;
41
+ created_at: string;
42
+ updated_at: string;
43
+ }
44
+ interface CreatePinRequest {
45
+ data_type: PinDataType;
46
+ pin_card_type?: PinCardType;
47
+ content: any;
48
+ metadata?: Pin['metadata'];
49
+ }
50
+ interface UpdatePinRequest {
51
+ content?: any;
52
+ metadata?: Pin['metadata'];
53
+ }
54
+ interface SharePinRequest {
55
+ is_public?: boolean;
56
+ allow_edit?: boolean;
57
+ require_sign_in?: boolean;
58
+ allow_comments?: boolean;
59
+ }
60
+ interface ListPinsOptions {
61
+ limit?: number;
62
+ offset?: number;
63
+ }
64
+ interface Pinboard {
65
+ id: string;
66
+ user_id: string;
67
+ title: string;
68
+ description?: string;
69
+ tags?: string[];
70
+ layout?: Record<string, any>;
71
+ mobile_layout?: Record<string, any>;
72
+ pins?: Pin[];
73
+ is_public: boolean;
74
+ allow_comments: boolean;
75
+ require_sign_in: boolean;
76
+ created_at: string;
77
+ updated_at: string;
78
+ }
79
+ interface CreatePinboardRequest {
80
+ title: string;
81
+ description?: string;
82
+ tags?: string[];
83
+ layout?: Record<string, any>;
84
+ mobile_layout?: Record<string, any>;
85
+ }
86
+ interface UpdatePinboardRequest {
87
+ title?: string;
88
+ description?: string;
89
+ tags?: string[];
90
+ is_public?: boolean;
91
+ allow_comments?: boolean;
92
+ require_sign_in?: boolean;
93
+ }
94
+ interface AddPinToPinboardRequest {
95
+ pin_id: string;
96
+ position?: {
97
+ x: number;
98
+ y: number;
99
+ w: number;
100
+ h: number;
101
+ };
102
+ }
103
+ interface UpdatePinboardLayoutRequest {
104
+ layout?: Record<string, any>;
105
+ mobile_layout?: Record<string, any>;
106
+ }
107
+ type DatasetType = 'json' | 'markdown';
108
+ interface Dataset {
109
+ id: string;
110
+ user_id: string;
111
+ name: string;
112
+ type: DatasetType;
113
+ data: any;
114
+ description?: string;
115
+ created_at: string;
116
+ updated_at: string;
117
+ }
118
+ interface CreateDatasetRequest {
119
+ name: string;
120
+ type: DatasetType;
121
+ data: any;
122
+ description?: string;
123
+ }
124
+ interface UpdateDatasetRequest {
125
+ name?: string;
126
+ type?: DatasetType;
127
+ data?: any;
128
+ description?: string;
129
+ }
130
+ type BlockType = 'markdown' | 'mermaid' | 'conditional' | 'image' | 'stat-cards' | 'line-chart' | 'flexible-table' | 'embed';
131
+ interface Block {
132
+ id: string;
133
+ pin_id: string;
134
+ name: string;
135
+ type: BlockType;
136
+ template: string | Record<string, any>;
137
+ order: number;
138
+ created_at: string;
139
+ updated_at: string;
140
+ }
141
+ interface CreateBlockRequest {
142
+ name: string;
143
+ type: BlockType;
144
+ template: string | Record<string, any>;
145
+ order?: number;
146
+ }
147
+ interface UpdateBlockRequest {
148
+ name?: string;
149
+ type?: BlockType;
150
+ template?: string | Record<string, any>;
151
+ order?: number;
152
+ }
153
+ type CollaboratorRole = 'viewer' | 'editor' | 'owner';
154
+ interface Collaborator {
155
+ user_id: string;
156
+ email: string;
157
+ role: CollaboratorRole;
158
+ added_at: string;
159
+ }
160
+ interface InviteCollaboratorRequest {
161
+ email: string;
162
+ role: CollaboratorRole;
163
+ }
164
+ interface UpdateCollaboratorRoleRequest {
165
+ role: CollaboratorRole;
166
+ }
167
+ interface Permissions {
168
+ role: CollaboratorRole;
169
+ can_view: boolean;
170
+ can_edit: boolean;
171
+ can_delete: boolean;
172
+ can_share: boolean;
173
+ can_manage_collaborators: boolean;
174
+ }
175
+ interface RateLimitInfo {
176
+ tier: string;
177
+ minute: {
178
+ limit: number;
179
+ used: number;
180
+ remaining: number;
181
+ resetAt: Date;
182
+ };
183
+ hour: {
184
+ limit: number;
185
+ used: number;
186
+ remaining: number;
187
+ resetAt: Date;
188
+ };
189
+ }
190
+
191
+ /**
192
+ * Pins API Methods
193
+ */
194
+
195
+ declare class PinsMethods {
196
+ private client;
197
+ constructor(client: PindownClient);
198
+ /**
199
+ * Create a new pin
200
+ */
201
+ create(request: CreatePinRequest): Promise<Pin>;
202
+ /**
203
+ * Get a pin by ID
204
+ */
205
+ get(pinId: string): Promise<Pin>;
206
+ /**
207
+ * List all pins
208
+ */
209
+ list(options?: ListPinsOptions): Promise<PaginatedResponse<Pin>>;
210
+ /**
211
+ * Update a pin
212
+ */
213
+ update(pinId: string, request: UpdatePinRequest): Promise<Pin>;
214
+ /**
215
+ * Delete a pin
216
+ */
217
+ delete(pinId: string): Promise<void>;
218
+ /**
219
+ * Update pin sharing settings
220
+ */
221
+ share(pinId: string, request: SharePinRequest): Promise<Pin>;
222
+ /**
223
+ * Create a markdown pin
224
+ */
225
+ createMarkdown(content: string, metadata?: CreatePinRequest['metadata']): Promise<Pin>;
226
+ /**
227
+ * Create a stat card pin
228
+ */
229
+ createStatCard(data: {
230
+ title: string;
231
+ value: string | number;
232
+ change?: string;
233
+ icon?: string;
234
+ }, metadata?: CreatePinRequest['metadata']): Promise<Pin>;
235
+ /**
236
+ * Create a flexible table pin
237
+ */
238
+ createTable(data: {
239
+ columns: Array<{
240
+ id: string;
241
+ label: string;
242
+ type?: string;
243
+ }>;
244
+ rows: Array<Record<string, any>>;
245
+ }, metadata?: CreatePinRequest['metadata']): Promise<Pin>;
246
+ /**
247
+ * Create an embed pin (YouTube, Figma, etc.)
248
+ */
249
+ createEmbed(url: string, metadata?: CreatePinRequest['metadata']): Promise<Pin>;
250
+ }
251
+
252
+ /**
253
+ * Pinboards API Methods
254
+ */
255
+
256
+ declare class PinboardsMethods {
257
+ private client;
258
+ constructor(client: PindownClient);
259
+ /**
260
+ * Create a new pinboard
261
+ */
262
+ create(request: CreatePinboardRequest): Promise<Pinboard>;
263
+ /**
264
+ * Get a pinboard by ID
265
+ */
266
+ get(boardId: string): Promise<Pinboard>;
267
+ /**
268
+ * List all pinboards
269
+ */
270
+ list(): Promise<Pinboard[]>;
271
+ /**
272
+ * Update a pinboard
273
+ */
274
+ update(boardId: string, request: UpdatePinboardRequest): Promise<Pinboard>;
275
+ /**
276
+ * Delete a pinboard
277
+ */
278
+ delete(boardId: string): Promise<void>;
279
+ /**
280
+ * Add a pin to a pinboard
281
+ */
282
+ addPin(boardId: string, request: AddPinToPinboardRequest): Promise<Pinboard>;
283
+ /**
284
+ * Remove a pin from a pinboard
285
+ */
286
+ removePin(boardId: string, pinId: string): Promise<void>;
287
+ /**
288
+ * Update pinboard layout
289
+ */
290
+ updateLayout(boardId: string, request: UpdatePinboardLayoutRequest): Promise<Pinboard>;
291
+ /**
292
+ * Update pinboard sharing settings
293
+ */
294
+ share(boardId: string, request: {
295
+ is_public?: boolean;
296
+ require_sign_in?: boolean;
297
+ allow_comments?: boolean;
298
+ }): Promise<Pinboard>;
299
+ }
300
+
301
+ /**
302
+ * Datasets API Methods
303
+ */
304
+
305
+ declare class DatasetsMethods {
306
+ private client;
307
+ constructor(client: PindownClient);
308
+ /**
309
+ * Create a new dataset
310
+ */
311
+ create(request: CreateDatasetRequest): Promise<Dataset>;
312
+ /**
313
+ * Get a dataset by ID
314
+ */
315
+ get(datasetId: string): Promise<Dataset>;
316
+ /**
317
+ * List all datasets
318
+ */
319
+ list(): Promise<Dataset[]>;
320
+ /**
321
+ * Update a dataset
322
+ */
323
+ update(datasetId: string, request: UpdateDatasetRequest): Promise<Dataset>;
324
+ /**
325
+ * Delete a dataset
326
+ */
327
+ delete(datasetId: string): Promise<void>;
328
+ }
329
+
330
+ /**
331
+ * Blocks API Methods
332
+ */
333
+
334
+ declare class BlocksMethods {
335
+ private client;
336
+ constructor(client: PindownClient);
337
+ /**
338
+ * Create a new block for a pin
339
+ */
340
+ create(pinId: string, request: CreateBlockRequest): Promise<Block>;
341
+ /**
342
+ * Get a block by ID
343
+ */
344
+ get(pinId: string, blockId: string): Promise<Block>;
345
+ /**
346
+ * List all blocks in a pin
347
+ */
348
+ list(pinId: string): Promise<Block[]>;
349
+ /**
350
+ * Update a block
351
+ */
352
+ update(pinId: string, blockId: string, request: UpdateBlockRequest): Promise<Block>;
353
+ /**
354
+ * Delete a block
355
+ */
356
+ delete(pinId: string, blockId: string): Promise<void>;
357
+ }
358
+
359
+ /**
360
+ * Collaborators API Methods
361
+ */
362
+
363
+ declare class CollaboratorsMethods {
364
+ private client;
365
+ constructor(client: PindownClient);
366
+ /**
367
+ * List collaborators for a pin
368
+ */
369
+ listForPin(pinId: string): Promise<{
370
+ owner: Collaborator;
371
+ collaborators: Collaborator[];
372
+ pending_invites: Array<{
373
+ email: string;
374
+ role: string;
375
+ invited_at: string;
376
+ }>;
377
+ }>;
378
+ /**
379
+ * Invite a collaborator to a pin
380
+ */
381
+ inviteToPin(pinId: string, request: InviteCollaboratorRequest): Promise<void>;
382
+ /**
383
+ * Update a pin collaborator's role
384
+ */
385
+ updatePinRole(pinId: string, userId: string, request: UpdateCollaboratorRoleRequest): Promise<void>;
386
+ /**
387
+ * Remove a collaborator from a pin
388
+ */
389
+ removeFromPin(pinId: string, userId: string): Promise<void>;
390
+ /**
391
+ * Get current user's permissions for a pin
392
+ */
393
+ getPinPermissions(pinId: string): Promise<Permissions>;
394
+ /**
395
+ * List collaborators for a pinboard
396
+ */
397
+ listForPinboard(boardId: string): Promise<{
398
+ owner: Collaborator;
399
+ collaborators: Collaborator[];
400
+ pending_invites: Array<{
401
+ email: string;
402
+ role: string;
403
+ invited_at: string;
404
+ }>;
405
+ }>;
406
+ /**
407
+ * Invite a collaborator to a pinboard
408
+ */
409
+ inviteToPinboard(boardId: string, request: InviteCollaboratorRequest): Promise<void>;
410
+ /**
411
+ * Update a pinboard collaborator's role
412
+ */
413
+ updatePinboardRole(boardId: string, userId: string, request: UpdateCollaboratorRoleRequest): Promise<void>;
414
+ /**
415
+ * Remove a collaborator from a pinboard
416
+ */
417
+ removeFromPinboard(boardId: string, userId: string): Promise<void>;
418
+ /**
419
+ * Get current user's permissions for a pinboard
420
+ */
421
+ getPinboardPermissions(boardId: string): Promise<Permissions>;
422
+ }
423
+
424
+ /**
425
+ * Configuration types for Pindown API Client
426
+ */
427
+ type Tier = 'starter' | 'hobby' | 'pro' | 'teams' | 'agency';
428
+ interface PindownConfig {
429
+ /**
430
+ * Your Pindown API key (from https://pindown.ai/api-keys)
431
+ */
432
+ apiKey: string;
433
+ /**
434
+ * Your subscription tier (auto-detected from server if not provided)
435
+ * @internal Only use for testing - production should auto-detect
436
+ */
437
+ tier?: Tier;
438
+ /**
439
+ * Base URL for the API
440
+ * @default 'https://api.pindown.ai/api/v1'
441
+ */
442
+ baseURL?: string;
443
+ /**
444
+ * Enable rate limit tracking
445
+ * @default true
446
+ */
447
+ enableRateLimitTracking?: boolean;
448
+ /**
449
+ * Maximum number of retry attempts for failed requests
450
+ * @default 3
451
+ */
452
+ maxRetries?: number;
453
+ /**
454
+ * Timeout for requests in milliseconds
455
+ * @default 30000 (30 seconds)
456
+ */
457
+ timeout?: number;
458
+ }
459
+
460
+ /**
461
+ * Pindown API Client
462
+ */
463
+
464
+ declare class PindownClient {
465
+ private config;
466
+ private rateLimiter?;
467
+ private tierDetected;
468
+ readonly pins: PinsMethods;
469
+ readonly pinboards: PinboardsMethods;
470
+ readonly datasets: DatasetsMethods;
471
+ readonly blocks: BlocksMethods;
472
+ readonly collaborators: CollaboratorsMethods;
473
+ constructor(config: PindownConfig);
474
+ /**
475
+ * Core request method
476
+ */
477
+ request<T = any>(method: string, endpoint: string, data?: any): Promise<T>;
478
+ /**
479
+ * Handle error responses from API
480
+ */
481
+ private handleErrorResponse;
482
+ /**
483
+ * Detect tier from response headers
484
+ */
485
+ private detectTierFromHeaders;
486
+ /**
487
+ * Get current rate limit info
488
+ */
489
+ getRateLimitInfo(): RateLimitInfo | null;
490
+ /**
491
+ * Get current tier
492
+ */
493
+ getTier(): Tier | null;
494
+ /**
495
+ * Destroy the client (cleanup resources)
496
+ */
497
+ destroy(): void;
498
+ }
499
+
500
+ /**
501
+ * Error classes for Pindown API Client
502
+ */
503
+
504
+ declare class PindownError extends Error {
505
+ constructor(message: string);
506
+ }
507
+ declare class AuthenticationError extends PindownError {
508
+ constructor(message?: string);
509
+ }
510
+ declare class ForbiddenError extends PindownError {
511
+ constructor(message?: string);
512
+ }
513
+ declare class NotFoundError extends PindownError {
514
+ constructor(resource: string);
515
+ }
516
+ declare class ValidationError extends PindownError {
517
+ details?: any;
518
+ constructor(message: string, details?: any);
519
+ }
520
+ declare class RateLimitError extends PindownError {
521
+ window: 'minute' | 'hour';
522
+ limit: number;
523
+ used: number;
524
+ remaining: number;
525
+ resetAt: Date;
526
+ tier: Tier;
527
+ constructor(params: {
528
+ window: 'minute' | 'hour';
529
+ limit: number;
530
+ used: number;
531
+ remaining: number;
532
+ resetAt: Date;
533
+ tier: Tier;
534
+ });
535
+ }
536
+ declare class ServerError extends PindownError {
537
+ statusCode: number;
538
+ constructor(message: string, statusCode?: number);
539
+ }
540
+ declare class NetworkError extends PindownError {
541
+ constructor(message?: string);
542
+ }
543
+
544
+ export { type AddPinToPinboardRequest, type ApiResponse, AuthenticationError, type Block, type BlockType, type Collaborator, type CollaboratorRole, type CreateBlockRequest, type CreateDatasetRequest, type CreatePinRequest, type CreatePinboardRequest, type Dataset, type DatasetType, ForbiddenError, type InviteCollaboratorRequest, type ListPinsOptions, NetworkError, NotFoundError, type PaginatedResponse, type Permissions, type Pin, type PinCardType, type PinDataType, type Pinboard, PindownClient, type PindownConfig, PindownError, RateLimitError, type RateLimitInfo, ServerError, type SharePinRequest, type Tier, type UpdateBlockRequest, type UpdateCollaboratorRoleRequest, type UpdateDatasetRequest, type UpdatePinRequest, type UpdatePinboardLayoutRequest, type UpdatePinboardRequest, ValidationError };
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ var C={starter:{tokensPerHour:16,tokensPerMinute:null},hobby:{tokensPerHour:6e3,tokensPerMinute:100},pro:{tokensPerHour:24e3,tokensPerMinute:400},teams:{tokensPerHour:6e4,tokensPerMinute:1e3},agency:{tokensPerHour:24e4,tokensPerMinute:4e3}};var E={GET:1,POST:1,PUT:1,DELETE:1,INVITE:3,SHARE:3,BATCH_1_10:3,BATCH_11_25:5,BATCH_26_50:10};var o=class extends Error{constructor(e){super(e),this.name="PindownError";}},d=class extends o{constructor(e="Authentication failed"){super(e),this.name="AuthenticationError";}},p=class extends o{constructor(e="Access forbidden"){super(e),this.name="ForbiddenError";}},m=class extends o{constructor(e){super(`${e} not found`),this.name="NotFoundError";}},c=class extends o{constructor(e,t){super(e),this.name="ValidationError",this.details=t;}},P=class extends o{constructor(e){super(`Rate limit exceeded: ${e.used}/${e.limit} tokens used in ${e.window} window. Resets at ${e.resetAt.toISOString()}`),this.name="RateLimitError",this.window=e.window,this.limit=e.limit,this.used=e.used,this.remaining=e.remaining,this.resetAt=e.resetAt,this.tier=e.tier;}},l=class extends o{constructor(e,t=500){super(e),this.name="ServerError",this.statusCode=t;}},h=class extends o{constructor(e="Network request failed"){super(e),this.name="NetworkError";}};var $=C,g=E,b=class{constructor(e){this.minuteTokens=new Map;this.hourTokens=new Map;this.tier=e,this.cleanupInterval=setInterval(()=>this.cleanup(),300*1e3);}checkLimit(e,t,r){let n=this.calculateTokenCost(e,t,r),a=this.getMinuteWindow(),u=this.getHourWindow(),i=$[this.tier];if(i.tokensPerMinute!==null){let k=this.minuteTokens.get(a)||0;if(k+n>i.tokensPerMinute)throw new P({window:"minute",limit:i.tokensPerMinute,used:k,remaining:Math.max(0,i.tokensPerMinute-k),resetAt:this.getMinuteResetTime(),tier:this.tier})}let y=this.hourTokens.get(u)||0;if(y+n>i.tokensPerHour)throw new P({window:"hour",limit:i.tokensPerHour,used:y,remaining:Math.max(0,i.tokensPerHour-y),resetAt:this.getHourResetTime(),tier:this.tier});this.incrementToken(a,n),this.incrementToken(u,n);}calculateTokenCost(e,t,r){if(t.includes("/batch")||t.includes("/sync")){if(r?.operations){let n=Array.isArray(r.operations)?r.operations.length:0;return n<=10?g.BATCH_1_10:n<=25?g.BATCH_11_25:(g.BATCH_26_50)}if(r?.pins){let n=Array.isArray(r.pins)?r.pins.length:0;return n<=16?5:(8)}}return t.includes("/collaborators")||t.includes("/invite")||t.includes("/share")?g.INVITE:g[e]||1}getMinuteWindow(){let e=new Date;return `minute_${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")}-${String(e.getHours()).padStart(2,"0")}-${String(e.getMinutes()).padStart(2,"0")}`}getHourWindow(){let e=new Date;return `hour_${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")}-${String(e.getHours()).padStart(2,"0")}`}incrementToken(e,t){if(e.startsWith("minute")){let r=this.minuteTokens.get(e)||0;this.minuteTokens.set(e,r+t);}else {let r=this.hourTokens.get(e)||0;this.hourTokens.set(e,r+t);}}getMinuteResetTime(){let e=new Date;return new Date(e.getFullYear(),e.getMonth(),e.getDate(),e.getHours(),e.getMinutes()+1,0,0)}getHourResetTime(){let e=new Date;return new Date(e.getFullYear(),e.getMonth(),e.getDate(),e.getHours()+1,0,0,0)}getRateLimitInfo(){let e=$[this.tier],t=this.getMinuteWindow(),r=this.getHourWindow(),n=this.minuteTokens.get(t)||0,a=this.hourTokens.get(r)||0;return {tier:this.tier,minute:{limit:e.tokensPerMinute||0,used:n,remaining:e.tokensPerMinute?Math.max(0,e.tokensPerMinute-n):1/0,resetAt:this.getMinuteResetTime()},hour:{limit:e.tokensPerHour,used:a,remaining:Math.max(0,e.tokensPerHour-a),resetAt:this.getHourResetTime()}}}cleanup(){let t=Date.now()-7200*1e3;for(let[r]of this.minuteTokens)this.parseWindowTimestamp(r)<t&&this.minuteTokens.delete(r);for(let[r]of this.hourTokens)this.parseWindowTimestamp(r)<t&&this.hourTokens.delete(r);}parseWindowTimestamp(e){let t=e.split("_")[1].split("-"),r=parseInt(t[0]),n=parseInt(t[1])-1,a=parseInt(t[2]),u=parseInt(t[3]),i=e.startsWith("minute")?parseInt(t[4]):0;return new Date(r,n,a,u,i).getTime()}destroy(){this.cleanupInterval&&clearInterval(this.cleanupInterval);}};var T=class{constructor(e){this.client=e;}async create(e){return this.client.request("POST","/pins",e)}async get(e){return this.client.request("GET",`/pins/${e}`)}async list(e){let t=new URLSearchParams;e?.limit&&t.append("limit",e.limit.toString()),e?.offset&&t.append("offset",e.offset.toString());let r=t.toString(),n=r?`/pins?${r}`:"/pins";return this.client.request("GET",n)}async update(e,t){return this.client.request("PUT",`/pins/${e}`,t)}async delete(e){return this.client.request("DELETE",`/pins/${e}`)}async share(e,t){return this.client.request("POST",`/pins/${e}/share`,t)}async createMarkdown(e,t){return this.create({data_type:"markdown",content:e,metadata:t})}async createStatCard(e,t){return this.create({data_type:"pin-card",pin_card_type:"stat-cards",content:[e],metadata:t})}async createTable(e,t){return this.create({data_type:"pin-card",pin_card_type:"flexible-table",content:e,metadata:t})}async createEmbed(e,t){return this.create({data_type:"pin-card",pin_card_type:"embed",content:{url:e},metadata:t})}};var w=class{constructor(e){this.client=e;}async create(e){return this.client.request("POST","/pinboards",e)}async get(e){return this.client.request("GET",`/pinboards/${e}`)}async list(){return this.client.request("GET","/pinboards")}async update(e,t){return this.client.request("PUT",`/pinboards/${e}`,t)}async delete(e){return this.client.request("DELETE",`/pinboards/${e}`)}async addPin(e,t){return this.client.request("POST",`/pinboards/${e}/pins`,t)}async removePin(e,t){return this.client.request("DELETE",`/pinboards/${e}/pins/${t}`)}async updateLayout(e,t){return this.client.request("PUT",`/pinboards/${e}/layout`,t)}async share(e,t){return this.client.request("POST",`/pinboards/${e}/share`,t)}};var f=class{constructor(e){this.client=e;}async create(e){return this.client.request("POST","/datasets",e)}async get(e){return this.client.request("GET",`/datasets/${e}`)}async list(){return this.client.request("GET","/datasets")}async update(e,t){return this.client.request("PUT",`/datasets/${e}`,t)}async delete(e){return this.client.request("DELETE",`/datasets/${e}`)}};var R=class{constructor(e){this.client=e;}async create(e,t){return this.client.request("POST",`/pins/${e}/blocks`,t)}async get(e,t){return this.client.request("GET",`/pins/${e}/blocks/${t}`)}async list(e){return this.client.request("GET",`/pins/${e}/blocks`)}async update(e,t,r){return this.client.request("PUT",`/pins/${e}/blocks/${t}`,r)}async delete(e,t){return this.client.request("DELETE",`/pins/${e}/blocks/${t}`)}};var q=class{constructor(e){this.client=e;}async listForPin(e){return this.client.request("GET",`/pins/${e}/collaborators`)}async inviteToPin(e,t){return this.client.request("POST",`/pins/${e}/collaborators`,t)}async updatePinRole(e,t,r){return this.client.request("PUT",`/pins/${e}/collaborators/${t}`,r)}async removeFromPin(e,t){return this.client.request("DELETE",`/pins/${e}/collaborators/${t}`)}async getPinPermissions(e){return this.client.request("GET",`/pins/${e}/permissions`)}async listForPinboard(e){return this.client.request("GET",`/pinboards/${e}/collaborators`)}async inviteToPinboard(e,t){return this.client.request("POST",`/pinboards/${e}/collaborators`,t)}async updatePinboardRole(e,t,r){return this.client.request("PUT",`/pinboards/${e}/collaborators/${t}`,r)}async removeFromPinboard(e,t){return this.client.request("DELETE",`/pinboards/${e}/collaborators/${t}`)}async getPinboardPermissions(e){return this.client.request("GET",`/pinboards/${e}/permissions`)}};var v=class{constructor(e){this.tierDetected=false;if(!e.apiKey)throw new Error("API key is required");this.config={apiKey:e.apiKey,tier:e.tier,baseURL:e.baseURL||"https://api.pindown.ai/api/v1",enableRateLimitTracking:e.enableRateLimitTracking??true,maxRetries:e.maxRetries??3,timeout:e.timeout??3e4},this.config.tier&&(this.rateLimiter=new b(this.config.tier),this.tierDetected=true),this.pins=new T(this),this.pinboards=new w(this),this.datasets=new f(this),this.blocks=new R(this),this.collaborators=new q(this);}async request(e,t,r){this.config.enableRateLimitTracking&&this.rateLimiter&&this.rateLimiter.checkLimit(e,t,r);let n=`${this.config.baseURL}${t}`,a={Authorization:`Bearer ${this.config.apiKey}`,"Content-Type":"application/json"},u={method:e,headers:a,signal:AbortSignal.timeout(this.config.timeout)};r&&(e==="POST"||e==="PUT")&&(u.body=JSON.stringify(r));try{let i=await fetch(n,u);return !this.tierDetected&&this.config.enableRateLimitTracking&&this.detectTierFromHeaders(i.headers),i.ok||await this.handleErrorResponse(i),(await i.json()).data}catch(i){throw i instanceof d||i instanceof p||i instanceof m||i instanceof c||i instanceof l?i:i.name==="AbortError"||i.name==="TimeoutError"?new h("Request timeout"):new h(i.message||"Network request failed")}}async handleErrorResponse(e){let t;try{t=await e.json();}catch{t={message:e.statusText};}let r=t.error?.message||t.message||"Unknown error";switch(e.status){case 401:throw new d(r);case 403:throw new p(r);case 404:throw new m(r);case 400:case 422:throw new c(r,t.error?.details);case 429:throw new c("Rate limit exceeded (server)",t);case 500:case 502:case 503:throw new l(r,e.status);default:throw new l(r,e.status)}}detectTierFromHeaders(e){let t=e.get("X-RateLimit-Tier");if(t&&!this.rateLimiter){let r=t.toLowerCase();console.log(`[Pindown Client] Auto-detected tier: ${r}`),this.config.tier=r,this.rateLimiter=new b(r),this.tierDetected=true;}}getRateLimitInfo(){return this.rateLimiter?this.rateLimiter.getRateLimitInfo():null}getTier(){return this.config.tier||null}destroy(){this.rateLimiter&&this.rateLimiter.destroy();}};/**
2
+ * @pindownai/client-js
3
+ *
4
+ * Official TypeScript/JavaScript client for Pindown.ai API
5
+ *
6
+ * @author Pindown.ai
7
+ * @license MIT
8
+ */export{d as AuthenticationError,p as ForbiddenError,h as NetworkError,m as NotFoundError,v as PindownClient,o as PindownError,P as RateLimitError,l as ServerError,c as ValidationError};//# sourceMappingURL=index.js.map
9
+ //# sourceMappingURL=index.js.map