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

@untool/react

Package Overview
Dependencies
Maintainers
4
Versions
98
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@untool/react - npm Package Compare versions

Comparing version 1.1.0 to 1.2.0

19

CHANGELOG.md

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

# [1.2.0](https://github.com/untool/untool/compare/v1.1.0...v1.2.0) (2019-02-27)
### Bug Fixes
* **react:** only allow arrow function with single import() statement ([2bbbdcc](https://github.com/untool/untool/commit/2bbbdcc))
### Features
* **react:** add arg validation to mixin methods ([c03e897](https://github.com/untool/untool/commit/c03e897))
* **react:** add arg/prop validation to public API ([9150954](https://github.com/untool/untool/commit/9150954))
* **react:** allow function as namespace resolver ([11d20a2](https://github.com/untool/untool/commit/11d20a2))
* **react:** allow import load function in importComponent ([dbeea04](https://github.com/untool/untool/commit/dbeea04))
# [1.1.0](https://github.com/untool/untool/compare/v1.0.0...v1.1.0) (2019-02-14)

@@ -8,0 +27,0 @@

26

lib/babel.js

@@ -23,5 +23,21 @@ 'use strict';

const argument = call.get('arguments')[0];
t.assertStringLiteral(argument);
const argument = call.get('arguments.0');
if (!argument) {
throw new Error(
'"importComponent" must be called with at least one parameter!'
);
}
let importedComponent;
if (t.isStringLiteral(argument)) {
importedComponent = argument.node.value;
} else {
t.assertArrowFunctionExpression(argument);
t.assertCallExpression(argument.get('body'));
t.assertImport(argument.get('body.callee'));
importedComponent = argument.get('body.arguments.0').node.value;
}
argument.replaceWith(

@@ -33,3 +49,5 @@ t.objectExpression([

[],
t.callExpression(t.identifier('import'), [argument.node])
t.callExpression(t.identifier('import'), [
t.stringLiteral(importedComponent),
])
)

@@ -44,3 +62,3 @@ ),

),
[argument.node]
[t.stringLiteral(importedComponent)]
)

@@ -47,0 +65,0 @@ ),

122

lib/runtime.js
'use strict';
/* global __webpack_modules__, __webpack_require__ */
const { createElement, Component } = require('react');
const { isValidElement, createElement, Component } = require('react');
const { default: withRouter } = require('react-router-dom/es/withRouter');
const isPlainObject = require('is-plain-object');
const PropTypes = require('prop-types');
const { initialize } = require('@untool/core');
const {
initialize,
internal: { invariant },
} = require('@untool/core');
exports.render = (element, options) => (...args) => {
invariant(
isValidElement(element),
'render(): Received invalid React element'
);
invariant(
options === undefined || isPlainObject(options),
'render(): Received invalid options'
);
const { render } = initialize({}, element, options);
if (!render) {
throw new Error("Can't use @untool/react mixin");
}
invariant(render, "Can't use @untool/react mixin");
return render(...args);
};
exports.Miss = withRouter(function Miss({ staticContext }) {
const Miss = ({ staticContext }) => {
if (staticContext) {

@@ -22,5 +33,9 @@ staticContext.miss = true;

return null;
});
};
Miss.propTypes = {
staticContext: PropTypes.object,
};
exports.Miss = withRouter(Miss);
exports.Status = withRouter(function Status({ staticContext, code }) {
const Status = ({ staticContext, code }) => {
if (staticContext) {

@@ -30,5 +45,10 @@ staticContext.status = code;

return null;
});
};
Status.propTypes = {
staticContext: PropTypes.object,
code: PropTypes.number.isRequired,
};
exports.Status = withRouter(Status);
exports.Header = withRouter(function Header({ staticContext, name, value }) {
const Header = ({ staticContext, name = '', value = '' }) => {
if (staticContext) {

@@ -38,45 +58,57 @@ staticContext.headers = { ...staticContext.headers, [name]: value };

return null;
});
};
Header.propTypes = {
staticContext: PropTypes.object,
name: PropTypes.string.isRequired,
value: PropTypes.string.isRequired,
};
exports.Header = withRouter(Header);
exports.importComponent = ({ load, moduleId }, name = 'default') => {
const Importer = withRouter(
class Importer extends Component {
constructor({ staticContext }) {
super();
if (staticContext) {
staticContext.modules.push(moduleId);
}
if (staticContext || __webpack_modules__[moduleId]) {
this.state = { Component: __webpack_require__(moduleId)[name] };
} else {
this.state = { loading: true };
}
const resolve = typeof name === 'function' ? name : (module) => module[name];
class Importer extends Component {
constructor({ staticContext }) {
super();
if (staticContext) {
staticContext.modules.push(moduleId);
}
componentDidMount() {
const { loader } = this.props;
const { loading } = this.state;
if (loading) {
const state = { Component: null, error: null, loading: false };
Promise.resolve()
.then(() => (loader ? loader(load) : load()))
.then(
({ [name]: Component }) => this.setState({ ...state, Component }),
(error) => this.setState({ ...state, error })
);
}
if (staticContext || __webpack_modules__[moduleId]) {
this.state = { Component: resolve(__webpack_require__(moduleId)) };
} else {
this.state = { loading: true };
}
render() {
const {
render = ({ Component, error, loading, ...props }) => {
return !(error || loading) ? createElement(Component, props) : null;
},
ownProps,
} = this.props;
return render({ ...ownProps, ...this.state });
}
componentDidMount() {
const { loader } = this.props;
const { loading } = this.state;
if (loading) {
const state = { Component: null, error: null, loading: false };
Promise.resolve()
.then(() => (loader ? loader(load) : load()))
.then(
(module) => this.setState({ ...state, Component: resolve(module) }),
(error) => this.setState({ ...state, error })
);
}
}
);
render() {
const {
render = ({ Component, error, loading, ...props }) => {
return !(error || loading) ? createElement(Component, props) : null;
},
ownProps,
} = this.props;
return render({ ...ownProps, ...this.state });
}
}
Importer.propTypes = {
staticContext: PropTypes.object,
ownProps: PropTypes.object.isRequired,
loader: PropTypes.func,
render: PropTypes.func,
};
const ImporterWithRouter = withRouter(Importer);
return function Import({ loader, render, ...ownProps }) {
return createElement(Importer, { loader, render, ownProps });
return createElement(ImporterWithRouter, { loader, render, ownProps });
};
};

@@ -5,6 +5,8 @@ 'use strict';

const { createElement } = require('react');
const { createElement, isValidElement } = require('react');
const { unmountComponentAtNode, hydrate, render } = require('react-dom');
const { default: BrowserRouter } = require('react-router-dom/es/BrowserRouter');
const isPlainObject = require('is-plain-object');
const {

@@ -15,3 +17,6 @@ override,

const { Mixin } = require('@untool/core');
const {
Mixin,
internal: { validate, invariant },
} = require('@untool/core');

@@ -50,8 +55,44 @@ class ReactMixin extends Mixin {

ReactMixin.strategies = {
bootstrap: parallel,
enhanceElement: compose,
fetchData: pipe,
render: override,
bootstrap: validate(parallel, ({ length }) => {
invariant(length === 0, 'bootstrap(): Received unexpected argument(s)');
}),
enhanceElement: validate(
compose,
([element]) => {
invariant(
isValidElement(element),
'enhanceElement(): Received invalid React element'
);
},
(result) => {
invariant(
isValidElement(result),
'enhanceElement(): Returned invalid React element'
);
}
),
fetchData: validate(
pipe,
([data, element]) => {
invariant(
isPlainObject(data),
'fetchData(): Received invalid data object'
);
invariant(
isValidElement(element),
'fetchData(): Received invalid React element'
);
},
(result) => {
invariant(
isPlainObject(result),
'fetchData(): Returned invalid data object'
);
}
),
render: validate(override, ({ length }) => {
invariant(length === 0, 'render(): Received unexpected argument(s)');
}),
};
module.exports = ReactMixin;

@@ -5,3 +5,3 @@ 'use strict';

const { createElement } = require('react');
const { createElement, isValidElement } = require('react');
const { renderToString } = require('react-dom/server');

@@ -13,2 +13,4 @@ const { default: StaticRouter } = require('react-router-dom/es/StaticRouter');

const isPlainObject = require('is-plain-object');
const {

@@ -19,3 +21,6 @@ override,

const { Mixin } = require('@untool/core');
const {
Mixin,
internal: { validate, invariant },
} = require('@untool/core');

@@ -79,9 +84,77 @@ const getAssets = require('../lib/assets');

ReactMixin.strategies = {
bootstrap: parallel,
enhanceElement: compose,
fetchData: pipe,
getTemplateData: pipe,
render: override,
bootstrap: validate(parallel, ([req, res]) => {
invariant(
req && req.app && req.url,
'bootstrap(): Received invalid HTTP request object'
);
invariant(
res && res.app && res.locals,
'bootstrap(): Received invalid HTTP response object'
);
}),
enhanceElement: validate(
compose,
([element]) => {
invariant(
isValidElement(element),
'enhanceElement(): Received invalid React element'
);
},
(result) => {
invariant(
isValidElement(result),
'enhanceElement(): Returned invalid React element'
);
}
),
fetchData: validate(
pipe,
([data, element]) => {
invariant(
isPlainObject(data),
'fetchData(): Received invalid data object'
);
invariant(
isValidElement(element),
'fetchData(): Received invalid React element'
);
},
(result) => {
invariant(
isPlainObject(result),
'fetchData(): Returned invalid data object'
);
}
),
getTemplateData: validate(
pipe,
([data]) => {
invariant(
isPlainObject(data),
'getTemplateData(): Received invalid data object'
);
},
(result) => {
invariant(
isPlainObject(result),
'getTemplateData(): Returned invalid data object'
);
}
),
render: validate(override, ([req, res, next]) => {
invariant(
req && req.app && req.url,
'render(): Received invalid HTTP request object'
);
invariant(
res && res.app && res.locals,
'render(): Received invalid HTTP response object'
);
invariant(
typeof next === 'function',
'render(): Received invalid next() function'
);
}),
};
module.exports = ReactMixin;
{
"name": "@untool/react",
"version": "1.1.0",
"version": "1.2.0",
"description": "untool react mixin",

@@ -23,6 +23,8 @@ "browser": "lib/runtime.js",

"@babel/preset-react": "^7.0.0",
"@untool/core": "^1.1.0",
"@untool/core": "^1.2.0",
"babel-plugin-transform-react-remove-prop-types": "^0.4.19",
"clone": "^2.1.2",
"is-plain-object": "^2.0.4",
"mixinable": "^4.0.0",
"prop-types": "^15.7.2",
"serialize-javascript": "^1.4.0"

@@ -39,3 +41,3 @@ },

},
"gitHead": "e92a4e17440f172b7211c57d7bbf9badd34ec8b3"
"gitHead": "0576dcfa7e743599b9f020024e1f479cdd7044b9"
}

@@ -56,3 +56,3 @@ # `@untool/react`

With this component, you can declaratively set arbitrary HTTP headers from your React application.
With this component, you can declaratively set arbitrary HTTP headers from your React application. On the client side, it is effectively a no-op.

@@ -65,3 +65,3 @@ ```javascript

### `importComponent(module, [exportName])`
### `importComponent(module|moduleLoader, [exportName|exportResolver])`

@@ -73,3 +73,3 @@ Using the `importComponent` helper, you can asynchronously require components into your application to help you reduce asset sizes. It works similarly to [`react-loadable`](https://github.com/jamiebuilds/react-loadable), but is deeply integrated with `untool`.

const Home = importComponent('./home');
const Home = importComponent('./home', 'Home');

@@ -79,2 +79,14 @@ export default () => <Home />;

Additionally, `importComponent` supports an alternative syntax that helps with editor and type checker integration since it does not rely on plain strings. The snippet below is functionally equivalent to the one above:
```javascript
import { importComponent } from '@untool/react';
const Home = importComponent(() => import('./home'), ({ Home }) => Home);
export default () => <Home />;
```
If you do no specify an `exportName` or `exportResolver`, `importComponent` will fall back to the imported modules `default` export.
`importComponent` itself returns a React component supporting some props that enable you to control module loading and (placeholder) rendering.

@@ -81,0 +93,0 @@

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