{"id":15801810,"url":"https://github.com/johnhof/simple-skeleton","last_synced_at":"2025-03-31T21:56:09.079Z","repository":{"id":23683612,"uuid":"27055240","full_name":"johnhof/simple-skeleton","owner":"johnhof","description":"skeleton framework for rapid development using angular/node","archived":false,"fork":false,"pushed_at":"2015-04-08T16:54:34.000Z","size":34176,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2023-03-29T00:36:43.855Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/johnhof.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-11-24T01:18:36.000Z","updated_at":"2015-01-05T23:12:45.000Z","dependencies_parsed_at":"2022-08-22T04:10:16.146Z","dependency_job_id":null,"html_url":"https://github.com/johnhof/simple-skeleton","commit_stats":null,"previous_names":[],"tags_count":null,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johnhof%2Fsimple-skeleton","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johnhof%2Fsimple-skeleton/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johnhof%2Fsimple-skeleton/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johnhof%2Fsimple-skeleton/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/johnhof","download_url":"https://codeload.github.com/johnhof/simple-skeleton/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246547388,"owners_count":20794970,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-05T01:40:55.722Z","updated_at":"2025-03-31T21:56:09.056Z","avatar_url":"https://github.com/johnhof.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"Simple Skeleton\n===============\n\nWeb service to compile and deliver local ice times (skate/stick time/pickup)\n\n* [Structure](#structure)\n* [To Run](#to-run)\n* [Useful Commands](#useful-commands)\n* [API](#api)\n* [App](#app)\n* [Mongoman](#mongoman)\n\n\nStructure \u003ca name=\"structure\"\u003e\u003c/a\u003e [↑](#top)\n=========\n\n**API**\n\n```\n\napi.js // base script\n\nconfig.json // configuration data\n\nroutes.js // route-\u003econtroller mapping\n\n\u003e\u003e lib // helpers, shared assets\n\n\u003e\u003e components // models and controllers\n\n  \u003e\u003e\u003e\u003e example\n\n  ------ example_ctrl.js (C)\n\n  ------ example_model.js (M) (IMPORTANT - all models `_model.js` are registered on server startup)\n\n```\n\n**App**\n\n```\n\n\u003e\u003e assets\n\n  \u003e\u003e\u003e\u003e fonts\n\n  \u003e\u003e\u003e\u003e images\n\n  \u003e\u003e\u003e\u003e partials\n\n  \u003e\u003e\u003e\u003e scripts\n\n  \u003e\u003e\u003e\u003e styles\n\n\u003e\u003e components\n\n  \u003e\u003e\u003e\u003e example\n\n    ---- example.html // (V)\n\n    ---- example.scss\n\n    ---- example_ctrl.js // (C)\n\n\u003e\u003e core\n\n  ---- app,js // angular setup and server management\n\n  ---- app_congif // app configuration\n\n  ---- index.html // main view container in which other views and partials are wrapped\n\n  ---- router.js // mapping of routes to views\n\n```\n\n**Dist**\n\nA collection of minified files made accessible to the client. This is where the actual Angular app runs. The App dir is for dev only\n\nTo Run \u003ca name=\"useful-commands\"\u003e\u003c/a\u003e [↑](#top)\n======\n\nGeneral\n * Requires MongoDB, Node, Compass (Ruby)\n * Clone Git Repo\n * npm install\n * bower install\n\nApp\n* `grunt app` -\u003e http://localhost:9000\n  * grunt will recompile portions of the server on save depending on the file type (eg: re-minify js)\n\nAPI\n* `npm install nodemon -g`\n* `[sudo] mongod`\n* `grunt api` -\u003e http://localhost:8000\n  * nodemon will restart the server for js changes\n\n\n**Coming Soon**\n* command line options\n\nUseful grunt commands \u003ca name=\"useful-commands\"\u003e\u003c/a\u003e [↑](#top)\n=====================\n\n`grunt clean:compiled` -\u003e removes compiled code (./tmp, ./dist, ./sass_cache)\n\n`grunt clean:modules` -\u003e  removes node modules and bower components\n\n`gunt dropdb` - \u003e drops the current local database\n\nAPI \u003ca name=\"api\"\u003e\u003c/a\u003e [↑](#top)\n===\n\nA few things are done automatically cut down on controller/model/router bloat:\n\n**Routing and Controllers**\n\nCRUD controllers can be added to the route file with internal helpers. useing `routeCrud('/', controller('home'))` will call `homeCtrl = require(process.cwd() + '/home/home_ctrl')(api)` then map the following routes automatically, **IF** the handler is defined in the controller\n\n * `POST /` -\u003e `homeCtrl.create(req, res, next)`\n * `GET /` -\u003e `homeCtrl.read(req, res, next)`\n * `PUT /` -\u003e `homeCtrl.update(req, res, next)`\n * `DELETE /` -\u003e `homeCtrl.destroy(req, res, next)`\n\nSub-controllers can be added in a dot-syntax string `routeCrud('/players/:playerId', controller('players.player'))` -\u003e `require(process.cwd() + '/players/player/player_ctrl.js')(api)`\n\n**Models**\n\nModels are all registered automatically on server startup. The server will crawl through the `/components` directory tree and `require` any js file ending in `_model.js`. if this is not done, the model will need to be added manually **BEFORE** it is used, or the server will crash.\n\n**General notes**\n\nboth routes and models can be added in the standard raw mongo/express methods, if you see fit. If thats the case, they need not follow the file structure used for automation.\n\nthe following variables and utils are cached by middleware\n* `req`\n  * `session`    - a copy of the parsed session cookie\n  * `signedIn()` - returns whether or not the user is signed in (using the hash to validate)\n* `res`\n  * `setSession(session, signedIn)` - takes `session[username]`, `session[email]` and `signedIn` to generate and set the session cookie. defaults to null values\n\n**Errors**\n\nCustom error handling middleware was added to standardize output. All errors will follow the structure\n\n```javascript\n{\n  error: 'string',\n  details: []\n}\n```\n\nto generate error on the fly, please use teh error generato  `require(process.cwd() + '/api/lib/error').errorGenerator(error)` which takes an object of the form:\n\n```javascript\n{\n  error   : 'string', // defaults to 'Could not process request'\n  status  : 'status code', // defaults to 400\n  details : [] // defaults to null\n}\n```\n\nwhich is then handled by the errorhandler middleware which applies defaults and sends the error object.\n\n**NOTE:** Raw mongoose/joi errors are accepted in both the error generator and the middleware. They will be processed and groomed into the standard error output. An example converted mongoose/joi validation error is listed below. The intent is for the APP to match paths to messages in form inputs\n\n```javascript\n{\n  \"error\": \"Validation failed\",\n  \"details\": [\n    {\n      \"path\": \"username\",\n      \"message\": \"Required\"\n    },\n    {\n      \"path\": \"password\",\n      \"message\": \"Password invalid\"\n    },\n    {\n      \"path\": \"email\",\n      \"message\": \"Email invalid\"\n    }\n  ]\n}\n```\n\n**Validation**\n\nThere is a wrapper for joi to handle errors for us. simply use\n\n```javascript\n  validate(req.body, {\n    email    : Joi.email(),\n    password : Joi.password()\n  }, handler(trimmedInput, callback) || [array, of, handlers], FinalcallbackAndErrorHandler);\n```\n\nif an arrray is passed in, it will execute an async.waterfall. the validator also adds a few minor Joi mixins, but Joi doesnt support true extension, so use with caution. the validator object also has a property `regex` containing an object of regex's to standardize use. the current supported reges's are below\n\n* `email` - small-ish version of the official regex\n* `password` - accepts letters and at least one number between 4 and 10 characters\n\n\n**Session**\n\nthe following utils are available from /lib/session.js\n* `isvalidSession(req)` - return whether or not this session is signed in with a valid hash\n* `primeSession(req, res, next)` - app level middleware that parses and sets up the session state/cookie. if neither are sent in the request, they are generated. the following utilities are added as well\n  * `req.session`    - a copy of the parsed session cookie\n  * `res.signedIn()` - returns whether or not the user is signed in (using the hash to vlaidate)\n  * `res.setSession(session, signedIn)` - takes `session[username]`, `session[email]` and `signedIn` to generate and set the session cookie. defaults to null values\n* `requireSession(req, res, next)` - Route level middleware. returns 401 if a valid session is not found\n\n\nAPP \u003ca name=\"app\"\u003e\u003c/a\u003e [↑](#top)\n===\n\n\nMongoman \u003ca name=\"mongoman\"\u003e\u003c/a\u003e [↑](#top)\n========\n\nI hate code bloat especially when its something that we'll need to do over and over again. So I made a wrapper MANage MONGOose/mongo and mongoose-validator.\n\nOnce this is near completion I'd like to make it into a separate module for public use.\n\n**Schema building**\n\nBelow is a simple Model constructor to demonstrate a use case\n\n```javascript\nvar Mongoman = require(process.cwd() + '/api/lib/mongoman');\n\n// register a user model\nmodule.exports = Mongoman.register('user', {\n  name : Mongoman('Name') // error templates will use the 'Name' string when specifying issues\n           .string().required().isAlphaNum().isLength([3, 50]) // it is a required, alaphanumeric, string, of length greater than 3 and less than 50\n         .fin() // compile the construcor object (some day, Mongoman.register will do this for us)\n});\n```\n\nHere is an example controller\n\n```javascript\nvar Mongoman = require(process.cwd() + '/api/lib/mongoman');\n\nmodule.exports = function accountController (api) {\n  return {\n    create : function (req, res, next) {\n      Mongoman.save('player', req.body, next, function () {\n        res.data = { success : true, }\n        return next();\n      });\n    },\n```\n\n**Constructor properties** - remeber to update me!!\n\n* `string()` - type `String`\n* `date()` - type `Date`\n* `number()` - type `Number`\n* `buffer()` - type `Buffer`\n* `booleand()` - type `Boolean`\n* `mixed()` - type `Mixed`\n* `objectId()` - type `ObjectId`\n* `array()` - type `Array`\n* `type(type)` - set type as 'type' parameter\n* `required()` - configure schema to require this property\n* `default(val)` - default to `val` parameter\n\n**Constructor validations** - remeber to update me!!\n\nAll validations that an error message param as the last argument to override the default error\n\n* `alphanum([msg])` - must be alpha numberic\n* `isLength(array, [msg])` - must be between `array[0]` and `array[1]`\n* `matches(regex, [msg])` - must match regex\n\n**Stand alone helpers**\n\n* `Mongoman.register(name, schema, [options])` - register new schema with a raw object (not a `Schema` instance)\n* `Mongoman.model(name)` - wrapper to get a model\n* `Mongoman.save(modelName, inputs, errorHandler, successHandler)` - save an `input` object to `modelName`, validation/DB errors will go to the `errorHandler` (generally `next()`), otherwise, `successHandler` is called\n* `Mongoman.schema(schemaObj)` - returns a new schema instance of the passed in object\n\nTesting\n============\nTo run the test suite run the following at the root folder\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjohnhof%2Fsimple-skeleton","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjohnhof%2Fsimple-skeleton","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjohnhof%2Fsimple-skeleton/lists"}