@bunny.net/storage-sdk
Version:
276 lines (270 loc) • 9.12 kB
JavaScript
var __defProp = Object.defineProperty;
var __export = (target, all) => {
for (var name2 in all)
__defProp(target, name2, { get: all[name2], enumerable: true });
};
// src/regions.ts
var regions_exports = {};
__export(regions_exports, {
StorageRegion: () => StorageRegion,
addr: () => addr
});
var StorageRegion = /* @__PURE__ */ ((StorageRegion2) => {
StorageRegion2["Falkenstein"] = "de";
StorageRegion2["London"] = "uk";
StorageRegion2["NewYork"] = "ny";
StorageRegion2["LosAngeles"] = "la";
StorageRegion2["Singapore"] = "sg";
StorageRegion2["Stockholm"] = "se";
StorageRegion2["SaoPaulo"] = "br";
StorageRegion2["Johannesburg"] = "jh";
StorageRegion2["Sydney"] = "syd";
return StorageRegion2;
})(StorageRegion || {});
function addr(value) {
switch (value) {
case "de" /* Falkenstein */:
return new URL("https://storage.bunnycdn.com");
case "uk" /* London */:
return new URL("https://uk.storage.bunnycdn.com");
case "ny" /* NewYork */:
return new URL("https://ny.storage.bunnycdn.com");
case "la" /* LosAngeles */:
return new URL("https://la.storage.bunnycdn.com");
case "sg" /* Singapore */:
return new URL("https://sg.storage.bunnycdn.com");
case "se" /* Stockholm */:
return new URL("https://se.storage.bunnycdn.com");
case "br" /* SaoPaulo */:
return new URL("https://br.storage.bunnycdn.com");
case "jh" /* Johannesburg */:
return new URL("https://jh.storage.bunnycdn.com");
case "syd" /* Sydney */:
return new URL("https://syd.storage.bunnycdn.com");
default:
throw new Error("Invalid Storage Region");
}
}
// src/file.ts
var file_exports = {};
__export(file_exports, {
ZoneSchema: () => ZoneSchema,
createDirectory: () => createDirectory,
download: () => download,
get: () => get,
list: () => list,
remove: () => remove,
removeDirectory: () => removeDirectory,
upload: () => upload
});
import { z as z2 } from "zod";
// src/zone.ts
var zone_exports = {};
__export(zone_exports, {
addr: () => addr2,
connect_with_accesskey: () => connect_with_accesskey,
key: () => key,
name: () => name
});
function addr2(value) {
return new URL(`${addr(value.region)}${value.name}/`);
}
function name(value) {
return value.name;
}
function key(value) {
return ["AccessKey", value.accessKey];
}
function connect_with_accesskey(region, name2, accessKey) {
return {
_tag: "StorageZone",
region,
name: name2,
accessKey
};
}
// src/api.ts
import { z } from "zod";
var ReplicatedZonesStringSchema = z.string();
var ReplicatedZonesSchema = ReplicatedZonesStringSchema.transform((str) => {
const zones = str.split(",").map((zone) => zone.trim()).filter((x) => x != "");
return zones.map((zone) => ZoneSchema.parse(zone));
});
var StorageFileSchemaDescribe = z.object({
Guid: z.string(),
UserId: z.string(),
LastChanged: z.coerce.date(),
DateCreated: z.coerce.date(),
StorageZoneName: z.string(),
Path: z.string(),
ObjectName: z.string(),
Length: z.number(),
StorageZoneId: z.number(),
IsDirectory: z.boolean(),
ServerId: z.number(),
Checksum: z.nullable(z.string()),
ReplicatedZones: z.nullable(ReplicatedZonesSchema),
ContentType: z.string()
});
var StorageFileListing = z.array(StorageFileSchemaDescribe);
// src/file.ts
var ZoneSchema = z2.union([
z2.literal("SE"),
z2.literal("CZ"),
z2.literal("UK"),
z2.literal("ES"),
z2.literal("NY"),
z2.literal("WA"),
z2.literal("MI"),
z2.literal("LA"),
z2.literal("JH"),
z2.literal("HK"),
z2.literal("BR"),
z2.literal("SG"),
z2.literal("JP"),
z2.literal("SYD")
]);
async function get(storageZone, path) {
const url = addr2(storageZone);
url.pathname = `${url.pathname}${path}`;
const [auth_header, key2] = key(storageZone);
const response = await fetch(url, { method: "DESCRIBE", headers: { "Accept": "application/json", [auth_header]: key2 } });
if (!response.ok) {
throw statusCodeToException(storageZone, response.status, path);
}
const rawData = await response.json();
const processedData = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
...rawData,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
LastChanged: new Date(rawData.LastChanged),
// eslint-disable-next-line @typescript-eslint/no-explicit-any
DateCreated: new Date(rawData.DateCreated)
};
const result = StorageFileSchemaDescribe.parse(processedData);
return {
_tag: "StorageFile",
guid: result.Guid,
userId: result.UserId,
lastChanged: result.LastChanged,
dateCreated: result.DateCreated,
storageZoneName: result.StorageZoneName,
path: result.Path,
objectName: result.ObjectName,
length: result.Length,
storageZoneId: result.StorageZoneId,
isDirectory: result.IsDirectory,
serverId: result.ServerId,
checksum: result.Checksum,
replicatedZones: result.ReplicatedZones,
contentType: result.ContentType,
data: () => download(storageZone, path)
};
}
async function list(storageZone, path) {
const url = addr2(storageZone);
const directory_path = path.endsWith("/") ? path : `${path}/`;
url.pathname = `${url.pathname}${directory_path}`;
const [auth_header, key2] = key(storageZone);
const response = await fetch(url, { method: "GET", headers: { "Accept": "application/json", [auth_header]: key2 } });
if (!response.ok) {
throw statusCodeToException(storageZone, response.status, path);
}
const j = await response.json();
try {
StorageFileListing.parse(j);
} catch (e) {
console.error(e);
}
return StorageFileListing.parse(j).map((result) => ({
_tag: "StorageFile",
guid: result.Guid,
userId: result.UserId,
lastChanged: result.LastChanged,
dateCreated: result.DateCreated,
storageZoneName: result.StorageZoneName,
path: result.Path,
objectName: result.ObjectName,
length: result.Length,
storageZoneId: result.StorageZoneId,
isDirectory: result.IsDirectory,
serverId: result.ServerId,
checksum: result.Checksum,
replicatedZones: result.ReplicatedZones,
contentType: result.ContentType,
data: () => download(storageZone, result.Path)
}));
}
async function remove(storageZone, path) {
const url = addr2(storageZone);
url.pathname = `${url.pathname}${path}`;
const [auth_header, key2] = key(storageZone);
const response = await fetch(url, { method: "DELETE", headers: { [auth_header]: key2 } });
return response.ok;
}
async function createDirectory(storageZone, path) {
const url = addr2(storageZone);
const directory_path = path.endsWith("/") ? path : `${path}/`;
url.pathname = `${url.pathname}${directory_path}`;
const [auth_header, key2] = key(storageZone);
const response = await fetch(url, { method: "PUT", headers: { [auth_header]: key2 } });
return response.ok;
}
async function removeDirectory(storageZone, path) {
const url = addr2(storageZone);
const directory_path = path.endsWith("/") ? path : `${path}/`;
url.pathname = `${url.pathname}${directory_path}`;
const [auth_header, key2] = key(storageZone);
const response = await fetch(url, { method: "DELETE", headers: { [auth_header]: key2 } });
return response.ok;
}
async function upload(storageZone, path, stream, options) {
const url = addr2(storageZone);
url.pathname = `${url.pathname}${path}`;
const [auth_header, key2] = key(storageZone);
const headers = {
[auth_header]: key2,
"Content-Type": "application/octet-stream"
};
if (options?.contentType) headers["Override-Content-Type"] = options.contentType;
if (options?.sha256Checksum) headers["Checksum"] = options.sha256Checksum;
const response = await fetch(url, { method: "PUT", headers, body: stream, duplex: "half" });
if (!response.ok) {
throw statusCodeToException(storageZone, response.status, path);
}
return response.ok;
}
async function download(storageZone, path) {
const url = addr2(storageZone);
url.pathname = `${url.pathname}${path}`;
const [auth_header, key2] = key(storageZone);
const response = await fetch(url, { method: "GET", headers: { [auth_header]: key2 } });
if (!response.ok) {
throw statusCodeToException(storageZone, response.status, path);
}
const contentLength = response.headers.has("content-length") ? parseInt(response.headers.get("content-length")) : void 0;
if (!response.body) {
throw new Error("Response has no body");
}
const stream = response.body;
return { stream, response, length: contentLength };
}
function statusCodeToException(storageZone, status, path) {
switch (status) {
case 404:
return new Error(`File not found: ${path}`);
case 400:
return new Error("Unable to upload file. Either invalid path specified, either provided checksum invalid");
case 401:
return new Error(
`Unauthorized access to storage zone: ${name(storageZone)}`
);
default:
return new Error("An unknown error has occurred during the request.");
}
}
export {
file_exports as file,
regions_exports as regions,
zone_exports as zone
};