@air/api-rest 0.1.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.
package/dist/index.cjs ADDED
@@ -0,0 +1,613 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ APIError: () => import_api_core2.APIError,
34
+ AirApi: () => AirApi,
35
+ AirBase: () => import_api_core2.AirBase,
36
+ Assets: () => Assets,
37
+ AuthenticationError: () => import_api_core2.AuthenticationError,
38
+ BadRequestError: () => import_api_core2.BadRequestError,
39
+ Boards: () => Boards,
40
+ ConnectionError: () => import_api_core2.ConnectionError,
41
+ CursorPage: () => import_api_core2.CursorPage,
42
+ CustomFields: () => CustomFields,
43
+ Imports: () => Imports,
44
+ InternalServerError: () => import_api_core2.InternalServerError,
45
+ NotFoundError: () => import_api_core2.NotFoundError,
46
+ PagePromise: () => import_api_core2.PagePromise,
47
+ PermissionError: () => import_api_core2.PermissionError,
48
+ RateLimitError: () => import_api_core2.RateLimitError,
49
+ Roles: () => Roles,
50
+ Tags: () => Tags,
51
+ TimeoutError: () => import_api_core2.TimeoutError,
52
+ Uploads: () => Uploads,
53
+ VERSION: () => import_api_core2.VERSION
54
+ });
55
+ module.exports = __toCommonJS(index_exports);
56
+
57
+ // src/api.ts
58
+ var import_api_core = require("@air/api-core");
59
+
60
+ // src/resources/assets.ts
61
+ var Assets = class {
62
+ constructor(client) {
63
+ this.client = client;
64
+ }
65
+ list(params = {}) {
66
+ const query = {
67
+ limit: params.limit,
68
+ cursor: params.cursor,
69
+ parentBoardId: params.parentBoardId,
70
+ search: params.search
71
+ };
72
+ if (params.includeNestedAssets !== void 0) {
73
+ query.includeNestedAssets = params.includeNestedAssets;
74
+ }
75
+ if (params.tag) {
76
+ query.tag = params.tag;
77
+ }
78
+ if (params.customField) {
79
+ query.customField = params.customField;
80
+ }
81
+ if (params["createdAt[gte]"]) {
82
+ query["createdAt[gte]"] = params["createdAt[gte]"];
83
+ }
84
+ if (params["createdAt[lte]"]) {
85
+ query["createdAt[lte]"] = params["createdAt[lte]"];
86
+ }
87
+ return this.client.requestCursorPage({ method: "GET", path: "/assets", query }, query);
88
+ }
89
+ async get(assetId) {
90
+ return this.client.request({
91
+ method: "GET",
92
+ path: `/assets/${assetId}`
93
+ });
94
+ }
95
+ async delete(assetId) {
96
+ return this.client.request({
97
+ method: "DELETE",
98
+ path: `/assets/${assetId}`
99
+ });
100
+ }
101
+ async setCustomField(assetId, customFieldId, params) {
102
+ return this.client.request({
103
+ method: "PUT",
104
+ path: `/assets/${assetId}/customfields/${customFieldId}`,
105
+ body: params
106
+ });
107
+ }
108
+ async listVersions(assetId) {
109
+ return this.client.request({
110
+ method: "GET",
111
+ path: `/assets/${assetId}/versions`
112
+ });
113
+ }
114
+ async getVersion(assetId, versionId) {
115
+ return this.client.request({
116
+ method: "GET",
117
+ path: `/assets/${assetId}/versions/${versionId}`
118
+ });
119
+ }
120
+ async updateVersion(assetId, versionId, params) {
121
+ return this.client.request({
122
+ method: "PATCH",
123
+ path: `/assets/${assetId}/versions/${versionId}`,
124
+ body: params
125
+ });
126
+ }
127
+ async getVersionDownloadUrl(assetId, versionId) {
128
+ return this.client.request({
129
+ method: "GET",
130
+ path: `/assets/${assetId}/versions/${versionId}/download`
131
+ });
132
+ }
133
+ async addVersionTag(assetId, versionId, params) {
134
+ return this.client.request({
135
+ method: "POST",
136
+ path: `/assets/${assetId}/versions/${versionId}/tags`,
137
+ body: params
138
+ });
139
+ }
140
+ async removeVersionTag(assetId, versionId, tagId) {
141
+ return this.client.request({
142
+ method: "DELETE",
143
+ path: `/assets/${assetId}/versions/${versionId}/tags/${tagId}`
144
+ });
145
+ }
146
+ listBoards(assetId, params = {}) {
147
+ const query = {
148
+ limit: params.limit,
149
+ cursor: params.cursor
150
+ };
151
+ if (params.includeCustomFields !== void 0) {
152
+ query.includeCustomFields = params.includeCustomFields;
153
+ }
154
+ return this.client.requestCursorPage(
155
+ { method: "GET", path: `/assets/${assetId}/boards`, query },
156
+ query
157
+ );
158
+ }
159
+ };
160
+
161
+ // src/resources/boards.ts
162
+ var Boards = class {
163
+ constructor(client) {
164
+ this.client = client;
165
+ }
166
+ list(params = {}) {
167
+ const query = {
168
+ limit: params.limit,
169
+ cursor: params.cursor,
170
+ name: params.name,
171
+ parentBoardId: params.parentBoardId
172
+ };
173
+ if (params.customField) {
174
+ query.customField = params.customField;
175
+ }
176
+ return this.client.requestCursorPage({ method: "GET", path: "/boards", query }, query);
177
+ }
178
+ async get(boardId) {
179
+ return this.client.request({
180
+ method: "GET",
181
+ path: `/boards/${boardId}`
182
+ });
183
+ }
184
+ async create(params) {
185
+ return this.client.request({
186
+ method: "POST",
187
+ path: "/boards",
188
+ body: params
189
+ });
190
+ }
191
+ async update(boardId, params) {
192
+ return this.client.request({
193
+ method: "PATCH",
194
+ path: `/boards/${boardId}`,
195
+ body: params
196
+ });
197
+ }
198
+ async delete(boardId) {
199
+ return this.client.request({
200
+ method: "DELETE",
201
+ path: `/boards/${boardId}`
202
+ });
203
+ }
204
+ async addAssets(boardId, params) {
205
+ return this.client.request({
206
+ method: "POST",
207
+ path: `/boards/${boardId}/assets`,
208
+ body: params
209
+ });
210
+ }
211
+ async removeAsset(boardId, assetId) {
212
+ return this.client.request({
213
+ method: "DELETE",
214
+ path: `/boards/${boardId}/assets/${assetId}`
215
+ });
216
+ }
217
+ async setCustomField(boardId, customFieldId, params) {
218
+ return this.client.request({
219
+ method: "PUT",
220
+ path: `/boards/${boardId}/customFields/${customFieldId}`,
221
+ body: params
222
+ });
223
+ }
224
+ async addGuest(boardId, params) {
225
+ return this.client.request({
226
+ method: "POST",
227
+ path: `/boards/${boardId}/guests`,
228
+ body: params
229
+ });
230
+ }
231
+ async listGuests(boardId, params = {}) {
232
+ const response = await this.client.request({
233
+ method: "GET",
234
+ path: `/boards/${boardId}/guests`,
235
+ query: params.email ? { email: params.email } : void 0
236
+ });
237
+ return response.data;
238
+ }
239
+ async updateGuest(boardId, guestId, params) {
240
+ return this.client.request({
241
+ method: "PATCH",
242
+ path: `/boards/${boardId}/guests/${guestId}`,
243
+ body: params
244
+ });
245
+ }
246
+ async removeGuest(boardId, guestId) {
247
+ return this.client.request({
248
+ method: "DELETE",
249
+ path: `/boards/${boardId}/guests/${guestId}`
250
+ });
251
+ }
252
+ };
253
+
254
+ // src/resources/custom-fields.ts
255
+ var CustomFields = class {
256
+ constructor(client) {
257
+ this.client = client;
258
+ }
259
+ list(params = {}) {
260
+ return this.client.requestCursorPage(
261
+ {
262
+ method: "GET",
263
+ path: "/customfields",
264
+ query: params
265
+ },
266
+ params
267
+ );
268
+ }
269
+ async get(customFieldId) {
270
+ return this.client.request({
271
+ method: "GET",
272
+ path: `/customfields/${customFieldId}`
273
+ });
274
+ }
275
+ async create(params) {
276
+ return this.client.request({
277
+ method: "POST",
278
+ path: "/customfields",
279
+ body: params
280
+ });
281
+ }
282
+ async update(customFieldId, params) {
283
+ return this.client.request({
284
+ method: "PATCH",
285
+ path: `/customfields/${customFieldId}`,
286
+ body: params
287
+ });
288
+ }
289
+ async delete(customFieldId) {
290
+ return this.client.request({
291
+ method: "DELETE",
292
+ path: `/customfields/${customFieldId}`
293
+ });
294
+ }
295
+ async createValue(customFieldId, params) {
296
+ return this.client.request({
297
+ method: "POST",
298
+ path: `/customfields/${customFieldId}/values`,
299
+ body: params
300
+ });
301
+ }
302
+ async updateValue(customFieldId, valueId, params) {
303
+ return this.client.request({
304
+ method: "PATCH",
305
+ path: `/customfields/${customFieldId}/values/${valueId}`,
306
+ body: params
307
+ });
308
+ }
309
+ async deleteValue(customFieldId, valueId) {
310
+ return this.client.request({
311
+ method: "DELETE",
312
+ path: `/customfields/${customFieldId}/values/${valueId}`
313
+ });
314
+ }
315
+ };
316
+
317
+ // src/resources/imports.ts
318
+ var Imports = class {
319
+ constructor(client) {
320
+ this.client = client;
321
+ }
322
+ async create(params) {
323
+ return this.client.request({
324
+ method: "POST",
325
+ path: "/imports",
326
+ body: params
327
+ });
328
+ }
329
+ async getStatus(importId) {
330
+ return this.client.request({
331
+ method: "GET",
332
+ path: `/imports/${importId}/status`
333
+ });
334
+ }
335
+ };
336
+
337
+ // src/resources/roles.ts
338
+ var Roles = class {
339
+ constructor(client) {
340
+ this.client = client;
341
+ }
342
+ async list(params = { type: "guest" }) {
343
+ const response = await this.client.request({
344
+ method: "GET",
345
+ path: "/roles",
346
+ query: { type: params.type }
347
+ });
348
+ return response.data;
349
+ }
350
+ };
351
+
352
+ // src/resources/tags.ts
353
+ var Tags = class {
354
+ constructor(client) {
355
+ this.client = client;
356
+ }
357
+ list(params = {}) {
358
+ return this.client.requestCursorPage(
359
+ {
360
+ method: "GET",
361
+ path: "/tags",
362
+ query: params
363
+ },
364
+ params
365
+ );
366
+ }
367
+ async get(tagId) {
368
+ return this.client.request({
369
+ method: "GET",
370
+ path: `/tags/${tagId}`
371
+ });
372
+ }
373
+ async create(params) {
374
+ return this.client.request({
375
+ method: "POST",
376
+ path: "/tags",
377
+ body: params
378
+ });
379
+ }
380
+ async update(tagId, params) {
381
+ return this.client.request({
382
+ method: "PATCH",
383
+ path: `/tags/${tagId}`,
384
+ body: params
385
+ });
386
+ }
387
+ async delete(tagId) {
388
+ return this.client.request({
389
+ method: "DELETE",
390
+ path: `/tags/${tagId}`
391
+ });
392
+ }
393
+ };
394
+
395
+ // src/resources/uploads.ts
396
+ var DEFAULT_PART_SIZE = 100 * 1024 * 1024;
397
+ var Uploads = class {
398
+ constructor(client) {
399
+ this.client = client;
400
+ }
401
+ async create(params) {
402
+ return this.client.request({
403
+ method: "POST",
404
+ path: "/uploads",
405
+ body: params
406
+ });
407
+ }
408
+ async getPartUploadUrl(params) {
409
+ return this.client.request({
410
+ method: "POST",
411
+ path: "/uploads/uploadPart",
412
+ body: params
413
+ });
414
+ }
415
+ async completeMultipart(params) {
416
+ return this.client.request({
417
+ method: "POST",
418
+ path: "/uploads/completeMultipart",
419
+ body: params
420
+ });
421
+ }
422
+ async uploadFile(params, options = {}) {
423
+ const { fileData, fileName, ext, mime, size } = await resolveFileData(params);
424
+ const uploadResponse = await this.create({
425
+ fileName,
426
+ ext,
427
+ size,
428
+ mime,
429
+ parentBoardId: options.parentBoardId,
430
+ assetId: options.assetId,
431
+ customFields: options.customFields,
432
+ tags: options.tags
433
+ });
434
+ if (isSmallUpload(uploadResponse)) {
435
+ await this._uploadSmallFile(uploadResponse.uploadUrl, fileData, options.onProgress, size);
436
+ return { assetId: uploadResponse.assetId, versionId: uploadResponse.versionId };
437
+ }
438
+ await this._uploadLargeFile(uploadResponse, fileData, size, options.onProgress);
439
+ return { assetId: uploadResponse.assetId, versionId: uploadResponse.versionId };
440
+ }
441
+ async _uploadSmallFile(url, data, onProgress, totalSize) {
442
+ const fetchFn = this.client.fetchFn;
443
+ const response = await fetchFn(url, {
444
+ method: "PUT",
445
+ body: data
446
+ });
447
+ if (!response.ok) {
448
+ throw new Error(`Upload failed with status ${response.status}`);
449
+ }
450
+ if (onProgress && totalSize) {
451
+ onProgress({ percentage: 100, uploadedBytes: totalSize, totalBytes: totalSize });
452
+ }
453
+ }
454
+ async _uploadLargeFile(uploadInfo, data, totalSize, onProgress) {
455
+ const { multiPartUploadId, key } = uploadInfo;
456
+ const buffer = data instanceof Buffer ? data : Buffer.from(data);
457
+ const partCount = Math.ceil(totalSize / DEFAULT_PART_SIZE);
458
+ const parts = [];
459
+ let uploadedBytes = 0;
460
+ const fetchFn = this.client.fetchFn;
461
+ for (let i = 0; i < partCount; i++) {
462
+ const partNumber = i + 1;
463
+ const start = i * DEFAULT_PART_SIZE;
464
+ const end = Math.min(start + DEFAULT_PART_SIZE, totalSize);
465
+ const chunk = buffer.subarray(start, end);
466
+ const { url } = await this.getPartUploadUrl({
467
+ multiPartUploadId,
468
+ key,
469
+ partNumber
470
+ });
471
+ const response = await fetchFn(url, {
472
+ method: "PUT",
473
+ body: chunk
474
+ });
475
+ if (!response.ok) {
476
+ throw new Error(`Part ${partNumber} upload failed with status ${response.status}`);
477
+ }
478
+ const etag = response.headers.get("etag");
479
+ if (!etag) {
480
+ throw new Error(`Part ${partNumber} upload did not return an ETag`);
481
+ }
482
+ parts.push({ etag, partNumber });
483
+ uploadedBytes += chunk.byteLength;
484
+ if (onProgress) {
485
+ onProgress({
486
+ percentage: Math.round(uploadedBytes / totalSize * 100),
487
+ uploadedBytes,
488
+ totalBytes: totalSize
489
+ });
490
+ }
491
+ }
492
+ await this.completeMultipart({ multiPartUploadId, key, parts });
493
+ }
494
+ };
495
+ function isSmallUpload(response) {
496
+ return "uploadUrl" in response;
497
+ }
498
+ async function resolveFileData(params) {
499
+ if (params.filePath) {
500
+ const fs = await import("fs");
501
+ const path = await import("path");
502
+ const fileData = fs.readFileSync(params.filePath);
503
+ const parsed = path.parse(params.filePath);
504
+ const fileName = params.fileName ?? parsed.name;
505
+ const ext = params.ext ?? parsed.ext.replace(/^\./, "");
506
+ const mime = params.mime ?? guessMime(ext);
507
+ return { fileData, fileName, ext, mime, size: fileData.byteLength };
508
+ }
509
+ if (params.buffer) {
510
+ const data = params.buffer instanceof Buffer ? params.buffer : Buffer.from(params.buffer);
511
+ if (!params.fileName || !params.ext) {
512
+ throw new Error("fileName and ext are required when uploading from a buffer");
513
+ }
514
+ const mime = params.mime ?? guessMime(params.ext);
515
+ return {
516
+ fileData: data,
517
+ fileName: params.fileName,
518
+ ext: params.ext,
519
+ mime,
520
+ size: data.byteLength
521
+ };
522
+ }
523
+ if (params.file) {
524
+ const arrayBuffer = await params.file.arrayBuffer();
525
+ const data = new Uint8Array(arrayBuffer);
526
+ const name = params.file.name;
527
+ const dotIndex = name.lastIndexOf(".");
528
+ const fileName = params.fileName ?? (dotIndex > 0 ? name.substring(0, dotIndex) : name);
529
+ const ext = params.ext ?? (dotIndex > 0 ? name.substring(dotIndex + 1) : "");
530
+ const mime = params.mime ?? (params.file.type || guessMime(ext));
531
+ return { fileData: data, fileName, ext, mime, size: data.byteLength };
532
+ }
533
+ throw new Error("One of filePath, buffer, or file must be provided");
534
+ }
535
+ function guessMime(ext) {
536
+ const mimeMap = {
537
+ jpg: "image/jpeg",
538
+ jpeg: "image/jpeg",
539
+ png: "image/png",
540
+ gif: "image/gif",
541
+ webp: "image/webp",
542
+ svg: "image/svg+xml",
543
+ mp4: "video/mp4",
544
+ mov: "video/quicktime",
545
+ avi: "video/x-msvideo",
546
+ webm: "video/webm",
547
+ mp3: "audio/mpeg",
548
+ wav: "audio/wav",
549
+ pdf: "application/pdf",
550
+ doc: "application/msword",
551
+ docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
552
+ xls: "application/vnd.ms-excel",
553
+ xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
554
+ ppt: "application/vnd.ms-powerpoint",
555
+ pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
556
+ zip: "application/zip",
557
+ psd: "image/vnd.adobe.photoshop",
558
+ ai: "application/postscript",
559
+ eps: "application/postscript",
560
+ tif: "image/tiff",
561
+ tiff: "image/tiff",
562
+ bmp: "image/bmp"
563
+ };
564
+ return mimeMap[ext.toLowerCase()] ?? "application/octet-stream";
565
+ }
566
+
567
+ // src/api.ts
568
+ var AirApi = class extends import_api_core.AirBase {
569
+ assets;
570
+ boards;
571
+ tags;
572
+ customFields;
573
+ roles;
574
+ imports;
575
+ uploads;
576
+ constructor(options = {}) {
577
+ super(options);
578
+ this.assets = new Assets(this);
579
+ this.boards = new Boards(this);
580
+ this.tags = new Tags(this);
581
+ this.customFields = new CustomFields(this);
582
+ this.roles = new Roles(this);
583
+ this.imports = new Imports(this);
584
+ this.uploads = new Uploads(this);
585
+ }
586
+ };
587
+
588
+ // src/index.ts
589
+ var import_api_core2 = require("@air/api-core");
590
+ // Annotate the CommonJS export names for ESM import in node:
591
+ 0 && (module.exports = {
592
+ APIError,
593
+ AirApi,
594
+ AirBase,
595
+ Assets,
596
+ AuthenticationError,
597
+ BadRequestError,
598
+ Boards,
599
+ ConnectionError,
600
+ CursorPage,
601
+ CustomFields,
602
+ Imports,
603
+ InternalServerError,
604
+ NotFoundError,
605
+ PagePromise,
606
+ PermissionError,
607
+ RateLimitError,
608
+ Roles,
609
+ Tags,
610
+ TimeoutError,
611
+ Uploads,
612
+ VERSION
613
+ });