mappersmith
Advanced tools
Comparing version 2.38.1 to 2.39.0
import type { GlobalConfigs, ManifestOptions, ResourceTypeConstraint } from './manifest' | ||
export type { GlobalConfigs, ManifestOptions, ResourceTypeConstraint } | ||
export type { Request } from './request' | ||
export type { Headers, Params as Parameters } from './types' | ||
export type { Headers, Params as Parameters, Auth as Authorization } from './types' | ||
export type { Gateway } from './gateway' | ||
@@ -18,3 +18,2 @@ export type { XHR as XhrGateway } from './gateway/xhr' | ||
AbortFn, | ||
Authorization, | ||
Context, | ||
@@ -21,0 +20,0 @@ Middleware, |
@@ -6,3 +6,3 @@ "use strict"; | ||
var _process, defaultGateway; // Prevents webpack to load the nodejs processs polyfill | ||
var _process, defaultGateway; // Prevents webpack to load the nodejs process polyfill | ||
@@ -12,3 +12,3 @@ | ||
// eslint-disable-next-line no-eval | ||
_process = eval('typeof process === "object" ? process : undefined'); | ||
_process = eval('typeof __TEST_SERVICE_WORKER__ === "undefined" && typeof process === "object" ? process : undefined'); | ||
} catch (e) {} // eslint-disable-line no-empty | ||
@@ -23,2 +23,5 @@ | ||
defaultGateway = require('./gateway/http')["default"]; | ||
} else if (typeof self !== 'undefined') { | ||
// For service workers use fetch adapter | ||
defaultGateway = require('./gateway/fetch')["default"]; | ||
} | ||
@@ -25,0 +28,0 @@ |
@@ -1,3 +0,17 @@ | ||
import { Middleware, Authorization } from './index' | ||
export default function BasicAuthMiddleware(authConfig: Authorization): Middleware | ||
import { Auth } from 'types'; | ||
import { Middleware } from './index'; | ||
declare const _default: (authConfig: Auth) => Middleware; | ||
/** | ||
* Automatically configure your requests with basic auth | ||
* | ||
* Example: | ||
* In your manifest: | ||
* { | ||
* middleware: [ BasicAuthMiddleware({ username: 'bob', password: 'bob' }) ] | ||
* } | ||
* | ||
* Making the call: | ||
* client.User.all() | ||
* // => header: "Authorization: Basic Ym9iOmJvYg==" | ||
*/ | ||
export default _default; |
@@ -10,2 +10,6 @@ "use strict"; | ||
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } | ||
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } | ||
/** | ||
@@ -28,3 +32,4 @@ * Automatically configure your requests with basic auth | ||
prepareRequest: function prepareRequest(next) { | ||
return next().then(function (request) { | ||
return _asyncToGenerator(function* () { | ||
var request = yield next(); | ||
var auth = request.auth(); | ||
@@ -35,3 +40,3 @@ return !auth // Keep the override | ||
}) : request; | ||
}); | ||
})(); | ||
} | ||
@@ -38,0 +43,0 @@ }; |
@@ -1,3 +0,6 @@ | ||
import { Middleware } from './index' | ||
export default function CSRF(...headers: string[]): Middleware | ||
import { Middleware } from './index'; | ||
declare const _default: (cookieName?: string, headerName?: string) => Middleware; | ||
/** | ||
* Sets a request header with the value of a cookie from document.cookie, if it exists | ||
*/ | ||
export default _default; |
@@ -10,2 +10,6 @@ "use strict"; | ||
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } | ||
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } | ||
/** | ||
@@ -27,3 +31,5 @@ * Sets a request header with the value of a cookie from document.cookie, if it exists | ||
prepareRequest: function prepareRequest(next) { | ||
return next().then(function (request) { | ||
return _asyncToGenerator(function* () { | ||
var request = yield next(); | ||
if (typeof document === 'undefined') { | ||
@@ -37,3 +43,3 @@ return request; | ||
}); | ||
}); | ||
})(); | ||
} | ||
@@ -40,0 +46,0 @@ }; |
@@ -1,4 +0,6 @@ | ||
import { Middleware } from './index' | ||
declare const Duration: Middleware | ||
export default Duration | ||
import { Middleware } from './index'; | ||
/** | ||
* Adds started_at, ended_at and duration headers to the response | ||
*/ | ||
declare const DurationMiddleware: Middleware; | ||
export default DurationMiddleware; |
@@ -1,6 +0,12 @@ | ||
import { Middleware } from './index' | ||
declare const EncodeJson: Middleware | ||
export const CONTENT_TYPE_JSON: string | ||
export default EncodeJson | ||
import { Middleware } from './index'; | ||
export declare const CONTENT_TYPE_JSON: string; | ||
/** | ||
* Automatically encode your objects into JSON | ||
* | ||
* Example: | ||
* client.User.all({ body: { name: 'bob' } }) | ||
* // => body: {"name":"bob"} | ||
* // => header: "Content-Type=application/json;charset=utf-8" | ||
*/ | ||
declare const EncodeJsonMiddleware: Middleware; | ||
export default EncodeJsonMiddleware; |
@@ -7,2 +7,7 @@ "use strict"; | ||
exports["default"] = exports.CONTENT_TYPE_JSON = void 0; | ||
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } | ||
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } | ||
var mediaType = 'application/json'; | ||
@@ -33,3 +38,5 @@ var charset = 'charset=utf-8'; | ||
prepareRequest: function prepareRequest(next) { | ||
return next().then(function (request) { | ||
return _asyncToGenerator(function* () { | ||
var request = yield next(); | ||
try { | ||
@@ -40,3 +47,3 @@ var body = request.body(); | ||
if (body) { | ||
var shouldEncodeBody = contentType == null || isJson(contentType) && !alreadyEncoded(body); | ||
var shouldEncodeBody = contentType == null || typeof contentType === 'string' && isJson(contentType) && !alreadyEncoded(body); | ||
var encodedBody = shouldEncodeBody ? JSON.stringify(body) : body; | ||
@@ -54,3 +61,3 @@ return request.enhance({ | ||
return request; | ||
}); | ||
})(); | ||
} | ||
@@ -57,0 +64,0 @@ }; |
@@ -1,9 +0,10 @@ | ||
import { Middleware } from './index' | ||
import { Response } from '../response' | ||
declare const GlobalErrorHandler: Middleware | ||
export type ErrorHandlerMiddlewareCallback = (response: Response) => boolean | ||
export function setErrorHandler(fn: ErrorHandlerMiddlewareCallback): void | ||
export default GlobalErrorHandler | ||
import { Response } from '../response'; | ||
import { Middleware } from './index'; | ||
export declare type ErrorHandlerMiddlewareCallback = (response: Response) => boolean; | ||
export declare const setErrorHandler: (errorHandler: ErrorHandlerMiddlewareCallback) => void; | ||
/** | ||
* Provides a catch-all function for all requests. If the catch-all | ||
* function returns `true` it prevents the original promise to continue. | ||
*/ | ||
declare const GlobalErrorHandlerMiddleware: Middleware; | ||
export default GlobalErrorHandlerMiddleware; |
@@ -26,2 +26,6 @@ "use strict"; | ||
response: function response(next) { | ||
if (!_index.configs.Promise) { | ||
return next(); | ||
} | ||
return new _index.configs.Promise(function (resolve, reject) { | ||
@@ -28,0 +32,0 @@ next().then(function (response) { |
import { Request } from '../request'; | ||
import { Response } from '../response'; | ||
export interface Authorization { | ||
readonly password: string; | ||
readonly username: string; | ||
} | ||
export declare type Context = object; | ||
@@ -32,2 +28,10 @@ export declare type RequestGetter = () => Promise<Request>; | ||
} | ||
export declare type Middleware = (params: MiddlewareParams) => Partial<MiddlewareDescriptor>; | ||
declare type DefaultPrivateProps = {}; | ||
/** | ||
* Mappersmith middleware, used to describe a factory function that given MiddlewareParams | ||
* returns a middleware object (partial of MiddlewareDescriptor). | ||
* | ||
* If the middleware needs to save local state you can use PrivateProps to allow it. | ||
*/ | ||
export declare type Middleware<PrivateProps extends Record<string, unknown> = DefaultPrivateProps> = (params: MiddlewareParams) => Partial<MiddlewareDescriptor & PrivateProps>; | ||
export {}; |
@@ -1,4 +0,11 @@ | ||
import { Middleware } from './index' | ||
declare const Log: Middleware | ||
export default Log | ||
import { Middleware } from './index'; | ||
export declare const defaultSuccessLogger: (message: string) => void; | ||
export declare const defaultErrorLogger: (message: string) => void; | ||
export declare const setSuccessLogger: (logger: (message: string) => void) => void; | ||
export declare const setErrorLogger: (logger: (message: string) => void) => void; | ||
export declare const setLoggerEnabled: (value: boolean) => void; | ||
/** | ||
* Log all requests and responses. | ||
*/ | ||
declare const ConsoleLogMiddleware: Middleware; | ||
export default ConsoleLogMiddleware; |
@@ -8,2 +8,8 @@ "use strict"; | ||
var _response = require("../response"); | ||
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } | ||
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } | ||
var defaultSuccessLogger = function defaultSuccessLogger(message) { | ||
@@ -22,3 +28,3 @@ var logger = console.info ? console.info : console.log; | ||
exports.defaultErrorLogger = defaultErrorLogger; | ||
var isLoggerEnabled = console && console.log; | ||
var isLoggerEnabled = Boolean(console && console.log); | ||
var successLogger = defaultSuccessLogger; | ||
@@ -66,13 +72,22 @@ var errorLogger = defaultErrorLogger; | ||
prepareRequest: function prepareRequest(next) { | ||
return next().then(function (request) { | ||
return log(request); | ||
}); | ||
return _asyncToGenerator(function* () { | ||
var request = yield next(); | ||
log(request); | ||
return request; | ||
})(); | ||
}, | ||
response: function response(next) { | ||
return next().then(function (response) { | ||
return log(response.request(), response); | ||
})["catch"](function (response) { | ||
log(response.request(), response); | ||
throw response; | ||
}); | ||
return _asyncToGenerator(function* () { | ||
try { | ||
var response = yield next(); | ||
log(response.request(), response); | ||
return response; | ||
} catch (err) { | ||
if (err instanceof _response.Response) { | ||
log(err.request(), err); | ||
} | ||
throw err; | ||
} | ||
})(); | ||
} | ||
@@ -79,0 +94,0 @@ }; |
@@ -1,15 +0,50 @@ | ||
import { Response } from '../../../response' | ||
import { Middleware } from '../../index' | ||
import { Middleware } from '../../index'; | ||
import { Response } from '../../../response'; | ||
import { Request } from '../../../request'; | ||
export interface RetryMiddlewareOptions { | ||
readonly headerRetryCount: string | ||
readonly headerRetryTime: string | ||
readonly maxRetryTimeInSecs: number | ||
readonly initialRetryTimeInSecs: number | ||
readonly factor: number | ||
readonly multiplier: number | ||
readonly retries: number | ||
validateRetry(response: Response): boolean | ||
readonly headerRetryCount: string; | ||
readonly headerRetryTime: string; | ||
readonly maxRetryTimeInSecs: number; | ||
readonly initialRetryTimeInSecs: number; | ||
readonly factor: number; | ||
readonly multiplier: number; | ||
readonly retries: number; | ||
validateRetry(response: Response): boolean; | ||
} | ||
export default function Retry(config?: Partial<RetryMiddlewareOptions>): Middleware | ||
export declare const defaultRetryConfigs: RetryMiddlewareOptions; | ||
declare type RetryMiddleware = Middleware<{ | ||
enableRetry: boolean; | ||
inboundRequest: Request; | ||
}>; | ||
declare const _default: (customConfigs?: Partial<RetryMiddlewareOptions>) => RetryMiddleware; | ||
/** | ||
* This middleware will automatically retry GET requests up to the configured amount of | ||
* retries using a randomization function that grows exponentially. The retry count and | ||
* the time used will be included as a header in the response. | ||
* | ||
* The retry time is calculated using the following formula: | ||
* retryTime = min( | ||
* random(previousRetryTime - randomizedFactor, previousRetryTime + randomizedFactor) * multipler, | ||
* maxRetryTime | ||
* ) | ||
* | ||
* Take a look at `calculateExponentialRetryTime` for more information. | ||
* | ||
* @param {Object} retryConfigs | ||
* @param {String} retryConfigs.headerRetryCount (default: 'X-Mappersmith-Retry-Count') | ||
* @param {String} retryConfigs.headerRetryTime (default: 'X-Mappersmith-Retry-Time') | ||
* @param {Number} retryConfigs.maxRetryTimeInSecs (default: 5) | ||
* @param {Number} retryConfigs.initialRetryTimeInSecs (default: 1) | ||
* @param {Number} retryConfigs.factor (default: 0.2) - randomization factor | ||
* @param {Number} retryConfigs.multiplier (default: 2) - exponential factor | ||
* @param {Number} retryConfigs.retries (default: 5) - max retries | ||
*/ | ||
export default _default; | ||
/** | ||
* Increases the retry time for each attempt using a randomization function that grows exponentially. | ||
* The value is limited by `retryConfigs.maxRetryTimeInSecs`. | ||
* @param {Number} retryTime | ||
* | ||
* @return {Number} | ||
*/ | ||
export declare const calculateExponentialRetryTime: (retryTime: number, retryConfigs: RetryMiddlewareOptions) => number; |
@@ -12,8 +12,8 @@ "use strict"; | ||
var _response = _interopRequireDefault(require("../../../response")); | ||
var _response = require("../../../response"); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); } | ||
var defaultRetryConfigs = { | ||
@@ -35,2 +35,4 @@ headerRetryCount: 'X-Mappersmith-Retry-Count', | ||
}; | ||
exports.defaultRetryConfigs = defaultRetryConfigs; | ||
/** | ||
@@ -58,5 +60,2 @@ * This middleware will automatically retry GET requests up to the configured amount of | ||
*/ | ||
exports.defaultRetryConfigs = defaultRetryConfigs; | ||
var _default = function _default() { | ||
@@ -72,5 +71,4 @@ var customConfigs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
response: function response(next) { | ||
var _this = this; | ||
var retryConfigs = (0, _utils.assign)({}, defaultRetryConfigs, customConfigs); | ||
var inboundRequest = this.inboundRequest; | ||
@@ -81,5 +79,13 @@ if (!this.enableRetry) { | ||
if (!_index.configs.Promise) { | ||
return next(); | ||
} | ||
if (!inboundRequest) { | ||
return next(); | ||
} | ||
return new _index.configs.Promise(function (resolve, reject) { | ||
var retryTime = retryConfigs.initialRetryTimeInSecs * 1000; | ||
retriableRequest(resolve, reject, next, _this.inboundRequest)(randomFromRetryTime(retryTime, retryConfigs.factor), 0, retryConfigs); | ||
retriableRequest(resolve, reject, next, inboundRequest)(randomFromRetryTime(retryTime, retryConfigs.factor), 0, retryConfigs); | ||
}); | ||
@@ -111,4 +117,13 @@ } | ||
} catch (e) { | ||
var errorMessage = response instanceof Error ? response.message : e.message; | ||
reject(new _response["default"](request, 400, errorMessage, {}, [response])); | ||
var errorMessage = ''; | ||
if (response instanceof Error) { | ||
errorMessage = response.message; | ||
} | ||
if (_typeof(e) === 'object' && e !== null && 'message' in e) { | ||
errorMessage = e.message; | ||
} | ||
reject(new _response.Response(request, 400, errorMessage, {}, [response])); | ||
} | ||
@@ -123,4 +138,13 @@ } | ||
} catch (e) { | ||
var errorMessage = response instanceof Error ? response.message : e.message; | ||
reject(new _response["default"](request, 400, errorMessage, {}, [response])); | ||
var errorMessage = ''; | ||
if (response instanceof Error) { | ||
errorMessage = response.message; | ||
} | ||
if (_typeof(e) === 'object' && e !== null && 'message' in e) { | ||
errorMessage = e.message; | ||
} | ||
reject(new _response.Response(request, 400, errorMessage, {}, [response])); | ||
} | ||
@@ -127,0 +151,0 @@ } |
@@ -1,5 +0,16 @@ | ||
import { Middleware } from './index' | ||
export type Milliseconds = number | ||
export default function Timeout(duration: Milliseconds): Middleware | ||
import { Middleware } from './index'; | ||
export declare type Milliseconds = number; | ||
declare const _default: (timeoutValue: Milliseconds) => Middleware; | ||
/** | ||
* Automatically configure your requests with a default timeout | ||
* | ||
* Example: | ||
* In your manifest: | ||
* { | ||
* middleware: [ TimeoutMiddleware(500) ] | ||
* } | ||
* | ||
* You can still override the default value: | ||
* client.User.all({ timeout: 100 }) | ||
*/ | ||
export default _default; |
@@ -8,2 +8,6 @@ "use strict"; | ||
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } | ||
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } | ||
/** | ||
@@ -25,3 +29,4 @@ * Automatically configure your requests with a default timeout | ||
prepareRequest: function prepareRequest(next) { | ||
return next().then(function (request) { | ||
return _asyncToGenerator(function* () { | ||
var request = yield next(); | ||
var timeout = request.timeout(); | ||
@@ -32,3 +37,3 @@ return !timeout // Keep the override | ||
}) : request; | ||
}); | ||
})(); | ||
} | ||
@@ -35,0 +40,0 @@ }; |
{ | ||
"name": "mappersmith", | ||
"version": "2.38.1", | ||
"version": "2.39.0", | ||
"description": "It is a lightweight rest client for node.js and the browser", | ||
@@ -21,2 +21,4 @@ "author": "Tulio Ornelas <ornelas.tulio@gmail.com>", | ||
"test:node:watch": "yarn jest --config jestSetup/configs/config.node.json --watchAll", | ||
"test:service-worker": "yarn jest --config jestSetup/configs/config.sw.json", | ||
"test:service-worker:watch": "yarn jest --config jestSetup/configs/config.sw.json --watchAll", | ||
"test:types": "yarn tsc --noEmit", | ||
@@ -62,3 +64,3 @@ "test:types:watch": "yarn test:types --watch", | ||
"volta": { | ||
"node": "12.22.7", | ||
"node": "14.18.2", | ||
"yarn": "1.22.11" | ||
@@ -111,2 +113,3 @@ }, | ||
"multer": "^1.4.3", | ||
"node-fetch": "^2.6.7", | ||
"prettier": "^2.5.0", | ||
@@ -113,0 +116,0 @@ "puppeteer": "^13.1.1", |
import { MethodDescriptor } from './method-descriptor'; | ||
import type { Auth, Headers, NestedParam, NestedParamArray, Primitive, RequestParams } from './types'; | ||
import type { Auth, Body, Headers, RequestParams } from './types'; | ||
/** | ||
@@ -58,3 +58,3 @@ * Removes the object type without removing Record types in the union | ||
header<T extends string | number | boolean>(name: string): T | undefined; | ||
body(): object | Primitive | NestedParam | NestedParamArray | null | undefined; | ||
body(): Body; | ||
auth(): Auth; | ||
@@ -61,0 +61,0 @@ timeout(): number; |
@@ -24,5 +24,5 @@ import { Request } from './request'; | ||
readonly responseHeaders: Headers; | ||
readonly errors: Array<Error | string>; | ||
readonly errors: Array<Response | Error | string>; | ||
timeElapsed: number | null; | ||
constructor(originalRequest: Request, responseStatus: number, responseData?: string | null, responseHeaders?: Headers, errors?: Array<Error | string>); | ||
constructor(originalRequest: Request, responseStatus: number, responseData?: string | null, responseHeaders?: Headers, errors?: Array<Response | Error | string>); | ||
request(): Request; | ||
@@ -58,3 +58,3 @@ status(): number; | ||
*/ | ||
error(): Error | null; | ||
error(): Error | Response<ParsedJSON> | null; | ||
/** | ||
@@ -61,0 +61,0 @@ * Enhances current Response returning a new Response |
@@ -37,2 +37,3 @@ "use strict"; | ||
var Response = /*#__PURE__*/function () { | ||
// eslint-disable-next-line no-use-before-define | ||
function Response(originalRequest, responseStatus, responseData, responseHeaders, errors) { | ||
@@ -39,0 +40,0 @@ _classCallCheck(this, Response); |
@@ -8,2 +8,3 @@ export declare type Primitive = string | number | boolean; | ||
} | ||
export declare type Body = Record<string, unknown> | string; | ||
export interface Auth { | ||
@@ -24,3 +25,3 @@ username?: string; | ||
readonly auth?: Auth; | ||
readonly body?: object | string; | ||
readonly body?: Body; | ||
readonly headers?: Headers; | ||
@@ -27,0 +28,0 @@ readonly host?: string; |
@@ -1,1 +0,1 @@ | ||
{"version":"2.38.1"} | ||
{"version":"2.39.0"} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
241705
4236
55