@medialane/sdk 0.88.0 → 0.90.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.cjs +123 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -1
- package/dist/index.d.ts +32 -1
- package/dist/index.js +115 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -296,15 +296,15 @@ var ApiClient = class {
|
|
|
296
296
|
}
|
|
297
297
|
async request(path, init, opts) {
|
|
298
298
|
const url = `${this.baseUrl.replace(/\/$/, "")}${path}`;
|
|
299
|
-
const
|
|
299
|
+
const headers2 = { ...this.baseHeaders };
|
|
300
300
|
if (!(init?.body instanceof FormData)) {
|
|
301
|
-
|
|
301
|
+
headers2["Content-Type"] = "application/json";
|
|
302
302
|
}
|
|
303
303
|
const allowed = (status) => opts?.allow404 === true && status === 404 || opts?.allow403 === true && status === 403;
|
|
304
304
|
const res = await withRetry(async () => {
|
|
305
305
|
const response = await fetch(url, {
|
|
306
306
|
...init,
|
|
307
|
-
headers: { ...
|
|
307
|
+
headers: { ...headers2, ...init?.headers }
|
|
308
308
|
});
|
|
309
309
|
if (!response.ok && !allowed(response.status)) {
|
|
310
310
|
const text = await response.text().catch(() => response.statusText);
|
|
@@ -1342,7 +1342,7 @@ function proxyError(code, message, status) {
|
|
|
1342
1342
|
}
|
|
1343
1343
|
function createBackendProxyHandler(config) {
|
|
1344
1344
|
const doFetch = config.fetchImpl ?? fetch;
|
|
1345
|
-
const
|
|
1345
|
+
const endpoint2 = `${config.backendUrl.replace(/\/$/, "")}/${config.path.replace(/^\//, "")}`;
|
|
1346
1346
|
return async function handleBackendProxy(req) {
|
|
1347
1347
|
if (!isSameOrigin(req)) {
|
|
1348
1348
|
return proxyError(-32600, "Cross-origin requests are not allowed", 403);
|
|
@@ -1360,7 +1360,7 @@ function createBackendProxyHandler(config) {
|
|
|
1360
1360
|
return proxyError(-32700, "Parse error", 400);
|
|
1361
1361
|
}
|
|
1362
1362
|
try {
|
|
1363
|
-
const upstream = await doFetch(
|
|
1363
|
+
const upstream = await doFetch(endpoint2, {
|
|
1364
1364
|
method: "POST",
|
|
1365
1365
|
headers: { "Content-Type": "application/json", "x-api-key": config.apiKey },
|
|
1366
1366
|
body: JSON.stringify(body)
|
|
@@ -1381,6 +1381,115 @@ function createRpcProxyHandler(config) {
|
|
|
1381
1381
|
return createBackendProxyHandler({ ...config, path: "/v1/rpc" });
|
|
1382
1382
|
}
|
|
1383
1383
|
|
|
1384
|
+
// src/server/ssrf-guard.ts
|
|
1385
|
+
var ALLOWED_IMAGE_CONTENT_TYPES = /* @__PURE__ */ new Set([
|
|
1386
|
+
"image/jpeg",
|
|
1387
|
+
"image/jpg",
|
|
1388
|
+
"image/png",
|
|
1389
|
+
"image/gif",
|
|
1390
|
+
"image/webp",
|
|
1391
|
+
"image/svg+xml",
|
|
1392
|
+
"image/avif",
|
|
1393
|
+
"image/bmp",
|
|
1394
|
+
"image/tiff"
|
|
1395
|
+
]);
|
|
1396
|
+
var MAX_IMAGE_REDIRECTS = 5;
|
|
1397
|
+
var MAX_IMAGE_PROXY_BYTES = 15 * 1024 * 1024;
|
|
1398
|
+
function isPrivateHost(hostname) {
|
|
1399
|
+
const h = hostname.toLowerCase().replace(/^\[|\]$/g, "");
|
|
1400
|
+
if (h === "localhost" || h === "127.0.0.1" || h === "0.0.0.0") return true;
|
|
1401
|
+
if (/^\d+$/.test(h)) {
|
|
1402
|
+
const n = parseInt(h, 10);
|
|
1403
|
+
if (n === 2130706433 || n === 0 || n >= 2886729728 && n <= 2887778303 || n >= 3232235520 && n <= 3232301055 || n >= 167772160 && n <= 184549375 || n >= 2851995648 && n <= 2852061183) return true;
|
|
1404
|
+
}
|
|
1405
|
+
if (/^0x[0-9a-f]+$/i.test(h)) {
|
|
1406
|
+
const n = parseInt(h, 16);
|
|
1407
|
+
if (n === 2130706433 || n === 0 || n >= 2886729728 && n <= 2887778303 || n >= 3232235520 && n <= 3232301055 || n >= 167772160 && n <= 184549375 || n >= 2851995648 && n <= 2852061183) return true;
|
|
1408
|
+
}
|
|
1409
|
+
if (/^0\d+\.\d+\.\d+\.\d+$/.test(h)) return true;
|
|
1410
|
+
if (h === "::1" || /^0*:0*:0*:0*:0*:0*:0*:0*1$/.test(h)) return true;
|
|
1411
|
+
const v4mapped = h.match(/^::ffff:(\d+\.\d+\.\d+\.\d+)$/i);
|
|
1412
|
+
if (v4mapped) return isPrivateHost(v4mapped[1]);
|
|
1413
|
+
if (/^10\./.test(h)) return true;
|
|
1414
|
+
if (/^172\.(1[6-9]|2\d|3[01])\./.test(h)) return true;
|
|
1415
|
+
if (/^192\.168\./.test(h)) return true;
|
|
1416
|
+
if (/^169\.254\./.test(h)) return true;
|
|
1417
|
+
if (/^100\.(6[4-9]|[7-9]\d|1[01]\d|12[0-7])\./.test(h)) return true;
|
|
1418
|
+
if (/^fe80:/i.test(h)) return true;
|
|
1419
|
+
if (/^f[cd][0-9a-f]{2}:/i.test(h)) return true;
|
|
1420
|
+
if (h.endsWith(".local")) return true;
|
|
1421
|
+
if (h === "metadata.google.internal") return true;
|
|
1422
|
+
if (h === "metadata.azure.internal") return true;
|
|
1423
|
+
return false;
|
|
1424
|
+
}
|
|
1425
|
+
function validateUrl(raw) {
|
|
1426
|
+
let parsed;
|
|
1427
|
+
try {
|
|
1428
|
+
parsed = new URL(raw);
|
|
1429
|
+
} catch {
|
|
1430
|
+
return { error: "Invalid url", status: 400 };
|
|
1431
|
+
}
|
|
1432
|
+
if (parsed.protocol !== "https:") {
|
|
1433
|
+
return { error: "Only https URLs allowed", status: 400 };
|
|
1434
|
+
}
|
|
1435
|
+
if (parsed.username || parsed.password) {
|
|
1436
|
+
return { error: "URL credentials not allowed", status: 400 };
|
|
1437
|
+
}
|
|
1438
|
+
if (isPrivateHost(parsed.hostname)) {
|
|
1439
|
+
return { error: "URL not allowed", status: 400 };
|
|
1440
|
+
}
|
|
1441
|
+
return { url: parsed };
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1444
|
+
// src/server/backend-metadata.ts
|
|
1445
|
+
function endpoint(config, path) {
|
|
1446
|
+
return `${config.backendUrl.replace(/\/$/, "")}/v1/metadata/${path}`;
|
|
1447
|
+
}
|
|
1448
|
+
function headers(config, extra) {
|
|
1449
|
+
return { "x-api-key": config.apiKey, ...extra };
|
|
1450
|
+
}
|
|
1451
|
+
async function uploadJsonToBackend(config, json) {
|
|
1452
|
+
const res = await (config.fetchImpl ?? fetch)(endpoint(config, "upload"), {
|
|
1453
|
+
method: "POST",
|
|
1454
|
+
headers: headers(config, { "Content-Type": "application/json" }),
|
|
1455
|
+
body: JSON.stringify(json)
|
|
1456
|
+
});
|
|
1457
|
+
const data = await res.json().catch(() => ({}));
|
|
1458
|
+
if (!res.ok || !data.data) throw new Error(data.error ?? "Metadata upload failed");
|
|
1459
|
+
return { cid: data.data.cid, uri: data.data.url };
|
|
1460
|
+
}
|
|
1461
|
+
async function uploadFileToBackend(config, file) {
|
|
1462
|
+
const form = new FormData();
|
|
1463
|
+
form.append("file", file, file.name);
|
|
1464
|
+
const res = await (config.fetchImpl ?? fetch)(endpoint(config, "upload-file"), {
|
|
1465
|
+
method: "POST",
|
|
1466
|
+
headers: headers(config),
|
|
1467
|
+
body: form
|
|
1468
|
+
});
|
|
1469
|
+
const data = await res.json().catch(() => ({}));
|
|
1470
|
+
if (!res.ok || !data.data) throw new Error(data.error ?? "File upload failed");
|
|
1471
|
+
return { cid: data.data.cid, uri: data.data.url };
|
|
1472
|
+
}
|
|
1473
|
+
async function uploadDirectoryToBackend(config, files) {
|
|
1474
|
+
const res = await (config.fetchImpl ?? fetch)(endpoint(config, "upload-directory"), {
|
|
1475
|
+
method: "POST",
|
|
1476
|
+
headers: headers(config, { "Content-Type": "application/json" }),
|
|
1477
|
+
body: JSON.stringify({ files })
|
|
1478
|
+
});
|
|
1479
|
+
const data = await res.json().catch(() => ({}));
|
|
1480
|
+
if (!res.ok || !data.data) throw new Error(data.error ?? "Directory pin failed");
|
|
1481
|
+
return data.data;
|
|
1482
|
+
}
|
|
1483
|
+
async function getBackendSignedUrl(config, kind = "image") {
|
|
1484
|
+
const res = await (config.fetchImpl ?? fetch)(`${endpoint(config, "signed-url")}?kind=${kind}`, {
|
|
1485
|
+
method: "GET",
|
|
1486
|
+
headers: headers(config)
|
|
1487
|
+
});
|
|
1488
|
+
const data = await res.json().catch(() => ({}));
|
|
1489
|
+
if (!res.ok || !data.data) throw new Error(data.error ?? "Failed to create upload URL");
|
|
1490
|
+
return data.data.url;
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1384
1493
|
// src/metadata.ts
|
|
1385
1494
|
var RESERVED_TRAITS = /* @__PURE__ */ new Set([
|
|
1386
1495
|
"Creator",
|
|
@@ -1474,12 +1583,15 @@ function resolveSafeImageContentType(contentType) {
|
|
|
1474
1583
|
}
|
|
1475
1584
|
var MAX_IPFS_GATEWAY_RESPONSE_BYTES = 25 * 1024 * 1024;
|
|
1476
1585
|
|
|
1586
|
+
exports.ALLOWED_IMAGE_CONTENT_TYPES = ALLOWED_IMAGE_CONTENT_TYPES;
|
|
1477
1587
|
exports.ApiClient = ApiClient;
|
|
1478
1588
|
exports.CHAINS = CHAINS;
|
|
1479
1589
|
exports.DEFAULT_CHAIN = DEFAULT_CHAIN;
|
|
1480
1590
|
exports.DEFAULT_CURRENCY = DEFAULT_CURRENCY;
|
|
1481
1591
|
exports.FeeConfigSchema = FeeConfigSchema;
|
|
1482
1592
|
exports.IPFS_SAFE_CONTENT_TYPE_PREFIXES = IPFS_SAFE_CONTENT_TYPE_PREFIXES;
|
|
1593
|
+
exports.MAX_IMAGE_PROXY_BYTES = MAX_IMAGE_PROXY_BYTES;
|
|
1594
|
+
exports.MAX_IMAGE_REDIRECTS = MAX_IMAGE_REDIRECTS;
|
|
1483
1595
|
exports.MAX_IPFS_GATEWAY_RESPONSE_BYTES = MAX_IPFS_GATEWAY_RESPONSE_BYTES;
|
|
1484
1596
|
exports.MedialaneApiError = MedialaneApiError;
|
|
1485
1597
|
exports.OPEN_LICENSES = OPEN_LICENSES;
|
|
@@ -1530,6 +1642,7 @@ exports.createRateLimiter = createRateLimiter;
|
|
|
1530
1642
|
exports.createRpcProxyHandler = createRpcProxyHandler;
|
|
1531
1643
|
exports.encodeU256 = encodeU256;
|
|
1532
1644
|
exports.formatAmount = formatAmount;
|
|
1645
|
+
exports.getBackendSignedUrl = getBackendSignedUrl;
|
|
1533
1646
|
exports.getCoordinates = getCoordinates;
|
|
1534
1647
|
exports.getDerivativesTerm = getDerivativesTerm;
|
|
1535
1648
|
exports.getListableTokens = getListableTokens;
|
|
@@ -1539,6 +1652,7 @@ exports.getStarknetCoordinates = getStarknetCoordinates;
|
|
|
1539
1652
|
exports.getTokenByAddress = getTokenByAddress;
|
|
1540
1653
|
exports.getTokenBySymbol = getTokenBySymbol;
|
|
1541
1654
|
exports.hasCapability = hasCapability;
|
|
1655
|
+
exports.isPrivateHost = isPrivateHost;
|
|
1542
1656
|
exports.isSameOrigin = isSameOrigin;
|
|
1543
1657
|
exports.isServiceId = isServiceId;
|
|
1544
1658
|
exports.isTransientRpcError = isTransientRpcError;
|
|
@@ -1556,5 +1670,9 @@ exports.resolveSafeImageContentType = resolveSafeImageContentType;
|
|
|
1556
1670
|
exports.shortenAddress = shortenAddress;
|
|
1557
1671
|
exports.stringifyBigInts = stringifyBigInts;
|
|
1558
1672
|
exports.u256ToBigInt = u256ToBigInt;
|
|
1673
|
+
exports.uploadDirectoryToBackend = uploadDirectoryToBackend;
|
|
1674
|
+
exports.uploadFileToBackend = uploadFileToBackend;
|
|
1675
|
+
exports.uploadJsonToBackend = uploadJsonToBackend;
|
|
1676
|
+
exports.validateUrl = validateUrl;
|
|
1559
1677
|
//# sourceMappingURL=index.cjs.map
|
|
1560
1678
|
//# sourceMappingURL=index.cjs.map
|