Socket
Socket
Sign inDemoInstall

@pollyjs/core

Package Overview
Dependencies
Maintainers
2
Versions
47
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@pollyjs/core - npm Package Compare versions

Comparing version 1.2.0 to 1.3.0

src/utils/merge-configs.js

20

CHANGELOG.md

@@ -6,2 +6,22 @@ # Change Log

# [1.3.0](https://github.com/netflix/pollyjs/tree/master/packages/@pollyjs/core/compare/v1.2.0...v1.3.0) (2018-11-28)
### Bug Fixes
* Support URL objects ([#139](https://github.com/netflix/pollyjs/tree/master/packages/[@pollyjs](https://github.com/pollyjs)/core/issues/139)) ([cf0d755](https://github.com/netflix/pollyjs/tree/master/packages/@pollyjs/core/commit/cf0d755))
* **core:** Handle trailing slashes when generating route names ([#142](https://github.com/netflix/pollyjs/tree/master/packages/[@pollyjs](https://github.com/pollyjs)/core/issues/142)) ([19147f7](https://github.com/netflix/pollyjs/tree/master/packages/@pollyjs/core/commit/19147f7))
* **core:** Ignore `context` options from being deep merged ([#144](https://github.com/netflix/pollyjs/tree/master/packages/[@pollyjs](https://github.com/pollyjs)/core/issues/144)) ([2123d83](https://github.com/netflix/pollyjs/tree/master/packages/@pollyjs/core/commit/2123d83))
* **core:** Support multiple handlers for same paths ([#141](https://github.com/netflix/pollyjs/tree/master/packages/[@pollyjs](https://github.com/pollyjs)/core/issues/141)) ([79e04b8](https://github.com/netflix/pollyjs/tree/master/packages/@pollyjs/core/commit/79e04b8))
### Features
* **core:** Support custom functions in matchRequestsBy config options ([#138](https://github.com/netflix/pollyjs/tree/master/packages/[@pollyjs](https://github.com/pollyjs)/core/issues/138)) ([626a84c](https://github.com/netflix/pollyjs/tree/master/packages/@pollyjs/core/commit/626a84c))
* Add an onIdentifyRequest hook to allow adapter level serialization ([#140](https://github.com/netflix/pollyjs/tree/master/packages/[@pollyjs](https://github.com/pollyjs)/core/issues/140)) ([548002c](https://github.com/netflix/pollyjs/tree/master/packages/@pollyjs/core/commit/548002c))
<a name="1.2.0"></a>

@@ -8,0 +28,0 @@ # 1.2.0 (2018-09-16)

24

package.json
{
"name": "@pollyjs/core",
"version": "1.2.0",
"version": "1.3.0",
"description": "Record, replay, and stub HTTP Interactions",

@@ -20,4 +20,2 @@ "main": "dist/cjs/pollyjs-core.js",

"watch": "yarn rollup -w",
"format": "prettier --config ../../../.prettier.js --write **/*.js",
"lint": "eslint ./*.js src tests",
"prepublishOnly": "npm-run-all clean --parallel rollup rollup:prod"

@@ -50,3 +48,3 @@ },

"dependencies": {
"@pollyjs/utils": "^1.2.0",
"@pollyjs/utils": "^1.3.0",
"@sindresorhus/fnv1a": "^1.0.0",

@@ -56,17 +54,15 @@ "blueimp-md5": "^2.10.0",

"is-absolute-url": "^2.1.0",
"lodash-es": "^4.17.10",
"merge-options": "^1.0.1",
"lodash-es": "^4.17.11",
"route-recognizer": "^0.3.4",
"slugify": "^1.3.1"
"slugify": "^1.3.3"
},
"devDependencies": {
"@pollyjs/adapter": "^1.2.0",
"@pollyjs/adapter-fetch": "^1.2.0",
"@pollyjs/persister": "^1.2.0",
"eslint": "^4.18.1",
"@pollyjs/adapter": "^1.3.0",
"@pollyjs/adapter-fetch": "^1.3.0",
"@pollyjs/persister": "^1.3.0",
"npm-run-all": "^4.1.3",
"prettier": "^1.14.2",
"rimraf": "^2.6.2",
"rollup": "^0.65.2"
}
"rollup": "^0.67.0"
},
"gitHead": "222c38c81155b4f737e9dfcfe1f61a985465b812"
}

@@ -12,2 +12,4 @@ <p align="center">

> Interested in contributing or just seeing Polly in action? Head over to [CONTRIBUTING.md](CONTRIBUTING.md) to learn how to spin up the project!
## Why Polly?

@@ -180,2 +182,19 @@

## Credits
_In alphabetical order:_
- [Jason Mitchell](https://twitter.com/_jasonmit) - Creator / Maintainer
- [Offir Golan](https://twitter.com/offirgolan) - Creator / Maintainer
- [Sophinie Som](https://twitter.com/s0phinie) - Branding / Logo
## We're hiring!
Join the Netflix Studio & Content Engineering teams to help us build projects like this!
Open Roles:
- [Senior UI Engineer - Production Visibility Engineering](https://jobs.netflix.com/jobs/868295)
- [Senior UI Engineer - Production Workflows Engineering](https://jobs.netflix.com/jobs/868224)
## License

@@ -182,0 +201,0 @@

@@ -1,4 +0,5 @@

import HTTPHeaders from '../utils/http-headers';
import stringify from 'fast-json-stable-stringify';
import HTTPHeaders from '../utils/http-headers';
const { freeze } = Object;

@@ -5,0 +6,0 @@ const { parse } = JSON;

import md5 from 'blueimp-md5';
import stringify from 'fast-json-stable-stringify';
import mergeOptions from 'merge-options';
import PollyResponse from './response';
import isAbsoluteUrl from 'is-absolute-url';
import { URL, assert, timestamp } from '@pollyjs/utils';
import NormalizeRequest from '../utils/normalize-request';
import parseUrl from '../utils/parse-url';
import serializeRequestBody from '../utils/serialize-request-body';
import guidForRecording from '../utils/guid-for-recording';
import mergeConfigs from '../utils/merge-configs';
import defer from '../utils/deferred-promise';
import isAbsoluteUrl from 'is-absolute-url';
import HTTPBase from './http-base';
import { URL, assert, timestamp } from '@pollyjs/utils';
import {

@@ -18,8 +16,15 @@ validateRecordingName,

import HTTPBase from './http-base';
import PollyResponse from './response';
import EventEmitter from './event-emitter';
const { keys, freeze } = Object;
const PARSED_URL = Symbol();
const ROUTE = Symbol();
const POLLY = Symbol();
const PARSED_URL = Symbol();
const EVENT_EMITTER = Symbol();
const SUPPORTED_EVENTS = ['identify'];
export default class PollyRequest extends HTTPBase {

@@ -29,4 +34,7 @@ constructor(polly, request) {

assert('Url is required.', typeof request.url === 'string');
assert('Method is required.', typeof request.method === 'string');
assert('Url is required.', request.url);
assert(
'Method is required.',
request.method && typeof request.method === 'string'
);

@@ -43,2 +51,3 @@ this.didRespond = false;

this[POLLY] = polly;
this[EVENT_EMITTER] = new EventEmitter({ eventNames: SUPPORTED_EVENTS });

@@ -72,3 +81,5 @@ /*

set url(value) {
this[PARSED_URL] = parseUrl(value, true);
// Make sure to coerce the value into a string as the passed value could be
// a WHATWG's URL object.
this[PARSED_URL] = parseUrl(`${value}`, true);
}

@@ -126,2 +137,20 @@

on(eventName, listener) {
this[EVENT_EMITTER].on(eventName, listener);
return this;
}
once(eventName, listener) {
this[EVENT_EMITTER].once(eventName, listener);
return this;
}
off(eventName, listener) {
this[EVENT_EMITTER].off(eventName, listener);
return this;
}
async setup() {

@@ -135,7 +164,4 @@ // Trigger the `request` event

// Serialize the body which handles FormData + Blobs/Files
this.serializedBody = await this.serializeBody();
// Setup this request's identifiers, id, and order
this._identify();
await this._identify();

@@ -179,6 +205,2 @@ // Timestamp the request

async serializeBody() {
return serializeRequestBody(this.body);
}
_overrideRecordingName(recordingName) {

@@ -192,3 +214,3 @@ validateRecordingName(recordingName);

validateRequestConfig(config);
this.config = mergeOptions(this[POLLY].config, this.config || {}, config);
this.config = mergeConfigs(this[POLLY].config, this.config || {}, config);
}

@@ -204,13 +226,14 @@

_identify() {
async _identify() {
const polly = this[POLLY];
const { _requests: requests } = polly;
const { matchRequestsBy } = this.config;
const identifiers = {};
this.identifiers = {};
// Iterate through each normalizer
keys(NormalizeRequest).forEach(key => {
if (this[key] && matchRequestsBy[key]) {
identifiers[key] = NormalizeRequest[key](
key === 'body' ? this.serializedBody : this[key],
this.identifiers[key] = NormalizeRequest[key](
this[key],
matchRequestsBy[key]

@@ -221,7 +244,10 @@ );

// Store the identifiers for debugging and testing
this.identifiers = freeze(identifiers);
// Emit the `identify` event which adapters can use to serialize the request body
await this[EVENT_EMITTER].emit('identify', this);
// Freeze the identifiers so they can no longer be modified
freeze(this.identifiers);
// Guid is a string representation of the identifiers
this.id = md5(stringify(identifiers));
this.id = md5(stringify(this.identifiers));

@@ -228,0 +254,0 @@ // Order is calculated on other requests with the same id

@@ -1,4 +0,5 @@

import HTTPBase from './http-base';
import { assert, HTTP_STATUS_CODES } from '@pollyjs/utils';
import HTTPBase from './http-base';
const DEFAULT_STATUS_CODE = 200;

@@ -5,0 +6,0 @@

import { MODES } from '@pollyjs/utils';
import Timing from '../utils/timing';

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

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

import mergeOptions from 'merge-options';
import { MODES, assert } from '@pollyjs/utils';
import { version } from '../package.json';
import Logger from './-private/logger';

@@ -7,7 +10,6 @@ import Container from './-private/container';

import guidForRecording from './utils/guid-for-recording';
import mergeConfigs from './utils/merge-configs';
import EventEmitter from './-private/event-emitter';
import Server from './server';
import { validateRecordingName } from './utils/validators';
import { version } from '../package.json';
import { MODES, assert } from '@pollyjs/utils';

@@ -161,3 +163,3 @@ const RECORDING_NAME = Symbol();

this.config = mergeOptions(DefaultConfig, this.config, config);
this.config = mergeConfigs(DefaultConfig, this.config, config);

@@ -164,0 +166,0 @@ // Register and connect to all specified adapters

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

import { assert } from '@pollyjs/utils';
import EventEmitter from '../-private/event-emitter';
import { assert } from '@pollyjs/utils';
import {

@@ -4,0 +5,0 @@ validateRecordingName,

import RouteRecognizer from 'route-recognizer';
import castArray from 'lodash-es/castArray';
import { URL, assert, timeout, buildUrl } from '@pollyjs/utils';
import Route from './route';
import Handler from './handler';
import Middleware from './middleware';
import removeHostFromUrl from '../utils/remove-host-from-url';
import castArray from 'lodash-es/castArray';
import { URL, assert, timeout, buildUrl } from '@pollyjs/utils';

@@ -13,5 +13,10 @@ const HOST = Symbol();

const MIDDLEWARE = Symbol();
const SLASH = '/';
const STAR = '*';
const HANDLERS = Symbol();
const CHARS = {
SLASH: '/',
STAR: '*',
COLON: ':'
};
const METHODS = ['GET', 'PUT', 'POST', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'];

@@ -22,3 +27,3 @@

function parseUrl(url) {
const path = new URL(url);
const parsedUrl = new URL(url);
/*

@@ -28,6 +33,6 @@ Use the full origin (http://hostname:port) if the host exists. If there

*/
const host = path.host ? path.origin : SLASH;
const href = removeHostFromUrl(path).href;
const host = parsedUrl.host ? parsedUrl.origin : CHARS.SLASH;
const path = parsedUrl.pathname || CHARS.SLASH;
return { host, path: href };
return { host, path };
}

@@ -113,4 +118,11 @@

const registry = this._registryForHost(host);
const name = this._nameForPath(path);
const router = registry[method.toUpperCase()];
registry[method.toUpperCase()].add([{ path, handler }]);
if (router[HANDLERS].has(name)) {
router[HANDLERS].get(name).push(handler);
} else {
router[HANDLERS].set(name, [handler]);
router.add([{ path, handler: router[HANDLERS].get(name) }]);
}
});

@@ -131,3 +143,3 @@

if (
(!route || route === STAR) &&
(!route || route === CHARS.STAR) &&
!this[HOST] &&

@@ -165,8 +177,36 @@ this[NAMESPACES].length === 0

/**
* Converts a url path into a name used to combine route handlers by
* normalizing dynamic and star segments
* @param {String} path
* @returns {String}
*/
_nameForPath(path = '') {
const name = path
.split(CHARS.SLASH)
.map(segment => {
switch (segment.charAt(0)) {
// If this is a dynamic segment (e.g. :id), then just return `:`
// since /path/:id is the same as /path/:uuid
case CHARS.COLON:
return CHARS.COLON;
// If this is a star segment (e.g. *path), then just return `*`
// since /path/*path is the same as /path/*all
case CHARS.STAR:
return CHARS.STAR;
default:
return segment;
}
})
.join(CHARS.SLASH);
// Remove trailing slash, if we result with an empty string, return a slash
return name.replace(/\/$/, '') || CHARS.SLASH;
}
_registryForHost(host) {
host = host || SLASH;
if (!this[REGISTRY][host]) {
this[REGISTRY][host] = METHODS.reduce((acc, method) => {
acc[method] = new RouteRecognizer();
acc[method][HANDLERS] = new Map();

@@ -173,0 +213,0 @@ return acc;

import RouteRecognizer from 'route-recognizer';
import Route from './route';

@@ -14,3 +15,5 @@

this.paths.forEach(path => this._routeRecognizer.add([{ path, handler }]));
this.paths.forEach(path =>
this._routeRecognizer.add([{ path, handler: [handler] }])
);
}

@@ -17,0 +20,0 @@

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

import Handler from './handler';
import mergeOptions from 'merge-options';
import mergeConfigs from '../utils/merge-configs';

@@ -31,6 +30,8 @@ async function invoke(fn, route, req, ...args) {

async function emit(route, eventName, ...args) {
const listeners = route.handler._eventEmitter.listeners(eventName);
for (const handler of route.handlers) {
const listeners = handler._eventEmitter.listeners(eventName);
for (const listener of listeners) {
await invoke(listener, route, ...args);
for (const listener of listeners) {
await invoke(listener, route, ...args);
}
}

@@ -50,11 +51,10 @@ }

this.queryParams = {};
this.handlers = [];
this.middleware = middleware || [];
if (result) {
this.handler = result.handler;
this.handlers = result.handler;
this.params = { ...result.params };
this.queryParams = recognizeResults.queryParams;
}
this.handler = this.handler || new Handler();
}

@@ -75,4 +75,4 @@

config() {
return mergeOptions(
...this._orderedRoutes().map(r => r.handler.get('config'))
return mergeConfigs(
...this._orderedHandlers().map(handler => handler.get('config'))
);

@@ -88,5 +88,5 @@ }

async intercept(req, res, interceptor) {
for (const route of this._orderedRoutes()) {
if (route.handler.has('intercept') && interceptor.shouldIntercept) {
await invoke(route.handler.get('intercept'), this, ...arguments);
for (const handler of this._orderedHandlers()) {
if (handler.has('intercept') && interceptor.shouldIntercept) {
await invoke(handler.get('intercept'), this, ...arguments);
}

@@ -110,4 +110,8 @@ }

_orderedRoutes() {
return [...this.middleware, this];
_orderedHandlers() {
return [...this.middleware, this].reduce((handlers, route) => {
handlers.push(...route.handlers);
return handlers;
}, []);
}

@@ -118,5 +122,5 @@

for (const route of this._orderedRoutes()) {
if (route.handler.has(key)) {
value = route.handler.get(key);
for (const handler of this._orderedHandlers()) {
if (handler.has(key)) {
value = handler.get(key);
}

@@ -123,0 +127,0 @@ }

@@ -1,6 +0,7 @@

import parseUrl from './parse-url';
import isObjectLike from 'lodash-es/isObjectLike';
import HTTPHeaders from './http-headers';
import stringify from 'fast-json-stable-stringify';
import parseUrl from './parse-url';
import HTTPHeaders from './http-headers';
const { keys } = Object;

@@ -10,6 +11,10 @@ const { isArray } = Array;

export function method(method) {
return (method || 'GET').toUpperCase();
function isFunction(fn) {
return typeof fn === 'function';
}
export function method(method, config) {
return isFunction(config) ? config(method) : method.toUpperCase();
}
export function url(url, config = {}) {

@@ -19,3 +24,9 @@ const parsedUrl = parseUrl(url, true);

// Remove any url properties that have been disabled via the config
keys(config).forEach(key => !config[key] && parsedUrl.set(key, ''));
keys(config).forEach(key => {
if (isFunction(config[key])) {
parsedUrl.set(key, config[key](parsedUrl[key]));
} else if (!config[key]) {
parsedUrl.set(key, '');
}
});

@@ -31,11 +42,10 @@ // Sort Query Params

export function headers(headers, config) {
let normalizedHeaders = headers;
const normalizedHeaders = new HTTPHeaders(headers);
if (isObjectLike(normalizedHeaders)) {
normalizedHeaders = new HTTPHeaders(normalizedHeaders);
if (isFunction(config)) {
return config(normalizedHeaders);
}
// Filter out excluded headers
if (isObjectLike(config) && isArray(config.exclude)) {
config.exclude.forEach(header => (normalizedHeaders[header] = null));
}
if (isObjectLike(config) && isArray(config.exclude)) {
config.exclude.forEach(header => delete normalizedHeaders[header]);
}

@@ -46,4 +56,4 @@

export function body(body) {
return body;
export function body(body, config) {
return isFunction(config) ? config(body) : body;
}

@@ -50,0 +60,0 @@

import isAbsoluteUrl from 'is-absolute-url';
import removeHostFromUrl from './remove-host-from-url';
import { URL } from '@pollyjs/utils';
import removeHostFromUrl from './remove-host-from-url';
/**

@@ -6,0 +7,0 @@ * Creates an exact representation of the passed url string with url-parse.

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

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