diff --git a/README.md b/README.md index 446b560..ec0c32f 100644 --- a/README.md +++ b/README.md @@ -114,12 +114,12 @@ You can let bumblebee generate the transformer for you by running: adonis make:transformer User ``` -The class must extend `Adonis/Addons/Bumblebee/TransformerAbstract` and implement at least a `transform` method. +The class must extend `BaseTransformer` and implement at least a `transform` method. ```js -const TransformerAbstract = use('Adonis/Addons/Bumblebee/TransformerAbstract') +const BaseTransformer = use('BaseTransformer') -class UserTransformer extends TransformerAbstract { +class UserTransformer extends BaseTransformer { transform (model) { return { id: model.id, @@ -146,6 +146,8 @@ const users = await User.all() return transform.collection(users, UserTransformer) ``` +*Note:* You can also directly use the namespace of the transformer. `transform.collection(users, 'App/Transformers/UserTransformer')` + *Note:* Passing the Transformer as the second argument will terminate the fluent interface. If you want to chain more methods after the call to `collection` or `item` you should only pass the first argument and then use the `transformWith` method to define the transformer. See [Fluent Interface](#fluent-interface) @@ -158,7 +160,7 @@ Most of the time our data does not only consist of simple properties on the mode ```js class BookTransformer extends TransformerAbstract { - defaultInclude () { + static get defaultInclude () { return [ 'author' ] @@ -180,9 +182,9 @@ class BookTransformer extends TransformerAbstract { module.exports = BookTransformer ``` -Includes defined in the `defaultInclude` method will always be included in the returned data. +Includes defined in the `defaultInclude` getter will always be included in the returned data. -You have to specify the name of the include by returning an array of all includes from the `defaultInclude` method. +You have to specify the name of the include by returning an array of all includes from the `defaultInclude` getter. Then you create an additional Method for each include named like in the example: `include{Name}` The include method returns a new resource, that can either be an `item` or a `collection`. See [Resources](#resources) @@ -196,7 +198,7 @@ The include method returns a new resource, that can either be an `item` or a `co ```js class BookTransformer extends TransformerAbstract { - availableInclude () { + static get availableInclude () { return [ 'author' ] diff --git a/providers/BumblebeeProvider.js b/providers/BumblebeeProvider.js index 18049ef..843b27b 100644 --- a/providers/BumblebeeProvider.js +++ b/providers/BumblebeeProvider.js @@ -29,6 +29,8 @@ class BumblebeeProvider extends ServiceProvider { this.app.bind('Adonis/Addons/Bumblebee', app => { return Bumblebee }) + + this.app.alias('Adonis/Addons/Bumblebee/TransformerAbstract', 'BaseTransformer') } /** diff --git a/src/Bumblebee/Scope.js b/src/Bumblebee/Scope.js index eb88f80..ecd4a8f 100644 --- a/src/Bumblebee/Scope.js +++ b/src/Bumblebee/Scope.js @@ -1,5 +1,7 @@ 'use strict' +const { ioc } = require('@adonisjs/fold') + const TransformerAbstract = require('./TransformerAbstract') const Resources = require('./Resources') @@ -29,7 +31,7 @@ class Scope { /** * Passes the data through the transformers and serializers and returns the transformed data */ - async toArray () { + async toJSON () { // run the transformation on the data let [rawData] = await this._executeResourceTransformers() @@ -174,6 +176,11 @@ class Scope { * @param {*} Transformer */ _getTransformerInstance (Transformer) { + // if the transformer is a string, use the IoC to fetch the instance. + if (typeof Transformer === 'string') { + return ioc.use(Transformer) + } + // if the transformer is a class, create a new instance if (Transformer && Transformer.prototype instanceof TransformerAbstract) { return new Transformer() @@ -199,8 +206,8 @@ class Scope { * @param {*} Transformer */ _transformerHasIncludes (Transformer) { - let defaultInclude = Transformer.defaultInclude() - let availableInclude = Transformer.availableInclude() + let defaultInclude = Transformer.constructor.defaultInclude + let availableInclude = Transformer.constructor.availableInclude return defaultInclude.length > 0 || availableInclude.length > 0 } diff --git a/src/Bumblebee/TransformerAbstract.js b/src/Bumblebee/TransformerAbstract.js index e9e60b6..2d29eb9 100644 --- a/src/Bumblebee/TransformerAbstract.js +++ b/src/Bumblebee/TransformerAbstract.js @@ -12,14 +12,14 @@ class TransformerAbstract { /* * Resources that can be included if requested */ - availableInclude () { + static get availableInclude () { return [] } /* * List of resources to automatically include */ - defaultInclude () { + static get defaultInclude () { return [] } @@ -82,7 +82,7 @@ class TransformerAbstract { // if the include uses a resource, run the data through the transformer chain if (resource instanceof Resources.ResourceAbstract) { - includeData[include] = await this._createChildScopeFor(parentScope, resource, include).toArray() + includeData[include] = await this._createChildScopeFor(parentScope, resource, include).toJSON() } else { // otherwise, return the data as is includeData[include] = resource @@ -115,9 +115,9 @@ class TransformerAbstract { * @param {*} parentScope */ _figureOutWhichIncludes (parentScope) { - let includes = this.defaultInclude() + let includes = this.constructor.defaultInclude - let requestedAvailableIncludes = this.availableInclude().filter(i => parentScope._isRequested(i)) + let requestedAvailableIncludes = this.constructor.availableInclude.filter(i => parentScope._isRequested(i)) return includes.concat(requestedAvailableIncludes) } diff --git a/src/Bumblebee/index.js b/src/Bumblebee/index.js index eb6861d..67b57da 100644 --- a/src/Bumblebee/index.js +++ b/src/Bumblebee/index.js @@ -58,7 +58,7 @@ class Bumblebee { if (transformer) { this.transformWith(transformer) - return this.toArray() + return this.toJSON() } return this @@ -76,7 +76,7 @@ class Bumblebee { if (transformer) { this.transformWith(transformer) - return this.toArray() + return this.toJSON() } return this @@ -115,7 +115,7 @@ class Bumblebee { if (transformer) { this.transformWith(transformer) - return this.toArray() + return this.toJSON() } return this @@ -191,7 +191,14 @@ class Bumblebee { * Terminates the fluid interface and returns the transformed data. */ toArray () { - return this._createData().toArray() + return this.toJSON() + } + + /** + * Terminates the fluid interface and returns the transformed data. + */ + toJSON () { + return this._createData().toJSON() } /** diff --git a/test/available-includes.spec.js b/test/available-includes.spec.js index cdb4cc4..3212ecc 100644 --- a/test/available-includes.spec.js +++ b/test/available-includes.spec.js @@ -16,7 +16,7 @@ const Bumblebee = require('../src/Bumblebee') const TransformerAbstract = require('../src/Bumblebee/TransformerAbstract') class Book1Transformer extends TransformerAbstract { - availableInclude () { + static get availableInclude () { return [ 'author', 'characters' @@ -40,7 +40,7 @@ class Book1Transformer extends TransformerAbstract { } class Book2Transformer extends TransformerAbstract { - availableInclude () { + static get availableInclude () { return [ 'author', 'characters' @@ -62,7 +62,7 @@ class Book2Transformer extends TransformerAbstract { } class Book2CharacterTransformer extends TransformerAbstract { - availableInclude () { + static get availableInclude () { return [ 'actor' ] diff --git a/test/context.spec.js b/test/context.spec.js index b903a34..7844560 100644 --- a/test/context.spec.js +++ b/test/context.spec.js @@ -17,7 +17,7 @@ const Bumblebee = require('../src/Bumblebee') const TransformerAbstract = require('../src/Bumblebee/TransformerAbstract') class IDTransformer extends TransformerAbstract { - availableInclude () { + static get availableInclude () { return [ 'ienv' ] @@ -50,7 +50,7 @@ test.group('Context', (group) => { .item(data) .transformWith(IDTransformer) .withContext(ctx) - .toArray() + .toJSON() assert.equal(transformed.id, 3) assert.equal(transformed.env, 'testing') @@ -67,7 +67,7 @@ test.group('Context', (group) => { .include('ienv') .transformWith(IDTransformer) .withContext(ctx) - .toArray() + .toJSON() assert.equal(transformed.id, 3) assert.equal(transformed.env, 'testing') @@ -83,7 +83,7 @@ test.group('Context', (group) => { let transformed = await transform .item(data) .transformWith(model => ({ id: model.item_id })) - .toArray() + .toJSON() assert.equal(transformed.id, 3) }) @@ -97,7 +97,7 @@ test.group('Context', (group) => { let transformed = await transform .item(data) .transformWith(IDTransformer) - .toArray() + .toJSON() assert.equal(transformed.id, 3) assert.equal(transformed.env, 'testing') @@ -119,7 +119,7 @@ test.group('Context', (group) => { let transformed = await Bumblebee.create() .item(data) .transformWith(UserTransformer) - .toArray() + .toJSON() assert.equal(transformed.id, 42) }) diff --git a/test/detault-includes.spec.js b/test/detault-includes.spec.js index 4514f8c..7cdbab5 100644 --- a/test/detault-includes.spec.js +++ b/test/detault-includes.spec.js @@ -15,7 +15,7 @@ const Bumblebee = require('../src/Bumblebee') const TransformerAbstract = require('../src/Bumblebee/TransformerAbstract') class Book1Transformer extends TransformerAbstract { - defaultInclude () { + static get defaultInclude () { return [ 'author' ] @@ -35,7 +35,7 @@ class Book1Transformer extends TransformerAbstract { } class Book2Transformer extends TransformerAbstract { - defaultInclude () { + static get defaultInclude () { return [ 'author', 'characters', @@ -82,7 +82,7 @@ test.group('Default Includes', () => { let transformed = await Bumblebee.create() .item(data) .transformWith(Book1Transformer) - .toArray() + .toJSON() assert.deepEqual(transformed, { id: 1, @@ -110,7 +110,7 @@ test.group('Default Includes', () => { let transformed = await Bumblebee.create() .item(data) .transformWith(Book2Transformer) - .toArray() + .toJSON() assert.deepEqual(transformed, { title: 'Harry Potter and the Chamber of Secrets', diff --git a/test/eagerload.spec.js b/test/eagerload.spec.js index bc3dfcd..fa49ae3 100644 --- a/test/eagerload.spec.js +++ b/test/eagerload.spec.js @@ -15,7 +15,7 @@ const Bumblebee = require('../src/Bumblebee') const TransformerAbstract = require('../src/Bumblebee/TransformerAbstract') class Book1Transformer extends TransformerAbstract { - availableInclude () { + static get availableInclude () { return [ 'author', 'dragon', @@ -83,7 +83,7 @@ test.group('EagerLoading', (group) => { .item(data) .transformWith(Book1Transformer) .include(['author']) - .toArray() + .toJSON() assert.equal(data.$loadCalled, 1) assert.deepEqual(transformed, { @@ -101,7 +101,7 @@ test.group('EagerLoading', (group) => { .item(data) .transformWith(Book1Transformer) .include(['author', 'characters']) - .toArray() + .toJSON() assert.equal(data.$loadCalled, 1) assert.deepEqual(transformed, { @@ -135,7 +135,7 @@ test.group('EagerLoading', (group) => { .item(data) .transformWith(Book1Transformer) .include(['author']) - .toArray() + .toJSON() assert.equal(data.$loadCalled, 1) assert.deepEqual(transformed, { @@ -160,7 +160,7 @@ test.group('EagerLoading', (group) => { .item(data) .transformWith(Book1Transformer) .include(['dragon']) - .toArray() + .toJSON() assert.equal(data.$loadCalled, 1) assert.deepEqual(transformed, { diff --git a/test/exception.spec.js b/test/exception.spec.js index c7ac452..d28e858 100644 --- a/test/exception.spec.js +++ b/test/exception.spec.js @@ -16,7 +16,7 @@ const Bumblebee = require('../src/Bumblebee') const TransformerAbstract = require('../src/Bumblebee/TransformerAbstract') class IDTransformer extends TransformerAbstract { - availableInclude () { + static get availableInclude () { return [ 'notexisting' ] @@ -40,7 +40,7 @@ test.group('Exception', (group) => { .item(data) .include(['notexisting']) .transformWith(IDTransformer) - .toArray() + .toJSON() } catch ({ message }) { assert.equal(message, 'A method called \'includeNotexisting\' could not be found in \'IDTransformer\'') } @@ -70,7 +70,7 @@ test.group('Exception', (group) => { try { await Bumblebee.create() ._setData('ResourceAbstract', [{ item_id: 3 }]) - .toArray() + .toJSON() } catch ({ message }) { assert.equal(message, 'This resourcetype is not supported. Use Item or Collection') } diff --git a/test/includes.spec.js b/test/includes.spec.js index 249f53e..040170b 100644 --- a/test/includes.spec.js +++ b/test/includes.spec.js @@ -16,7 +16,7 @@ const Bumblebee = require('../src/Bumblebee') const TransformerAbstract = require('../src/Bumblebee/TransformerAbstract') class Book2Transformer extends TransformerAbstract { - availableInclude () { + static get availableInclude () { return [ 'author', 'characters', @@ -42,7 +42,7 @@ class Book2Transformer extends TransformerAbstract { } class Book2CharacterTransformer extends TransformerAbstract { - availableInclude () { + static get availableInclude () { return [ 'actor' ] @@ -60,7 +60,7 @@ class Book2CharacterTransformer extends TransformerAbstract { } class CamelCaseTransformer extends TransformerAbstract { - availableInclude () { + static get availableInclude () { return [ 'authorName' ] @@ -123,7 +123,7 @@ test.group('Includes can be an array or a string', () => { .include(['author', 'characters.actor']) .item(data) .transformWith(Book2Transformer) - .toArray() + .toJSON() assert.deepEqual(transformed, expectedTransform) @@ -131,7 +131,7 @@ test.group('Includes can be an array or a string', () => { .include('author,characters.actor') .item(data) .transformWith(Book2Transformer) - .toArray() + .toJSON() assert.deepEqual(transformedFromString, expectedTransform) }) @@ -152,7 +152,7 @@ test.group('Includes can be an array or a string', () => { .item(data) .transformWith(Book2Transformer) .withContext(ctx) - .toArray() + .toJSON() assert.deepEqual(transformed, expectedTransform) @@ -163,7 +163,7 @@ test.group('Includes can be an array or a string', () => { .item(data) .transformWith(Book2Transformer) .withContext(ctx) - .toArray() + .toJSON() assert.deepEqual(transformed, { title: 'Harry Potter and the Deathly Hallows' }) }) @@ -173,7 +173,7 @@ test.group('Includes can be an array or a string', () => { .include(['school']) .item(data) .transformWith(Book2Transformer) - .toArray() + .toJSON() assert.deepEqual(transformed, { title: 'Harry Potter and the Deathly Hallows', @@ -204,7 +204,7 @@ test.group('Includes can be an array or a string', () => { .include(['name']) .item(data) .transformWith(CollisionTransformer) - .toArray() + .toJSON() assert.deepEqual(transformed, { name: 'Harry Potter and the Deathly Hallows' @@ -216,7 +216,7 @@ test.group('Includes can be an array or a string', () => { .include(['authorName']) .item(data) .transformWith(CamelCaseTransformer) - .toArray() + .toJSON() assert.deepEqual(transformed, { name: 'Harry Potter and the Deathly Hallows', @@ -229,7 +229,7 @@ test.group('Includes can be an array or a string', () => { .include(['author_name']) .item(data) .transformWith(CamelCaseTransformer) - .toArray() + .toJSON() assert.deepEqual(transformed, { name: 'Harry Potter and the Deathly Hallows', diff --git a/test/meta.spec.js b/test/meta.spec.js index 0c3d177..b1fc7cb 100644 --- a/test/meta.spec.js +++ b/test/meta.spec.js @@ -21,7 +21,7 @@ test.group('Meta', () => { .item(data) .meta({ link: 'rhwilr/adonis-bumblebee' }) .transformWith(d => ({ id: d.id })) - .toArray() + .toJSON() assert.deepEqual(transformed, { id: 3, meta: { link: 'rhwilr/adonis-bumblebee' } }) }) @@ -33,7 +33,7 @@ test.group('Meta', () => { .collection(data) .meta({ link: 'rhwilr/adonis-bumblebee' }) .transformWith(d => ({ id: d.id })) - .toArray() + .toJSON() assert.deepEqual(transformed, { data: [{ id: 3 }, { id: 7 }], meta: { link: 'rhwilr/adonis-bumblebee' } }) }) @@ -45,7 +45,7 @@ test.group('Meta', () => { .item(data) .meta({ link: 'rhwilr/adonis-bumblebee' }) .transformWith(d => (d)) - .toArray() + .toJSON() assert.deepEqual(transformed, { data: 1, meta: { link: 'rhwilr/adonis-bumblebee' } }) }) diff --git a/test/pagination.spec.js b/test/pagination.spec.js index 4c93cfc..556b4e0 100644 --- a/test/pagination.spec.js +++ b/test/pagination.spec.js @@ -29,7 +29,7 @@ test.group('Pagination', () => { .paginate(data) .transformWith(d => ({ id: d.item_id })) .serializeWith('data') - .toArray() + .toJSON() assert.deepEqual(transformed, { pagination: { @@ -50,7 +50,7 @@ test.group('Pagination', () => { .paginate(data) .transformWith(d => ({ id: d.item_id })) .serializeWith('data') - .toArray() + .toJSON() assert.deepEqual(transformed, { pagination: { @@ -75,7 +75,7 @@ test.group('Pagination', () => { total: 5 } - let transformed = await bumblebee.toArray() + let transformed = await bumblebee.toJSON() assert.deepEqual(transformed, { data: { id: 3 } @@ -93,7 +93,7 @@ test.group('Pagination', () => { total: 5 } - let transformed = await bumblebee.toArray() + let transformed = await bumblebee.toJSON() assert.deepEqual(transformed, null) }) diff --git a/test/promise.spec.js b/test/promise.spec.js index c7f5965..aba3a83 100644 --- a/test/promise.spec.js +++ b/test/promise.spec.js @@ -16,7 +16,7 @@ const setup = require('./setup') const TransformerAbstract = require('../src/Bumblebee/TransformerAbstract') class BookTransformer extends TransformerAbstract { - defaultInclude () { + static get defaultInclude () { return [ 'author' ] diff --git a/test/serializers/data-serializer.spec.js b/test/serializers/data-serializer.spec.js index fcdc442..fa0bdc3 100644 --- a/test/serializers/data-serializer.spec.js +++ b/test/serializers/data-serializer.spec.js @@ -15,7 +15,7 @@ const Bumblebee = require('../../src/Bumblebee') const TransformerAbstract = require('../../src/Bumblebee/TransformerAbstract') class IDTransformer extends TransformerAbstract { - availableInclude () { + static get availableInclude () { return [ 'primitive', 'item', diff --git a/test/serializers/plain-serializer.spec.js b/test/serializers/plain-serializer.spec.js index 6dd286c..4f7f49d 100644 --- a/test/serializers/plain-serializer.spec.js +++ b/test/serializers/plain-serializer.spec.js @@ -15,7 +15,7 @@ const Bumblebee = require('../../src/Bumblebee') const TransformerAbstract = require('../../src/Bumblebee/TransformerAbstract') class IDTransformer extends TransformerAbstract { - availableInclude () { + static get availableInclude () { return [ 'primitive', 'item', diff --git a/test/transformer.spec.js b/test/transformer.spec.js index 6c87c50..e2e2ea4 100644 --- a/test/transformer.spec.js +++ b/test/transformer.spec.js @@ -10,6 +10,7 @@ */ const test = require('japa') +const { ioc } = require('@adonisjs/fold') const Bumblebee = require('../src/Bumblebee') const TransformerAbstract = require('../src/Bumblebee/TransformerAbstract') @@ -29,13 +30,41 @@ class PrimitiveTransformer extends TransformerAbstract { } test.group('Transformer', () => { + test('a transformer can be resolved using its namespace', async (assert) => { + ioc.bind('App/Transformers/IDTransformer', () => new IDTransformer()) + + let data = { item_id: 3 } + + let transformed = await Bumblebee.create() + .item(data) + .transformWith('App/Transformers/IDTransformer') + .toJSON() + + assert.equal(transformed.id, 3) + }) + + test('an exception is thrown when namespace doesn\'t exists', async (assert) => { + assert.plan(1) + + let data = { item_id: 3 } + + try { + await Bumblebee.create() + .item(data) + .transformWith('IDontExists') + .toJSON() + } catch (e) { + assert.equal(e.message, 'Cannot find module \'IDontExists\'') + } + }) + test('a transformer maps item properties', async (assert) => { let data = { item_id: 3 } let transformed = await Bumblebee.create() .item(data) .transformWith(IDTransformer) - .toArray() + .toJSON() assert.equal(transformed.id, 3) }) @@ -46,7 +75,7 @@ test.group('Transformer', () => { let transformed = await Bumblebee.create() .collection(data) .transformWith(IDTransformer) - .toArray() + .toJSON() assert.deepEqual(transformed, [{ id: 3 }, { id: 55 }]) }) @@ -57,7 +86,7 @@ test.group('Transformer', () => { let transformed = await Bumblebee.create() .collection(data) .transformWith(PrimitiveTransformer) - .toArray() + .toJSON() assert.deepEqual(transformed, ['John', 'Bob']) }) @@ -71,7 +100,7 @@ test.group('Transformer', () => { await Bumblebee.create() .item(data) .transformWith(InvalidTransformer) - .toArray() + .toJSON() } catch ({ message }) { assert.equal(message, 'You have to implement the method transform!') } @@ -85,7 +114,7 @@ test.group('Transformer', () => { .transformWith(model => ({ id: model.item_id })) - .toArray() + .toJSON() assert.equal(transformed.id, 3) }) @@ -98,7 +127,7 @@ test.group('Transformer', () => { await Bumblebee.create() .item(data) .transformWith({}) - .toArray() + .toJSON() } catch ({ message }) { assert.equal(message, 'A transformer must be a function or a class extending TransformerAbstract') } @@ -107,7 +136,7 @@ test.group('Transformer', () => { await Bumblebee.create() .item(data) .transformWith(undefined) - .toArray() + .toJSON() } catch ({ message }) { assert.equal(message, 'A transformer must be a function or a class extending TransformerAbstract') } @@ -116,7 +145,7 @@ test.group('Transformer', () => { test('the null transformer returns always null', async (assert) => { let transformed = await Bumblebee.create() .null() - .toArray() + .toJSON() assert.equal(transformed, null) }) @@ -125,7 +154,7 @@ test.group('Transformer', () => { let transformed = await Bumblebee.create() .item(null) .transformWith(IDTransformer) - .toArray() + .toJSON() assert.deepEqual(transformed, null) }) @@ -134,7 +163,7 @@ test.group('Transformer', () => { let transformed = await Bumblebee.create() .collection(null) .transformWith(IDTransformer) - .toArray() + .toJSON() assert.deepEqual(transformed, null) }) @@ -142,15 +171,15 @@ test.group('Transformer', () => { test('data and transformer can be passed to create method directly', async (assert) => { let item = { item_id: 3 } - let transformedItem = await Bumblebee.create(item, IDTransformer).toArray() + let transformedItem = await Bumblebee.create(item, IDTransformer).toJSON() assert.equal(transformedItem.id, 3) let collection = [{ item_id: 3 }, { item_id: 55 }] - let transformedCollection = await Bumblebee.create(collection, IDTransformer).toArray() + let transformedCollection = await Bumblebee.create(collection, IDTransformer).toJSON() assert.deepEqual(transformedCollection, [{ id: 3 }, { id: 55 }]) - let transformedNull = await Bumblebee.create(null, IDTransformer).toArray() + let transformedNull = await Bumblebee.create(null, IDTransformer).toJSON() assert.deepEqual(transformedNull, null) }) })