diff --git a/lib/SequelizeResolver.ts b/lib/SequelizeResolver.ts index aaf89be..82a45dc 100644 --- a/lib/SequelizeResolver.ts +++ b/lib/SequelizeResolver.ts @@ -4,6 +4,7 @@ import { Transformer } from './transformer' export class SequelizeResolver extends FabrixResolver { private _connection + private _sequelize private _sequelizeModel constructor (model: FabrixModel, datastore?: Sequelize) { @@ -11,6 +12,7 @@ export class SequelizeResolver extends FabrixResolver { if (!model) { throw new RangeError('Resolver must be given a Model to bind to') } + this._sequelize = datastore } get connection() { @@ -25,6 +27,10 @@ export class SequelizeResolver extends FabrixResolver { return this._sequelizeModel } + get sequelize() { + return this._sequelize + } + public connect(modelName, schema, options) { this._sequelizeModel = this._connection.define(modelName, schema, options) this._sequelizeModel.app = this.app diff --git a/lib/api/services/SequelizeService.ts b/lib/api/services/SequelizeService.ts new file mode 100644 index 0000000..7b36aa9 --- /dev/null +++ b/lib/api/services/SequelizeService.ts @@ -0,0 +1,123 @@ +import { FabrixService as Service } from '@fabrix/fabrix/dist/common' + +import { defaults, omitBy, isArray, isObject, isString, isNil, merge } from 'lodash' + +export class SequelizeService extends Service { + /** + * + * @param options + * @returns {*|{}} + */ + mergeOptionDefaults(...options) { + let wheres = {} + let limits = null + let offsets = null + let includes = [] + let orders = [] + let newOptions + + for (const option of options) { + if (!(option instanceof Object)) { + throw new Error(`Option must be an object, type of option was ${ typeof option }`) + } + includes = this.mergeOptionIncludes(includes, option.include) + orders = this.mergeOptionOrders(orders, option.order) + wheres = this.mergeOptionWheres(wheres, option.where) + limits = this.mergeOptionLimits(limits, option.limit) + offsets = this.mergeOptionOffsets(offsets, option.offset) + } + + newOptions = { + include: includes, + order: orders, + where: wheres, + limit: limits, + offset: offsets + } + + for (const option of options.reverse()) { + newOptions = defaults({}, newOptions, option) + } + return omitBy(newOptions, isNil) + } + + /** + * + * @param defaults + * @param overrides + * @returns {*|Array} + */ + mergeOptionIncludes(originals = [], overrides = []) { + const includes = originals + + if (!isArray(originals) || !isArray(overrides)) { + throw new Error('include must be an array') + } + + overrides.map(include => { + const inIncludes = includes.findIndex(i => i.model === include.model) + if (inIncludes !== -1 && includes[inIncludes]['as'] === include.as) { + includes[inIncludes] = include + } + else { + includes.push(include) + } + }) + return includes + } + + /** + * + */ + mergeOptionOrders(originals = [], overrides = []) { + + if (isString(originals)) { + originals = [originals.trim().split(' ')] + } + + let order = originals + + if (isString(overrides)) { + order.push(overrides.trim().split(' ')) + } + else if (isArray(overrides)) { + order = order.concat(overrides) + } + else if (isObject(overrides)) { + order.push([overrides]) + } + + + return order // = defaultsDeep(order, overrides) + } + + /** + * + */ + mergeOptionWheres(originals = {}, overrides = {}) { + const where = merge(originals, overrides) + return where + } + + /** + * + */ + mergeOptionOffsets(originals, overrides) { + let offset = originals + if (overrides) { + offset = overrides + } + return offset + } + + /** + * + */ + mergeOptionLimits(originals, overrides) { + let limit = originals + if (overrides) { + limit = overrides + } + return limit + } +} diff --git a/lib/api/services/index.ts b/lib/api/services/index.ts index 26372e0..bf2fe6a 100755 --- a/lib/api/services/index.ts +++ b/lib/api/services/index.ts @@ -1,2 +1,3 @@ export { SchemaMigrationService } from './SchemaMigrationService' +export { SequelizeService } from './SequelizeService' export { TapestryService } from './TapestryService' diff --git a/package-lock.json b/package-lock.json index 05332e4..79ab386 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@fabrix/spool-sequelize", - "version": "1.1.0", + "version": "1.1.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -114,9 +114,9 @@ } }, "@fabrix/fabrix": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@fabrix/fabrix/-/fabrix-1.1.0.tgz", - "integrity": "sha512-1r7TmtG24rX0Xemr6cWu0L7vUpUhINxyRaPwwc2bhts+NoIFR+5jJBSP1b1+dGsKV2GLYDQwIqmMgavNImVI8g==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@fabrix/fabrix/-/fabrix-1.1.1.tgz", + "integrity": "sha512-CL06baNKFPUB5dFKVCtwgZzKNeQeJyXVwaZhs0JPe7hL/7+LhAZ8zmh0ugcva1YuXecGASp3zXuTdGODGhgCBA==", "dev": true, "requires": { "lodash": "4.17.10", @@ -130,9 +130,9 @@ "dev": true }, "@fabrix/spool-router": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@fabrix/spool-router/-/spool-router-1.1.0.tgz", - "integrity": "sha512-MUnTK5F8xrI7EYkHeuvo50pYVp0jJ+xKXULXGeTzrm11IcQJ2JVb9y95AuzQpdHmLnY/TKYswZaWTG3rlGcn1Q==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@fabrix/spool-router/-/spool-router-1.1.2.tgz", + "integrity": "sha512-a+EF5G8NCq9T5nP1Hn9nNzZWC306IEBA7Sh3Nt1DoziVCwOcd6lRMrvY7FdfLIi+I/TPqn5UC22GSQgd99N1Hw==", "dev": true, "requires": { "call": "5.0.1", @@ -141,9 +141,9 @@ } }, "@fabrix/spool-tapestries": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@fabrix/spool-tapestries/-/spool-tapestries-1.1.0.tgz", - "integrity": "sha512-Y8dxJpm+52yHz64tHo3Fh+VUQIEPvL4V6cHtMr7cMzlcUs7yUR6L0v5xfXMdROPDZGGZFosCog34mH5F/W2K5g==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@fabrix/spool-tapestries/-/spool-tapestries-1.1.2.tgz", + "integrity": "sha512-PiMPrCoq4kQOWEPWQcZbzYmhgnP4GRdC4fy8ypL5DKeDA2KZggP7I7CiP5Qw7dkaCUhbJp5e/c+0JLJCChrrGA==", "dev": true, "requires": { "lodash": "4.17.10" diff --git a/package.json b/package.json index 10e6c3c..e30b1e8 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@fabrix/spool-sequelize", - "version": "1.1.0", + "version": "1.1.1", "description": "Spool - Datastore Spool for Sequelize.js http://sequelizejs.com", "scripts": { "build": "tsc -p ./lib/tsconfig.release.json", @@ -52,10 +52,10 @@ "sequelize": "^4.37.10" }, "devDependencies": { - "@fabrix/fabrix": "^1.1.0", + "@fabrix/fabrix": "^1.1.1", "@fabrix/lint": "^1.0.0-alpha.3", - "@fabrix/spool-router": "^1.1.0", - "@fabrix/spool-tapestries": "^1.1.0", + "@fabrix/spool-router": "^1.1.2", + "@fabrix/spool-tapestries": "^1.1.1", "@types/lodash": "^4.14.109", "@types/node": "~10.3.4", "mocha": "^5", @@ -70,8 +70,8 @@ "typescript": "~2.8.1" }, "peerDependencies": { - "@fabrix/fabrix": "^1.1.0", - "@fabrix/spool-router": "^1.1.0" + "@fabrix/fabrix": "^1.1.1", + "@fabrix/spool-router": "^1.1.2" }, "engines": { "node": ">= 7.6.0" diff --git a/test/app.js b/test/fixtures/app.js similarity index 96% rename from test/app.js rename to test/fixtures/app.js index 0b26a4b..2e845e6 100755 --- a/test/app.js +++ b/test/fixtures/app.js @@ -2,13 +2,11 @@ const _ = require('lodash') const smokesignals = require('smokesignals') -const testModel = require('./fixtures/testmodel') -const SequelizeResolver = require('../dist').SequelizeResolver +const testModel = require('./testmodel') +const SequelizeResolver = require('../../dist/index').SequelizeResolver -// require('@fabrix/fabrix') const Model = require('@fabrix/fabrix/dist/common').FabrixModel - const App = { pkg: { name: 'spool-sequelize-test' @@ -205,7 +203,7 @@ const App = { spools: [ require('@fabrix/spool-router').RouterSpool, require('@fabrix/spool-tapestries').TapestriesSpool, - require('../dist').SequelizeSpool // spool-sequelize + require('../../dist/index').SequelizeSpool // spool-sequelize ] }, stores: { diff --git a/test/index.js b/test/index.js index e017a61..51bbabf 100755 --- a/test/index.js +++ b/test/index.js @@ -3,7 +3,7 @@ const FabrixApp = require('@fabrix/fabrix').FabrixApp before(() => { - global.app = new FabrixApp(require('./app')) + global.app = new FabrixApp(require('./fixtures/app')) return global.app.start().catch(global.app.stop) }) diff --git a/test/unit/lib/transformer.test.js b/test/unit/lib/transformer.test.js index 05db0f2..45df870 100755 --- a/test/unit/lib/transformer.test.js +++ b/test/unit/lib/transformer.test.js @@ -5,7 +5,7 @@ const FabrixApp = require('@fabrix/fabrix').FabrixApp describe('lib.Transformer', () => { let app beforeEach(() => { - app = new FabrixApp(require('../../app')) + app = new FabrixApp(require('../../fixtures/app')) }) describe('#getConnections', () => { diff --git a/test/unit/lib/validator.test.js b/test/unit/lib/validator.test.js index 13d8325..ea6a01b 100755 --- a/test/unit/lib/validator.test.js +++ b/test/unit/lib/validator.test.js @@ -1,5 +1,5 @@ const assert = require('assert') -const app = require('../../app') +const app = require('../../fixtures/app') const lib = require('../../../dist/index') describe('lib.Validator', () => { diff --git a/test/unit/services/SequelizeService.test.js b/test/unit/services/SequelizeService.test.js new file mode 100644 index 0000000..78e50d9 --- /dev/null +++ b/test/unit/services/SequelizeService.test.js @@ -0,0 +1,94 @@ +'use strict' + +const assert = require('assert') + +describe('api.services.SequelizeService', () => { + it.skip('should do stringify sort', (done) => { + const sort = [['created_at','ASC']] + const s = global.app.services.SequelizeService.sortToString(sort) + console.log('STRING', s) + done() + }) + it.skip('should do stringify a bad sort', (done) => { + const sort = [] + const s = global.app.services.SequelizeService.sortToString(sort) + console.log('STRING', s) + done() + }) + it('should merge includes', (done) => { + const newOptions = global.app.services.SequelizeService.mergeOptionDefaults({ + include: [{ model: 'hello' }] + }, { + include: [{ model: 'world'}] + }) + assert.equal(newOptions.include.length, 2) + assert.equal(newOptions.include[0].model, 'hello') + assert.equal(newOptions.include[1].model, 'world') + done() + }) + it('should merge duplicate includes', (done) => { + const newOptions = global.app.services.SequelizeService.mergeOptionDefaults({ + include: [{ model: 'hello', as: 'world' }] + }, { + include: [{ model: 'hello', as: 'world' }] + }) + assert.equal(newOptions.include.length, 1) + assert.equal(newOptions.include[0].model, 'hello') + done() + }) + it('should merge includes with same model', (done) => { + const newOptions = global.app.services.SequelizeService.mergeOptionDefaults({ + include: [{ model: 'hello', as: 'world' }] + }, { + include: [{ model: 'hello', as: 'planet' }] + }) + assert.equal(newOptions.include.length, 2) + assert.equal(newOptions.include[0].model, 'hello') + assert.equal(newOptions.include[1].model, 'hello') + done() + }) + it('should merge order and fix incorrect instances', (done) => { + const newOptions = global.app.services.SequelizeService.mergeOptionDefaults({ + order: [['created_at','ASC']] + }, { + order: 'updated_at DESC' + }) + assert.equal(newOptions.order.length, 2) + done() + }) + it('should merge wheres', (done) => { + const newOptions = global.app.services.SequelizeService.mergeOptionDefaults({ + where: { name: 'hello'} + }, { + where: { created_at: 'now' } + }) + assert.equal(newOptions.where.name, 'hello') + assert.equal(newOptions.where.created_at, 'now') + done() + }) + it('should merge limit', (done) => { + const newOptions = global.app.services.SequelizeService.mergeOptionDefaults({ + limit: null + }, { + limit: 10 + }) + assert.equal(newOptions.limit, 10) + done() + }) + it('should merge offset', (done) => { + const newOptions = global.app.services.SequelizeService.mergeOptionDefaults({ + offset: null + }, { + offset: 10 + }) + assert.equal(newOptions.offset, 10) + done() + }) + it('should merge with unknown variables', (done) => { + const newOptions = global.app.services.SequelizeService.mergeOptionDefaults({ + hello: 'world' + }, {}) + assert.equal(newOptions.hello, 'world') + done() + }) +})