Compare commits
20 Commits
Author | SHA1 | Date | |
---|---|---|---|
823a65991a | |||
f9b997b65c | |||
7c2b146eed | |||
a54683e29a | |||
a855665777 | |||
034287672c | |||
e8c0e61c6b | |||
a64a55af0d | |||
6c46ff68d0 | |||
29ee49fc62 | |||
d142e6c553 | |||
fb06d9cd27 | |||
b9e150200f | |||
fe6881099f | |||
6786b9b487 | |||
aa06808ab2 | |||
2d1ab6b75a | |||
2ea6c2e3a8 | |||
c0cb2c44e0 | |||
e7bc048a46 |
13
.babelrc
13
.babelrc
@ -1,3 +1,14 @@
|
|||||||
{
|
{
|
||||||
"stage": 1
|
"presets": [
|
||||||
|
"stage-1"
|
||||||
|
],
|
||||||
|
"plugins": [
|
||||||
|
"transform-object-rest-spread",
|
||||||
|
"transform-class-properties",
|
||||||
|
"add-module-exports",
|
||||||
|
"closure-elimination",
|
||||||
|
"transform-decorators-legacy",
|
||||||
|
"transform-es2015-modules-commonjs"
|
||||||
|
],
|
||||||
|
"sourceMaps": true
|
||||||
}
|
}
|
||||||
|
29
Gruntfile.js
29
Gruntfile.js
@ -1,29 +0,0 @@
|
|||||||
module.exports = function(grunt) {
|
|
||||||
grunt.initConfig({
|
|
||||||
babel: {
|
|
||||||
scripts: {
|
|
||||||
files: [{
|
|
||||||
expand: true,
|
|
||||||
cwd: 'src',
|
|
||||||
src: '**/*.js',
|
|
||||||
dest: 'build/'
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
clean: {
|
|
||||||
files: ['build/**/*.js']
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
scripts: {
|
|
||||||
files: ['src/**/*.js', 'server/**/*.js'],
|
|
||||||
tasks: ['babel']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
grunt.loadNpmTasks('grunt-babel');
|
|
||||||
grunt.loadNpmTasks('grunt-contrib-clean');
|
|
||||||
grunt.loadNpmTasks('grunt-contrib-watch');
|
|
||||||
|
|
||||||
grunt.registerTask('default', ['clean', 'babel']);
|
|
||||||
};
|
|
33
README.md
33
README.md
@ -28,11 +28,42 @@ await register({
|
|||||||
register: require('hapi-sequelize-crud'),
|
register: require('hapi-sequelize-crud'),
|
||||||
options: {
|
options: {
|
||||||
prefix: '/v1',
|
prefix: '/v1',
|
||||||
defaultConfig: { ... } // passed as `config` to all routes created
|
name: 'db', // the same name you used for configuring `hapi-sequelize` (options.name)
|
||||||
|
defaultConfig: { ... }, // passed as `config` to all routes created
|
||||||
|
models: ['cat', 'dog'] // only the cat and dog models will have routes created
|
||||||
|
// or
|
||||||
|
models: [
|
||||||
|
// possible methods: list, get, scope, create, destroy, destroyAll, destroyScope, update
|
||||||
|
// the cat model only has get and list methods enabled
|
||||||
|
{model: 'cat', methods: ['get', 'list']},
|
||||||
|
// the dog model has all methods enabled
|
||||||
|
{model: 'dog'},
|
||||||
|
// the cow model also has all methods enabled
|
||||||
|
'cow',
|
||||||
|
// the bat model as a custom config for the list method, but uses the default config for create.
|
||||||
|
// `config` if provided, overrides the default config
|
||||||
|
{model: 'bat', methods: ['list'], config: { ... }},
|
||||||
|
{model: 'bat', methods: ['create']}
|
||||||
|
]
|
||||||
|
models: {
|
||||||
|
bat: {
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Methods
|
||||||
|
* list: get all rows in a table
|
||||||
|
* get: get a single row
|
||||||
|
* scope: reference a [sequelize scope](http://docs.sequelizejs.com/en/latest/api/model/#scopeoptions-model)
|
||||||
|
* create: create a new row
|
||||||
|
* destroy: delete a row
|
||||||
|
* destroyAll: delete all models in the table
|
||||||
|
* destroyScope: use a [sequelize scope](http://docs.sequelizejs.com/en/latest/api/model/#scopeoptions-model) to find rows, then delete them
|
||||||
|
* update: update a row
|
||||||
|
|
||||||
|
|
||||||
Please note that you should register `hapi-sequelize-crud` after defining your
|
Please note that you should register `hapi-sequelize-crud` after defining your
|
||||||
associations.
|
associations.
|
||||||
|
|
||||||
|
26
package.json
26
package.json
@ -1,19 +1,21 @@
|
|||||||
{
|
{
|
||||||
"name": "hapi-sequelize-crud",
|
"name": "@getable/hapi-sequelize-crud",
|
||||||
"version": "2.1.0",
|
"version": "2.5.1",
|
||||||
"description": "Hapi plugin that automatically generates RESTful API for CRUD",
|
"description": "Hapi plugin that automatically generates RESTful API for CRUD",
|
||||||
"main": "build/index.js",
|
"main": "build/index.js",
|
||||||
"config": {
|
"config": {
|
||||||
"ghooks": {
|
"ghooks": {
|
||||||
"pre-commit": "npm run lint && grunt"
|
"pre-commit": "npm run lint && npm run build"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "eslint src test",
|
"lint": "eslint src test",
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"build": "scripty",
|
||||||
|
"watch": "scripty"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"git": "https://github.com/mdibaiee/hapi-sequelize-crud"
|
"git": "https://github.com/Getable/hapi-sequelize-crud"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"build"
|
"build"
|
||||||
@ -21,14 +23,16 @@
|
|||||||
"author": "Mahdi Dibaiee <mdibaiee@aol.com> (http://dibaiee.ir/)",
|
"author": "Mahdi Dibaiee <mdibaiee@aol.com> (http://dibaiee.ir/)",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel": "5.8.3",
|
"babel-cli": "^6.10.1",
|
||||||
|
"babel-plugin-add-module-exports": "^0.2.1",
|
||||||
|
"babel-plugin-closure-elimination": "^1.0.6",
|
||||||
|
"babel-plugin-transform-decorators-legacy": "^1.3.4",
|
||||||
|
"babel-plugin-transform-es2015-modules-commonjs": "^6.10.3",
|
||||||
|
"babel-preset-stage-1": "^6.5.0",
|
||||||
"eslint": "2.10.2",
|
"eslint": "2.10.2",
|
||||||
"eslint-config-pichak": "1.0.1",
|
"eslint-config-pichak": "1.1.0",
|
||||||
"ghooks": "1.0.3",
|
"ghooks": "1.0.3",
|
||||||
"grunt": "0.4.5",
|
"scripty": "^1.6.0"
|
||||||
"grunt-babel": "5.0.3",
|
|
||||||
"grunt-contrib-clean": "0.7.0",
|
|
||||||
"grunt-contrib-watch": "0.6.1"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"babel": "5.8.3",
|
"babel": "5.8.3",
|
||||||
|
15
scripts/build.sh
Executable file
15
scripts/build.sh
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# strict mode http://redsymbol.net/articles/unofficial-bash-strict-mode/
|
||||||
|
set -euo pipefail
|
||||||
|
IFS=$'\n\t'
|
||||||
|
|
||||||
|
|
||||||
|
source "scripts/env.sh"
|
||||||
|
|
||||||
|
babel="./node_modules/.bin/babel"
|
||||||
|
|
||||||
|
build () {
|
||||||
|
$babel "$SRC_DIR" --out-dir "$OUT_DIR" $@
|
||||||
|
}
|
||||||
|
|
||||||
|
build $@
|
7
scripts/env.sh
Normal file
7
scripts/env.sh
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# strict mode http://redsymbol.net/articles/unofficial-bash-strict-mode/
|
||||||
|
set -euo pipefail
|
||||||
|
IFS=$'\n\t'
|
||||||
|
|
||||||
|
export SRC_DIR="./src"
|
||||||
|
export OUT_DIR="./build"
|
6
scripts/watch.sh
Executable file
6
scripts/watch.sh
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# strict mode http://redsymbol.net/articles/unofficial-bash-strict-mode/
|
||||||
|
set -euo pipefail
|
||||||
|
IFS=$'\n\t'
|
||||||
|
|
||||||
|
./scripts/build.sh --watch
|
@ -14,15 +14,15 @@ export default (server, a, b, names, options) => {
|
|||||||
|
|
||||||
@error
|
@error
|
||||||
async handler(request, reply) {
|
async handler(request, reply) {
|
||||||
let instanceb = await b.findOne({
|
const instanceb = await b.findOne({
|
||||||
where: {
|
where: {
|
||||||
id: request.params.bid,
|
[b.primaryKeyField]: request.params.bid,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
let instancea = await a.findOne({
|
const instancea = await a.findOne({
|
||||||
where: {
|
where: {
|
||||||
id: request.params.aid,
|
[a.primaryKeyField]: request.params.aid,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -28,18 +28,23 @@ export const get = (server, a, b, names) => {
|
|||||||
async handler(request, reply) {
|
async handler(request, reply) {
|
||||||
const include = parseInclude(request);
|
const include = parseInclude(request);
|
||||||
|
|
||||||
const base = a.findOne({
|
const base = await a.findOne({
|
||||||
where: {
|
where: {
|
||||||
id: request.params.aid,
|
[a.primaryKeyField]: request.params.aid,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const method = getMethod(base, names.b);
|
const method = getMethod(base, names.b);
|
||||||
|
|
||||||
const list = await method({ where: {
|
const list = await method({ where: {
|
||||||
id: request.params.bid,
|
[b.primaryKeyField]: request.params.bid,
|
||||||
}, include });
|
}, include });
|
||||||
|
|
||||||
|
if (Array.isArray(list)) {
|
||||||
|
reply(list[0]);
|
||||||
|
} else {
|
||||||
reply(list);
|
reply(list);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
config: defaultConfig,
|
config: defaultConfig,
|
||||||
@ -58,7 +63,7 @@ export const list = (server, a, b, names) => {
|
|||||||
|
|
||||||
const base = await a.findOne({
|
const base = await a.findOne({
|
||||||
where: {
|
where: {
|
||||||
id: request.params.aid,
|
[a.primaryKeyField]: request.params.aid,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -73,7 +78,7 @@ export const list = (server, a, b, names) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const scope = (server, a, b, names) => {
|
export const scope = (server, a, b, names) => {
|
||||||
let scopes = Object.keys(b.options.scopes);
|
const scopes = Object.keys(b.options.scopes);
|
||||||
|
|
||||||
server.route({
|
server.route({
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
@ -86,7 +91,7 @@ export const scope = (server, a, b, names) => {
|
|||||||
|
|
||||||
const base = await a.findOne({
|
const base = await a.findOne({
|
||||||
where: {
|
where: {
|
||||||
id: request.params.aid,
|
[a.primaryKeyField]: request.params.aid,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -112,7 +117,7 @@ export const scope = (server, a, b, names) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const scopeScope = (server, a, b, names) => {
|
export const scopeScope = (server, a, b, names) => {
|
||||||
let scopes = {
|
const scopes = {
|
||||||
a: Object.keys(a.options.scopes),
|
a: Object.keys(a.options.scopes),
|
||||||
b: Object.keys(b.options.scopes),
|
b: Object.keys(b.options.scopes),
|
||||||
};
|
};
|
||||||
@ -126,7 +131,7 @@ export const scopeScope = (server, a, b, names) => {
|
|||||||
const include = parseInclude(request);
|
const include = parseInclude(request);
|
||||||
const where = parseWhere(request);
|
const where = parseWhere(request);
|
||||||
|
|
||||||
let list = await b.scope(request.params.scopeb).findAll({
|
const list = await b.scope(request.params.scopeb).findAll({
|
||||||
where,
|
where,
|
||||||
include: include.concat({
|
include: include.concat({
|
||||||
model: a.scope(request.params.scopea),
|
model: a.scope(request.params.scopea),
|
||||||
@ -159,7 +164,7 @@ export const destroy = (server, a, b, names) => {
|
|||||||
|
|
||||||
const base = await a.findOne({
|
const base = await a.findOne({
|
||||||
where: {
|
where: {
|
||||||
id: request.params.aid,
|
[a.primaryKeyField]: request.params.aid,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -175,7 +180,7 @@ export const destroy = (server, a, b, names) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const destroyScope = (server, a, b, names) => {
|
export const destroyScope = (server, a, b, names) => {
|
||||||
let scopes = Object.keys(b.options.scopes);
|
const scopes = Object.keys(b.options.scopes);
|
||||||
|
|
||||||
server.route({
|
server.route({
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
@ -188,7 +193,7 @@ export const destroyScope = (server, a, b, names) => {
|
|||||||
|
|
||||||
const base = await a.findOne({
|
const base = await a.findOne({
|
||||||
where: {
|
where: {
|
||||||
id: request.params.aid,
|
[a.primarykeyField]: request.params.aid,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -228,7 +233,7 @@ export const update = (server, a, b, names) => {
|
|||||||
|
|
||||||
const base = await a.findOne({
|
const base = await a.findOne({
|
||||||
where: {
|
where: {
|
||||||
id: request.params.aid,
|
[a.primaryKeyField]: request.params.aid,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ export const get = (server, a, b, names) => {
|
|||||||
|
|
||||||
const base = await a.findOne({
|
const base = await a.findOne({
|
||||||
where: {
|
where: {
|
||||||
id: request.params.aid,
|
[a.primaryKeyField]: request.params.aid,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const method = getMethod(base, names.b, false);
|
const method = getMethod(base, names.b, false);
|
||||||
@ -53,7 +53,7 @@ export const create = (server, a, b, names) => {
|
|||||||
async handler(request, reply) {
|
async handler(request, reply) {
|
||||||
const base = await a.findOne({
|
const base = await a.findOne({
|
||||||
where: {
|
where: {
|
||||||
id: request.params.id,
|
[a.primaryKeyField]: request.params.id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -79,10 +79,12 @@ export const destroy = (server, a, b, names) => {
|
|||||||
|
|
||||||
const base = await a.findOne({
|
const base = await a.findOne({
|
||||||
where: {
|
where: {
|
||||||
id: request.params.aid,
|
[a.primaryKeyField]: request.params.aid,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
where[b.primaryKeyField] = request.params.bid;
|
||||||
|
|
||||||
const method = getMethod(base, names.b, false, 'get');
|
const method = getMethod(base, names.b, false, 'get');
|
||||||
const instance = await method({ where, include });
|
const instance = await method({ where, include });
|
||||||
await instance.destroy();
|
await instance.destroy();
|
||||||
@ -110,6 +112,8 @@ export const update = (server, a, b, names) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
where[b.primaryKeyField] = request.params.bid;
|
||||||
|
|
||||||
const method = getMethod(base, names.b, false);
|
const method = getMethod(base, names.b, false);
|
||||||
|
|
||||||
const instance = await method({ where, include });
|
const instance = await method({ where, include });
|
||||||
|
119
src/crud.js
119
src/crud.js
@ -4,24 +4,65 @@ import _ from 'lodash';
|
|||||||
import { parseInclude, parseWhere } from './utils';
|
import { parseInclude, parseWhere } from './utils';
|
||||||
import { notFound } from 'boom';
|
import { notFound } from 'boom';
|
||||||
|
|
||||||
let prefix;
|
const createAll = ({ server, model, prefix, config }) => {
|
||||||
let defaultConfig;
|
Object.keys(methods).forEach((method) => {
|
||||||
|
methods[method]({ server, model, prefix, config });
|
||||||
export default (server, model, options) => {
|
});
|
||||||
prefix = options.prefix;
|
|
||||||
defaultConfig = options.defaultConfig;
|
|
||||||
|
|
||||||
list(server, model);
|
|
||||||
get(server, model);
|
|
||||||
scope(server, model);
|
|
||||||
create(server, model);
|
|
||||||
destroy(server, model);
|
|
||||||
destroyAll(server, model);
|
|
||||||
destroyScope(server, model);
|
|
||||||
update(server, model);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const list = (server, model) => {
|
/*
|
||||||
|
The `models` option, becomes `permissions`, and can look like:
|
||||||
|
|
||||||
|
```
|
||||||
|
models: ['cat', 'dog']
|
||||||
|
```
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
```
|
||||||
|
models: {
|
||||||
|
cat: ['list', 'get']
|
||||||
|
, dog: true // all
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default (server, model, { prefix, defaultConfig: config, models: permissions }) => {
|
||||||
|
const modelName = model._singular;
|
||||||
|
const permissionsIsArray = Array.isArray(permissions);
|
||||||
|
|
||||||
|
if (!permissions) {
|
||||||
|
createAll({ server, model, prefix, config });
|
||||||
|
} else if (permissionsIsArray && permissions.includes(modelName)) {
|
||||||
|
createAll({ server, model, prefix, config });
|
||||||
|
} else if (permissionsIsArray) {
|
||||||
|
const permissionOptions = permissions.filter((permission) => {
|
||||||
|
return permission.model === modelName;
|
||||||
|
});
|
||||||
|
|
||||||
|
permissionOptions.forEach((permissionOption) => {
|
||||||
|
if (_.isPlainObject(permissionOption)) {
|
||||||
|
const permissionConfig = permissionOption.config || config;
|
||||||
|
|
||||||
|
if (permissionOption.methods) {
|
||||||
|
permissionOption.methods.forEach((method) => {
|
||||||
|
methods[method]({
|
||||||
|
server,
|
||||||
|
model,
|
||||||
|
prefix,
|
||||||
|
config: permissionConfig,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
createAll({ server, model, prefix, config: permissionConfig });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const list = ({ server, model, prefix, config }) => {
|
||||||
server.route({
|
server.route({
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
path: `${prefix}/${model._plural}`,
|
path: `${prefix}/${model._plural}`,
|
||||||
@ -31,6 +72,8 @@ export const list = (server, model) => {
|
|||||||
const include = parseInclude(request);
|
const include = parseInclude(request);
|
||||||
const where = parseWhere(request);
|
const where = parseWhere(request);
|
||||||
|
|
||||||
|
if (include instanceof Error) return void reply(include);
|
||||||
|
|
||||||
const list = await model.findAll({
|
const list = await model.findAll({
|
||||||
where, include,
|
where, include,
|
||||||
});
|
});
|
||||||
@ -38,11 +81,11 @@ export const list = (server, model) => {
|
|||||||
reply(list);
|
reply(list);
|
||||||
},
|
},
|
||||||
|
|
||||||
config: defaultConfig,
|
config,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const get = (server, model) => {
|
export const get = ({ server, model, prefix, config }) => {
|
||||||
server.route({
|
server.route({
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
path: `${prefix}/${model._singular}/{id?}`,
|
path: `${prefix}/${model._singular}/{id?}`,
|
||||||
@ -52,7 +95,7 @@ export const get = (server, model) => {
|
|||||||
const include = parseInclude(request);
|
const include = parseInclude(request);
|
||||||
const where = parseWhere(request);
|
const where = parseWhere(request);
|
||||||
const { id } = request.params;
|
const { id } = request.params;
|
||||||
if (id) where.id = id;
|
if (id) where[model.primaryKeyField] = id;
|
||||||
|
|
||||||
const instance = await model.findOne({ where, include });
|
const instance = await model.findOne({ where, include });
|
||||||
|
|
||||||
@ -66,12 +109,12 @@ export const get = (server, model) => {
|
|||||||
id: joi.any(),
|
id: joi.any(),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
}, defaultConfig),
|
}, config),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const scope = (server, model) => {
|
export const scope = ({ server, model, prefix, config }) => {
|
||||||
let scopes = Object.keys(model.options.scopes);
|
const scopes = Object.keys(model.options.scopes);
|
||||||
|
|
||||||
server.route({
|
server.route({
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
@ -92,11 +135,11 @@ export const scope = (server, model) => {
|
|||||||
scope: joi.string().valid(...scopes),
|
scope: joi.string().valid(...scopes),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
}, defaultConfig),
|
}, config),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const create = (server, model) => {
|
export const create = ({ server, model, prefix, config }) => {
|
||||||
server.route({
|
server.route({
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
path: `${prefix}/${model._singular}`,
|
path: `${prefix}/${model._singular}`,
|
||||||
@ -108,11 +151,11 @@ export const create = (server, model) => {
|
|||||||
reply(instance);
|
reply(instance);
|
||||||
},
|
},
|
||||||
|
|
||||||
config: defaultConfig,
|
config,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const destroy = (server, model) => {
|
export const destroy = ({ server, model, prefix, config }) => {
|
||||||
server.route({
|
server.route({
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
path: `${prefix}/${model._singular}/{id?}`,
|
path: `${prefix}/${model._singular}/{id?}`,
|
||||||
@ -120,7 +163,7 @@ export const destroy = (server, model) => {
|
|||||||
@error
|
@error
|
||||||
async handler(request, reply) {
|
async handler(request, reply) {
|
||||||
const where = parseWhere(request);
|
const where = parseWhere(request);
|
||||||
if (request.params.id) where.id = request.params.id;
|
if (request.params.id) where[model.primaryKeyField] = request.params.id;
|
||||||
|
|
||||||
const list = await model.findAll({ where });
|
const list = await model.findAll({ where });
|
||||||
|
|
||||||
@ -129,11 +172,11 @@ export const destroy = (server, model) => {
|
|||||||
reply(list.length === 1 ? list[0] : list);
|
reply(list.length === 1 ? list[0] : list);
|
||||||
},
|
},
|
||||||
|
|
||||||
config: defaultConfig,
|
config,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const destroyAll = (server, model) => {
|
export const destroyAll = ({ server, model, prefix, config }) => {
|
||||||
server.route({
|
server.route({
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
path: `${prefix}/${model._plural}`,
|
path: `${prefix}/${model._plural}`,
|
||||||
@ -149,12 +192,12 @@ export const destroyAll = (server, model) => {
|
|||||||
reply(list.length === 1 ? list[0] : list);
|
reply(list.length === 1 ? list[0] : list);
|
||||||
},
|
},
|
||||||
|
|
||||||
config: defaultConfig,
|
config,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const destroyScope = (server, model) => {
|
export const destroyScope = ({ server, model, prefix, config }) => {
|
||||||
let scopes = Object.keys(model.options.scopes);
|
const scopes = Object.keys(model.options.scopes);
|
||||||
|
|
||||||
server.route({
|
server.route({
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
@ -165,7 +208,7 @@ export const destroyScope = (server, model) => {
|
|||||||
const include = parseInclude(request);
|
const include = parseInclude(request);
|
||||||
const where = parseWhere(request);
|
const where = parseWhere(request);
|
||||||
|
|
||||||
let list = await model.scope(request.params.scope).findAll({ include, where });
|
const list = await model.scope(request.params.scope).findAll({ include, where });
|
||||||
|
|
||||||
await Promise.all(list.map(instance => instance.destroy()));
|
await Promise.all(list.map(instance => instance.destroy()));
|
||||||
|
|
||||||
@ -177,11 +220,11 @@ export const destroyScope = (server, model) => {
|
|||||||
scope: joi.string().valid(...scopes),
|
scope: joi.string().valid(...scopes),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
}, defaultConfig),
|
}, config),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const update = (server, model) => {
|
export const update = ({ server, model, prefix, config }) => {
|
||||||
server.route({
|
server.route({
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
path: `${prefix}/${model._singular}/{id}`,
|
path: `${prefix}/${model._singular}/{id}`,
|
||||||
@ -206,9 +249,13 @@ export const update = (server, model) => {
|
|||||||
validate: {
|
validate: {
|
||||||
payload: joi.object().required(),
|
payload: joi.object().required(),
|
||||||
},
|
},
|
||||||
}, defaultConfig),
|
}, config),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
import * as associations from './associations/index';
|
import * as associations from './associations/index';
|
||||||
export { associations };
|
export { associations };
|
||||||
|
|
||||||
|
const methods = {
|
||||||
|
list, get, scope, create, destroy, destroyAll, destroyScope, update,
|
||||||
|
};
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
export default (target, key, descriptor) => {
|
export default (target, key, descriptor) => {
|
||||||
let fn = descriptor.value;
|
const fn = descriptor.value;
|
||||||
|
|
||||||
descriptor.value = async (request, reply) => {
|
descriptor.value = async (request, reply) => {
|
||||||
try {
|
try {
|
||||||
|
24
src/index.js
24
src/index.js
@ -8,9 +8,10 @@ import qs from 'qs';
|
|||||||
|
|
||||||
const register = (server, options = {}, next) => {
|
const register = (server, options = {}, next) => {
|
||||||
options.prefix = options.prefix || '';
|
options.prefix = options.prefix || '';
|
||||||
|
options.name = options.name || 'db';
|
||||||
|
|
||||||
let db = server.plugins['hapi-sequelize'].db;
|
const db = server.plugins['hapi-sequelize'][options.name];
|
||||||
let models = db.sequelize.models;
|
const models = db.sequelize.models;
|
||||||
|
|
||||||
const onRequest = function (request, reply) {
|
const onRequest = function (request, reply) {
|
||||||
const uri = request.raw.req.url;
|
const uri = request.raw.req.url;
|
||||||
@ -26,9 +27,9 @@ const register = (server, options = {}, next) => {
|
|||||||
method: onRequest,
|
method: onRequest,
|
||||||
});
|
});
|
||||||
|
|
||||||
for (let modelName of Object.keys(models)) {
|
for (const modelName of Object.keys(models)) {
|
||||||
let model = models[modelName];
|
const model = models[modelName];
|
||||||
let { plural, singular } = model.options.name;
|
const { plural, singular } = model.options.name;
|
||||||
model._plural = plural.toLowerCase();
|
model._plural = plural.toLowerCase();
|
||||||
model._singular = singular.toLowerCase();
|
model._singular = singular.toLowerCase();
|
||||||
|
|
||||||
@ -37,11 +38,11 @@ const register = (server, options = {}, next) => {
|
|||||||
|
|
||||||
crud(server, model, options);
|
crud(server, model, options);
|
||||||
|
|
||||||
for (let key of Object.keys(model.associations)) {
|
for (const key of Object.keys(model.associations)) {
|
||||||
let association = model.associations[key];
|
const association = model.associations[key];
|
||||||
let { source, target } = association;
|
const { source, target } = association;
|
||||||
|
|
||||||
let sourceName = source.options.name;
|
const sourceName = source.options.name;
|
||||||
|
|
||||||
const names = (rev) => {
|
const names = (rev) => {
|
||||||
const arr = [{
|
const arr = [{
|
||||||
@ -57,8 +58,9 @@ const register = (server, options = {}, next) => {
|
|||||||
return rev ? { b: arr[0], a: arr[1] } : { a: arr[0], b: arr[1] };
|
return rev ? { b: arr[0], a: arr[1] } : { a: arr[0], b: arr[1] };
|
||||||
};
|
};
|
||||||
|
|
||||||
let targetAssociations = target.associations[sourceName.plural] || target.associations[sourceName.singular];
|
const targetAssociations = target.associations[sourceName.plural]
|
||||||
let sourceType = association.associationType,
|
|| target.associations[sourceName.singular];
|
||||||
|
const sourceType = association.associationType,
|
||||||
targetType = (targetAssociations || {}).associationType;
|
targetType = (targetAssociations || {}).associationType;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
18
src/utils.js
18
src/utils.js
@ -1,18 +1,28 @@
|
|||||||
import { omit } from 'lodash';
|
import { omit, identity } from 'lodash';
|
||||||
|
|
||||||
export const parseInclude = request => {
|
export const parseInclude = request => {
|
||||||
const include = Array.isArray(request.query.include) ? request.query.include
|
const include = Array.isArray(request.query.include) ? request.query.include
|
||||||
: [request.query.include];
|
: [request.query.include];
|
||||||
|
|
||||||
|
const noGetDb = typeof request.getDb !== 'function';
|
||||||
|
const noRequestModels = !request.models;
|
||||||
|
|
||||||
|
if (noGetDb && noRequestModels) {
|
||||||
|
return new Error('`request.getDb` or `request.models` are not defined.'
|
||||||
|
+ 'Be sure to load hapi-sequelize before hapi-sequelize-crud.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const { models } = noGetDb ? request : request.getDb();
|
||||||
|
|
||||||
return include.map(a => {
|
return include.map(a => {
|
||||||
if (typeof a === 'string') return request.models[a];
|
if (typeof a === 'string') return models[a];
|
||||||
|
|
||||||
if (a && typeof a.model === 'string' && a.model.length) {
|
if (a && typeof a.model === 'string' && a.model.length) {
|
||||||
a.model = request.models[a.model];
|
a.model = models[a.model];
|
||||||
}
|
}
|
||||||
|
|
||||||
return a;
|
return a;
|
||||||
}).filter(a => a);
|
}).filter(identity);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const parseWhere = request => {
|
export const parseWhere = request => {
|
||||||
|
Reference in New Issue
Block a user