Skip to content

Commit

Permalink
Merge pull request #146 from Chia-Network/feat/address-book-backend
Browse files Browse the repository at this point in the history
feat: add address book module
  • Loading branch information
wwills2 authored Jan 3, 2025
2 parents 5a76e03 + 551cbf9 commit 31eaa28
Show file tree
Hide file tree
Showing 16 changed files with 363 additions and 0 deletions.
127 changes: 127 additions & 0 deletions src/controllers/addressBook.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import _ from 'lodash';
import { AddressBook } from '../models';
import {
paginationParams,
optionallyPaginatedResponse,
} from '../utils/helpers';
import { genericSortColumnRegex } from '../utils/string-utils';

export const findAll = async (req, res) => {
try {
let { page, limit, order } = req.query;

let pagination = paginationParams(page, limit);

// default to DESC
let resultOrder = [['createdAt', 'DESC']];

if (order?.match(genericSortColumnRegex)) {
const matches = order.match(genericSortColumnRegex);
resultOrder = [[matches[1], matches[2]]];
}

let results;

results = await AddressBook.findAndCountAll({
order: resultOrder,
...pagination,
});

return res.json(optionallyPaginatedResponse(results, page, limit));
} catch (error) {
res.status(400).json({
message: 'Can not retrieve address book data',
error: error.message,
success: false,
});
}
};

export const findOne = async (req, res) => {
try {
const query = {
where: { id: req.query.id },
};

res.json(await AddressBook.findOne(query));
} catch (error) {
res.status(400).json({
message: 'Error retrieving address',
error: error.message,
success: false,
});
}
};

export const create = async (req, res) => {
try {
const newRecord = _.cloneDeep(req.body);

await AddressBook.create({
name: newRecord.name,
walletAddress: newRecord.walletAddress,
});

res.json({
message: 'successfully created address book entry',
success: true,
});
} catch (error) {
res.status(400).json({
message: error.message,
success: false,
});
}
};

export const update = async (req, res) => {
try {
const data = _.cloneDeep(req.body);
const id = data.id;

await AddressBook.update(
{
...data,
},
{
where: {
id,
},
},
);

res.json({
message: 'successfully updated address book entry',
success: true,
});
} catch (error) {
res.status(400).json({
message: error.message,
success: false,
});
}
};

export const destroy = async (req, res) => {
try {
const data = _.cloneDeep(req.body);
const id = data.id;

const result = await AddressBook.destroy({
where: {
id,
},
});
if (result)
res.json({
message: 'Address deleted successfully',
success: true,
});
else res.status(204).json({ message: 'No rows deleted', success: false });
} catch (error) {
res.status(400).json({
message: error.message,
success: false,
});
}
};
1 change: 1 addition & 0 deletions src/controllers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export * as GovernanceController from './governance.controller';
export * as FileStoreController from './fileStore.controller';
export * as OfferController from './offer.controller';
export * as StatisticsController from './statistics.controller';
export * as AddressBookController from './addressBook.controller';
34 changes: 34 additions & 0 deletions src/database/migrations/20241127214244-create-address-book.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
'use strict';
/** @type {import('sequelize-cli').Migration} */
import { v4 as uuidv4 } from 'uuid';

export default {
async up(queryInterface, Sequelize) {
await queryInterface.createTable('addressBook', {
id: {
type: Sequelize.STRING,
allowNull: false,
unique: true,
defaultValue: uuidv4(),
primaryKey: true,
},
name: {
type: Sequelize.STRING,
},
walletAddress: {
type: Sequelize.STRING,
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
},
});
},
async down(queryInterface) {
await queryInterface.dropTable('addressBook');
},
};
5 changes: 5 additions & 0 deletions src/database/migrations/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import OrgSyncRemaining from './20231020214357-OrgSyncRemainingCount';
import UnitOwnerNotRequired from './20231016190739-UnitOwnerNotRequired';
import AddGenerationIndexToAudit from './20231207142225-AddGenerationIndexToAudit';
import CreateStatisticsCache from './20240607005647-create-statistics-cache.js';
import CreateAddressBook from './20241127214244-create-address-book.js';

export const migrations = [
{
Expand Down Expand Up @@ -194,4 +195,8 @@ export const migrations = [
migration: CreateStatisticsCache,
name: '20240607005647-create-statistics-cache',
},
{
migration: CreateAddressBook,
name: '20241127214244-create-address-book.js',
},
];
5 changes: 5 additions & 0 deletions src/models/address-book/address-book.mock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import stub from './address-book.stub.js';

export const StatisticsMock = {
findAll: () => stub,
};
53 changes: 53 additions & 0 deletions src/models/address-book/address-book.model.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
'use strict';

import ModelTypes from './address-book.modeltypes.cjs';
import Sequelize from 'sequelize';
const { Model } = Sequelize;
import { sequelize, safeMirrorDbHandler } from '../../database/index.js';
import { AddressBookMirror } from './address-book.model.mirror.js';

class AddressBook extends Model {
static async create(values, options) {
safeMirrorDbHandler(async () => {
const mirrorOptions = {
...options,
transaction: options?.mirrorTransaction,
};
await AddressBookMirror.create(values, mirrorOptions);
});
return super.create(values, options);
}

static async update(values, options) {
safeMirrorDbHandler(async () => {
const mirrorOptions = {
...options,
transaction: options?.mirrorTransaction,
};
await AddressBookMirror.update(values, mirrorOptions);
});
return super.update(values, options);
}

static async destroy(options) {
safeMirrorDbHandler(async () => {
const mirrorOptions = {
...options,
transaction: options?.mirrorTransaction,
};
await AddressBookMirror.destroy(mirrorOptions);
});
return super.destroy(options);
}
}

AddressBook.init(ModelTypes, {
sequelize,
modelName: 'addressBook',
freezeTableName: true,
timestamps: true,
createdAt: true,
updatedAt: true,
});

export { AddressBook };
29 changes: 29 additions & 0 deletions src/models/address-book/address-book.model.mirror.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'use strict';

import Sequelize from 'sequelize';
const { Model } = Sequelize;

import { sequelizeMirror, safeMirrorDbHandler } from '../../database';
import ModelTypes from './address-book.modeltypes.cjs';

class AddressBookMirror extends Model {}

safeMirrorDbHandler(() => {
AddressBookMirror.init(ModelTypes, {
sequelize: sequelizeMirror,
modelName: 'addressBook',
freezeTableName: true,
timezone: '+00:00',
define: {
charset: 'utf8mb4',
collate: 'utf8mb4_general_ci',
},
dialectOptions: {
charset: 'utf8mb4',
dateStrings: true,
typeCast: true,
},
});
});

export { AddressBookMirror };
26 changes: 26 additions & 0 deletions src/models/address-book/address-book.modeltypes.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const Sequelize = require('sequelize');
const { uuid: uuidv4 } = require('uuidv4');

module.exports = {
id: {
type: Sequelize.STRING,
allowNull: false,
unique: true,
defaultValue: () => uuidv4(),
primaryKey: true,
},
name: {
type: Sequelize.STRING,
},
walletAddress: {
type: Sequelize.STRING,
},
createdAt: {
type: Sequelize.DATE,
defaultValue: Sequelize.NOW,
},
updatedAt: {
type: Sequelize.DATE,
defaultValue: Sequelize.NOW,
},
};
1 change: 1 addition & 0 deletions src/models/address-book/address-book.stub.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default [];
2 changes: 2 additions & 0 deletions src/models/address-book/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './address-book.model';
export * from './address-book.mock';
1 change: 1 addition & 0 deletions src/models/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export * from './audit';
export * from './governance';
export * from './file-store';
export * from './statistics';
export * from './address-book';

export const ModelKeys = {
unit: Unit,
Expand Down
2 changes: 2 additions & 0 deletions src/routes/v1/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
FileStoreRouter,
OfferRouter,
StatisticsRouter,
AddressBookRouter,
} from './resources';

V1Router.use('/projects', ProjectRouter);
Expand All @@ -28,5 +29,6 @@ V1Router.use('/governance', GovernanceRouter);
V1Router.use('/filestore', FileStoreRouter);
V1Router.use('/offer', OfferRouter);
V1Router.use('/statistics', StatisticsRouter);
V1Router.use('/addressBook', AddressBookRouter);

export { V1Router };
45 changes: 45 additions & 0 deletions src/routes/v1/resources/address-book.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
'use strict';

import express from 'express';
import { AddressBookController } from '../../../controllers';
import joiExpress from 'express-joi-validation';

import {
addressBookPostSchema,
addressBookGetQuerySchema,
addressBookUpdateSchema,
addressBookDeleteSchema,
} from '../../../validations';

const validator = joiExpress.createValidator({ passError: true });
const AddressBookRouter = express.Router();

AddressBookRouter.get(
'/',
validator.query(addressBookGetQuerySchema),
(req, res) => {
return req.query.id
? AddressBookController.findOne(req, res)
: AddressBookController.findAll(req, res);
},
);

AddressBookRouter.post(
'/',
validator.body(addressBookPostSchema),
AddressBookController.create,
);

AddressBookRouter.put(
'/',
validator.body(addressBookUpdateSchema),
(req, res) => AddressBookController.update(req, res, false),
);

AddressBookRouter.delete(
'/',
validator.body(addressBookDeleteSchema),
AddressBookController.destroy,
);

export { AddressBookRouter };
1 change: 1 addition & 0 deletions src/routes/v1/resources/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export * from './governance';
export * from './filestore';
export * from './offer';
export * from './statistics';
export * from './address-book';
Loading

0 comments on commit 31eaa28

Please sign in to comment.