@knorm/soft-delete
Advanced tools
Comparing version 1.0.0 to 2.0.0
@@ -49,3 +49,3 @@ const { Knorm } = require('@knorm/knorm'); | ||
knorm.Model = SoftDeleteModel; | ||
knorm.updateModel(SoftDeleteModel); | ||
} | ||
@@ -95,4 +95,4 @@ | ||
addWhereDeleted({ forInsert }) { | ||
if (forInsert) { | ||
addWhereDeleted() { | ||
if (this.config.forInsert) { | ||
return; | ||
@@ -120,5 +120,5 @@ } | ||
prepareSql(sql, options) { | ||
this.addWhereDeleted(options); | ||
return super.prepareSql(sql, options); | ||
prepareSql(sql) { | ||
this.addWhereDeleted(); | ||
return super.prepareSql(sql); | ||
} | ||
@@ -194,3 +194,3 @@ | ||
knorm.Model.Query = knorm.Query = SoftDeleteQuery; | ||
knorm.updateQuery(SoftDeleteQuery); | ||
} | ||
@@ -197,0 +197,0 @@ |
{ | ||
"name": "@knorm/soft-delete", | ||
"version": "1.0.0", | ||
"version": "2.0.0", | ||
"description": "Soft-delete plugin for @knorm/knorm", | ||
@@ -9,8 +9,6 @@ "main": "index.js", | ||
"lint:fix": "eslint --fix .", | ||
"test": "mocha --exit 'test/**/*.spec.js'", | ||
"coverage": "nyc npm test", | ||
"coveralls": "nyc report --reporter=text-lcov | coveralls", | ||
"postgres": "docker-compose exec postgres echo 'postgres running ...' || docker-compose up -d postgres", | ||
"postgres:stop": "docker-compose stop postgres", | ||
"postgres:remove": "docker-compose rm -sf postgres" | ||
"test": "docker-compose run --rm knorm-soft-delete", | ||
"test:mocha": "mocha --exit --recursive", | ||
"coverage": "nyc npm run test:mocha", | ||
"coveralls": "nyc report --reporter=text-lcov | coveralls" | ||
}, | ||
@@ -20,22 +18,27 @@ "author": "Joel Mukuthu <joelmukuthu@gmail.com>", | ||
"peerDependencies": { | ||
"@knorm/knorm": "^1.0.0" | ||
"@knorm/knorm": "^2.0.0" | ||
}, | ||
"devDependencies": { | ||
"@knorm/knorm": "^1.0.0", | ||
"@knorm/paginate": "^1.0.0", | ||
"@knorm/postgres": "^1.0.0", | ||
"coveralls": "^3.0.0", | ||
"eslint": "^4.13.1", | ||
"eslint-config-ganintegrity": "^2.0.2", | ||
"knex": "^0.14.0", | ||
"mocha": "^5.0.4", | ||
"npm-run-all": "^4.1.2", | ||
"nyc": "^11.4.1", | ||
"pg": "^7.4.0", | ||
"prettier": "^1.9.2", | ||
"proxyquire": "^2.0.0", | ||
"sinon": "^5.0.0", | ||
"unexpected": "^10.36.2", | ||
"unexpected-knex": "^1.2.0", | ||
"unexpected-sinon": "^10.8.2" | ||
"@knorm/knorm": "2.0.0", | ||
"@knorm/paginate": "2.0.0", | ||
"@knorm/postgres": "2.0.0", | ||
"@semantic-release/changelog": "3.0.2", | ||
"@semantic-release/git": "7.0.8", | ||
"@semantic-release/github": "5.2.10", | ||
"@semantic-release/npm": "5.1.4", | ||
"coveralls": "3.0.2", | ||
"eslint": "5.13.0", | ||
"eslint-config-ganintegrity": "3.1.4", | ||
"knex": "0.15.2", | ||
"mocha": "5.2.0", | ||
"npm-run-all": "4.1.5", | ||
"nyc": "13.1.0", | ||
"pg": "7.8.0", | ||
"prettier": "1.16.4", | ||
"proxyquire": "2.1.0", | ||
"semantic-release": "15.13.3", | ||
"sinon": "7.2.3", | ||
"unexpected": "11.0.1", | ||
"unexpected-knex": "2.0.0", | ||
"unexpected-sinon": "10.11.0" | ||
}, | ||
@@ -42,0 +45,0 @@ "directories": { |
112
README.md
@@ -7,114 +7,8 @@ # @knorm/soft-delete | ||
[![dependency status](https://david-dm.org/knorm/soft-delete.svg)](https://david-dm.org/knorm/soft-delete) | ||
[![Greenkeeper badge](https://badges.greenkeeper.io/knorm/soft-delete.svg)](https://greenkeeper.io/) | ||
Soft-delete plugin for [knorm](https://www.npmjs.com/package/knorm). | ||
## Installation | ||
## [Documentation](https://knorm.netlify.com/plugins/soft-delete.html) | ||
```bash | ||
npm install --save @knorm/knorm @knorm/soft-delete | ||
``` | ||
> @knorm/soft-delete has a peer dependency on [@knorm/knorm](https://www.npmjs.com/package/@knorm/knorm) | ||
## Usage | ||
```js | ||
const knorm = require('@knorm/knorm'); | ||
const knormSoftDelete = require('@knorm/soft-delete'); | ||
const orm = knorm({ | ||
// knorm options | ||
}).use(knormSoftDelete({ | ||
// knormSoftDelete options | ||
})); | ||
``` | ||
## Options | ||
### name | ||
The name of the plugin, defaults to `'soft-delete'`. | ||
### deleted | ||
The `deleted` field is always added, but the field and column names can be | ||
configured. By default, the field has this config: | ||
- field-name: `deleted` | ||
- column-name: `deleted` | ||
If passed as an object, supports these config options: | ||
- `name` *string, default: deleted*: the field name to use instead of `deleted` | ||
- `column` *string, default: deleted*: the column name to use instead of | ||
`deleted` | ||
### deletedAt | ||
Can either be `true` or an object for further configuration. If `true`, it adds | ||
a field to the `Model` class with this config: | ||
- field-name: `deletedAt` | ||
- column-name: `deleted_at` | ||
If passed as an object, supports these config options: | ||
- `name` *string, default: deletedAt*: the field name to use instead of | ||
`deletedAt` | ||
- `column` *string, default: deleted_at*: the column name to use instead of | ||
`deleted_at` | ||
## How it works | ||
This plugin adds `deleted` (by default) and `deletedAt` (if configured) fields | ||
to your models and also updates your query methods so that the `delete` method | ||
does not actually delete a row but rather sets the `deleted` column to `true` | ||
and `deletedAt` to the current time (i.e. `new Date()`) if the field is enabled. | ||
For `Query.prototype.insert`, `deleted` will be set to `false`. | ||
It also modifies the behaviour of `Query.prototype.fetch`, | ||
`Query.prototype.update` and `Query.prototype.delete` so that they always filter | ||
out soft-deleted rows. To work with soft-deleted rows, use | ||
`Query.prototype.withDeleted`, `Query.prototype.onlyDeleted` or directly use the | ||
`Query.prototype.where` (or `whereNot`, `orWhere`, `orWhereNot`) method: | ||
```js | ||
// to update only soft-deleted rows: | ||
await Model.query.onlyDeleted().update({ foo: 'bar' }); | ||
// or: | ||
await Model.query.where({ deleted: true }).update({ foo: 'bar' }); | ||
// to fetch rows including soft-deleted rows: | ||
await Model.query.withDeleted().where({ foo: 'bar' }).fetch(); | ||
// or: | ||
await Model.query.where({ foo: 'bar', deleted: [ true, false ] }).fetch(); | ||
``` | ||
> **NOTE:** `withDeleted` performs better than | ||
`where({ deleted: [true, false] })` | ||
> `where({ deleted: [true, false] })` translates to | ||
`WHERE deleted IN (true, false)` | ||
> The field name used in the `where` method depends on your | ||
[configuration](#deleted) (but defaults to `deleted`) | ||
This plugin also adds `Query.prototype.restore`, `Model.prototype.restore` and | ||
`Model.restore` methods that can be used to restore soft-deleted records. | ||
Conversely, it also adds `Query.prototype.hardDelete`, | ||
`Model.prototype.hardDelete` and `Model.hardDelete` that can be used to | ||
hard-delete records: | ||
```js | ||
// to delete: | ||
await new Model({ id: 1 }).delete(); | ||
// to restore: | ||
await new Model({ id: 1 }).restore(); | ||
// or: | ||
await Model.restore({ where: { id: 1 } }); | ||
// or to hard-delete: | ||
await new Model({ id: 1 }).hardDelete(); | ||
// or: | ||
await Model.hardDelete({ where: { id: 1 } }); | ||
``` | ||
View the docs on @knorm/knorm's documentation site | ||
[here](https://knorm.netlify.com/plugins/soft-delete.html). |
@@ -11,40 +11,3 @@ const knorm = require('@knorm/knorm'); | ||
.use(require('unexpected-sinon')) | ||
.use(require('unexpected-knex')) | ||
.addAssertion( | ||
'<Promise> to be fulfilled with sorted rows [exhaustively] satisfying <array>', | ||
(expect, subject, value) => { | ||
const ascendingOrder = (a, b) => parseInt(a.id) - parseInt(b.id); | ||
expect.errorMode = 'bubble'; | ||
return expect( | ||
subject, | ||
'to be fulfilled with value satisfying', | ||
subject => { | ||
expect(subject, 'to be an array'); | ||
expect( | ||
subject, | ||
'sorted by', | ||
ascendingOrder, | ||
'to [exhaustively] satisfy', | ||
value | ||
); | ||
} | ||
); | ||
} | ||
) | ||
.addAssertion( | ||
'<knexQuery> to have sorted rows [exhaustively] satisfying <array>', | ||
(expect, subject, value) => { | ||
const ascendingOrder = (a, b) => parseInt(a.id) - parseInt(b.id); | ||
expect.errorMode = 'bubble'; | ||
return expect(subject, 'to have rows satisfying', rows => | ||
expect( | ||
rows, | ||
'sorted by', | ||
ascendingOrder, | ||
'to [exhaustively] satisfy', | ||
value | ||
) | ||
); | ||
} | ||
); | ||
.use(require('unexpected-knex')); | ||
@@ -702,6 +665,6 @@ const { | ||
}).insert(); | ||
const spy = sinon.spy(Query.prototype, 'query'); | ||
const execute = sinon.spy(Query.prototype, 'execute'); | ||
await user.restore({ returning: 'id' }); | ||
await expect(spy, 'to have calls satisfying', () => { | ||
spy( | ||
await expect(execute, 'to have calls satisfying', () => { | ||
execute( | ||
expect.it( | ||
@@ -711,7 +674,7 @@ 'when passed as parameter to', | ||
'to end with', | ||
'RETURNING "user"."id" as "user.id"' | ||
'RETURNING "user"."id" AS "user.id"' | ||
) | ||
); | ||
}); | ||
spy.restore(); | ||
execute.restore(); | ||
}); | ||
@@ -768,6 +731,6 @@ }); | ||
const user = await new User({ id: 1, name: 'one' }).insert(); | ||
const spy = sinon.spy(Query.prototype, 'query'); | ||
const execute = sinon.spy(Query.prototype, 'execute'); | ||
await user.hardDelete({ returning: 'id' }); | ||
await expect(spy, 'to have calls satisfying', () => { | ||
spy( | ||
await expect(execute, 'to have calls satisfying', () => { | ||
execute( | ||
expect.it( | ||
@@ -777,7 +740,7 @@ 'when passed as parameter to', | ||
'to end with', | ||
'RETURNING "user"."id" as "user.id"' | ||
'RETURNING "user"."id" AS "user.id"' | ||
) | ||
); | ||
}); | ||
spy.restore(); | ||
execute.restore(); | ||
}); | ||
@@ -784,0 +747,0 @@ }); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
38591
19
22
922
14
1