express-example.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /**
  2. * Module dependencies
  3. */
  4. var express = require('express');
  5. var bodyParser = require('body-parser');
  6. var DiskAdapter = require('sails-disk');
  7. var MySQLAdapter = require('sails-mysql');
  8. // - - - - - - - - - - - - - - - - - - - - - - - - - - -
  9. var Waterline = require('../../');
  10. // ^^ or if running this example outside of this repo,
  11. // require the following instead:
  12. // ```
  13. // var Waterline = require('waterline');
  14. // ```
  15. // - - - - - - - - - - - - - - - - - - - - - - - - - - -
  16. /**
  17. * A simple example of how to use Waterline v0.13 with Express 4.
  18. *
  19. * Before running this example, be sure and do:
  20. * ```
  21. * npm install express body-parser waterline sails-disk
  22. * ```
  23. */
  24. //////////////////////////////////////////////////////////////////
  25. // WATERLINE SETUP
  26. //////////////////////////////////////////////////////////////////
  27. // Instantiate a new instance of the ORM
  28. Waterline.start({
  29. adapters: {
  30. 'sails-disk': DiskAdapter,
  31. 'sails-mysql': MySQLAdapter,
  32. // ...other Waterline-compatible adapters (e.g. 'sails-mysql') might go here
  33. },
  34. datastores: {
  35. default: {
  36. adapter: 'sails-disk',
  37. // ...any misc. special config might go here
  38. },
  39. customerDb: {
  40. adapter: 'sails-mysql',
  41. url: 'localhost/foobar',
  42. // ...any misc. special config might go here
  43. },
  44. // ...any other datastores go here
  45. },
  46. models: {
  47. user: {
  48. attributes: {
  49. emailAddress: { type: 'string', required: true },
  50. firstName: { type: 'string' },
  51. lastName: { type: 'string' },
  52. numChickens: { type: 'number' },
  53. pets: { collection: 'pet' }
  54. }
  55. },
  56. pet: {
  57. datastore: 'customerDb',
  58. attributes: {
  59. name: { type: 'string', required: true },
  60. breed: {
  61. type: 'string',
  62. validations: {
  63. isIn: ['chihuahua', 'great dane', 'collie', 'unknown']
  64. },
  65. defaultsTo: 'unknown'
  66. }
  67. }
  68. }
  69. // ...any other model defs go here
  70. },
  71. defaultModelSettings: {
  72. primaryKey: 'id',
  73. datastore: 'default',
  74. attributes: {
  75. id: { type: 'number', autoMigrations: { autoIncrement: true } },
  76. },
  77. // ...any other orm-wide default settings for all models go here
  78. }
  79. }, function(err, orm){
  80. if(err) {
  81. console.error('Could not start up the ORM:\n',err);
  82. return process.exit(1);
  83. }
  84. // ORM is now running!
  85. //////////////////////////////////////////////////////////////////
  86. // EXPRESS SETUP
  87. //////////////////////////////////////////////////////////////////
  88. // Setup simple Express application.
  89. var app = express();
  90. app.use(bodyParser.urlencoded({ extended: false }));
  91. app.use(bodyParser.json());
  92. // Bind Express Routes (CRUD routes for /users)
  93. // Find all users
  94. app.get('/users', function(req, res) {
  95. Waterline.getModel('user', orm)
  96. .find().exec(function(err, records) {
  97. if(err) {
  98. switch (err.name) {
  99. case 'UsageError':
  100. return res.sendStatus(400);
  101. default:
  102. console.error('Unexpected error occurred:',err.stack);
  103. return res.sendStatus(500);
  104. }
  105. }//-•
  106. return res.json(records);
  107. });
  108. });
  109. // Find one user
  110. app.get('/users/:id', function(req, res) {
  111. Waterline.getModel('user', orm)
  112. .findOne({ id: req.params.id }, function(err, record) {
  113. if(err && err.name === 'UsageError') {
  114. return res.sendStatus(400);
  115. }
  116. else if (err && err.name === 'AdapterError' && err.code === 'E_UNIQUE') {
  117. return res.status(401).json(err);
  118. }
  119. else if (err) {
  120. console.error('Unexpected error occurred:',err.stack);
  121. return res.sendStatus(500);
  122. }
  123. else {
  124. return res.json(record);
  125. }
  126. });
  127. });
  128. // Create a user
  129. // (This one uses promises, just for fun.)
  130. app.post('/users', function(req, res) {
  131. Waterline.getModel('user', orm)
  132. .create(req.body)
  133. .meta({fetch:true})
  134. .catch({name:'UsageError'}, function (err) {
  135. console.log('Refusing to perform impossible/confusing query. Details:',err);
  136. return res.sendStatus(400);
  137. })
  138. .catch({name:'AdapterError', code:'E_UNIQUE'}, function (err) {
  139. console.log('Refusing to create duplicate user. Details:',err);
  140. return res.status(401).json(err);
  141. })
  142. .catch(function (err) {
  143. console.error('Unexpected error occurred:',err.stack);
  144. return res.sendStatus(500);
  145. })
  146. .then(function (newRecord){
  147. return res.status(201).json(newRecord);
  148. });
  149. });
  150. // Destroy a user (if it exists)
  151. app.delete('/users/:id', function(req, res) {
  152. Waterline.getModel('user', orm)
  153. .destroy({ id: req.params.id }, function(err) {
  154. if(err && err.name === 'UsageError') {
  155. return res.sendStatus(400);
  156. }
  157. else if (err) {
  158. console.error('Unexpected error occurred:',err.stack);
  159. return res.sendStatus(500);
  160. }
  161. else {
  162. return res.sendStatus(200);
  163. }
  164. });
  165. });
  166. // Update a user
  167. app.put('/users/:id', function(req, res) {
  168. // Don't pass ID to update
  169. // > (We don't want to try to change the primary key this way, at least not
  170. // > for this example. It's totally possible to do that, of course... just
  171. // > kind of weird.)
  172. var valuesToSet = req.body;
  173. delete valuesToSet.id;
  174. // In this example, we'll send back a JSON representation of the newly-updated
  175. // user record, just for kicks.
  176. Waterline.getModel('user', orm)
  177. .update({ id: req.params.id })
  178. .set(valuesToSet)
  179. .meta({fetch:true})
  180. .exec(function(err, updatedUsers) {
  181. if(err && err.name === 'UsageError') {
  182. return res.sendStatus(400);
  183. }
  184. else if (err && err.name === 'AdapterError' && err.code === 'E_UNIQUE') {
  185. return res.status(401).json(err);
  186. }
  187. else if (err) {
  188. console.error('Unexpected error occurred:',err.stack);
  189. return res.sendStatus(500);
  190. }
  191. else if (updatedUsers.length < 1) {
  192. return res.sendStatus(404);
  193. }
  194. else {
  195. return res.status(200).json(updatedUsers[0]);
  196. }
  197. });
  198. });
  199. // Lift Express server and start listening to requests
  200. app.listen(3000, function (err){
  201. if (err) {
  202. console.error('Failed to lift express server:', err);
  203. console.error('(Attempting to shut down ORM...)');
  204. Waterline.stop(orm, function(err){
  205. if (err) {
  206. console.error('Unexpected failure when attempting to shut down ORM! Details:', err);
  207. return process.exit(1);
  208. }
  209. console.error('ORM was shut down successfully.');
  210. return process.exit(1);
  211. });//_∏_
  212. return;
  213. }//-•
  214. console.log('Express server is running and ORM is started!');
  215. console.log('To see saved users, visit http://localhost:3000/users');
  216. console.log('Press CTRL+C to terminate process.');
  217. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  218. // NOTE: Sails takes care of all this kind of stuff automatically, but if you're using
  219. // vanilla express, it would be a good idea to bind SIGINT/SIGTERM listeners here and have
  220. // them shut down the ORM if fired.
  221. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  222. });
  223. });