Skip to content

Instantly share code, notes, and snippets.

@eric-burel
Created June 21, 2018 15:51
Show Gist options
  • Save eric-burel/cf2bf5735e5380c109a80e19d6e7be29 to your computer and use it in GitHub Desktop.
Save eric-burel/cf2bf5735e5380c109a80e19d6e7be29 to your computer and use it in GitHub Desktop.
// my-service.hooks.js
module.exports = {
before:{
find:[
async findQuery(context){
// get the client (Express global)
const { db } = context.app.get('knexClient')
// build and run the query
const q = db.raw(`SELECT * FROM TABLE`)
const res = await q
// when context.result is set, the next hooks will be ignored,
// so the service won't trigger its own automatically generated query
context.result = res
return context
}
]
}
// ...other hooks
}
@morphatic
Copy link

AMAZING!!! Exactly what I needed! I have a SQLite database that has a many-to-many relationship between Students and Courses (A Student can be enrolled in many Courses, and a Course will have many Students on a roster). There are three relevant tables: students, courses, and courses_students. I'm using the feathers-knex library, as I suspect you are. I found a couple of things:

  1. There was no db property on my knexClient so your destructuring step didn't work for me, but it did give me enough clues to eventually figure out what to do. I don't know if the API has changed since you wrote that or what...
  2. By modifying context.result directly (as I do below) I was able to avoid skipping the rest of the hooks. This allowed me to keep my hooks nice and cleanly separated and not have to do too many things at once.

Here's a couple of relevant excerpts from my code:

// /src/services/students/students.hooks.js
module.exports = {
  before: { /* before hooks */ },
  after: {
    get: [
      // get all courses related to this student
      async function(context) {
        // write our sql
        const sql = `SELECT c.id, c.code
                     FROM   courses_students cs, courses c
                     WHERE  cs.course_id = c.id AND
                            cs.student_id = ?`;
        // get the knex db client
        const knex = context.app.get('knexClient');
        // run our query
        const result = await knex.raw(sql, [context.id]);
        // add our results to the previous result
        context.result['courses'] = result;
        return context;
      }
    ]
  },
  error: { /* error hooks */ }
};

and:

// /src/services/courses/courses.hooks.js
module.exports = {
  before: { /* before hooks */ },
  after: {
    get: [
      // get all students related to this course
      async function(context) {
        // write our sql
        const sql = `SELECT s.id, s.first_name, s.last_name
                     FROM   courses_students cs, students s
                     WHERE  cs.student_id = s.id AND
                            cs.course_id = ?`;
        // get the db client (Express global)
        const knex = context.app.get('knexClient');
        // run our query
        const result = await knex.raw(sql, [context.id]);
        // add our results to the previous result
        context.result['students'] = result;
        return context;
      }
    ],
  },
  error: { /* error hooks */}
};

Thank you!!! I hope this helps you or the next person...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment