pinata 1.7.2 → 1.8.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/index.mjs CHANGED
@@ -84,20 +84,101 @@ var testAuthentication = async (config) => {
84
84
  }
85
85
  };
86
86
 
87
+ // src/utils/resumable.ts
88
+ function getFileIdFromUrl(url) {
89
+ const match = url.match(/\/files\/([^\/]+)/);
90
+ if (match && match[1]) {
91
+ return match[1];
92
+ }
93
+ throw new NetworkError("File ID not found in URL", 400, url);
94
+ }
95
+
87
96
  // src/core/uploads/file.ts
88
97
  var uploadFile = async (config, file, options) => {
89
98
  if (!config) {
90
99
  throw new ValidationError("Pinata configuration is missing");
91
100
  }
92
101
  const jwt = options?.keys || config.pinataJwt;
93
- const data = new FormData();
94
- data.append("file", file, file.name);
95
- data.append("name", options?.metadata?.name || file.name || "File from SDK");
96
- if (options?.groupId) {
97
- data.append("group_id", options.groupId);
102
+ let endpoint = "https://uploads.pinata.cloud/v3";
103
+ if (config.uploadUrl) {
104
+ endpoint = config.uploadUrl;
98
105
  }
99
- if (options?.metadata?.keyvalues) {
100
- data.append("keyvalues", JSON.stringify(options.metadata.keyvalues));
106
+ if (file.size > 94371840) {
107
+ let headers2;
108
+ if (config.customHeaders && Object.keys(config.customHeaders).length > 0) {
109
+ headers2 = {
110
+ Authorization: `Bearer ${jwt}`,
111
+ ...config.customHeaders
112
+ };
113
+ } else {
114
+ headers2 = {
115
+ Authorization: `Bearer ${jwt}`,
116
+ Source: "sdk/file"
117
+ };
118
+ }
119
+ const name = options?.metadata?.name || file.name || "File from SDK";
120
+ let metadata = `filename ${btoa(name)},filetype ${btoa(file.type)}`;
121
+ if (options?.groupId) {
122
+ metadata + `,group_id ${btoa(options.groupId)}`;
123
+ }
124
+ if (options?.metadata?.keyvalues) {
125
+ metadata + `,keyvalues ${btoa(JSON.stringify(options.metadata.keyvalues))}`;
126
+ }
127
+ const urlReq = await fetch(`${endpoint}/files`, {
128
+ method: "POST",
129
+ headers: {
130
+ "Upload-Length": `${file.size}`,
131
+ "Upload-Metadata": metadata,
132
+ ...headers2
133
+ }
134
+ });
135
+ const url = urlReq.headers.get("Location");
136
+ if (!url) {
137
+ throw new NetworkError("Upload URL not provided", urlReq.status, "");
138
+ }
139
+ const chunkSize = 50 * 1024 * 1024;
140
+ const totalChunks = Math.ceil(file.size / chunkSize);
141
+ let offset = 0;
142
+ let uploadReq;
143
+ for (let i = 0; i < totalChunks; i++) {
144
+ const chunk = file.slice(offset, offset + chunkSize);
145
+ uploadReq = await fetch(url, {
146
+ method: "PATCH",
147
+ headers: {
148
+ "Content-Type": "application/offset+octet-stream",
149
+ "Upload-Offset": offset.toString(),
150
+ ...headers2
151
+ },
152
+ body: chunk
153
+ });
154
+ if (!uploadReq.ok) {
155
+ const errorData = await uploadReq.text();
156
+ throw new NetworkError(
157
+ `HTTP error during chunk upload: ${errorData}`,
158
+ uploadReq.status,
159
+ errorData
160
+ );
161
+ }
162
+ offset += chunk.size;
163
+ }
164
+ if (uploadReq.status === 204) {
165
+ const fileId = getFileIdFromUrl(url);
166
+ let dataEndpoint;
167
+ if (config.endpointUrl) {
168
+ dataEndpoint = config.endpointUrl;
169
+ } else {
170
+ dataEndpoint = "https://api.pinata.cloud/v3";
171
+ }
172
+ const fileInfoReq = await fetch(`${dataEndpoint}/files/${fileId}`, {
173
+ method: "GET",
174
+ headers: {
175
+ Authorization: `Bearer ${process.env.PINATA_JWT}`
176
+ }
177
+ });
178
+ const fileInfo = await fileInfoReq.json();
179
+ const data2 = fileInfo.data;
180
+ return data2;
181
+ }
101
182
  }
102
183
  let headers;
103
184
  if (config.customHeaders && Object.keys(config.customHeaders).length > 0) {
@@ -111,9 +192,14 @@ var uploadFile = async (config, file, options) => {
111
192
  Source: "sdk/file"
112
193
  };
113
194
  }
114
- let endpoint = "https://uploads.pinata.cloud/v3";
115
- if (config.uploadUrl) {
116
- endpoint = config.uploadUrl;
195
+ const data = new FormData();
196
+ data.append("file", file, file.name);
197
+ data.append("name", options?.metadata?.name || file.name || "File from SDK");
198
+ if (options?.groupId) {
199
+ data.append("group_id", options.groupId);
200
+ }
201
+ if (options?.metadata?.keyvalues) {
202
+ data.append("keyvalues", JSON.stringify(options.metadata.keyvalues));
117
203
  }
118
204
  try {
119
205
  const request = await fetch(`${endpoint}/files`, {
@@ -1384,6 +1470,211 @@ var deleteGroup = async (config, options) => {
1384
1470
  }
1385
1471
  };
1386
1472
 
1473
+ // src/core/analytics/analyticsTopUsage.ts
1474
+ var analyticsTopUsage = async (config, options) => {
1475
+ if (!config) {
1476
+ throw new ValidationError("Pinata configuration is missing");
1477
+ }
1478
+ const params = new URLSearchParams();
1479
+ if (options) {
1480
+ const {
1481
+ cid,
1482
+ gateway_domain,
1483
+ start_date,
1484
+ end_date,
1485
+ file_name,
1486
+ user_agent,
1487
+ country,
1488
+ region,
1489
+ referer,
1490
+ limit,
1491
+ sort_order,
1492
+ sort_by,
1493
+ attribute
1494
+ } = options;
1495
+ const domain = gateway_domain || config.pinataGateway;
1496
+ if (domain) {
1497
+ const cleanDomain = domain.replace(/^https?:\/\//, "");
1498
+ params.append("gateway_domain", cleanDomain);
1499
+ }
1500
+ if (cid) {
1501
+ params.append("cid", cid);
1502
+ }
1503
+ if (start_date)
1504
+ params.append("start_date", start_date);
1505
+ if (end_date)
1506
+ params.append("end_date", end_date);
1507
+ if (file_name)
1508
+ params.append("file_name", file_name);
1509
+ if (user_agent)
1510
+ params.append("user_agent", user_agent.toString());
1511
+ if (country)
1512
+ params.append("country", country.toString());
1513
+ if (region)
1514
+ params.append("region", region);
1515
+ if (referer)
1516
+ params.append("referer", referer.toString());
1517
+ if (limit)
1518
+ params.append("limit", limit.toString());
1519
+ if (sort_order)
1520
+ params.append("sort_order", sort_order);
1521
+ if (sort_by)
1522
+ params.append("sort_by", sort_by);
1523
+ if (attribute)
1524
+ params.append("by", attribute);
1525
+ }
1526
+ let endpoint = "https://api.pinata.cloud/v3";
1527
+ if (config.endpointUrl) {
1528
+ endpoint = config.endpointUrl;
1529
+ }
1530
+ const url = `${endpoint}/ipfs/gateway_analytics_top?${params.toString()}`;
1531
+ try {
1532
+ let headers;
1533
+ if (config.customHeaders && Object.keys(config.customHeaders).length > 0) {
1534
+ headers = { ...config.customHeaders };
1535
+ } else {
1536
+ headers = {
1537
+ Authorization: `Bearer ${config.pinataJwt}`,
1538
+ Source: "sdk/analyticsTopUsage"
1539
+ };
1540
+ }
1541
+ const request = await fetch(url, {
1542
+ method: "GET",
1543
+ headers
1544
+ });
1545
+ if (!request.ok) {
1546
+ const errorData = await request.text();
1547
+ if (request.status === 401 || request.status === 403) {
1548
+ throw new AuthenticationError(
1549
+ `Authentication failed: ${errorData}`,
1550
+ request.status,
1551
+ errorData
1552
+ );
1553
+ }
1554
+ throw new NetworkError(
1555
+ `HTTP error: ${errorData}`,
1556
+ request.status,
1557
+ errorData
1558
+ );
1559
+ }
1560
+ const res = await request.json();
1561
+ return res;
1562
+ } catch (error) {
1563
+ if (error instanceof PinataError) {
1564
+ throw error;
1565
+ }
1566
+ if (error instanceof Error) {
1567
+ throw new PinataError(
1568
+ `Error processing anaytics usage: ${error.message}`
1569
+ );
1570
+ }
1571
+ throw new PinataError(
1572
+ "An unknown error occurred while fetching gateway usage"
1573
+ );
1574
+ }
1575
+ };
1576
+
1577
+ // src/core/analytics/analyticsDateInterval.ts
1578
+ var analyticsDateInterval = async (config, options) => {
1579
+ if (!config) {
1580
+ throw new ValidationError("Pinata configuration is missing");
1581
+ }
1582
+ const params = new URLSearchParams();
1583
+ if (options) {
1584
+ const {
1585
+ cid,
1586
+ gateway_domain,
1587
+ start_date,
1588
+ end_date,
1589
+ file_name,
1590
+ user_agent,
1591
+ country,
1592
+ region,
1593
+ referer,
1594
+ limit,
1595
+ sort_order,
1596
+ date_interval,
1597
+ sort_by
1598
+ } = options;
1599
+ if (cid)
1600
+ params.append("cid", cid);
1601
+ if (gateway_domain)
1602
+ params.append("gateway_domain", gateway_domain);
1603
+ if (start_date)
1604
+ params.append("start_date", start_date);
1605
+ if (end_date)
1606
+ params.append("end_date", end_date);
1607
+ if (file_name)
1608
+ params.append("file_name", file_name);
1609
+ if (user_agent)
1610
+ params.append("user_agent", user_agent.toString());
1611
+ if (country)
1612
+ params.append("country", country.toString());
1613
+ if (region)
1614
+ params.append("region", region);
1615
+ if (referer)
1616
+ params.append("referer", referer.toString());
1617
+ if (limit)
1618
+ params.append("limit", limit.toString());
1619
+ if (sort_order)
1620
+ params.append("sort_order", sort_order);
1621
+ if (sort_by)
1622
+ params.append("sort_by", sort_by);
1623
+ if (date_interval)
1624
+ params.append("by", date_interval);
1625
+ }
1626
+ let endpoint = "https://api.pinata.cloud/v3";
1627
+ if (config.endpointUrl) {
1628
+ endpoint = config.endpointUrl;
1629
+ }
1630
+ const url = `${endpoint}/ipfs/gateway_analytics_time_series?${params.toString()}`;
1631
+ try {
1632
+ let headers;
1633
+ if (config.customHeaders && Object.keys(config.customHeaders).length > 0) {
1634
+ headers = { ...config.customHeaders };
1635
+ } else {
1636
+ headers = {
1637
+ Authorization: `Bearer ${config.pinataJwt}`,
1638
+ Source: "sdk/analyticsDateInterval"
1639
+ };
1640
+ }
1641
+ const request = await fetch(url, {
1642
+ method: "GET",
1643
+ headers
1644
+ });
1645
+ if (!request.ok) {
1646
+ const errorData = await request.text();
1647
+ if (request.status === 401 || request.status === 403) {
1648
+ throw new AuthenticationError(
1649
+ `Authentication failed: ${errorData}`,
1650
+ request.status,
1651
+ errorData
1652
+ );
1653
+ }
1654
+ throw new NetworkError(
1655
+ `HTTP error: ${errorData}`,
1656
+ request.status,
1657
+ errorData
1658
+ );
1659
+ }
1660
+ const res = await request.json();
1661
+ const resData = res.data;
1662
+ return resData;
1663
+ } catch (error) {
1664
+ if (error instanceof PinataError) {
1665
+ throw error;
1666
+ }
1667
+ if (error instanceof Error) {
1668
+ throw new PinataError(
1669
+ `Error processing anaytics usage: ${error.message}`
1670
+ );
1671
+ }
1672
+ throw new PinataError(
1673
+ "An unknown error occurred while fetching gateway usage"
1674
+ );
1675
+ }
1676
+ };
1677
+
1387
1678
  // src/core/files/swapCid.ts
1388
1679
  var swapCid = async (config, options) => {
1389
1680
  if (!config) {
@@ -1719,6 +2010,7 @@ var PinataSDK = class {
1719
2010
  this.gateways = new Gateways(this.config);
1720
2011
  this.keys = new Keys(this.config);
1721
2012
  this.groups = new Groups(this.config);
2013
+ this.analytics = new Analytics(this.config);
1722
2014
  }
1723
2015
  setNewHeaders(headers) {
1724
2016
  if (!this.config) {
@@ -1730,6 +2022,7 @@ var PinataSDK = class {
1730
2022
  this.gateways.updateConfig(this.config);
1731
2023
  this.keys.updateConfig(this.config);
1732
2024
  this.groups.updateConfig(this.config);
2025
+ this.analytics.updateConfig(this.config);
1733
2026
  }
1734
2027
  setNewJwt(jwt) {
1735
2028
  if (!this.config) {
@@ -1741,6 +2034,7 @@ var PinataSDK = class {
1741
2034
  this.gateways.updateConfig(this.config);
1742
2035
  this.keys.updateConfig(this.config);
1743
2036
  this.groups.updateConfig(this.config);
2037
+ this.analytics.updateConfig(this.config);
1744
2038
  }
1745
2039
  testAuthentication() {
1746
2040
  return testAuthentication(this.config);
@@ -2195,6 +2489,251 @@ var FilterGroups = class {
2195
2489
  return allItems;
2196
2490
  }
2197
2491
  };
2492
+ var Analytics = class {
2493
+ constructor(config) {
2494
+ this.config = formatConfig(config);
2495
+ this.requests = new AnalyticsRequests(this.config);
2496
+ this.bandwidth = new AnalyticsBandwidth(this.config);
2497
+ }
2498
+ updateConfig(newConfig) {
2499
+ this.config = newConfig;
2500
+ this.requests.updateConfig(newConfig);
2501
+ this.bandwidth.updateConfig(newConfig);
2502
+ }
2503
+ // detailed(options: {
2504
+ // domain: string;
2505
+ // start: string;
2506
+ // end: string;
2507
+ // sortBy: "requests" | "bandwidth";
2508
+ // attribute:
2509
+ // | "cid"
2510
+ // | "country"
2511
+ // | "region"
2512
+ // | "user_agent"
2513
+ // | "referer"
2514
+ // | "file_name";
2515
+ // }): TopAnalyticsBuilder {
2516
+ // return new TopAnalyticsBuilder(
2517
+ // this.config,
2518
+ // options.domain,
2519
+ // options.start,
2520
+ // options.end,
2521
+ // options.sortBy,
2522
+ // options.attribute,
2523
+ // );
2524
+ // }
2525
+ summary(options) {
2526
+ return new TimeIntervalAnalyticsBuilder(
2527
+ this.config,
2528
+ options.domain,
2529
+ options.start,
2530
+ options.end,
2531
+ options.interval
2532
+ );
2533
+ }
2534
+ };
2535
+ var calculateDates = (days) => {
2536
+ const end = /* @__PURE__ */ new Date();
2537
+ const start = /* @__PURE__ */ new Date();
2538
+ start.setDate(start.getDate() - days);
2539
+ return {
2540
+ start: start.toISOString().split("T")[0],
2541
+ end: end.toISOString().split("T")[0]
2542
+ };
2543
+ };
2544
+ var AnalyticsFilter = class {
2545
+ constructor(config, domain, start, end) {
2546
+ this.config = config;
2547
+ this.query = {
2548
+ gateway_domain: domain,
2549
+ start_date: start,
2550
+ end_date: end,
2551
+ sort_by: "requests",
2552
+ // Will be overridden in child classes
2553
+ attribute: "cid"
2554
+ };
2555
+ }
2556
+ cid(cid) {
2557
+ this.query.attribute = "cid";
2558
+ if (cid) {
2559
+ this.query.cid = cid;
2560
+ }
2561
+ return this;
2562
+ }
2563
+ fileName(fileName) {
2564
+ this.query.attribute = "file_name";
2565
+ if (fileName) {
2566
+ this.query.file_name = fileName;
2567
+ }
2568
+ return this;
2569
+ }
2570
+ userAgent(userAgent) {
2571
+ this.query.attribute = "user_agent";
2572
+ if (userAgent) {
2573
+ this.query.user_agent = userAgent;
2574
+ }
2575
+ return this;
2576
+ }
2577
+ country(country) {
2578
+ this.query.attribute = "country";
2579
+ if (country) {
2580
+ this.query.country = country;
2581
+ }
2582
+ return this;
2583
+ }
2584
+ region(region) {
2585
+ this.query.attribute = "region";
2586
+ if (region) {
2587
+ this.query.region = region;
2588
+ }
2589
+ return this;
2590
+ }
2591
+ referer(referer) {
2592
+ this.query.attribute = "referer";
2593
+ if (referer) {
2594
+ this.query.referer = referer;
2595
+ }
2596
+ return this;
2597
+ }
2598
+ limit(limit) {
2599
+ this.query.limit = limit;
2600
+ return this;
2601
+ }
2602
+ sort(order) {
2603
+ this.query.sort_order = order;
2604
+ return this;
2605
+ }
2606
+ days(numberOfDays) {
2607
+ const { start, end } = calculateDates(numberOfDays);
2608
+ this.query.start_date = start;
2609
+ this.query.end_date = end;
2610
+ return this;
2611
+ }
2612
+ then(onfulfilled) {
2613
+ return analyticsTopUsage(this.config, this.query).then(onfulfilled);
2614
+ }
2615
+ };
2616
+ var AnalyticsRequests = class extends AnalyticsFilter {
2617
+ constructor(config) {
2618
+ super(config, "", "", "");
2619
+ this.query.sort_by = "requests";
2620
+ }
2621
+ updateConfig(newConfig) {
2622
+ this.config = newConfig;
2623
+ }
2624
+ customDates(start, end) {
2625
+ if (start)
2626
+ this.query.start_date = start;
2627
+ if (end)
2628
+ this.query.end_date = end;
2629
+ return this;
2630
+ }
2631
+ from(domain) {
2632
+ this.query.gateway_domain = domain;
2633
+ return this;
2634
+ }
2635
+ };
2636
+ var AnalyticsBandwidth = class extends AnalyticsFilter {
2637
+ constructor(config) {
2638
+ super(config, "", "", "");
2639
+ this.query.sort_by = "bandwidth";
2640
+ }
2641
+ updateConfig(newConfig) {
2642
+ this.config = newConfig;
2643
+ }
2644
+ customDates(start, end) {
2645
+ if (start)
2646
+ this.query.start_date = start;
2647
+ if (end)
2648
+ this.query.end_date = end;
2649
+ return this;
2650
+ }
2651
+ from(domain) {
2652
+ this.query.gateway_domain = domain;
2653
+ return this;
2654
+ }
2655
+ };
2656
+ var AnalyticsBuilder = class {
2657
+ constructor(config, query) {
2658
+ this.requestCount = 0;
2659
+ this.lastRequestTime = 0;
2660
+ this.MAX_REQUESTS_PER_MINUTE = 30;
2661
+ this.MINUTE_IN_MS = 6e4;
2662
+ this.config = config;
2663
+ this.query = query;
2664
+ }
2665
+ cid(cid) {
2666
+ this.query.cid = cid;
2667
+ return this;
2668
+ }
2669
+ fileName(fileName) {
2670
+ this.query.file_name = fileName;
2671
+ return this;
2672
+ }
2673
+ userAgent(userAgent) {
2674
+ this.query.user_agent = userAgent;
2675
+ return this;
2676
+ }
2677
+ country(country) {
2678
+ this.query.country = country;
2679
+ return this;
2680
+ }
2681
+ region(region) {
2682
+ this.query.region = region;
2683
+ return this;
2684
+ }
2685
+ referer(referer) {
2686
+ this.query.referer = referer;
2687
+ return this;
2688
+ }
2689
+ limit(limit) {
2690
+ this.query.limit = limit;
2691
+ return this;
2692
+ }
2693
+ sort(order) {
2694
+ this.query.sort_order = order;
2695
+ return this;
2696
+ }
2697
+ // private async rateLimit(): Promise<void> {
2698
+ // this.requestCount++;
2699
+ // const now = Date.now();
2700
+ // if (this.requestCount >= this.MAX_REQUESTS_PER_MINUTE) {
2701
+ // const timePassedSinceLastRequest = now - this.lastRequestTime;
2702
+ // if (timePassedSinceLastRequest < this.MINUTE_IN_MS) {
2703
+ // const delayTime = this.MINUTE_IN_MS - timePassedSinceLastRequest;
2704
+ // await new Promise((resolve) => setTimeout(resolve, delayTime));
2705
+ // }
2706
+ // this.requestCount = 0;
2707
+ // }
2708
+ // this.lastRequestTime = Date.now();
2709
+ // }
2710
+ async getAnalytics() {
2711
+ throw new Error("getAnalytics method must be implemented in derived class");
2712
+ }
2713
+ then(onfulfilled) {
2714
+ return this.getAnalytics().then(onfulfilled);
2715
+ }
2716
+ };
2717
+ var TimeIntervalAnalyticsBuilder = class extends AnalyticsBuilder {
2718
+ constructor(config, domain, start, end, dateInterval) {
2719
+ super(config, {
2720
+ gateway_domain: domain,
2721
+ start_date: start,
2722
+ end_date: end,
2723
+ date_interval: dateInterval
2724
+ });
2725
+ }
2726
+ sortBy(sortBy) {
2727
+ this.query.sort_by = sortBy;
2728
+ return this;
2729
+ }
2730
+ async getAnalytics() {
2731
+ return analyticsDateInterval(this.config, this.query);
2732
+ }
2733
+ async all() {
2734
+ return this.getAnalytics();
2735
+ }
2736
+ };
2198
2737
  export {
2199
2738
  PinataSDK
2200
2739
  };