From ae5b5032ba23d5e13ebee81a5ebb55cd83405dde Mon Sep 17 00:00:00 2001 From: David Kebler Date: Thu, 20 Feb 2020 21:34:20 -0800 Subject: [PATCH] refactor from aggregation repo --- .eslintrc.js | 37 +++++++++++++++++++++++++++++ .gitignore | 1 + .npmignore | 4 ++++ README.md | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 33 ++++++++++++++++++++++++++ src/merge.js | 39 +++++++++++++++++++++++++++++++ test/merge.js | 41 ++++++++++++++++++++++++++++++++ 7 files changed, 220 insertions(+) create mode 100644 .eslintrc.js create mode 100644 .gitignore create mode 100644 .npmignore create mode 100644 README.md create mode 100644 package.json create mode 100644 src/merge.js create mode 100644 test/merge.js diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..49bac18 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,37 @@ +module.exports = { + "ecmaFeatures": { + "modules": true, + "spread" : true, + "restParams" : true + }, + // "plugins": [ + // "unicorn" + // ], + "env": { + "es6": true, + "node": true, + "mocha": true + }, + "parserOptions": { + "ecmaVersion": 2017, + "sourceType": "module" + }, + "extends": "eslint:recommended", + "rules": { + "indent": [ + "error", + 2 + ], + // "unicorn/no-array-instanceof": "error", + "no-console": 0, + "semi": ["error", "never"], + "linebreak-style": [ + "error", + "unix" + ], + "quotes": [ + "error", + "single" + ] + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..f16fc41 --- /dev/null +++ b/.npmignore @@ -0,0 +1,4 @@ +tests/ +test/ +*.test.js +testing/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..948c3ac --- /dev/null +++ b/README.md @@ -0,0 +1,65 @@ + +Class Merge +=========== + +Merge of additional (mixin) Classes into an primary (base) class + + +About +----- + +Class Merge is a very small JavaScript library for Node.js environments, +providing just a single function for use in ECMAScript 6 class +inheritance. It aggregates/merges a base class and one or +more mixin classes into an aggregate class, which then is usually +subsequently used as the base class for another class. + +Installation +------------ + +```shell +$ npm install @uci-utils/class-merge +``` + + +Usage +----- + +#### ECMAScript 6 + +requires using -r esm + +```js +import merge from '@uci-utils/class-merge' + +class Colored { + initializer () { this._color = "white" } + get color () { return this._color } + set color (v) { this._color = v } +} + +class ZCoord { + initializer () { this._z = 0 } + get z () { return this._z } + set z (v) { this._z = v } +} + +class Shape { + constructor (x, y) { this._x = x; this._y = y } + get x () { return this._x } + set x (v) { this._x = v } + get y () { return this._y } + set y (v) { this._y = v } +} + +class Rectangle extends merge(Shape, Colored, ZCoord) {} + +var rect = new Rectangle(7, 42) +rect.z = 1000 +rect.color = "red" + + +Credits +------- + +aggregation 2015-2019 by Dr. Ralf S. Engelschall (http://engelschall.com/) diff --git a/package.json b/package.json new file mode 100644 index 0000000..df74282 --- /dev/null +++ b/package.json @@ -0,0 +1,33 @@ +{ + "name": "@uci-utils/class-merge", + "version": "1.0.1", + "description": "Function to merge classes when making an extended class", + "main": "src/merge.js", + "scripts": { + "test": "./node_modules/.bin/mocha -r esm --timeout 30000", + "testd": "UCI_ENV=dev ./node_modules/.bin/nodemon --exec './node_modules/.bin/mocha -r esm --timeout 30000' || exit 0" + }, + "author": "David Kebler", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/uCOMmandIt/uci-utils-class-merge.git" + }, + "keywords": [ + "node.js", + "class", + "ES6", + "merge", + "extend" + ], + "bugs": { + "url": "https://github.com/uCOMmandIt/uci-utils-class-merge/issues" + }, + "homepage": "https://github.com/uCOMmandIt/uci-utils/class-merge#readme", + "devDependencies": { + "chai": "^4.2.0", + "esm": "^3.2.25", + "mocha": "^7.0.1", + "nodemon": "^2.0.2" + } +} diff --git a/src/merge.js b/src/merge.js new file mode 100644 index 0000000..3aa25ce --- /dev/null +++ b/src/merge.js @@ -0,0 +1,39 @@ + +/* ==== ECMAScript 6 variant ==== */ + +export default (base, ...mixins) => { + + /* create aggregation class */ + const merge = class __Merge extends base { + constructor (...args) { + /* call base class constructor */ + super(...args) + + /* call mixin's initializer */ + mixins.forEach((mixin) => { + if (typeof mixin.prototype.initializer === 'function') + mixin.prototype.initializer.apply(this, args) + }) + } + } + + /* copy properties */ + let copyProps = (target, source) => { + Reflect.ownKeys(source) + .forEach((prop) => { + if (typeof prop.match ==='function') { + if (prop.match(/^(?:initializer|constructor|prototype|arguments|caller|name|bind|call|apply|toString|length)$/)) + return + } + Reflect.set(target,prop,Reflect.getOwnPropertyDescriptor(source, prop)) + }) + } + + /* copy all properties of all mixins into aggregation class */ + mixins.forEach((mixin) => { + copyProps(merge.prototype, mixin.prototype) + copyProps(merge, mixin) + }) + + return merge +} diff --git a/test/merge.js b/test/merge.js new file mode 100644 index 0000000..fa79611 --- /dev/null +++ b/test/merge.js @@ -0,0 +1,41 @@ +import merge from '../src/merge.js' +import { expect } from 'chai' + + +describe('Class Merge', function () { + + class Colored { + initializer () { this._color = 'white' } + get color () { return this._color } + set color (v) { this._color = v } + } + + class ZCoord { + initializer () { this._z = 0 } + get z () { return this._z } + set z (v) { this._z = v } + } + + class Shape { + constructor (x, y) { this._x = x; this._y = y } + get x () { return this._x } + set x (v) { this._x = v } + get y () { return this._y } + set y (v) { this._y = v } + } + + var Rectangle = class Rectangle extends merge(Shape, Colored, ZCoord) {} + + var rect = new Rectangle(7, 42) + rect.z = 1000 + rect.color = 'red' + + + it('Should merge three classes', function () { + expect(rect.x).to.be.equal(7) + expect(rect.y).to.be.equal(42) + expect(rect.z).to.be.equal(1000) + expect(rect.color).to.be.equal('red') + }) + +})