{"id":20195845,"url":"https://github.com/ralphv/nodetastic","last_synced_at":"2025-09-03T13:17:20.207Z","repository":{"id":29095148,"uuid":"32624394","full_name":"ralphv/nodetastic","owner":"ralphv","description":"Will be a mirror of https://bitbucket.org/ralphv/nodetastic/","archived":false,"fork":false,"pushed_at":"2017-07-08T06:28:44.000Z","size":173,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-31T20:54:36.390Z","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":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ralphv.png","metadata":{"files":{"readme":"README.md","changelog":"ChangeLog","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-03-21T07:49:49.000Z","updated_at":"2016-02-13T10:13:57.000Z","dependencies_parsed_at":"2022-08-02T16:45:11.172Z","dependency_job_id":null,"html_url":"https://github.com/ralphv/nodetastic","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ralphv/nodetastic","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ralphv%2Fnodetastic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ralphv%2Fnodetastic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ralphv%2Fnodetastic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ralphv%2Fnodetastic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ralphv","download_url":"https://codeload.github.com/ralphv/nodetastic/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ralphv%2Fnodetastic/sbom","scorecard":{"id":760487,"data":{"date":"2025-08-11","repo":{"name":"github.com/ralphv/nodetastic","commit":"1a8ca12d94f8c7227bfdb52f103b382fa61154bf"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":9,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Warn: project license file does not contain an FSF or OSI license."],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-22T23:19:04.261Z","repository_id":29095148,"created_at":"2025-08-22T23:19:04.261Z","updated_at":"2025-08-22T23:19:04.261Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273448662,"owners_count":25107609,"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","status":"online","status_checked_at":"2025-09-03T02:00:09.631Z","response_time":76,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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-11-14T04:19:30.159Z","updated_at":"2025-09-03T13:17:20.146Z","avatar_url":"https://github.com/ralphv.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# nodetastic - A dependency injection Node.JS API Server with a twist\n\n[![Join the chat at https://gitter.im/ralphv/nodetastic](https://badges.gitter.im/ralphv/nodetastic.svg)](https://gitter.im/ralphv/nodetastic?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge)\n\n[![NPM](https://nodei.co/npm/nodetastic.png?mini=true)](https://nodei.co/npm/nodetastic/)\n\n* [Features](#features)\n* [Getting started](#getting-started)\n* [Samples](#samples)\n* [API](#api)\n* [Reserved words](#reserved-words)\n* [The command line](#the-command-line)\n* [License](#license)\n* [Changelog](#change-log)\n\n## Features\n\n* A web server with a dependency injection engine.\n* Advanced meta-data per function (Attributes in C#/Annotations in JAVA) via specially formatted embedded comments.\n* Parameters of functions are either reserved words (factories) or GET/POST parameters.\n* Basic GET/POST parameters are automatically checked and can be type checked as well via hungarian notation.\n* Path is deduced from the nesting structure of handlers.\n* If you are familiar with AngularJS, you will feel right at home.\n* In theory your code can be used by multiple transport layers (other than http) because of the abstraction provided.\n* Support for client side caching (304) and server side cashing.\n* Support for integrated socket.io handling.\n* Support for side loading services that have access to meta-data and can control the flow of requests/responses.\n* Built on top of express, it will automatically detect express 3 vs express 4.\n* Built-in server or integrate with your own setup.\n* Don't like the different routing approach nodetastic offers? use mapper.wrap directly with express functions.\n\n## Getting started\n\n    $ npm install -g nodetastic\n\nSimple example:\n\n```javascript\nvar nodetastic = require(\"nodetastic\");\n\nvar mapper = nodetastic.CreateNodeTastic();\n\nmapper.registerController({\n  HelloNodeTastic: function(cb) { // http://localhost/HelloNodeTastic\n    cb(null, \"Hello NodeTastic!\");\n  },\n  HelloBack: function(strName, cb) { // http://localhost/HelloBack?strName=Master\n    cb(null, \"Hello \" + strName + \"!\");\n  },\n  session: {\n    set : function($session, objData, cb) { // http://localhost/session/set?objData={\"key\":\"value}\n      $session.set(\"data\", objData);\n      cb();\n    },\n    get: function($session, cb) { // http://localhost/session/get\n      cb(null, $session.get(\"data\"));\n    }\n  }\n});\n\nmapper.startServer(80);\n```\n\n## Samples\n\n* [Sample1](https://raw.githubusercontent.com/ralphv/nodetastic/master/samples/sample1.js)\nBasic sample (getting started).\n\n* [Sample2: multiple handlers](https://raw.githubusercontent.com/ralphv/nodetastic/master/samples/sample2-multi-handlers.js)\nRegister multiple handlers with different prefixes.\n\n* [Sample3: new session initializer](https://raw.githubusercontent.com/ralphv/nodetastic/master/samples/sample3-reg-new-session-fn.js)\nRegister new session function that gets called on new sessions, get a chance to initialize code as you need.\n\n* [Sample4: states, loggedIn, loggedOut and access control](https://raw.githubusercontent.com/ralphv/nodetastic/master/samples/sample4-states-login-logout.js)\nMake use of the service \"StateService\", define two basic states. Control access to APIs based on current state.\n\n* [Sample5: make use of meta-data for simple cash control](https://raw.githubusercontent.com/ralphv/nodetastic/master/samples/sample5-meta-data-expires.js)\nMake use of the meta-data feature in nodetastic, use the service \"ExpiresService\" to provide simple cash control.\n\n* [Sample6: inject your own reserved words](https://raw.githubusercontent.com/ralphv/nodetastic/master/samples/sample6-custom-reserved-words.js)\nSee how easy it is to add your own set of reserved words and consume them easily in your functions.\nThe best of dependency injection at work.\n\n* [Sample7: control client side cash (304)](https://raw.githubusercontent.com/ralphv/nodetastic/master/samples/sample7-client-cache.js)\nMultiple levels of cash control.\n\n* [Sample8: server side cash](https://raw.githubusercontent.com/ralphv/nodetastic/master/samples/sample8-server-cache.js)\nServer side easy cash control.\n\n* [Sample9: Supply functions dynamically](https://raw.githubusercontent.com/ralphv/nodetastic/master/samples/sample9-get-function.js)\nSupply functions dynamically at runtime.\n\n* [Sample10: Use DI directly with express](https://raw.githubusercontent.com/ralphv/nodetastic/master/samples/sample10-with-express.js)\nDon't like the built in routing of nodetastic, use it's DI engine directly with express.\n\n## API\n\n### setOptions(config)\n\nChange the options of nodetastic.\nThe properties are those of [./config.js](https://raw.githubusercontent.com/ralphv/nodetastic/master/config.js).\n\n__Arguments__\n\n* `config` - The configuration object.\n\n__Examples__\n\n```js\nvar nodetastic = require(\"nodetastic\");\n\n// set own cookieSecret and change the http verbose level to 2\nnodetastic.setOptions({cookieSecret:\"new-secret\", httpVerbose:2});\n```\n\n### CreateNodeTastic()\n\nCreate an instance of nodetastic.\n\n__Examples__\n\n[Sample1](https://raw.githubusercontent.com/ralphv/nodetastic/master/samples/sample1.js)\n\n### registerController([prefix], handler)\n\nRegister an object as a handler for a certain url prefix or for the top level (without prefix).\nNodetastic resolves paths differently. It deduces the path relative to the object's properties.\nEach sub-object is a url path part and each function is an endpoint target.\n\n__Arguments__\n\n* `[prefix]` - Optional prefix.\n* `handler` - An object containing nested objects and functions.\n\n__Examples__\n\n[Sample2: multiple handlers](https://raw.githubusercontent.com/ralphv/nodetastic/master/samples/sample2-multi-handlers.js)\n\n### startServer(port, [callback])\n\nStart express server on the given port.\nExpress 3 vs 4 will be automatically detected.\n\n__Arguments__\n\n* `port` - Port number.\n* `[callback]` - An optional callback handler that will be called when the server starts.\n\n__Examples__\n\n[Sample1](https://raw.githubusercontent.com/ralphv/nodetastic/master/samples/sample1.js)\n\n### setTranslateResultFunction(fn)\n\nSet a translation function. This function will be called to translate between cb-result and between the actual object that will be returned as JSON over http.\n\n__Arguments__\n\n* `fn(result)` - Takes in the result object and returns the desired translated object.\n\n__Examples__\n\n[Sample1](https://raw.githubusercontent.com/ralphv/nodetastic/master/samples/sample1.js)\n\n### injectReservedValue(reservedValueName, fn)\n\nCreates a custom reserved value that you \"request\" in your handler functions.\nThe `fn` will be called whenever the reserved value is required by a handler function.\nThe parameters of fn should always start with two variables, `[context](#context)` and `param`.\nThe `fn` can depend on other reserved words as long as they don't have a circular dependency.\nIf you specify the last parameter as `cb` then this is an indicator that `fn` is to be called in async mode.\n\n__Arguments__\n\n* `reservedValueName` - The reserved value name. Should always start with a $ sign.\n* `fn` the function that will provide the reserved value.\n\n__Examples__\n\n[Sample6: inject your own reserved words](https://raw.githubusercontent.com/ralphv/nodetastic/master/samples/sample6-custom-reserved-words.js)\n\n### setGlobalPrefix(prefix)\n\nSometimes it is useful to have a global prefix added to all handlers, this is usually in environments behind a reverse proxy.\n\n__Arguments__\n\n* `prefix` - The prefix to use\n\n### setupSocketIO(sessionToSocketIORoomFn, socketIoReceiveDataFn)\n\nEasily integrate socket.io in your server code. On the client side you should attempt to connect after you establish proper authorization (login)\nand disconnect when you logout.\n\n__Arguments__\n\n* `sessionToSocketIORoomFn(session)` - A function that takes a session object (raw session) and should return a room id for socket.io\nBasically this would be something that identifies your session either uniquely (if you want a room per session).\nOr it can be some session information data such as the logged in user id, in this case all users logged in with the same id will share the same chat room.\n* `socketIoReceiveDataFn(data)` - A function handler that will receive the data sent from the client.\n\n__Examples__\n\n(will follow)\n\n### setTemporaryHalt(object)\n\nIf you need to temporary halt all responses and return one data for all functions.\nIt can be data that indicates a temporary state, like server under maintenance.\n\n__Arguments__\n\n* `object` - The raw object to return for all responses.\n\n### removeTemporaryHalt()\n\nRemove the temporary halt.\n\n### registerNewSessionFunction(newSessionFn)\n\nIf you need to do any initialization for new sessions, pass a handler to this function.\n\n__Arguments__\n\n* `newSessionFn([context](#context), $inject, cb)` -  The handler would take the [context](#context) object, $inject to allow access to any reserved values and a callback to call when done.\n\n__Examples__\n\n[Sample3: new session initializer](https://raw.githubusercontent.com/ralphv/nodetastic/master/samples/sample3-reg-new-session-fn.js)\n\n### getRouteRequestFunction()\n\nWhile nodetastic has it's own server code that you can use with [startServer](#start-server) sometimes you might want to integrate it with code you already have.\n\n__Examples__\n\n```js\nvar nodetastic = require(\"nodetastic\");\n\nvar mapper = nodetastic.CreateNodeTastic();\n// setup mapper as needed (handlers, reserved words...)\n\n// app is your express server from your existing setup\n// link routes\napp.all('*', mapper.getRouteRequestFunction());\napp.disable('etag');\n```\n\n### Context object definition\n\nThe context is an object that has all the data needed for the current request/response to be processed by nodetastic.\nThe current step of processing will effect the properties the context has so far.\n\n__Properties__\n\n* `req` - The underlying request object (http/express). You should not use this directly.\n* `res` - The underlying response object (http/express). You should not use this directly.\n* `skipInvokeFunction(data)` - A function that can be used from services to skip calling the target function and return the data supplied instead.\n* `invoke_cb_result` - The cb-result object when the target function has been called and it's data returned.\n* `resultObject` - The translated invoke_cb_result that should be returned instead. Use [setTranslateResultFunction](#set-translate-result-function) to setup the translator.\n* `handler` - The handler responsible for this request, based on the registered handlers and their prefixes.\n* `fn` - The target function of the handler that will be called to process this request/response.\n* `args` - The compiled arguments that will be sent to the target function, the dependency injection engine will decide what they are.\n* `map.params` - The data generated by the discovery function of the dependency injection engine.\n* `meta` - The meta-data object extracted from the specially formulated embedded comments inside the target function. //\u003cmeta\u003e{...}\u003c/meta\u003e\n* `$session` - The session wrapper object of the current request/response.\n\n## Reserved words\n\nYou can add your own reserved words (values) via the api function [injectReservedValue](#inject-reserved-value).\nReserved words always start with a $ sign, otherwise it will be a GET/POST parameter.\nThe set of built in reserved words:\n\n    $session: An object that provides access to session variables via setters/getters\n    $eTagChecksum: The passed etag that the client passes with the request\n    $cache$[XX]: Access to server side cache, the XX is the number of minutes. (ex: $cache$15, $cache$30)\n    $files: Access to uploaded files\n    $data: GET/POST data for those parameters that are not always mandatory\n    $urlParams: Data embedded in path parameters by preceding the path part with a $ sign ex: /path/$param1/get\n    $HttpCacheIndicator: A helper class for controlling client side caching (304)\n    $inject: Provides access to other reserved words\n    $socket: emit data to socket.io (only supported with express4 + socket.io integration)\n\nThe following reserved words are also available but it is recommended not to use them.\nThey will bind your code with http related concepts and break the abstraction.\n\n    $path: The path of the http request\n    $request: The req object\n    $response: The res object\n    $method: The method of the http request\n    $body: Data passed through (POST) parameters\n    $query: Data passed through query parameters (GET)\n\n## The command line\n\nThe command line arguments you pass serve the purpose of modifying one or more configuration properties found in [./config.js](https://raw.githubusercontent.com/ralphv/nodetastic/master/config.js).\nThe format of the arguments is in the form of X=Y, check the next samples.\nYou could also modify options via setOptions function.\n\n    $ node (your project) param=value\n    $ node (your project) 'param=value with spaces'\n    $ node (your project) 'array_param=[\"array element 1\", \"array element 2\"]'\n    $ node (your project) array_param=element_one,element_two,element_three\n\n## License\n\nnodetastic is licensed under the [BSD-3 License](https://raw.githubusercontent.com/ralphv/nodetastic/master/LICENSE).\n\n## Changelog\n\n* 1.0.6: Adding support for server-timing and x-response-time.\n\n* 1.0.2: Bug fix involving a rare case where the cb was called more than once.\n\n* 1.0.1: Added support for promises, advanced format and case insensitive function resolving.\n\n* 1.0.0: Change to github\n\n* 0.1.4: Added ability to use the DI injection directly in express commands.\n\n* 0.1.3: Added ability to call functions post-fixed with method name.\n\n* 0.1.2: APIs documentation added.\n\n* 0.1.1: Samples added.\n\n* 0.1.0: Initial version.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fralphv%2Fnodetastic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fralphv%2Fnodetastic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fralphv%2Fnodetastic/lists"}