@bem-react/di
Advanced tools
Comparing version 2.1.0 to 2.1.1-dev.6
@@ -65,2 +65,15 @@ 'use strict'; | ||
}; | ||
var registryHocMark = 'RegistryHoc'; | ||
function getBaseComponentNotFoundMessage(hoc) { | ||
return "Not found base component for enhance HOC: " + hoc.toString(); | ||
} | ||
function withBase(hoc) { | ||
var fakeComponent = function () { throw new Error(getBaseComponentNotFoundMessage(hoc)); }; | ||
fakeComponent.$symbol = registryHocMark; | ||
fakeComponent.hoc = hoc; | ||
return fakeComponent; | ||
} | ||
function isHoc(component) { | ||
return component.$symbol === registryHocMark; | ||
} | ||
var Registry = /** @class */ (function () { | ||
@@ -84,2 +97,12 @@ function Registry(_a) { | ||
/** | ||
* Set hoc for extends component in registry by id | ||
* | ||
* @param id component id | ||
* @param hoc hoc for extends component | ||
*/ | ||
Registry.prototype.extends = function (id, hoc) { | ||
this.components[id] = withBase(hoc); | ||
return this; | ||
}; | ||
/** | ||
* Set react components in registry via object literal. | ||
@@ -114,10 +137,37 @@ * | ||
* Override components by external registry. | ||
* @internal | ||
* | ||
* @param registry external registry | ||
* @param otherRegistry external registry | ||
*/ | ||
Registry.prototype.merge = function (registry) { | ||
Registry.prototype.merge = function (otherRegistry) { | ||
var clone = new Registry({ id: this.id, overridable: this.overridable }); | ||
clone.components = __assign({}, this.components, (registry ? registry.snapshot() : {})); | ||
clone.fill(this.components); | ||
if (!otherRegistry) | ||
return clone; | ||
var otherRegistryComponents = otherRegistry.snapshot(); | ||
for (var componentName in otherRegistryComponents) { | ||
if (!otherRegistryComponents.hasOwnProperty(componentName)) | ||
continue; | ||
clone.components[componentName] = this.mergeComponents(clone.components[componentName], otherRegistryComponents[componentName]); | ||
} | ||
return clone; | ||
}; | ||
/** | ||
* Returns extended or replacing for base impleme | ||
* | ||
* @param base base implementation | ||
* @param overrides overridden implementation | ||
*/ | ||
Registry.prototype.mergeComponents = function (base, overrides) { | ||
if (isHoc(overrides)) { | ||
if (!base) | ||
throw new Error(getBaseComponentNotFoundMessage(overrides.hoc)); | ||
if (isHoc(base)) { | ||
// If both components are hocs, then create compose-hoc | ||
return withBase(function (Base) { return overrides.hoc(base.hoc(Base)); }); | ||
} | ||
return overrides.hoc(base); | ||
} | ||
return overrides; | ||
}; | ||
return Registry; | ||
@@ -124,0 +174,0 @@ }()); |
@@ -1,1 +0,1 @@ | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var React=require("react"),__assign=function(){return(__assign=Object.assign||function(e){for(var t,r=1,n=arguments.length;r<n;r++)for(var s in t=arguments[r])Object.prototype.hasOwnProperty.call(t,s)&&(e[s]=t[s]);return e}).apply(this,arguments)},registryContext=React.createContext({}),RegistryProvider=registryContext.Provider,RegistryConsumer=registryContext.Consumer;function withRegistry(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return function(t){var r=function(r){return React.createElement(RegistryConsumer,null,function(n){var s=__assign({},n);return e.forEach(function(e){var t=n[e.id];s[e.id]=e.overridable?t?e.merge(t):e:e&&t?t.merge(e):e}),React.createElement(RegistryProvider,{value:s},React.createElement(t,__assign({},r)))})};return r.displayName="RegistryResolver("+e.map(function(e){return e.id}).join(", ")+")",r}}var ComponentRegistryConsumer=function(e){return React.createElement(RegistryConsumer,null,function(t){return e.children(t[e.id].snapshot())})},useRegistries=function(){return React.useContext(registryContext)},useComponentRegistry=function(e){return useRegistries()[e].snapshot()},Registry=function(){function e(e){var t=e.id,r=e.overridable,n=void 0===r||r;this.components={},this.id=t,this.overridable=n}return e.prototype.set=function(e,t){return this.components[e]=t,this},e.prototype.fill=function(e){return this.components=__assign({},this.components,e),this},e.prototype.get=function(e){return this.components[e]},e.prototype.snapshot=function(){return this.components},e.prototype.merge=function(t){var r=new e({id:this.id,overridable:this.overridable});return r.components=__assign({},this.components,t?t.snapshot():{}),r},e}();exports.ComponentRegistryConsumer=ComponentRegistryConsumer,exports.Registry=Registry,exports.RegistryConsumer=RegistryConsumer,exports.registryContext=registryContext,exports.useComponentRegistry=useComponentRegistry,exports.useRegistries=useRegistries,exports.withRegistry=withRegistry; | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var React=require("react"),__assign=function(){return(__assign=Object.assign||function(e){for(var t,r=1,n=arguments.length;r<n;r++)for(var o in t=arguments[r])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e}).apply(this,arguments)},registryContext=React.createContext({}),RegistryProvider=registryContext.Provider,RegistryConsumer=registryContext.Consumer;function withRegistry(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return function(t){var r=function(r){return React.createElement(RegistryConsumer,null,function(n){var o=__assign({},n);return e.forEach(function(e){var t=n[e.id];o[e.id]=e.overridable?t?e.merge(t):e:e&&t?t.merge(e):e}),React.createElement(RegistryProvider,{value:o},React.createElement(t,__assign({},r)))})};return r.displayName="RegistryResolver("+e.map(function(e){return e.id}).join(", ")+")",r}}var ComponentRegistryConsumer=function(e){return React.createElement(RegistryConsumer,null,function(t){return e.children(t[e.id].snapshot())})},useRegistries=function(){return React.useContext(registryContext)},useComponentRegistry=function(e){return useRegistries()[e].snapshot()},registryHocMark="RegistryHoc";function getBaseComponentNotFoundMessage(e){return"Not found base component for enhance HOC: "+e.toString()}function withBase(e){var t=function(){throw new Error(getBaseComponentNotFoundMessage(e))};return t.$symbol=registryHocMark,t.hoc=e,t}function isHoc(e){return e.$symbol===registryHocMark}var Registry=function(){function e(e){var t=e.id,r=e.overridable,n=void 0===r||r;this.components={},this.id=t,this.overridable=n}return e.prototype.set=function(e,t){return this.components[e]=t,this},e.prototype.extends=function(e,t){return this.components[e]=withBase(t),this},e.prototype.fill=function(e){return this.components=__assign({},this.components,e),this},e.prototype.get=function(e){return this.components[e]},e.prototype.snapshot=function(){return this.components},e.prototype.merge=function(t){var r=new e({id:this.id,overridable:this.overridable});if(r.fill(this.components),!t)return r;var n=t.snapshot();for(var o in n)n.hasOwnProperty(o)&&(r.components[o]=this.mergeComponents(r.components[o],n[o]));return r},e.prototype.mergeComponents=function(e,t){if(isHoc(t)){if(!e)throw new Error(getBaseComponentNotFoundMessage(t.hoc));return isHoc(e)?withBase(function(r){return t.hoc(e.hoc(r))}):t.hoc(e)}return t},e}();exports.ComponentRegistryConsumer=ComponentRegistryConsumer,exports.Registry=Registry,exports.RegistryConsumer=RegistryConsumer,exports.registryContext=registryContext,exports.useComponentRegistry=useComponentRegistry,exports.useRegistries=useRegistries,exports.withRegistry=withRegistry; |
@@ -6,2 +6,8 @@ # Change Log | ||
# [2.2.0](https://github.com/bem/bem-react/compare/@bem-react/di@2.1.0...@bem-react/di@2.2.0) (2019-12-23) | ||
### Features | ||
- **di:** Add withBase-hoc as a way of extending components ([dda4d8b](https://github.com/bem/bem-react/commit/dda4d8b22325331a46e19dad75dae7da5a388aed)) | ||
# [2.1.0](https://github.com/bem/bem-react/compare/@bem-react/di@2.0.4...@bem-react/di@2.1.0) (2019-12-02) | ||
@@ -8,0 +14,0 @@ |
30
di.d.ts
@@ -17,4 +17,9 @@ import React, { ReactNode, FC, ComponentType } from 'react'; | ||
} | ||
interface IRegistryComponents { | ||
[key: string]: any; | ||
declare const registryHocMark = "RegistryHoc"; | ||
export declare type HOC<T> = (WrappedComponent: ComponentType) => ComponentType<T>; | ||
declare type IRegistryEntity<T = any> = ComponentType<T> | IRegistryHOC<T>; | ||
declare type IRegistryComponents = Record<string, IRegistryEntity>; | ||
interface IRegistryHOC<T> extends React.FC<T> { | ||
$symbol: typeof registryHocMark; | ||
hoc: HOC<T>; | ||
} | ||
@@ -34,2 +39,9 @@ export declare class Registry { | ||
/** | ||
* Set hoc for extends component in registry by id | ||
* | ||
* @param id component id | ||
* @param hoc hoc for extends component | ||
*/ | ||
extends<T>(id: string, hoc: HOC<T>): this; | ||
/** | ||
* Set react components in registry via object literal. | ||
@@ -45,3 +57,3 @@ * | ||
*/ | ||
get<T>(id: string): ComponentType<T>; | ||
get<T>(id: string): IRegistryEntity<T>; | ||
/** | ||
@@ -53,7 +65,15 @@ * Returns list of components from registry. | ||
* Override components by external registry. | ||
* @internal | ||
* | ||
* @param registry external registry | ||
* @param otherRegistry external registry | ||
*/ | ||
merge(registry: Registry): Registry; | ||
merge(otherRegistry?: Registry): Registry; | ||
/** | ||
* Returns extended or replacing for base impleme | ||
* | ||
* @param base base implementation | ||
* @param overrides overridden implementation | ||
*/ | ||
private mergeComponents; | ||
} | ||
export {}; |
{ | ||
"name": "@bem-react/di", | ||
"version": "2.1.0", | ||
"version": "2.1.1-dev.6+f35b964", | ||
"description": "BEM React Dependency Injection", | ||
@@ -51,3 +51,3 @@ "homepage": "https://github.com/bem/bem-react/tree/master/packages/di", | ||
}, | ||
"gitHead": "e9d8011ed9f975b3b94dd710045d4027e1ad8cc2" | ||
"gitHead": "f35b964d0a4035168b4c708d6db2ca5f29e37d3d" | ||
} |
@@ -219,1 +219,24 @@ # @bem-react/di · [![npm (scoped)](https://img.shields.io/npm/v/@bem-react/di.svg)](https://www.npmjs.com/package/@bem-react/di) [![npm bundle size (minified + gzip)](https://img.shields.io/bundlephobia/minzip/@bem-react/di.svg)](https://bundlephobia.com/result?p=@bem-react/di) | ||
``` | ||
## Extending components | ||
You can extend (e.g. for experiments) a component using method `extends(...)` in overridden registry. | ||
```tsx | ||
import { Registry, withRegistry, withBase } from '@bem-react/di' | ||
import { AppDesktop, registryId } from './App@desktop' | ||
const expRegistry = new Registry({ id: registryId }) | ||
// extends original Header | ||
expRegistry.extends('Header', BaseHeader => props => ( | ||
<div> | ||
<BaseHeader height={200} color={red}/> | ||
</div> | ||
)) | ||
// AppDesktopExperimental will call App with extended 'Header' | ||
export const AppDesktopExperimental = withRegistry(expRegistry)(AppDesktop) | ||
``` | ||
_DI_ merges nested registries composing and ordinary components for you. So you always can get a reference to previous component's implementation. |
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
26591
265
242
2
2