imgproxy
Version:
NodeJS client library to generate imgproxy urls
257 lines (249 loc) • 7.99 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
Imgproxy: () => Imgproxy,
WatermarkPosition: () => WatermarkPosition,
default: () => Imgproxy
});
module.exports = __toCommonJS(index_exports);
// src/utils.ts
var import_crypto = __toESM(require("crypto"));
var isRGBColor = (obj) => {
return typeof obj === "object" && "r" in obj && "g" in obj && "b" in obj;
};
var isFocusPoint = (obj) => {
return typeof obj === "object" && "x" in obj && "y" in obj;
};
var isOffsetGravity = (obj) => {
return typeof obj === "object" && "xOffset" in obj && "yOffset" in obj && "type" in obj;
};
var isSecureConfig = (config) => {
return "key" in config && "salt" in config;
};
var hexDecode = (hex) => Buffer.from(hex, "hex");
var encodeUrlChars = (url) => url.replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
var urlSafeEncode = (data) => {
if (Buffer.isBuffer(data)) {
return encodeUrlChars(data.toString("base64"));
}
return encodeUrlChars(Buffer.from(data, "utf-8").toString("base64"));
};
var sign = (key, salt, target, size = 32) => {
const hmac = import_crypto.default.createHmac("sha256", hexDecode(key));
hmac.update(hexDecode(salt));
hmac.update(target);
return urlSafeEncode(hmac.digest().slice(0, size));
};
// src/base-builder.ts
var BaseBuilder = class {
constructor(config) {
this.config = config;
this.config = config;
}
/**
* Generates a URL based on the set options.
*
* @param uri The uri of the image
* @param extension optional string to append as extension
*/
generateUrl(uri, extension) {
const options = this.serializeOptions();
const config = this.config;
const encode = config.encode !== false;
uri = encode ? urlSafeEncode(uri) : `plain/${uri}`;
uri = extension ? `${uri}${encode ? "." : "@"}${extension}` : uri;
uri = `/${options ? `${options}/` : ""}${uri}`;
const signature = isSecureConfig(config) ? sign(config.key, config.salt, uri, config.signatureSize || 32) : typeof config.insecure === "string" ? config.insecure : "insecure";
const url = new URL(`${signature}${uri}`, config.baseUrl);
return url.toString();
}
};
// src/builder.ts
var ImgproxyBuilder = class extends BaseBuilder {
options = {};
resize(type, width, height, enlarge) {
return this.setOption(
"rs",
[type, width, height, enlarge ? 1 : 0].join(":")
);
}
size(width, height, enlarge) {
return this.setOption("s", [width, height, enlarge ? 1 : 0].join(":"));
}
resizingType(type) {
return this.setOption("rs", type);
}
width(width) {
return this.setOption("w", `${width}`);
}
height(height) {
return this.setOption("h", `${height}`);
}
minWidth(width) {
return this.setOption("mw", `${width}`);
}
minHeight(height) {
return this.setOption("mh", `${height}`);
}
// allow for strings since javascript float precision sucks
dpr(dpr) {
if (dpr > 0) {
this.setOption("dpr", `${dpr}`);
}
return this;
}
enlarge(enlarge) {
return this.setOption("el", `${enlarge}`);
}
gravity(gravity) {
if (isFocusPoint(gravity)) {
return this.setOption("g", `fp:${gravity.x}:${gravity.y}`);
} else if (isOffsetGravity(gravity)) {
return this.setOption(
"g",
`${gravity.type}:${gravity.xOffset}:${gravity.yOffset}`
);
} else {
return this.setOption("g", gravity);
}
}
quality(quality) {
return this.setOption("q", `${quality}`);
}
background(color) {
if (isRGBColor(color)) {
return this.setOption("bg", `${color.r}:${color.g}:${color.b}`);
} else {
return this.setOption("bg", color);
}
}
blur(sigma) {
return this.setOption("bl", `${sigma}`);
}
sharpen(sigma) {
return this.setOption("sh", `${sigma}`);
}
watermark(opacity, position, offset, scale) {
return this.setOption(
"wm",
`${opacity}:${position}:${offset ? `${offset.x}:${offset.y}` : ""}:${scale}`
);
}
preset(...presets) {
return this.setOption("pr", presets.join(":"));
}
cacheBuster(buster) {
return this.setOption("cb", buster);
}
format(extension) {
return this.setOption("f", extension);
}
maxBytes(bytes) {
return this.setOption("mb", `${bytes}`);
}
expires(timestamp) {
return this.setOption("exp", `${timestamp}`);
}
crop(width, height, gravity) {
let crop = `${width}:${height}`;
if (gravity) {
if (isFocusPoint(gravity)) {
crop = `${crop}:fp:${gravity.x}:${gravity.y}`;
} else if (isOffsetGravity(gravity)) {
crop = `${crop}:${gravity.type}:${gravity.xOffset}:${gravity.yOffset}`;
} else {
crop = `${crop}:${gravity}`;
}
}
return this.setOption("c", crop);
}
setOption(option, value) {
this.options[option] = value;
return this;
}
clearOption(option) {
this.options[option] = void 0;
return this;
}
serializeOptions() {
return Object.keys(this.options).filter((option) => !!this.options[option]).map((option) => `${option}:${this.options[option]}`).join("/");
}
};
// src/preset-only-builder.ts
var ImgproxyPresetOnlyBuilder = class extends BaseBuilder {
presets = [];
preset(...presets) {
this.presets = this.presets.concat(presets);
return this;
}
serializeOptions() {
return this.presets.join(":");
}
};
// src/types.ts
var WatermarkPosition = /* @__PURE__ */ ((WatermarkPosition2) => {
WatermarkPosition2["center"] = "ce";
WatermarkPosition2["north"] = "no";
WatermarkPosition2["south"] = "so";
WatermarkPosition2["east"] = "ea";
WatermarkPosition2["west"] = "we";
WatermarkPosition2["north_east"] = "noea";
WatermarkPosition2["north_west"] = "nowe";
WatermarkPosition2["south_east"] = "soea";
WatermarkPosition2["south_west"] = "sowe";
WatermarkPosition2["replicate"] = "re";
return WatermarkPosition2;
})(WatermarkPosition || {});
// src/index.ts
var Imgproxy = class {
config;
constructor(config) {
if (isSecureConfig(config) && typeof config.signatureSize !== "undefined") {
if (config.signatureSize < 1 || config.signatureSize > 32) {
throw new Error(
"`signatureSize` must be greater than or equal to 1, and less than or equal to 32"
);
}
}
this.config = config;
}
builder() {
return new ImgproxyBuilder(this.config);
}
presetOnlyBuilder() {
return new ImgproxyPresetOnlyBuilder(this.config);
}
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
Imgproxy,
WatermarkPosition
});