Giter VIP home page Giter VIP logo

knex-express-project-sample's Introduction

Knex/Express Project Sample

This is an example project structure that uses both Express and Knex. It assumes the creation of a "server" JSON API using a Postgres database and creates a basic relation between users and projects to demonstrate how such simple data structures might be modeled using nothing more than Knex and plain JS.

If you like this kind of architecture, you may also like cred-server which is something I'm working on as a more specific implementation of these ideas :)

Folder Structure

/config
  database.js -- loads the knexfile using settings for the current environment
/db
  /migrations
  /seeds
/server
  /controllers -- business logic for handling API endpoints
    project_controller.js
    user_controller.js
  /helpers -- modules for common functions that sit outside controllers/models
  /models  -- simple collections of db queries and utilities for user data
    index.js -- creates a single object with each model as a property
    project.js
    user.js
  /routes -- defines API endpoints and passes requests to corresponding controllers
    project_routes.js
    user_routes.js
  index.js -- the main Express app
knexfile.js -- defines all database settings for different environments
package.json -- defines scripts for utilities like migrations and seeds

Why?

I'm tired of ORMs. I came from a Rails background where Active Record held my hand all the time, and when something went wrong I had to decipher where (in AR) it happened. It was a mysterious black box of goodies that helped me get pretty far without really understanding what was happening between my app and the DB.

Then I started working more with JS and was feeling a little naked without AR. I tried Loopback, Sequelize, Bookshelf, Sails, Waterline, Mongoose, and ORM2. Each has their own strengths and weaknesses. None was as stable and feature-rich as Active Record. All of them had the same major problem: they're all ORMs!

The problem with ORMs is that they try to hide the business logic of interacting with your database. But, at it's core, an API is nothing more than an interface to a database. Take that out and you have to question what it is that you're actually trying to accomplish.

But I'm also not into raw SQL syntax (it's kind of ugly). So a "query builder" like Knex, which enables the construction of SQL queries in my native language, is more to my liking.

I've also created my own "models" which are just Nodejs modules that are a bunch of helper functions that store all the queries to the database in one place where I can change and customize them (they don't even really need to use Knex if I want to make my queries more raw).

Along with these pseudo-models, I've organized a simple Express app into "controllers" and "routes" to fill out what a basic JSON API server application might look like.

Maybe this is helpful to you to give you some ideas on how to structure your own project. Maybe this can even be a starting template for your project. Mainly, I want to show you that it's ok to take off the training wheels and ditch the ORM you think you need. You don't need all that hidden abstraction (and baggage) when all you really need is a series of database query functions which control the data flowing in and out and present the outside world with some kind of interface (like the JSON REST API used here).

The less you depend on, the more control you gain, and the fewer problems you inherit. But you also have to be more diciplined, responsible, sensible, and organized so as not to turn your beautiful app into a pile of spaghetti ;)

Knex

I like knex because it just does what it says on the tin: it builds SQL queries.

But it also comes with some handy CLI tools for running migrations and seeding your database (along with connecting to it in the first place from within your app).

This is all I really wanted from an ORM. I'll structure my in-memory representation of my data myself. I mean, that is what my app is so how could an ORM know how to do it for me?

I just think it makes things much more straight-forward and simple. This makes it obvious where something has gone wrong (so I can fix it) and makes for more hooks where I can easily add on additional functionality. But that's just me. YMMV.

License

MIT

knex-express-project-sample's People

Contributors

robmclarty avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

knex-express-project-sample's Issues

dependency bcrypt returns 404 when downloading

Error:
node-pre-gyp ERR! Tried to download(404): https://github.com/kelektiv/node.bcrypt.js/releases/download/v1.0.3/bcrypt_lib-v1.0.3-node-v64-win32-x64.tar.gz

Temporary Solution: I have upgrade to 3.0.0

"dependencies": {
    "bcrypt": "^3.0.0",
    "body-parser": "^1.18.2",
    "express": "^4.16.3",
    "knex": "^0.14.4",
    "pg": "^7.4.1"
  }

Failed to migrate knex database

I followed the steps below:

OS: Linux 20.04

  1. Clone the repository;
  2. Run command npm install on root folder;
  3. Run command npm run db:migrate on root folder;

I received the log below after message Using environment: development. I require some instructions to reproduce this repository behaviour and features.

TimeoutError: Knex: Timeout acquiring a connection. The pool is probably full. Are you missing a .transacting(trx) call?
    at /home/brunolnetto/github/knex-express-project-sample/node_modules/knex/lib/client.js:348:17
    at tryCatcher (/home/brunolnetto/github/knex-express-project-sample/node_modules/bluebird/js/release/util.js:16:23)
    at /home/brunolnetto/github/knex-express-project-sample/node_modules/bluebird/js/release/catch_filter.js:17:41
    at tryCatcher (/home/brunolnetto/github/knex-express-project-sample/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (/home/brunolnetto/github/knex-express-project-sample/node_modules/bluebird/js/release/promise.js:547:31)
    at Promise._settlePromise (/home/brunolnetto/github/knex-express-project-sample/node_modules/bluebird/js/release/promise.js:604:18)
    at Promise._settlePromise0 (/home/brunolnetto/github/knex-express-project-sample/node_modules/bluebird/js/release/promise.js:649:10)
    at Promise._settlePromises (/home/brunolnetto/github/knex-express-project-sample/node_modules/bluebird/js/release/promise.js:725:18)
    at _drainQueueStep (/home/brunolnetto/github/knex-express-project-sample/node_modules/bluebird/js/release/async.js:93:12)
    at _drainQueue (/home/brunolnetto/github/knex-express-project-sample/node_modules/bluebird/js/release/async.js:86:9)
    at Async._drainQueues (/home/brunolnetto/github/knex-express-project-sample/node_modules/bluebird/js/release/async.js:102:5)
    at Immediate.Async.drainQueues [as _onImmediate] (/home/brunolnetto/github/knex-express-project-sample/node_modules/bluebird/js/release/async.js:15:14)
    at processImmediate (node:internal/timers:466:21)

Undefined binding(s) detected

I git cloned the repo and it's giving me this error when I send POST data (username and password) to /register:

Undefined binding(s) detected when compiling SELECT. Undefined column(s): [username] query: select id, username, email, updated_at, created_at from users where username = ?

When I access the database on the sqlite3 CLI, I get the expected results:

sqlite> SELECT username from users;
admin
first-user

Is there any more info I can provide to help? Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.