objection-unique
Advanced tools
# Changelog | ||
## [v1.1.0](https://github.com/seegno/objection-unique/tree/v1.1.0) (2019-10-01) | ||
[Full Changelog](https://github.com/seegno/objection-unique/compare/v1.0.1...v1.1.0) | ||
**Merged pull requests:** | ||
- Support for compound fields [\#15](https://github.com/seegno/objection-unique/pull/15) ([nicolaracco](https://github.com/nicolaracco)) | ||
## [v1.0.1](https://github.com/seegno/objection-unique/tree/v1.0.1) (2018-03-26) | ||
@@ -4,0 +11,0 @@ [Full Changelog](https://github.com/seegno/objection-unique/compare/v1.0.0...v1.0.1) |
32
index.js
@@ -8,3 +8,4 @@ 'use strict'; | ||
const isEmpty = require('lodash.isempty'); | ||
const isNil = require('lodash.isnil'); | ||
const castArray = require('lodash.castarray'); | ||
const compact = require('lodash.compact'); | ||
const util = require('util'); | ||
@@ -82,11 +83,16 @@ | ||
return options.fields.reduce((queries, field, index) => { | ||
if (isNil(this[field])) { | ||
const knex = Model.knex(); | ||
const collection = knex(this.constructor.tableName); | ||
const fields = castArray(field); | ||
if (isEmpty(compact(fields.map(fieldName => this[fieldName])))) { | ||
return queries; | ||
} | ||
const knex = Model.knex(); | ||
const query = knex(this.constructor.tableName) | ||
.select() | ||
.where(field, this[field]) | ||
.limit(1); | ||
const query = ( | ||
fields.reduce( | ||
(subset, fieldName) => subset.where(fieldName, this[fieldName] || queryOptions.old[fieldName]), | ||
collection.select(), | ||
) | ||
).limit(1); | ||
@@ -112,6 +118,10 @@ if (update) { | ||
if (!isEmpty(error)) { | ||
errors[[options.fields[index]]] = [{ | ||
keyword: 'unique', | ||
message: util.format('%s already in use.', options.fields[index]) | ||
}]; | ||
const fields = castArray(options.fields[index]); | ||
fields.forEach(field => { | ||
errors[[field]] = [{ | ||
keyword: 'unique', | ||
message: util.format('%s already in use.', options.fields[index]) | ||
}]; | ||
}); | ||
} | ||
@@ -118,0 +128,0 @@ |
{ | ||
"name": "objection-unique", | ||
"version": "1.0.1", | ||
"version": "1.1.0", | ||
"description": "objection-unique", | ||
@@ -42,4 +42,5 @@ "keywords": [ | ||
"dependencies": { | ||
"lodash.isempty": "^4.4.0", | ||
"lodash.isnil": "^4.0.0" | ||
"lodash.castarray": "^4.4.0", | ||
"lodash.compact": "^3.0.1", | ||
"lodash.isempty": "^4.4.0" | ||
}, | ||
@@ -60,3 +61,3 @@ "devDependencies": { | ||
"pre-commit": "^1.2.2", | ||
"sqlite3": "^3.1.8" | ||
"sqlite3": "^4.0.6" | ||
}, | ||
@@ -63,0 +64,0 @@ "peerDependencies": { |
@@ -36,3 +36,3 @@ # Unique validation for Objection.js | ||
const unique = require('objection-unique')({ | ||
fields: ['email', 'username'], | ||
fields: ['email', 'username', ['phone_prefix','phone_number']], | ||
identifiers: ['id'] | ||
@@ -108,3 +108,3 @@ }); | ||
**fields:** The unique fields. | ||
**fields:** The unique fields. Compound fields can be specified as an array | ||
@@ -117,3 +117,3 @@ **identifiers:** The fields that identifies the model. (Default: ['id']) | ||
const unique = require('objection-unique')({ | ||
fields: ['email', 'username'], | ||
fields: ['email', 'username', ['phone_prefix', 'phone_number']], | ||
identifiers: ['id'] | ||
@@ -120,0 +120,0 @@ }); |
@@ -22,2 +22,3 @@ #!/usr/bin/env node | ||
await knex.schema.dropTableIfExists('Test'); | ||
await knex.schema.dropTableIfExists('CompoundTest'); | ||
@@ -33,3 +34,13 @@ // Create `Test` table. | ||
// Create `CompoundTest` table. | ||
await knex.schema | ||
.createTableIfNotExists('CompoundTest', table => { | ||
table.increments('id').primary(); | ||
table.string('foo'); | ||
table.string('bar'); | ||
table.string('biz'); | ||
table.unique(['foo', 'bar']); | ||
}); | ||
exit(); | ||
})(); |
@@ -8,2 +8,3 @@ | ||
import clearDatabase from './utils/clear-database'; | ||
import compoundModelFactory from './utils/compound-model-factory'; | ||
import modelFactory from './utils/model-factory'; | ||
@@ -202,3 +203,46 @@ | ||
}); | ||
it('when applied to multiple fields should create and update entity.', async () => { | ||
const CompoundTestModel = compoundModelFactory({ | ||
fields: [['bar', 'foo']] | ||
}); | ||
await CompoundTestModel.query().insertAndFetch({ bar: 'bar', foo: 'foo' }); | ||
let result = await CompoundTestModel.query().insertAndFetch({ bar: 'foo', foo: 'bar' }); | ||
result = await result.$query().patchAndFetch({ bar: 'biz' }); | ||
expect(result.bar).toBe('biz'); | ||
}); | ||
it('when applied to multiple fields should throw a `ValidationError` for all fields when patching.', async () => { | ||
const CompoundTestModel = compoundModelFactory({ | ||
fields: [['bar', 'foo']] | ||
}); | ||
await CompoundTestModel.query().insert({ bar: 'arg', foo: 'gar' }); | ||
const result = await CompoundTestModel.query().insertAndFetch({ bar: 'biz', foo: 'gar' }); | ||
try { | ||
await result.$query().patch({ bar: 'arg' }); | ||
fail(); | ||
} catch (e) { | ||
expect(e).toBeInstanceOf(ValidationError); | ||
expect(e.message).toEqual('Unique Validation Failed'); | ||
expect(e.type).toEqual('ModelValidation'); | ||
expect(e.data).toEqual({ | ||
bar: [{ | ||
keyword: 'unique', | ||
message: 'bar,foo already in use.' | ||
}], | ||
foo: [{ | ||
keyword: 'unique', | ||
message: 'bar,foo already in use.' | ||
}] | ||
}); | ||
} | ||
}); | ||
}); | ||
}); |
@@ -14,4 +14,6 @@ | ||
const TestModel = modelFactory(); | ||
const CompoundTestModel = modelFactory(); | ||
await TestModel.query().del(); | ||
await TestModel.query().truncate(); | ||
await CompoundTestModel.query().truncate(); | ||
}; |
Sorry, the diff of this file is not supported yet
403
22.49%162586
-43.13%4
33.33%