@bunny.net/storage-sdk
Version:
299 lines (292 loc) • 10.4 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name2 in all)
__defProp(target, name2, { get: all[name2], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key2 of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key2) && key2 !== except)
__defProp(to, key2, { get: () => from[key2], enumerable: !(desc = __getOwnPropDesc(from, key2)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/lib.ts
var lib_exports = {};
__export(lib_exports, {
file: () => file_exports,
regions: () => regions_exports,
zone: () => zone_exports
});
module.exports = __toCommonJS(lib_exports);
// 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
});
var import_zod2 = require("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
var import_zod = require("zod");
var ReplicatedZonesStringSchema = import_zod.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 = import_zod.z.object({
Guid: import_zod.z.string(),
UserId: import_zod.z.string(),
LastChanged: import_zod.z.coerce.date(),
DateCreated: import_zod.z.coerce.date(),
StorageZoneName: import_zod.z.string(),
Path: import_zod.z.string(),
ObjectName: import_zod.z.string(),
Length: import_zod.z.number(),
StorageZoneId: import_zod.z.number(),
IsDirectory: import_zod.z.boolean(),
ServerId: import_zod.z.number(),
Checksum: import_zod.z.nullable(import_zod.z.string()),
ReplicatedZones: import_zod.z.nullable(ReplicatedZonesSchema),
ContentType: import_zod.z.string()
});
var StorageFileListing = import_zod.z.array(StorageFileSchemaDescribe);
// src/file.ts
var ZoneSchema = import_zod2.z.union([
import_zod2.z.literal("SE"),
import_zod2.z.literal("CZ"),
import_zod2.z.literal("UK"),
import_zod2.z.literal("ES"),
import_zod2.z.literal("NY"),
import_zod2.z.literal("WA"),
import_zod2.z.literal("MI"),
import_zod2.z.literal("LA"),
import_zod2.z.literal("JH"),
import_zod2.z.literal("HK"),
import_zod2.z.literal("BR"),
import_zod2.z.literal("SG"),
import_zod2.z.literal("JP"),
import_zod2.z.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.");
}
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
file,
regions,
zone
});