Skip to content

Commit

Permalink
Merge pull request #59 from thevahidal/bulk-endpoints
Browse files Browse the repository at this point in the history
Bulk endpoints
  • Loading branch information
thevahidal authored Nov 3, 2022
2 parents 061b40b + 9cd55d0 commit 225c23a
Show file tree
Hide file tree
Showing 8 changed files with 442 additions and 4 deletions.
2 changes: 1 addition & 1 deletion core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "soul-cli",
"version": "0.0.7",
"version": "0.0.8",
"description": "A SQLite RESTful server",
"main": "src/server.js",
"bin": {
Expand Down
158 changes: 157 additions & 1 deletion core/src/controllers/rows.js
Original file line number Diff line number Diff line change
Expand Up @@ -578,10 +578,94 @@ const updateRowInTableByPK = async (req, res) => {

const query = `UPDATE ${tableName} SET ${fieldsString} WHERE ${lookupField} = '${pk}'`;
try {
db.prepare(query).run();
const data = db.prepare(query).run();

res.json({
message: 'Row updated',
data,
});
} catch (error) {
res.status(400).json({
message: error.message,
error: error,
});
}
};

// Update a row by pk
const bulkUpdateRowsInTableByPK = async (req, res) => {
/*
#swagger.tags = ['Rows']
#swagger.summary = 'Bulk Update Rows'
#swagger.description = 'Bulk Update rows by primary key'
#swagger.parameters['name'] = {
in: 'path',
description: 'Table name',
required: true,
type: 'string'
}
#swagger.parameters['body'] = {
in: 'body',
required: true,
type: 'object',
schema: { $ref: "#/definitions/BulkUpdateRowsRequestBody" }
}
#swagger.parameters['_lookup_field'] = {
in: 'query',
description: 'If you want to update row by any other field than primary key, use this parameter',
required: false,
type: 'string'
}
*/

const { name: tableName } = req.params;
const { pks, fields } = req.body;
const { _lookup_field } = req.query;

let lookupField = _lookup_field;

if (!_lookup_field) {
// find the primary key of the table
try {
lookupField = db
.prepare(`PRAGMA table_info(${tableName})`)
.all()
.find((field) => field.pk === 1).name;
} catch (error) {
return res.status(400).json({
message: error.message,
error: error,
});
}
}

// wrap text values in quotes
const fieldsString = Object.keys(fields)
.map((key) => {
let value = fields[key];
if (typeof value === 'string') {
value = `'${value}'`;
}
return `${key} = ${value}`;
})
.join(', ');

if (fieldsString === '') {
return res.status(400).json({
message: 'No fields provided',
error: 'no_fields_provided',
});
}

const query = `UPDATE ${tableName} SET ${fieldsString} WHERE ${lookupField} in (${pks})`;
try {
const data = db.prepare(query).run();

res.json({
message: 'Rows updated',
data,
});
} catch (error) {
res.status(400).json({
Expand Down Expand Up @@ -659,10 +743,82 @@ const deleteRowInTableByPK = async (req, res) => {
}
};

// Bulk Delete rows by id
const bulkDeleteRowsInTableByPK = async (req, res) => {
/*
#swagger.tags = ['Rows']
#swagger.summary = 'Bulk Delete Rows'
#swagger.description = 'Bulks Delete rows by primary key'
#swagger.parameters['name'] = {
in: 'path',
description: 'Table name',
required: true,
type: 'string'
}
#swagger.parameters['_lookup_field'] = {
in: 'query',
description: 'If you want to delete row by any other field than primary key, use this parameter',
required: false,
type: 'string'
}
#swagger.parameters['body'] = {
in: 'body',
required: true,
type: 'object',
schema: { $ref: "#/definitions/BulkDeleteRowsRequestBody" }
}
*/
const { name: tableName } = req.params;
const { _lookup_field } = req.query;
const { pks } = req.body;

let lookupField = _lookup_field;

if (!_lookup_field) {
// find the primary key of the table
try {
lookupField = db
.prepare(`PRAGMA table_info(${tableName})`)
.all()
.find((field) => field.pk === 1).name;
} catch (error) {
return res.status(400).json({
message: error.message,
error: error,
});
}
}

const query = `DELETE FROM ${tableName} WHERE ${lookupField} in (${pks})`;

try {
const data = db.prepare(query).run();

if (data.changes === 0) {
res.status(404).json({
error: 'not_found',
});
} else {
res.json({
message: 'Rows deleted',
data,
});
}
} catch (error) {
res.status(400).json({
message: error.message,
error: error,
});
}
};

module.exports = {
listTableRows,
insertRowInTable,
getRowInTableByPK,
updateRowInTableByPK,
bulkUpdateRowsInTableByPK,
deleteRowInTableByPK,
bulkDeleteRowsInTableByPK,
};
3 changes: 2 additions & 1 deletion core/src/middlewares/validation.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const validator = (schema) => (req, res, next) => {
const data = { ...req.body, ...req.params, ...req.query };
const { error } = schema.validate(data);
const { value, error } = schema.validate(data);

if (error) {
res.status(400).json({
message: error.message,
Expand Down
10 changes: 10 additions & 0 deletions core/src/routes/rows.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,21 @@ router.get(
validator(schema.getRowInTableByPK),
controllers.getRowInTableByPK
);
router.put(
'/:name/rows/bulk',
validator(schema.bulkUpdateRowsInTableByPK),
controllers.bulkUpdateRowsInTableByPK
);
router.put(
'/:name/rows/:pk',
validator(schema.updateRowInTableByPK),
controllers.updateRowInTableByPK
);
router.delete(
'/:name/rows/bulk',
validator(schema.bulkDeleteRowsInTableByPK),
controllers.bulkDeleteRowsInTableByPK
);
router.delete(
'/:name/rows/:pk',
validator(schema.deleteRowInTableByPK),
Expand Down
15 changes: 15 additions & 0 deletions core/src/schemas/rows.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,31 @@ const updateRowInTableByPK = Joi.object({
_lookup_field: Joi.string().min(3).max(30),
});

const bulkUpdateRowsInTableByPK = Joi.object({
name: Joi.string().min(3).max(30).required(),
pks: Joi.array().items(Joi.required()).required(),
fields: Joi.object().required(),
_lookup_field: Joi.string().min(3).max(30),
});

const deleteRowInTableByPK = Joi.object({
name: Joi.string().min(3).max(30).required(),
pk: Joi.string().required(),
_lookup_field: Joi.string().min(3).max(30),
});

const bulkDeleteRowsInTableByPK = Joi.object({
name: Joi.string().min(3).max(30).required(),
pks: Joi.array().items(Joi.required()).required(),
_lookup_field: Joi.string().min(3).max(30),
});

module.exports = {
listTableRows,
insertRowInTable,
getRowInTableByPK,
updateRowInTableByPK,
bulkUpdateRowsInTableByPK,
deleteRowInTableByPK,
bulkDeleteRowsInTableByPK,
};
9 changes: 9 additions & 0 deletions core/src/swagger/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,15 @@ const doc = {
fields: [{ $ref: '#/definitions/Field' }],
},

BulkUpdateRowsRequestBody: {
pks: [1, 2, 3],
fields: [{ $ref: '#/definitions/Field' }],
},

BulkDeleteRowsRequestBody: {
pks: [1, 2, 3],
},

TransactionRequestBody: {
$ref: '#/definitions/Transaction',
},
Expand Down
Loading

0 comments on commit 225c23a

Please sign in to comment.