Home Reference Source Repository

src/decorators/mixin.js


import Property from "../Property";

/*
	Adds a mixin to a Property subclass. Mixins are a handy way to share life-cycle and shadow functionality
	across properties without using inheritance (which is fine too). A factory function is passed as the
	single parameter and returns a plain javascript object (https://lodash.com/docs#isPlainObject). The
	mixin object can have:
		* property lifecycle methods - these methods will be invoked before the property's implementation.
		* @shadow marked methods - these methods will be mapped onto the shadow after the actual property's
			shadow methods have been defined.
		* other methods - these will not be mapped onto the property or shadow so there is no chance of
			conflict with the property, shadow, or other mixins.

	A minimal mixin example:

		function mixinFactory(property) {
			// perform sub-property setup on the property (this example assumes ObjectProperty subclass)
			property.addPropertyClass(_connected, PrimitiveProperty, false, true);

			return {
				// lifecycle method
				propertyDidShadow() {
					console.log("Mixin propertyDidShadow() called");
				}

				// shadow method
				@shadow
				echo(msg) {
					console.log("Mixin echos: " + msg);
				}
			}
		}

	Use the mixin using the @mixin() decorator:

		@mixin(mixinFactory)
		class UsersCollection extends CollectionProperty { ... }

	Access the mixin shadow methods as normal:

		users.echo("Hello mixin");


	Parameter:
		mixinFactory - a function of the form: factory(property) : POJO
*/
export default function mixin(mixinFactory) {
	return function registerMixin(target, name, descriptor) {
		const p = Property;

		if (!Property.isPrototypeOf(target)) {
			throw new SyntaxError("@mixin() must be applied to a Property subclass.");
		}

		if (!target.mixins) {
			target.mixins = [];
		}

		target.mixins.push(mixinFactory);
	}
}