@netlify/content-engine
Version:
90 lines • 4.1 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ImageCDNUrlKeys = void 0;
exports.generateFileUrl = generateFileUrl;
exports.generateImageUrl = generateImageUrl;
const crypto_1 = __importDefault(require("crypto"));
const path_1 = require("path");
const url_1 = require("url");
const create_content_digest_1 = require("../../../core-utils/create-content-digest");
const types_1 = require("../types");
// this is an arbitrary origin that we use #branding so we can construct a full url for the URL constructor
const ORIGIN = `https://gatsbyjs.com`;
var ImageCDNUrlKeys;
(function (ImageCDNUrlKeys) {
ImageCDNUrlKeys["URL"] = "u";
ImageCDNUrlKeys["ENCRYPTED_URL"] = "eu";
ImageCDNUrlKeys["ARGS"] = "a";
ImageCDNUrlKeys["CONTENT_DIGEST"] = "cd";
})(ImageCDNUrlKeys || (exports.ImageCDNUrlKeys = ImageCDNUrlKeys = {}));
function encryptImageCdnUrl(secretKey, iv, urlToEncrypt) {
const randomPadding = crypto_1.default
.randomBytes(crypto_1.default.randomInt(32, 64))
.toString(`hex`);
const toEncrypt = `${randomPadding}:${urlToEncrypt}`;
const cipher = crypto_1.default.createCipheriv(`aes-256-ctr`, Buffer.from(secretKey, `hex`), Buffer.from(iv, `hex`));
const encrypted = cipher.update(toEncrypt);
const finalBuffer = Buffer.concat([encrypted, cipher.final()]);
return finalBuffer.toString(`hex`);
}
function appendUrlParamToSearchParams(searchParams, url) {
const key = process.env.IMAGE_CDN_ENCRYPTION_SECRET_KEY || ``;
const iv = process.env.IMAGE_CDN_ENCRYPTION_IV || ``;
const shouldEncrypt = !!(iv && key);
const paramName = shouldEncrypt
? ImageCDNUrlKeys.ENCRYPTED_URL
: ImageCDNUrlKeys.URL;
const finalUrl = shouldEncrypt ? encryptImageCdnUrl(key, iv, url) : url;
searchParams.append(paramName, finalUrl);
}
function generateFileUrl({ url, filename, }, store) {
const fileExt = (0, path_1.extname)(filename);
const filenameWithoutExt = (0, path_1.basename)(filename, fileExt);
const parsedURL = new url_1.URL(`${ORIGIN}${generatePublicUrl({
url,
}, store)}/${filenameWithoutExt}${fileExt}`);
appendUrlParamToSearchParams(parsedURL.searchParams, url);
return `${parsedURL.pathname}${parsedURL.search}`;
}
function generateImageUrl(source, imageArgs, store) {
const filenameWithoutExt = (0, path_1.basename)(source.filename, (0, path_1.extname)(source.filename));
const queryStr = generateImageArgs(imageArgs);
const parsedURL = new url_1.URL(`${ORIGIN}${generatePublicUrl(source, store)}/${(0, create_content_digest_1.createContentDigest)(queryStr)}/${filenameWithoutExt}.${imageArgs.format}`);
appendUrlParamToSearchParams(parsedURL.searchParams, source.url);
parsedURL.searchParams.append(ImageCDNUrlKeys.ARGS, queryStr);
parsedURL.searchParams.append(ImageCDNUrlKeys.CONTENT_DIGEST, source.internal.contentDigest);
return `${parsedURL.pathname}${parsedURL.search}`;
}
function generatePublicUrl({ url, mimeType, }, store) {
const state = store?.getState();
// @ts-ignore
const pathPrefix = state?.program?.prefixPaths
? // @ts-ignore
state?.config?.pathPrefix
: ``;
const remoteUrl = (0, create_content_digest_1.createContentDigest)(url);
let publicUrl = pathPrefix +
(mimeType && (0, types_1.isImage)({ mimeType }) ? `/_gatsby/image/` : `/_gatsby/file/`);
publicUrl += remoteUrl;
return publicUrl;
}
function generateImageArgs({ width, height, format, cropFocus, quality, }) {
const args = [];
if (width) {
args.push(`w=${width}`);
}
if (height) {
args.push(`h=${height}`);
}
if (cropFocus) {
args.push(`fit=crop`);
args.push(`crop=${Array.isArray(cropFocus) ? cropFocus.join(`,`) : cropFocus}`);
}
args.push(`fm=${format}`);
args.push(`q=${quality}`);
return args.join(`&`);
}
//# sourceMappingURL=url-generator.js.map
;