Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

caravaggio

Package Overview
Dependencies
Maintainers
1
Versions
53
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

caravaggio - npm Package Compare versions

Comparing version 2.0.2 to 2.1.0

codeclimate.json

5

CHANGELOG.md
# Changelog
## 2.1.0
- 😍 Errors are now amazing. They can be shown as text, json, html and also contain link to the relevant documentation
- ✨ Support gzip/deflate compression
## 2.0.2

@@ -4,0 +9,0 @@

15

config/default.js

@@ -126,4 +126,17 @@ /**

},
compress: true,
/**
* Let you decide how to show errors.
* It can be 'html', 'json' and 'plain'
* Default to 'html'
*/
errors: 'json',
/**
* Compress the response through deflate/gzip
* The requester must add `Accept-Encoding` header otherwise this option is ignored.
* By default is false because usually this behavior is delegated to CDNs
*/
compress: false,
};

@@ -7,3 +7,4 @@ module.exports = {

defaultTransformations: [],
errors: 'plain',
};

2

package.json
{
"name": "caravaggio",
"version": "2.0.2",
"version": "2.1.0",
"description": "A blazing fast image processor service",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -51,3 +51,3 @@ [![caravaggio logo](https://res.cloudinary.com/ramiel/image/upload/c_scale,r_0,w_100/v1517679412/caravaggio-logo_xdwpin.jpg)](https://res.cloudinary.com/ramiel/image/upload/c_scale,r_0,w_100/v1517679412/caravaggio-logo_xdwpin.jpg)

Please, refer to the [documentation](https://ramiel.gitlab.io/caravaggio/docs/docs.html) to know what are the available operations
Please, refer to the [documentation](https://ramiel.gitlab.io/caravaggio/docs/docs.html) to know what are the available operations.

@@ -54,0 +54,0 @@

@@ -0,9 +1,11 @@

const BadRequestError = require('./errors/BadRequestError');
/**
* Create a set of chainable validators on values
*/
const numberValidators = (parsed, errorMessage) => {
const numberValidators = (parsed, errorMessage, docUri) => {
const valuedValidators = {
min: (min) => {
if (parsed < min) {
throw new Error(errorMessage);
throw new BadRequestError(errorMessage, docUri);
}

@@ -15,3 +17,3 @@ return valuedValidators;

if (parsed > max) {
throw new Error(errorMessage);
throw new BadRequestError(errorMessage, docUri);
}

@@ -23,3 +25,3 @@ return valuedValidators;

if (parsed % divisor !== 0) {
throw new Error(errorMessage);
throw new BadRequestError(errorMessage, docUri);
}

@@ -34,7 +36,7 @@ return valuedValidators;

const stringValidators = (parsed, errorMessage) => {
const stringValidators = (parsed, errorMessage, docUri) => {
const valueValidators = {
enum: (accept = []) => {
if (accept.indexOf(parsed) === -1) {
throw new Error(errorMessage);
throw new BadRequestError(errorMessage, docUri);
}

@@ -45,3 +47,3 @@ return valueValidators;

if (!regex.test(parsed)) {
throw new Error(errorMessage);
throw new BadRequestError(errorMessage, docUri);
}

@@ -55,7 +57,7 @@ return valueValidators;

const boolValidators = (parsed, errorMessage) => {
const boolValidators = (parsed, errorMessage, docUri) => {
const valueValidators = {
isTrue: () => {
if (parsed !== true) {
throw new Error(errorMessage);
throw new BadRequestError(errorMessage, docUri);
}

@@ -66,3 +68,3 @@ return valueValidators;

if (parsed !== false) {
throw new Error(errorMessage);
throw new BadRequestError(errorMessage, docUri);
}

@@ -76,3 +78,3 @@ return valueValidators;

module.exports = (value, errorMessage = 'The value is in the wrong format') => {
module.exports = (value, errorMessage = 'The value is in the wrong format', docUri = 'docs.html') => {
/**

@@ -85,5 +87,5 @@ * Coherce a string to a typed value and return a set of validators on that value

if (Number.isNaN(res)) {
throw new Error(errorMessage);
throw new BadRequestError(errorMessage, docUri);
}
return numberValidators(res, errorMessage);
return numberValidators(res, errorMessage, docUri);
},

@@ -94,5 +96,5 @@

if (Number.isNaN(res)) {
throw new Error(errorMessage);
throw new BadRequestError(errorMessage, docUri);
}
return numberValidators(res, errorMessage);
return numberValidators(res, errorMessage, docUri);
},

@@ -103,8 +105,8 @@

if (Number.isNaN(res)) {
throw new Error(errorMessage);
throw new BadRequestError(errorMessage, docUri);
}
return numberValidators(res, errorMessage);
return numberValidators(res, errorMessage, docUri);
},
toString: () => stringValidators(`${value}`, errorMessage),
toString: () => stringValidators(`${value}`, errorMessage, docUri),

@@ -115,3 +117,3 @@ toBool: () => {

.value();
return boolValidators(res === 'true', errorMessage);
return boolValidators(res === 'true', errorMessage, docUri);
},

@@ -118,0 +120,0 @@ };

const { send } = require('micro');
const { buildDocumentationLink } = require('../utils');
module.exports = fn => async (req, res) => {
try {
return await fn(req, res);
} catch (err) {
return send(res, err.statusCode || 500, err.message || 'An unknown error happened');
const UNKNOWN_ERROR_MESSAGE = 'An unknown error happened :(';
const buildHtmlError = err => `
<!doctype html>
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>Error - Caravaggio</title>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<style>
body {
background-color: #4ABDAC;
margin: 0;
height: 100vh;
}
/*Typography*/
h1 { font-family: 'Droid sans', sans; font-weight: 400; font-style: italic; line-height: 44px;}
p { font-family: 'Droid Sans', sans-serif; font-size: 15px; font-weight: 400; line-height: 24px; margin: 0 0 14px; }
a { text-decoration: none; border-bottom: 1px solid #4c3a07; color: inherit; }
a:hover { color: #fff; background: #4ABDAC; }
/*/Typography*/
#container {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
#error {
display:flex;
flex-direction: horizontal;
justify-content: flex-start;
align-items:center;
background-color: #FF7964;
min-width: 30%;
padding: 1em;
margin: 0 auto;
border-radius: 5px;
}
#logo {
margin-right: 1em;
}
</style>
</head>
<body style="background-color: #4ABDAC;">
<div id="container">
<div id="error">
<div id="logo">
<img src="//res.cloudinary.com/ramiel/image/upload/v1519252402/caravaggio-logo-error_jvq4fg.png" alt="caravaggio distorted logo"/>
</div>
<div>
<h1>Error</h1>
<p>${err.message || UNKNOWN_ERROR_MESSAGE}
${err.docUri ? `<br />See <a target="_blank" href="${buildDocumentationLink(err.docUri)}">${buildDocumentationLink(err.docUri)}</a>` : ''}</p>
</div>
</div>
</div>
</body>
</html>
`;
const buildJsonError = err => ({
statusCode: err.statusCode,
error: err.message || UNKNOWN_ERROR_MESSAGE,
see: buildDocumentationLink(err.docUri),
});
const buildErrorText = err => `${err.message || UNKNOWN_ERROR_MESSAGE}${err.docUri ? `
See ${buildDocumentationLink(err.docUri)}` : ''}`;
module.exports = (config) => {
let build;
switch (config.get('errors')) {
case 'html':
build = buildHtmlError;
break;
case 'json':
build = buildJsonError;
break;
case 'plain':
default:
build = buildErrorText;
break;
}
return fn => async (req, res) => {
try {
return await fn(req, res);
} catch (err) {
return send(res, err.statusCode || 500, build(err));
}
};
};
const cohercer = require('../cohercer');
const { buildDocumentationLink } = require('../utils');
module.exports = (value) => {
const v = cohercer(value, `Blur must be a value between 0.3 and 1000.
See ${buildDocumentationLink('blur.html')}
`)
const v = cohercer(value, 'Blur must be a value between 0.3 and 1000.', 'blur.html')
.toFloat()

@@ -9,0 +6,0 @@ .min(0.3)

const cohercer = require('../cohercer');
const { buildDocumentationLink, isPercentage, percentageToPixel } = require('../utils');
const { isPercentage, percentageToPixel } = require('../utils');
module.exports = (x, y, w, h) => {
const left = cohercer(x, `Extract: the x parameter in in the wrong format.
See ${buildDocumentationLink('extract.html')}
`)
const left = cohercer(x, 'Extract: the x parameter in in the wrong format.', 'extract.html')
.toNumber()
.value();
const top = cohercer(y, `Extract: the y parameter in in the wrong format.
See ${buildDocumentationLink('extract.html')}
`)
const top = cohercer(y, 'Extract: the y parameter in in the wrong format.', 'extract.html')
.toNumber()
.value();
const width = cohercer(w, `Extract: the width parameter in in the wrong format.
See ${buildDocumentationLink('extract.html')}
`)
const width = cohercer(w, 'Extract: the width parameter in in the wrong format.', 'extract.html')
.toNumber()
.value();
const height = cohercer(h, `Extract: the width parameter in in the wrong format.
See ${buildDocumentationLink('extract.html')}
`)
const height = cohercer(h, 'Extract: the width parameter in in the wrong format.', 'extract.html')
.toNumber()

@@ -27,0 +19,0 @@ .value();

const cohercer = require('../cohercer');
const { buildDocumentationLink } = require('../utils');
module.exports = (value) => {
const operation = value && cohercer(value, `Flip accepts "x" or "y" as values.
See ${buildDocumentationLink('flip.html')}
`)
const operation = value && cohercer(value, 'Flip accepts "x" or "y" as values.', 'flip.html')
.toString()

@@ -9,0 +6,0 @@ .enum(['x', 'y'])

@@ -1,4 +0,3 @@

const { buildDocumentationLink } = require('../utils');
const UnknownOperationError = require('../errors/UnknownOperationError');
const blurNormalizer = require('./blur');
const cropNormalizer = require('./crop');
const flipNormalizer = require('./flip');

@@ -14,3 +13,2 @@ const oNormalizer = require('./o');

blur: blurNormalizer,
crop: cropNormalizer,
flip: flipNormalizer,

@@ -27,12 +25,2 @@ o: oNormalizer,

class UnknownOperation extends Error {
constructor(operation) {
super(`Unknown operation "${operation}"
See documentation at ${buildDocumentationLink('')}
`);
this.statusCode = 400;
}
}
module.exports = (config) => {

@@ -61,8 +49,5 @@ const defaultTransformations = config.get('defaultTransformations');

if (!normalizers[name]) {
throw new UnknownOperation(name);
throw new UnknownOperationError(name);
}
const normalized = normalizers[name](...params);
// const normalized = normalizers[name]
// ? normalizers[name](...params)
// : {};
return {

@@ -69,0 +54,0 @@ ...acc,

const cohercer = require('../cohercer');
const { buildDocumentationLink } = require('../utils');
module.exports = (value) => {
const format = cohercer(value, `Accepted values are "original", jpg", "jpeg", "png", "webp", "tiff".
See ${buildDocumentationLink('output.html')}
`)
const format = cohercer(value, 'Accepted values are "original", jpg", "jpeg", "png", "webp", "tiff".', 'output.html')
.toString()

@@ -9,0 +6,0 @@ .enum(['original', 'jpg', 'jpeg', 'png', 'webp', 'tiff'])

const cohercer = require('../cohercer');
const { buildDocumentationLink } = require('../utils');

@@ -10,5 +9,3 @@ const getOutputType = async pipeline => (pipeline.getOptions().o !== 'original'

module.exports = (value) => {
const progressive = cohercer(value, `Progressive value is not valid.
See ${buildDocumentationLink('progressive.html')}
`)
const progressive = cohercer(value, 'Progressive value is not valid.', 'progressive.html')
.toBool()

@@ -15,0 +12,0 @@ .value();

const cohercer = require('../cohercer');
const { buildDocumentationLink } = require('../utils');

@@ -37,5 +36,3 @@ const normalizeQ = value => Math.round((value * 80) / 100);

module.exports = (value) => {
const v = cohercer(value, `Quality must be a value between 1 and 100.
See ${buildDocumentationLink('quality.html')}
`)
const v = cohercer(value, 'Quality must be a value between 1 and 100.', 'quality.html')
.toInt()

@@ -42,0 +39,0 @@ .min(1)

@@ -1,2 +0,1 @@

const { buildDocumentationLink } = require('../../utils');
const cohercer = require('../../cohercer');

@@ -22,6 +21,4 @@

getColorFromParameter: (param, errorMessage) => {
const value = cohercer(param, errorMessage || `Invalid color paramter "${param}".
See ${buildDocumentationLink('resize.html#colors')}
`)
getColorFromParameter: (param, errorMessage = `Invalid color paramter "${param}".`, docUri = 'resize.html#colors') => {
const value = cohercer(param, errorMessage, docUri)
.toString()

@@ -28,0 +25,0 @@ .match(COLOR_REGEX)

@@ -1,2 +0,1 @@

const { buildDocumentationLink } = require('../../utils');
const cohercer = require('../../cohercer');

@@ -32,7 +31,5 @@

gravity,
{ acceptAuto, error } = { acceptAuto: false, error: null },
{ acceptAuto, error } = { acceptAuto: false, error: `Invalid gravity parameter "${gravity}".` },
) => {
let value = gravity && cohercer(gravity, error || `Invalid gravity parameter "${gravity}".
See ${buildDocumentationLink('resize.html#gravity')}
`)
let value = gravity && cohercer(gravity, error, 'resize.html#gravity')
.toString()

@@ -39,0 +36,0 @@ .match(acceptAuto ? EXTENDED_GRAVITY_PARAM_REGEX : GRAVITY_PARAM_REGEX)

const cohercer = require('../../cohercer');
const { buildDocumentationLink } = require('../../utils');
const scale = require('./scale');

@@ -58,5 +57,3 @@ const fit = require('./fit');

/* eslint-disable no-param-reassign */
size = cohercer(size, `Resize: the size parameter in in the wrong format.
See ${buildDocumentationLink('resize.html#sizes')}
`)
size = cohercer(size, 'Resize: the size parameter is in the wrong format.', 'resize.html#sizes')
.toString()

@@ -66,5 +63,3 @@ .match(RESIZE_PATTERN)

mode = cohercer(mode, `Resize, the mode ${mode} is not valid.
See ${buildDocumentationLink('resize.html')}
`)
mode = cohercer(mode, `Resize, the mode ${mode} is not valid.`, 'resize.html')
.toString()

@@ -71,0 +66,0 @@ .enum(AVAILABLE_MODES)

const cohercer = require('../cohercer');
const { buildDocumentationLink } = require('../utils');
module.exports = (value) => {
const angle = cohercer(value, `Angle must be multiple of 90°.
See ${buildDocumentationLink('rotate.html')}
`)
const angle = cohercer(value, 'Angle must be multiple of 90°.', 'rotate.html')
.toInt()

@@ -9,0 +6,0 @@ .multipleOf(90)

@@ -17,3 +17,2 @@ const normalizerFactory = require('./normalizers');

} catch (e) {
e.statusCode = 400;
throw e;

@@ -20,0 +19,0 @@ }

@@ -14,3 +14,3 @@ const { router, get } = require('microrouter');

compose(
errorHandler,
errorHandler(config),
domainWhitelist(whitelist),

@@ -17,0 +17,0 @@ )(indexRoute(config)(Cache(persistor))),

const { URL } = require('url');
const { createError } = require('micro');
const logger = require('../logger');
const parser = require('../parser');
const pipeline = require('../pipelines');
const { sendImage } = require('../sender');
const sender = require('../sender');
module.exports = (config) => {
const { parseOptions } = parser(config);
const { sendImage } = sender(config);

@@ -18,3 +18,3 @@ return cache => async (req, res) => {

logger.debug(`Cache hit for resource ${url.toString()} with options ${options.rawNormalizedOptions}`);
await sendImage(resource, options, res);
await sendImage(resource, options, req, res);
return;

@@ -26,8 +26,8 @@ }

const createdResource = await cache.set(url, options, imageBuffer);
await sendImage(createdResource, options, res);
await sendImage(createdResource, options, req, res);
} catch (e) {
logger.error(e);
throw createError(e.statusCode, e.message);
throw e;
}
};
};
const redirect = require('micro-redirect');
const { send } = require('micro');
const path = require('path');
const config = require('config');
const sharp = require('sharp');
const compressor = require('./compressor');
const browserCache = config.get('browserCache');
const guessTypeByExtension = config.get('guessTypeByExtension');
module.exports = (config) => {
const browserCache = config.get('browserCache');
const guessTypeByExtension = config.get('guessTypeByExtension');
const sendFactory = compressor(config);
const getTypeByUrl = resourceName => path.extname(resourceName)
.replace('.', '')
.replace('jpg', 'jpeg');
const getTypeByUrl = resourceName => path.extname(resourceName)
.replace('.', '')
.replace('jpg', 'jpeg');
const getTypeByMetadata = async resource => sharp(resource.buffer)
.metadata()
.then(({ format }) => format);
const getTypeByMetadata = async resource => sharp(resource.buffer)
.metadata()
.then(({ format }) => format);
const getTypeByResource = async (resource) => {
if (!guessTypeByExtension) {
return getTypeByMetadata(resource);
}
const extension = getTypeByUrl(resource.name);
if (!extension) {
return getTypeByMetadata(resource);
}
return extension;
};
const getTypeByResource = async (resource) => {
if (!guessTypeByExtension) {
return getTypeByMetadata(resource);
}
const extension = getTypeByUrl(resource.name);
if (!extension) {
return getTypeByMetadata(resource);
}
return extension;
};
const getMimeType = async (resource, options) => {
const type = options.o === 'original'
? await getTypeByResource(resource)
: options.o;
return `image/${type}`;
};
const getMimeType = async (resource, options) => {
const type = options.o === 'original'
? await getTypeByResource(resource)
: options.o;
return `image/${type}`;
};
const getCacheControlHeader = () => browserCache && `max-age=${browserCache.maxAge}`;
const getCacheControlHeader = () => browserCache && `max-age=${browserCache.maxAge}`;
module.exports = {
sendImage: async (resource, options, res) => {
switch (resource.type) {
case 'buffer': {
const cacheHeader = getCacheControlHeader();
if (cacheHeader) {
res.setHeader('cache-control', cacheHeader);
return {
sendImage: async (resource, options, req, res) => {
const send = sendFactory(req);
switch (resource.type) {
case 'buffer': {
const cacheHeader = getCacheControlHeader();
if (cacheHeader) {
res.setHeader('cache-control', cacheHeader);
}
res.setHeader('Content-Type', await getMimeType(resource, options));
res.setHeader('Content-Length', resource.buffer.length);
return send(res, 200, resource.buffer);
}
res.setHeader('Content-Type', await getMimeType(resource, options));
res.setHeader('Content-Length', resource.buffer.length);
return send(res, 200, resource.buffer);
case 'location':
return redirect(res, 301, resource.location);
default:
throw new Error(`Invalid type of resource ${resource.type}`);
}
case 'location':
return redirect(res, 301, resource.location);
default:
throw new Error(`Invalid type of resource ${resource.type}`);
}
},
},
};
};

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc