pinata 1.7.1 → 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.js CHANGED
@@ -110,20 +110,101 @@ var testAuthentication = async (config) => {
110
110
  }
111
111
  };
112
112
 
113
+ // src/utils/resumable.ts
114
+ function getFileIdFromUrl(url) {
115
+ const match = url.match(/\/files\/([^\/]+)/);
116
+ if (match && match[1]) {
117
+ return match[1];
118
+ }
119
+ throw new NetworkError("File ID not found in URL", 400, url);
120
+ }
121
+
113
122
  // src/core/uploads/file.ts
114
123
  var uploadFile = async (config, file, options) => {
115
124
  if (!config) {
116
125
  throw new ValidationError("Pinata configuration is missing");
117
126
  }
118
127
  const jwt = options?.keys || config.pinataJwt;
119
- const data = new FormData();
120
- data.append("file", file, file.name);
121
- data.append("name", options?.metadata?.name || file.name || "File from SDK");
122
- if (options?.groupId) {
123
- data.append("group_id", options.groupId);
128
+ let endpoint = "https://uploads.pinata.cloud/v3";
129
+ if (config.uploadUrl) {
130
+ endpoint = config.uploadUrl;
124
131
  }
125
- if (options?.metadata?.keyvalues) {
126
- data.append("keyvalues", JSON.stringify(options.metadata.keyvalues));
132
+ if (file.size > 94371840) {
133
+ let headers2;
134
+ if (config.customHeaders && Object.keys(config.customHeaders).length > 0) {
135
+ headers2 = {
136
+ Authorization: `Bearer ${jwt}`,
137
+ ...config.customHeaders
138
+ };
139
+ } else {
140
+ headers2 = {
141
+ Authorization: `Bearer ${jwt}`,
142
+ Source: "sdk/file"
143
+ };
144
+ }
145
+ const name = options?.metadata?.name || file.name || "File from SDK";
146
+ let metadata = `filename ${btoa(name)},filetype ${btoa(file.type)}`;
147
+ if (options?.groupId) {
148
+ metadata + `,group_id ${btoa(options.groupId)}`;
149
+ }
150
+ if (options?.metadata?.keyvalues) {
151
+ metadata + `,keyvalues ${btoa(JSON.stringify(options.metadata.keyvalues))}`;
152
+ }
153
+ const urlReq = await fetch(`${endpoint}/files`, {
154
+ method: "POST",
155
+ headers: {
156
+ "Upload-Length": `${file.size}`,
157
+ "Upload-Metadata": metadata,
158
+ ...headers2
159
+ }
160
+ });
161
+ const url = urlReq.headers.get("Location");
162
+ if (!url) {
163
+ throw new NetworkError("Upload URL not provided", urlReq.status, "");
164
+ }
165
+ const chunkSize = 50 * 1024 * 1024;
166
+ const totalChunks = Math.ceil(file.size / chunkSize);
167
+ let offset = 0;
168
+ let uploadReq;
169
+ for (let i = 0; i < totalChunks; i++) {
170
+ const chunk = file.slice(offset, offset + chunkSize);
171
+ uploadReq = await fetch(url, {
172
+ method: "PATCH",
173
+ headers: {
174
+ "Content-Type": "application/offset+octet-stream",
175
+ "Upload-Offset": offset.toString(),
176
+ ...headers2
177
+ },
178
+ body: chunk
179
+ });
180
+ if (!uploadReq.ok) {
181
+ const errorData = await uploadReq.text();
182
+ throw new NetworkError(
183
+ `HTTP error during chunk upload: ${errorData}`,
184
+ uploadReq.status,
185
+ errorData
186
+ );
187
+ }
188
+ offset += chunk.size;
189
+ }
190
+ if (uploadReq.status === 204) {
191
+ const fileId = getFileIdFromUrl(url);
192
+ let dataEndpoint;
193
+ if (config.endpointUrl) {
194
+ dataEndpoint = config.endpointUrl;
195
+ } else {
196
+ dataEndpoint = "https://api.pinata.cloud/v3";
197
+ }
198
+ const fileInfoReq = await fetch(`${dataEndpoint}/files/${fileId}`, {
199
+ method: "GET",
200
+ headers: {
201
+ Authorization: `Bearer ${process.env.PINATA_JWT}`
202
+ }
203
+ });
204
+ const fileInfo = await fileInfoReq.json();
205
+ const data2 = fileInfo.data;
206
+ return data2;
207
+ }
127
208
  }
128
209
  let headers;
129
210
  if (config.customHeaders && Object.keys(config.customHeaders).length > 0) {
@@ -137,9 +218,14 @@ var uploadFile = async (config, file, options) => {
137
218
  Source: "sdk/file"
138
219
  };
139
220
  }
140
- let endpoint = "https://uploads.pinata.cloud/v3";
141
- if (config.uploadUrl) {
142
- endpoint = config.uploadUrl;
221
+ const data = new FormData();
222
+ data.append("file", file, file.name);
223
+ data.append("name", options?.metadata?.name || file.name || "File from SDK");
224
+ if (options?.groupId) {
225
+ data.append("group_id", options.groupId);
226
+ }
227
+ if (options?.metadata?.keyvalues) {
228
+ data.append("keyvalues", JSON.stringify(options.metadata.keyvalues));
143
229
  }
144
230
  try {
145
231
  const request = await fetch(`${endpoint}/files`, {
@@ -1366,7 +1452,6 @@ var deleteGroup = async (config, options) => {
1366
1452
  "Content-Type": "application/json",
1367
1453
  ...config.customHeaders
1368
1454
  };
1369
- headers = { ...config.customHeaders };
1370
1455
  } else {
1371
1456
  headers = {
1372
1457
  Authorization: `Bearer ${config.pinataJwt}`,
@@ -1411,6 +1496,211 @@ var deleteGroup = async (config, options) => {
1411
1496
  }
1412
1497
  };
1413
1498
 
1499
+ // src/core/analytics/analyticsTopUsage.ts
1500
+ var analyticsTopUsage = async (config, options) => {
1501
+ if (!config) {
1502
+ throw new ValidationError("Pinata configuration is missing");
1503
+ }
1504
+ const params = new URLSearchParams();
1505
+ if (options) {
1506
+ const {
1507
+ cid,
1508
+ gateway_domain,
1509
+ start_date,
1510
+ end_date,
1511
+ file_name,
1512
+ user_agent,
1513
+ country,
1514
+ region,
1515
+ referer,
1516
+ limit,
1517
+ sort_order,
1518
+ sort_by,
1519
+ attribute
1520
+ } = options;
1521
+ const domain = gateway_domain || config.pinataGateway;
1522
+ if (domain) {
1523
+ const cleanDomain = domain.replace(/^https?:\/\//, "");
1524
+ params.append("gateway_domain", cleanDomain);
1525
+ }
1526
+ if (cid) {
1527
+ params.append("cid", cid);
1528
+ }
1529
+ if (start_date)
1530
+ params.append("start_date", start_date);
1531
+ if (end_date)
1532
+ params.append("end_date", end_date);
1533
+ if (file_name)
1534
+ params.append("file_name", file_name);
1535
+ if (user_agent)
1536
+ params.append("user_agent", user_agent.toString());
1537
+ if (country)
1538
+ params.append("country", country.toString());
1539
+ if (region)
1540
+ params.append("region", region);
1541
+ if (referer)
1542
+ params.append("referer", referer.toString());
1543
+ if (limit)
1544
+ params.append("limit", limit.toString());
1545
+ if (sort_order)
1546
+ params.append("sort_order", sort_order);
1547
+ if (sort_by)
1548
+ params.append("sort_by", sort_by);
1549
+ if (attribute)
1550
+ params.append("by", attribute);
1551
+ }
1552
+ let endpoint = "https://api.pinata.cloud/v3";
1553
+ if (config.endpointUrl) {
1554
+ endpoint = config.endpointUrl;
1555
+ }
1556
+ const url = `${endpoint}/ipfs/gateway_analytics_top?${params.toString()}`;
1557
+ try {
1558
+ let headers;
1559
+ if (config.customHeaders && Object.keys(config.customHeaders).length > 0) {
1560
+ headers = { ...config.customHeaders };
1561
+ } else {
1562
+ headers = {
1563
+ Authorization: `Bearer ${config.pinataJwt}`,
1564
+ Source: "sdk/analyticsTopUsage"
1565
+ };
1566
+ }
1567
+ const request = await fetch(url, {
1568
+ method: "GET",
1569
+ headers
1570
+ });
1571
+ if (!request.ok) {
1572
+ const errorData = await request.text();
1573
+ if (request.status === 401 || request.status === 403) {
1574
+ throw new AuthenticationError(
1575
+ `Authentication failed: ${errorData}`,
1576
+ request.status,
1577
+ errorData
1578
+ );
1579
+ }
1580
+ throw new NetworkError(
1581
+ `HTTP error: ${errorData}`,
1582
+ request.status,
1583
+ errorData
1584
+ );
1585
+ }
1586
+ const res = await request.json();
1587
+ return res;
1588
+ } catch (error) {
1589
+ if (error instanceof PinataError) {
1590
+ throw error;
1591
+ }
1592
+ if (error instanceof Error) {
1593
+ throw new PinataError(
1594
+ `Error processing anaytics usage: ${error.message}`
1595
+ );
1596
+ }
1597
+ throw new PinataError(
1598
+ "An unknown error occurred while fetching gateway usage"
1599
+ );
1600
+ }
1601
+ };
1602
+
1603
+ // src/core/analytics/analyticsDateInterval.ts
1604
+ var analyticsDateInterval = async (config, options) => {
1605
+ if (!config) {
1606
+ throw new ValidationError("Pinata configuration is missing");
1607
+ }
1608
+ const params = new URLSearchParams();
1609
+ if (options) {
1610
+ const {
1611
+ cid,
1612
+ gateway_domain,
1613
+ start_date,
1614
+ end_date,
1615
+ file_name,
1616
+ user_agent,
1617
+ country,
1618
+ region,
1619
+ referer,
1620
+ limit,
1621
+ sort_order,
1622
+ date_interval,
1623
+ sort_by
1624
+ } = options;
1625
+ if (cid)
1626
+ params.append("cid", cid);
1627
+ if (gateway_domain)
1628
+ params.append("gateway_domain", gateway_domain);
1629
+ if (start_date)
1630
+ params.append("start_date", start_date);
1631
+ if (end_date)
1632
+ params.append("end_date", end_date);
1633
+ if (file_name)
1634
+ params.append("file_name", file_name);
1635
+ if (user_agent)
1636
+ params.append("user_agent", user_agent.toString());
1637
+ if (country)
1638
+ params.append("country", country.toString());
1639
+ if (region)
1640
+ params.append("region", region);
1641
+ if (referer)
1642
+ params.append("referer", referer.toString());
1643
+ if (limit)
1644
+ params.append("limit", limit.toString());
1645
+ if (sort_order)
1646
+ params.append("sort_order", sort_order);
1647
+ if (sort_by)
1648
+ params.append("sort_by", sort_by);
1649
+ if (date_interval)
1650
+ params.append("by", date_interval);
1651
+ }
1652
+ let endpoint = "https://api.pinata.cloud/v3";
1653
+ if (config.endpointUrl) {
1654
+ endpoint = config.endpointUrl;
1655
+ }
1656
+ const url = `${endpoint}/ipfs/gateway_analytics_time_series?${params.toString()}`;
1657
+ try {
1658
+ let headers;
1659
+ if (config.customHeaders && Object.keys(config.customHeaders).length > 0) {
1660
+ headers = { ...config.customHeaders };
1661
+ } else {
1662
+ headers = {
1663
+ Authorization: `Bearer ${config.pinataJwt}`,
1664
+ Source: "sdk/analyticsDateInterval"
1665
+ };
1666
+ }
1667
+ const request = await fetch(url, {
1668
+ method: "GET",
1669
+ headers
1670
+ });
1671
+ if (!request.ok) {
1672
+ const errorData = await request.text();
1673
+ if (request.status === 401 || request.status === 403) {
1674
+ throw new AuthenticationError(
1675
+ `Authentication failed: ${errorData}`,
1676
+ request.status,
1677
+ errorData
1678
+ );
1679
+ }
1680
+ throw new NetworkError(
1681
+ `HTTP error: ${errorData}`,
1682
+ request.status,
1683
+ errorData
1684
+ );
1685
+ }
1686
+ const res = await request.json();
1687
+ const resData = res.data;
1688
+ return resData;
1689
+ } catch (error) {
1690
+ if (error instanceof PinataError) {
1691
+ throw error;
1692
+ }
1693
+ if (error instanceof Error) {
1694
+ throw new PinataError(
1695
+ `Error processing anaytics usage: ${error.message}`
1696
+ );
1697
+ }
1698
+ throw new PinataError(
1699
+ "An unknown error occurred while fetching gateway usage"
1700
+ );
1701
+ }
1702
+ };
1703
+
1414
1704
  // src/core/files/swapCid.ts
1415
1705
  var swapCid = async (config, options) => {
1416
1706
  if (!config) {
@@ -1746,6 +2036,7 @@ var PinataSDK = class {
1746
2036
  this.gateways = new Gateways(this.config);
1747
2037
  this.keys = new Keys(this.config);
1748
2038
  this.groups = new Groups(this.config);
2039
+ this.analytics = new Analytics(this.config);
1749
2040
  }
1750
2041
  setNewHeaders(headers) {
1751
2042
  if (!this.config) {
@@ -1757,6 +2048,7 @@ var PinataSDK = class {
1757
2048
  this.gateways.updateConfig(this.config);
1758
2049
  this.keys.updateConfig(this.config);
1759
2050
  this.groups.updateConfig(this.config);
2051
+ this.analytics.updateConfig(this.config);
1760
2052
  }
1761
2053
  setNewJwt(jwt) {
1762
2054
  if (!this.config) {
@@ -1768,6 +2060,7 @@ var PinataSDK = class {
1768
2060
  this.gateways.updateConfig(this.config);
1769
2061
  this.keys.updateConfig(this.config);
1770
2062
  this.groups.updateConfig(this.config);
2063
+ this.analytics.updateConfig(this.config);
1771
2064
  }
1772
2065
  testAuthentication() {
1773
2066
  return testAuthentication(this.config);
@@ -2222,6 +2515,251 @@ var FilterGroups = class {
2222
2515
  return allItems;
2223
2516
  }
2224
2517
  };
2518
+ var Analytics = class {
2519
+ constructor(config) {
2520
+ this.config = formatConfig(config);
2521
+ this.requests = new AnalyticsRequests(this.config);
2522
+ this.bandwidth = new AnalyticsBandwidth(this.config);
2523
+ }
2524
+ updateConfig(newConfig) {
2525
+ this.config = newConfig;
2526
+ this.requests.updateConfig(newConfig);
2527
+ this.bandwidth.updateConfig(newConfig);
2528
+ }
2529
+ // detailed(options: {
2530
+ // domain: string;
2531
+ // start: string;
2532
+ // end: string;
2533
+ // sortBy: "requests" | "bandwidth";
2534
+ // attribute:
2535
+ // | "cid"
2536
+ // | "country"
2537
+ // | "region"
2538
+ // | "user_agent"
2539
+ // | "referer"
2540
+ // | "file_name";
2541
+ // }): TopAnalyticsBuilder {
2542
+ // return new TopAnalyticsBuilder(
2543
+ // this.config,
2544
+ // options.domain,
2545
+ // options.start,
2546
+ // options.end,
2547
+ // options.sortBy,
2548
+ // options.attribute,
2549
+ // );
2550
+ // }
2551
+ summary(options) {
2552
+ return new TimeIntervalAnalyticsBuilder(
2553
+ this.config,
2554
+ options.domain,
2555
+ options.start,
2556
+ options.end,
2557
+ options.interval
2558
+ );
2559
+ }
2560
+ };
2561
+ var calculateDates = (days) => {
2562
+ const end = /* @__PURE__ */ new Date();
2563
+ const start = /* @__PURE__ */ new Date();
2564
+ start.setDate(start.getDate() - days);
2565
+ return {
2566
+ start: start.toISOString().split("T")[0],
2567
+ end: end.toISOString().split("T")[0]
2568
+ };
2569
+ };
2570
+ var AnalyticsFilter = class {
2571
+ constructor(config, domain, start, end) {
2572
+ this.config = config;
2573
+ this.query = {
2574
+ gateway_domain: domain,
2575
+ start_date: start,
2576
+ end_date: end,
2577
+ sort_by: "requests",
2578
+ // Will be overridden in child classes
2579
+ attribute: "cid"
2580
+ };
2581
+ }
2582
+ cid(cid) {
2583
+ this.query.attribute = "cid";
2584
+ if (cid) {
2585
+ this.query.cid = cid;
2586
+ }
2587
+ return this;
2588
+ }
2589
+ fileName(fileName) {
2590
+ this.query.attribute = "file_name";
2591
+ if (fileName) {
2592
+ this.query.file_name = fileName;
2593
+ }
2594
+ return this;
2595
+ }
2596
+ userAgent(userAgent) {
2597
+ this.query.attribute = "user_agent";
2598
+ if (userAgent) {
2599
+ this.query.user_agent = userAgent;
2600
+ }
2601
+ return this;
2602
+ }
2603
+ country(country) {
2604
+ this.query.attribute = "country";
2605
+ if (country) {
2606
+ this.query.country = country;
2607
+ }
2608
+ return this;
2609
+ }
2610
+ region(region) {
2611
+ this.query.attribute = "region";
2612
+ if (region) {
2613
+ this.query.region = region;
2614
+ }
2615
+ return this;
2616
+ }
2617
+ referer(referer) {
2618
+ this.query.attribute = "referer";
2619
+ if (referer) {
2620
+ this.query.referer = referer;
2621
+ }
2622
+ return this;
2623
+ }
2624
+ limit(limit) {
2625
+ this.query.limit = limit;
2626
+ return this;
2627
+ }
2628
+ sort(order) {
2629
+ this.query.sort_order = order;
2630
+ return this;
2631
+ }
2632
+ days(numberOfDays) {
2633
+ const { start, end } = calculateDates(numberOfDays);
2634
+ this.query.start_date = start;
2635
+ this.query.end_date = end;
2636
+ return this;
2637
+ }
2638
+ then(onfulfilled) {
2639
+ return analyticsTopUsage(this.config, this.query).then(onfulfilled);
2640
+ }
2641
+ };
2642
+ var AnalyticsRequests = class extends AnalyticsFilter {
2643
+ constructor(config) {
2644
+ super(config, "", "", "");
2645
+ this.query.sort_by = "requests";
2646
+ }
2647
+ updateConfig(newConfig) {
2648
+ this.config = newConfig;
2649
+ }
2650
+ customDates(start, end) {
2651
+ if (start)
2652
+ this.query.start_date = start;
2653
+ if (end)
2654
+ this.query.end_date = end;
2655
+ return this;
2656
+ }
2657
+ from(domain) {
2658
+ this.query.gateway_domain = domain;
2659
+ return this;
2660
+ }
2661
+ };
2662
+ var AnalyticsBandwidth = class extends AnalyticsFilter {
2663
+ constructor(config) {
2664
+ super(config, "", "", "");
2665
+ this.query.sort_by = "bandwidth";
2666
+ }
2667
+ updateConfig(newConfig) {
2668
+ this.config = newConfig;
2669
+ }
2670
+ customDates(start, end) {
2671
+ if (start)
2672
+ this.query.start_date = start;
2673
+ if (end)
2674
+ this.query.end_date = end;
2675
+ return this;
2676
+ }
2677
+ from(domain) {
2678
+ this.query.gateway_domain = domain;
2679
+ return this;
2680
+ }
2681
+ };
2682
+ var AnalyticsBuilder = class {
2683
+ constructor(config, query) {
2684
+ this.requestCount = 0;
2685
+ this.lastRequestTime = 0;
2686
+ this.MAX_REQUESTS_PER_MINUTE = 30;
2687
+ this.MINUTE_IN_MS = 6e4;
2688
+ this.config = config;
2689
+ this.query = query;
2690
+ }
2691
+ cid(cid) {
2692
+ this.query.cid = cid;
2693
+ return this;
2694
+ }
2695
+ fileName(fileName) {
2696
+ this.query.file_name = fileName;
2697
+ return this;
2698
+ }
2699
+ userAgent(userAgent) {
2700
+ this.query.user_agent = userAgent;
2701
+ return this;
2702
+ }
2703
+ country(country) {
2704
+ this.query.country = country;
2705
+ return this;
2706
+ }
2707
+ region(region) {
2708
+ this.query.region = region;
2709
+ return this;
2710
+ }
2711
+ referer(referer) {
2712
+ this.query.referer = referer;
2713
+ return this;
2714
+ }
2715
+ limit(limit) {
2716
+ this.query.limit = limit;
2717
+ return this;
2718
+ }
2719
+ sort(order) {
2720
+ this.query.sort_order = order;
2721
+ return this;
2722
+ }
2723
+ // private async rateLimit(): Promise<void> {
2724
+ // this.requestCount++;
2725
+ // const now = Date.now();
2726
+ // if (this.requestCount >= this.MAX_REQUESTS_PER_MINUTE) {
2727
+ // const timePassedSinceLastRequest = now - this.lastRequestTime;
2728
+ // if (timePassedSinceLastRequest < this.MINUTE_IN_MS) {
2729
+ // const delayTime = this.MINUTE_IN_MS - timePassedSinceLastRequest;
2730
+ // await new Promise((resolve) => setTimeout(resolve, delayTime));
2731
+ // }
2732
+ // this.requestCount = 0;
2733
+ // }
2734
+ // this.lastRequestTime = Date.now();
2735
+ // }
2736
+ async getAnalytics() {
2737
+ throw new Error("getAnalytics method must be implemented in derived class");
2738
+ }
2739
+ then(onfulfilled) {
2740
+ return this.getAnalytics().then(onfulfilled);
2741
+ }
2742
+ };
2743
+ var TimeIntervalAnalyticsBuilder = class extends AnalyticsBuilder {
2744
+ constructor(config, domain, start, end, dateInterval) {
2745
+ super(config, {
2746
+ gateway_domain: domain,
2747
+ start_date: start,
2748
+ end_date: end,
2749
+ date_interval: dateInterval
2750
+ });
2751
+ }
2752
+ sortBy(sortBy) {
2753
+ this.query.sort_by = sortBy;
2754
+ return this;
2755
+ }
2756
+ async getAnalytics() {
2757
+ return analyticsDateInterval(this.config, this.query);
2758
+ }
2759
+ async all() {
2760
+ return this.getAnalytics();
2761
+ }
2762
+ };
2225
2763
  // Annotate the CommonJS export names for ESM import in node:
2226
2764
  0 && (module.exports = {
2227
2765
  PinataSDK