Alessandro Rhomberg
Alessandro Rhomberg

Reputation: 155

solution approach for the same nodejs methods

I have a separate service for each collection. In each there are the same standard methods (CRUD).

for example

comment service (update comment, delete comment)

  static updateComment = async (args: { commentID: string; commentData: IComment }): Promise<IComment> => {
    const response = (await Comment.updateOne({ _id: args.commentID }, args.commentData)) as IComment;
    return response;
  };

  static deleteComment = async (args: { commentID: string }): Promise<IComment> => {
    const response: IComment = (await Comment.deleteOne({ _id: args.commentID })) as IComment;
    return response;
  };

event service (update event, delete event)

  static updateEvent = async (args: { eventID: string; eventData: IEvent }): Promise<IEvent> => {
    const response: IEvent = (await Event.updateOne({ _id: args.eventID }, args.eventData)) as IEvent;
    return response;
  };

  static deleteEvent = async (args: { eventID: string }): Promise<IEvent> => {
    const response: IEvent = (await Event.deleteOne({ _id: args.eventID })) as IEvent;
    return response;
  };

Now my question What possibilities are there to summarize these many standard methods? Is generic the right approach?

I hope you can help me, thanks in advance :)

Upvotes: 1

Views: 46

Answers (1)

eol
eol

Reputation: 24565

How about creating a generic service super class that your concrete service classes extend? Your concrete classes can still implement custom behaviour but all the common logic is moved up to the super class. Something like:

import mongoose, {Model, Schema,} from "mongoose";

interface IComment extends mongoose.Document {
    commentData: string;
}

const CommentSchema: Schema = new Schema({
    commentData: {type: String, required: true},
});

interface IEvent extends mongoose.Document {
    name: string;
    date: string;
}

const EventSchema: Schema = new Schema({
    name: {type: String, required: true},
    date: {type: String, required: true},
});

export class GenericDataService<S extends mongoose.Document> {
    private dataModel: Model<S>;

    constructor(collection: string, schema: Schema) {
        this.dataModel = mongoose.model(collection, schema);
    }

    async read(id: string): Promise<S> {
        const response = await this.dataModel.findById(id);
        return response;
    }
   
    // implement the rest of crud operations
}

export class CommentDataService extends GenericDataService<IComment> {
    // implement custom methods if needed
}

export class EventDataService extends GenericDataService<IEvent> {
    // implement custom methods if needed
}

You can then use it like this and typescript will automatically infer the correct types:

const commentDataService = new CommentDataService('Comment', CommentSchema);
const commentResult = await commentDataService.read("commentId"); // commentResult is typeof IComment

const eventDataService = new EventDataService('Event', EventSchema);
const eventResult = await eventDataService.read("eventId"); // eventResult is typeof IEvent

Upvotes: 1

Related Questions