{"id":26844924,"url":"https://github.com/gaafar/deppie","last_synced_at":"2025-10-11T04:55:50.557Z","repository":{"id":83092753,"uuid":"61149839","full_name":"Gaafar/deppie","owner":"Gaafar","description":"The simple, elegant Dependency Injection framework for javascript.","archived":false,"fork":false,"pushed_at":"2019-09-30T08:14:04.000Z","size":50,"stargazers_count":15,"open_issues_count":4,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-09-15T11:54:04.099Z","etag":null,"topics":["dependency-injection","framework","ioc","javascript","nodejs"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Gaafar.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-06-14T19:24:07.000Z","updated_at":"2022-09-28T13:00:31.000Z","dependencies_parsed_at":null,"dependency_job_id":"286512bf-65d2-4709-b7d5-ae5d56f0e319","html_url":"https://github.com/Gaafar/deppie","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Gaafar/deppie","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gaafar%2Fdeppie","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gaafar%2Fdeppie/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gaafar%2Fdeppie/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gaafar%2Fdeppie/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Gaafar","download_url":"https://codeload.github.com/Gaafar/deppie/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gaafar%2Fdeppie/sbom","scorecard":{"id":54301,"data":{"date":"2025-08-11","repo":{"name":"github.com/Gaafar/deppie","commit":"de03dc05d24aaede0a6c2eee3f833c69dca3d734"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.4,"checks":[{"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":10,"reason":"no dangerous workflow patterns detected","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":"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":"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":"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":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/nodejs.yml:1","Info: no jobLevel write permissions found"],"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":"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":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/nodejs.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/Gaafar/deppie/nodejs.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/nodejs.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/Gaafar/deppie/nodejs.yml/master?enable=pin","Warn: npmCommand not pinned by hash: .github/workflows/nodejs.yml:22","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 npmCommand dependencies pinned"],"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":"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":"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":"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":"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":"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":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"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-15T00:21:24.749Z","repository_id":83092753,"created_at":"2025-08-15T00:21:24.749Z","updated_at":"2025-08-15T00:21:24.749Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279006216,"owners_count":26084063,"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-10-11T02:00:06.511Z","response_time":55,"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":["dependency-injection","framework","ioc","javascript","nodejs"],"created_at":"2025-03-30T19:33:31.114Z","updated_at":"2025-10-11T04:55:50.512Z","avatar_url":"https://github.com/Gaafar.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![npm](https://img.shields.io/npm/v/deppie.svg?maxAge=2592000)](https://www.npmjs.com/package/deppie)\n[![Build Status](https://travis-ci.org/Gaafar/deppie.svg?branch=master)](https://travis-ci.org/Gaafar/deppie)\n[![Dependency Status](https://david-dm.org/Gaafar/deppie.svg)](https://david-dm.org/Gaafar/deppie)\n# deppie\n\nThe simple, elegant Dependency Injection framework for javascript.\n\n## Introduction\n\ndeppie provides a dead simple way to set up an Inversion of Control (IoC) container. It was born out of the frustration my team and I had trying to find a Dependency Injection (DI) framework to use in our projects that we could adopt effortlessly in our existing and new projects without writing extra code or config; or creating our modules in a convoluted way that the framework dictates; or worrying about the blood magic the framework is doing to summon our code.\n\n## Features\n\n- Minimal API that can be learned in a few minutes\n- No extra code/config/annotations required\n- One to one [direct mapping to `require` modules](#mapping-to-require)\n- Can be [adopted partially](#partial-adoption) to work with existing code\n\n## Do we need Dependency Injection?\n\nIf you're not familiar with DI \u0026 IoC you can refer to [this article by Martin Fowler][1], but the basic idea is that you write your code that depends on a module, without knowing (or caring) where that module comes from as long as it has the interface you expect.\n\n[This thread][2] has is a nice debate on whether we need DI or not, but, obviously, I believe we do for a few reasons\n\n1. Inject dependencies without knowing their paths. This means that if you change a module location on disk or swap it with another, you don't need to touch every file that depends on it.\n\n2. It makes it a lot easier to mock dependencies for testing without the pain of overriding the global `require` function in a way that works without problems.\n\n3. It helps you organize and reason about you application as loosely coupled modules.\n\n## Install\n\n`npm install --save deppie`\n\n## TLDR example\n\n```javascript\nconst deppie = require(\"deppie\")\n\n// this module has no dependencies and returns 1\nconst module1 = () =\u003e 1;\n\n// this module depends on module 1, and returns something based on it\nconst module2 = ({ module1 }) =\u003e module1 + 1;\n\n// this module depends on both, and returns nothing\n// as it is the entry point of the app, and no modules will depend on it\nconst main = ({ module1, module2 }) =\u003e {\n    console.log(`module1 = ${module1}, module2 = ${module2}`)\n}\n\n// wire up all modules by calling the functions with the right dependencies passed\ndeppie({ main, module1, module2 })\n// output to console: \"module1 = 1, module2 = 2\"\n```\n\n## What just happened?\n\nTwo things happened here\n\n1. **Declare dependencies**\n\n    Each of the modules (module1, module2, main) is defined as a \"constructor function\" that takes an object of all other modules and uses ES6/ES2015 destructuring to pick only the modules it depends on.\n\n2. **Wire up**\n\n    Now we need to invoke the constructor function of each module with the needed dependencies. All we have to do is to call `deppie` with an object that contains the name of each module as a key, and its constructor function as the corresponding value.\n\nIt is that simple. This is all it takes for deppie to create all your modules with the right dependencies. You don't have to write or maintain any special code or config.\n\n## Examples\n\nCheck out the [examples folder](https://github.com/Gaafar/deppie/tree/master/examples) for more detailed demos.\n\n## How it works\n\ndeppie works in a very straight-forward way. In fact, the core of it was written in one sitting for a few hours.\n\n`deppie(modules)` parses the signatures of the constructor functions of all the passed modules and keeps track of what dependencies they need in order to be created.  \n\nThen, deppie passes all the modules into a `reduce` function that goes through the  modules one by one, for each module it checks if its dependencies have been created or creates them if needed (recursively), then adds the created module(s) to the accumulator of the reduce function to be available for the next module.\n\n## Mapping to require\n\nIt is extremely easy to convert existing modules that `require` their dependencies to modules that use dependency injection.\n\neg: `myModule.js` with require\n\n```javascript\nconst dependency = require('path/to/dependency')\n\n// do something here\n\n//return something from this module\nmodule.exports = 42;\n```\n\nNow to write the same module using dependency injection there are 3 steps:\n\n1. Wrap every thing in a constructor function and export it.\n\n2. The required modules become parameters in the constructor function (as a desctructured object).\n\n3. The previous export of the module becomes the return.\n\n```javascript\nmodule.exports = ({ dependency }) =\u003e {\n    // do something here\n\n    //return something from this module\n    return 42;\n}\n```\n\n## Partial adoption\n\nThe full signature is of `deppie()` is\n`const createdModules = deppie(moduleDefinitions, initialModules)`\n\nIt takes 2 parameters\n- `moduleDefinitions`: object of module names as keys, and module constructors as values\n- `initialModules`: object of module names as keys, and alread created modules as values. These modules will not be created by deppie, but will be passed (as is) as dependencies to the new modules that are created `moduleDefinitions`.\n\nAnd returns\n- `createdModules`: object of module names as keys, and created modules as values. It includes the `initialModules` passed as well.\n\nAt its heart, deppie is just a reduce function that is passed an initial state (modules), and returns the final state. Where the initial state comes from and what to do with the final state is up to you.\n\nThis means that you can create modules in any way you want outside deppie, use them as dependencies inside deppie, and use the returned modules outside deppie again seamlessly.\n\nThis is helpful if you want to use a DI framework in a large project without taking the time to convert all existing modules at once, so you can move modules into deppie gradually.\n\nCheck [this example](https://github.com/Gaafar/deppie/tree/master/examples/partial) for an implementation of partial adoption.\n\n## Entry point(s)\n\nYou don't need to define any entry points explicitly to deppie. It can be any one of your modules, the only difference is that an entry point module will, naturally, have no return (void module). deppie will construct a void module just like any other module, except it will not allow you to inject it in other modules by throwing an error if you try to depend on a void module.\n\neg: `app.js`\n\n```javascript\nconst bodyParser = require('body-parser');\nconst express = require('express');\n\nmodule.exports = ({ getUsersRoute, config }) =\u003e {\n    const app = express()\n    .use(bodyParser.text())\n    .use(bodyParser.json())\n    .use(bodyParser.urlencoded({ extended: true }));\n\n    // Add routes\n    app.get('/api/users', getUsersRoute);\n\n    app.listen(config.port);\n    console.log(`listening on port ${config.port}`);\n    // don't return anything\n};\n```\n\n## Validations\n\ndeppie will check these rules for your modules when they are passed, and throw an error if they are violated\n- no missing dependencies\n- no circular dependencies\n- no self dependencies\n- can't depend on void modules\n- can't depend on modules that are not defined\n- can't modify properties of the returned object from calling `deppie`\n\nand warn you about some other rules\n- no unused modules (TODO)\n\n## Design decisions\n\n- The decision to use destructuring in the constructor function as opposed to ordered function parameters, means that you don't have to worry about an uglifier renaming your parameters and breaking injection (like AngularJS), or having to use string names of the dependencies then adding them as parameters with the same order as function parameters (like RequireJS).\n\n## Roadmap\n\n- Visualize dependency graph\n- Optimize package size\n- Add support for ES5\n- Add tests for browsers\n\n## Disclaimer\n\ndeppie is still in an early stage, and I wouldn't recommend using it in production just yet.\n\nBefore the first release (1.0), breaking changes will be marked by updating the minor version (eg: 0.1.8 to 0.2.0). However, owing to it's minimal API, I expect it to be relatively easy to modify your code for such changes if they happen.\n\nAfter the first release, I will be following semantic versioning for future releases.\n\n\u003c!--\nTODO:\n- review other frameworks\n- example for advanced composition of deppies\n- design decision, no asynchrony\n- Good Practices\n    index, app, routes\n- support returning promises?\n--\u003e\n\n\n[1]: http://martinfowler.com/articles/injection.html\n[2]: http://stackoverflow.com/questions/9250851/do-i-need-dependency-injection-in-nodejs-or-how-to-deal-with\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgaafar%2Fdeppie","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgaafar%2Fdeppie","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgaafar%2Fdeppie/lists"}