Skip to content

Commit c55f75d

Browse files
committed
restructured projetct, compatible with sequelize v6
The project is based on the repository https://github.com/diosney/node-sequelize-noupdate-attributes, now compatible with v6 of sequelize.
0 parents  commit c55f75d

14 files changed

+6355
-0
lines changed

.editorconfig

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# EditorConfig helps developers define and maintain consistent
2+
# coding styles between different editors and IDEs
3+
# editorconfig.org
4+
5+
root = true
6+
7+
[*]
8+
charset = utf-8
9+
end_of_line = lf
10+
indent_size = 2
11+
indent_style = space
12+
insert_final_newline = false
13+
max_line_length = 80
14+
trim_trailing_whitespace = true
15+
16+
[*.md]
17+
trim_trailing_whitespace = false

.eslintrc.json

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"env": {
3+
"commonjs": true,
4+
"es2021": true,
5+
"node": true
6+
},
7+
"extends": ["airbnb-base", "prettier", "plugin:jest/recommended"],
8+
"plugins": ["prettier", "jest"],
9+
"parserOptions": {
10+
"ecmaVersion": 12
11+
},
12+
"rules": {
13+
"prettier/prettier": "error",
14+
"camelcase": "off",
15+
"jest/no-disabled-tests": "warn",
16+
"jest/no-focused-tests": "error",
17+
"jest/no-identical-title": "error",
18+
"jest/prefer-to-have-length": "warn",
19+
"jest/valid-expect": "error",
20+
"no-underscore-dangle": "off"
21+
}
22+
}

.gitignore

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Logs
2+
logs
3+
*.log
4+
5+
# Runtime data
6+
pids
7+
*.pid
8+
*.seed
9+
10+
# Directory for instrumented libs generated by jscoverage/JSCover
11+
lib-cov
12+
13+
# Coverage directory used by tools like istanbul
14+
coverage
15+
16+
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
17+
.grunt
18+
19+
# Compiled binary addons (http://nodejs.org/api/addons.html)
20+
build/Release
21+
22+
# Dependency directory
23+
# Commenting this out is preferred by some people, see
24+
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git-
25+
node_modules
26+
27+
# Users Environment Variables
28+
.lock-wscript
29+
30+
# OS specific ignores
31+
.directory
32+
.idea

.prettierrc.json

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"singleQuote": true,
3+
"trailingComma": "es5",
4+
"printWidth": 80,
5+
"tabWidth": 2,
6+
"semi": true
7+
}

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
## Release notes
2+
3+
### 0.1.0
4+
5+
- restructured project, compatible with sequelize v6.
6+
- The project is based on the repository [node-sequelize-noupdate-attributes](https://github.com/diosney/node-sequelize-noupdate-attributes), now compatible with v6 of sequelize.

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) Diosney Sarmiento
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.

README.md

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# sequelize-noupdate-attributes
2+
3+
A very simple [Sequelize](https://github.com/sequelize/sequelize) plugin which adds **no update** and **readonly** attributes support. Compatible with sequelize v6.
4+
5+
# Warning
6+
7+
The project is based on the repository [node-sequelize-noupdate-attributes](https://github.com/diosney/node-sequelize-noupdate-attributes), now compatible with v6 of sequelize.
8+
9+
## Prerequisites
10+
11+
Have previously installed the `sequelize` package in the project.
12+
13+
## Install
14+
15+
```sh
16+
yarn add -D sequelize-noupdate-attributes
17+
```
18+
19+
## Usage
20+
21+
Add the plugin to the sequelize instance and then set the noupdate
22+
properties in your models, as shown in the basic example below:
23+
24+
```js
25+
var sequelizeNoUpdateAttributes = require('sequelize-noupdate-attributes');
26+
27+
var sequelize = new Sequelize('database', 'user', 'password');
28+
sequelizeNoUpdateAttributes(sequelize); // Note that is the `sequelize` instance the passed reference.
29+
30+
var Post = sequelize.define('Post', {
31+
content: {
32+
type: Sequelize.STRING,
33+
noUpdate: true,
34+
},
35+
});
36+
```
37+
38+
What this do is to mark the `content` attribute so if an update is done, then:
39+
40+
- if the field previous value is null, it will accept the change
41+
- if the field previous value is not null, it will trigger a `SequelizeValidationErrorItem` error.
42+
43+
so, the `content` field becomes a **readonly** after its becomes not null.
44+
45+
Works too with foreign key fields in associations:
46+
47+
```js
48+
models.Post.belongsTo(models.Person, {
49+
as: 'Creator',
50+
foreignKey: {
51+
allowNull: false,
52+
noUpdate: true, // Will mark the `CreatorId` field to be `noUpdate`d.
53+
},
54+
});
55+
```
56+
57+
### Readonly attributes
58+
59+
If you do want truly **readonly** attributes with no modifications at all
60+
being allowed, you can use the `readonly` option as shown below:
61+
62+
```js
63+
var Post = sequelize.define('Post', {
64+
content: {
65+
type: Sequelize.STRING,
66+
noUpdate: {
67+
readOnly: true,
68+
},
69+
},
70+
});
71+
```
72+
73+
which effectively disables any modification on the `content` attribute,
74+
no matter if the previous value was null or not, though exception is
75+
when the record is new.
76+
77+
## Issues
78+
79+
The source is available for download from [GitHub](https://github.com/daviddossantos/sequelize-noupdate-attributes)
80+
and there is a [issue tracker](https://github.com/daviddossantos/sequelize-noupdate-attributes/issues) so you can report bugs there.
81+
82+
## Tests
83+
84+
To run the tests just execute `yarn test`.
85+
86+
## License
87+
88+
The MIT License (MIT)
89+
90+
Copyright (c) David Cruz
91+
92+
Permission is hereby granted, free of charge, to any person obtaining a copy
93+
of this software and associated documentation files (the "Software"), to deal
94+
in the Software without restriction, including without limitation the rights
95+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
96+
copies of the Software, and to permit persons to whom the Software is
97+
furnished to do so, subject to the following conditions:
98+
99+
The above copyright notice and this permission notice shall be included in
100+
all copies or substantial portions of the Software.
101+
102+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
103+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
104+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
105+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
106+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
107+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
108+
THE SOFTWARE.

__tests__/no-update.test.js

+139
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
const { factory } = require('factory-girl');
2+
const { DataTypes, Sequelize } = require('sequelize');
3+
const faker = require('faker/locale/pt_BR');
4+
const sequelizeNoUpdate = require('../lib');
5+
6+
const sequelize = new Sequelize('sqlite::memory:', {
7+
logging: false, // Disables logging
8+
});
9+
10+
sequelizeNoUpdate(sequelize);
11+
12+
const Model_1 = sequelize.define('Model_1', {
13+
attr1: DataTypes.STRING,
14+
attr2: DataTypes.STRING,
15+
});
16+
17+
const Model_2 = sequelize.define('Model_2', {
18+
attr1: {
19+
type: DataTypes.STRING,
20+
noUpdate: true,
21+
},
22+
attr2: {
23+
type: DataTypes.STRING,
24+
noUpdate: false,
25+
},
26+
attr3: DataTypes.STRING,
27+
});
28+
29+
const Model_3 = sequelize.define('Model_3', {
30+
attr1: {
31+
type: DataTypes.STRING,
32+
noUpdate: {
33+
readOnly: true,
34+
},
35+
},
36+
attr2: {
37+
type: DataTypes.STRING,
38+
noUpdate: false,
39+
},
40+
attr3: DataTypes.STRING,
41+
});
42+
43+
factory.define('Model_1', Model_1, {
44+
attr1: faker.name.findName(),
45+
attr2: faker.name.findName(),
46+
attr3: faker.name.findName(),
47+
});
48+
factory.define('Model_2', Model_2, {
49+
attr1: faker.name.findName(),
50+
attr2: faker.name.findName(),
51+
attr3: faker.name.findName(),
52+
});
53+
factory.define('Model_3', Model_3, {
54+
attr1: faker.name.findName(),
55+
attr2: faker.name.findName(),
56+
attr3: faker.name.findName(),
57+
});
58+
59+
describe('if `noUpdate`', () => {
60+
beforeAll(() => {
61+
return sequelize.sync({
62+
force: true,
63+
});
64+
});
65+
66+
describe('was not set', () => {
67+
it('should allow attributes modifications', async () => {
68+
const model_1 = await factory.create('Model_1');
69+
70+
const response = model_1.update(
71+
{ attr1: 'david' },
72+
{
73+
where: { id: model_1.id },
74+
}
75+
);
76+
77+
await expect(response).resolves.toMatchObject(response);
78+
});
79+
});
80+
81+
describe('was set', () => {
82+
it('should allow modifications on attributes without `noUpdate` set', async () => {
83+
const model_2 = await factory.create('Model_2');
84+
85+
const response = model_2.update(
86+
{ attr3: 'david' },
87+
{
88+
where: { id: model_2.id },
89+
}
90+
);
91+
92+
await expect(response).resolves.toMatchObject(response);
93+
});
94+
it('should allow modifications on attributes with `noUpdate=false` set', async () => {
95+
const model_2 = await factory.create('Model_2');
96+
97+
const response = model_2.update(
98+
{ attr2: 'david' },
99+
{
100+
where: { id: model_2.id },
101+
}
102+
);
103+
104+
await expect(response).resolves.toMatchObject(response);
105+
});
106+
});
107+
108+
it('should not allow modifications on attributes with `noUpdate=true` set', async () => {
109+
const model_2 = await factory.create('Model_2');
110+
111+
const response = model_2.update(
112+
{ attr1: 'david' },
113+
{
114+
where: { id: model_2.id },
115+
}
116+
);
117+
118+
await expect(response).rejects.toThrow(
119+
'`attr1` cannot be updated due `noUpdate` constraint'
120+
);
121+
});
122+
123+
describe('and readonly was set', () => {
124+
it('should not allow modifications on attributes with `readOnly=true` set', async () => {
125+
const model_3 = await factory.create('Model_3');
126+
127+
const response = model_3.update(
128+
{ attr1: 'david' },
129+
{
130+
where: { id: model_3.id },
131+
}
132+
);
133+
134+
await expect(response).rejects.toThrow(
135+
'attr1` cannot be updated due `noUpdate:readOnly` constraint'
136+
);
137+
});
138+
});
139+
});

babel.config.js

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module.exports = {
2+
presets: [
3+
[
4+
'@babel/preset-env',
5+
{
6+
targets: {
7+
node: 'current',
8+
},
9+
},
10+
],
11+
],
12+
};

0 commit comments

Comments
 (0)