{"id":17011967,"url":"https://github.com/jaythomas/angular-initializer","last_synced_at":"2026-04-18T14:34:55.770Z","repository":{"id":57178553,"uuid":"230348056","full_name":"jaythomas/angular-initializer","owner":"jaythomas","description":"Structure a component dependency tree out of your legacy angularjs components.","archived":false,"fork":false,"pushed_at":"2019-12-27T01:01:53.000Z","size":5,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-06T22:27:23.418Z","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":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jaythomas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-12-27T00:55:05.000Z","updated_at":"2020-01-24T14:53:26.000Z","dependencies_parsed_at":"2022-09-09T19:00:11.549Z","dependency_job_id":null,"html_url":"https://github.com/jaythomas/angular-initializer","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/jaythomas/angular-initializer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaythomas%2Fangular-initializer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaythomas%2Fangular-initializer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaythomas%2Fangular-initializer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaythomas%2Fangular-initializer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jaythomas","download_url":"https://codeload.github.com/jaythomas/angular-initializer/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaythomas%2Fangular-initializer/sbom","scorecard":{"id":509311,"data":{"date":"2025-08-11","repo":{"name":"github.com/jaythomas/angular-initializer","commit":"1bb8216c97b223d11c4e33f8530bdd1768cff636"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/1 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":"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":"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":"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":-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":"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":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.md:0","Info: FSF or OSI recognized license: MIT License: LICENSE.md:0"],"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-20T00:07:37.225Z","repository_id":57178553,"created_at":"2025-08-20T00:07:37.225Z","updated_at":"2025-08-20T00:07:37.225Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31972477,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T00:39:45.007Z","status":"online","status_checked_at":"2026-04-18T02:00:07.018Z","response_time":103,"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-10-14T06:09:02.056Z","updated_at":"2026-04-18T14:34:55.752Z","avatar_url":"https://github.com/jaythomas.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# angular-initializer\n\n[![MIT license](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/jaythomas/angular-initializer/blob/master/LICENSE.md)\n\nStructure a component dependency tree out of your legacy angularjs components.\nThis allows for easier sharing of providers across multiple angular apps, unit testing a provider without needing to build the entire app, and simply incorporating legacy code into a newer app.\n\n- [Installation](#installation)\n- [Example](#example)\n- [What's it do exactly?](#whats-it-do-exactly)\n- [Caveats](#caveats)\n- [Provider API](#provider-api)\n  - [Components](#components)\n  - [Directives](#directives)\n  - [Configs and Run files](#configs-and-run-files)\n  - [Factories, Services, and Providers](#factories-services-and-providers)\n\n## Installation\n\nvia yarn\n```\nyarn add angular-initializer\n```\nor via npm\n```\nnpm install --save angular-initializer\n```\n\n## Example\n\nHere's what an example entry file might look like:\n\n```js\nimport { getModuleDeps, initializeExports } from 'angular-initializer'\nimport * as homePageComponent from './components/home-page'\n\nconst ngModule = angular.module('my-app', getModuleDeps(homePageComponent))\n// This line registers the homePage component as well as all its injections and so on recursively\ninitializeExports(ngModule, homePageComponent)\n```\n\nAnd your home-page component:\n\n```js\nimport * as myFactory from '../factories/my-factory'\n\n// Let angular-initializer know what dependencies this component\n// has that also need to be registered with the angular module\nexport const $deps = [myFactory]\n\n// Perhaps this component uses an external module as a dependency such as angular-bootstrap's modal service\nimport modal from 'angular-ui-bootstrap/src/modal'\n// angular-initializer's `getModuleDeps()` can extract out all external module dependencies in the entry file into\n// an array and de-dupe it. This array can be conveniently passed directly to angular when creating a new module.\nexport const $moduleDeps = [modal]\n\nexport const $component = {\n  bindings: {},\n  controller: controller,\n  name: 'homePage'\n}\n\nfunction controller($uibModal, myFactory) {\n  // etc...\n}\n```\n\n## What's it do exactly?\n\nSay you've moved away from concatenating your files with gulp and you've started using something like webpack.\nYour bundle's entry file might be setting up your core angular module and requiring all its providers recursively:\n\n```js\nimport angular from 'angular'\n// External module dependency for this app\nimport datepicker from 'angular-ui-bootstrap/src/datepicker'\n\nangular.module('app.core', ['datepicker'])\n\n// Require all files for a given folder\nfunction requireAll(requireContext) {\n\treturn requireContext.keys().map(value =\u003e valu{\n\t\treturn Object.assign({ filename: value.replace(/^.*[\\\\\\/]/, '').split('.')[0] }, requireContext(value))\n\t})\n}\n\nrequireAll(require.context('.', true, /src(\\\\|\\/)components(\\\\|\\/)(?!.*spec\\.js$).*\\.js$/)),\nrequireAll(require.context('.', true, /src(\\\\|\\/)factories(\\\\|\\/)(?!.*spec\\.js$).*\\.js$/)),\n```\n\nIn `src/component/` you may have declared your components like this:\n\n```js\nangular.module('app.core').component('dateRangePicker', {\n  controller: controller\n  // etc...\n})\n\ncontroller.$inject = ['dateFormat']\n\nfunction controller(dateFormat) {\n  // etc...\n}\n```\n\nAnd in `src/factories/` you may have declared your factories like this:\n\n```js\nangular.module('app.core').factory('dateFormat', factory)\n\nfactory.$inject = []\n\nfunction factory() {\n  // etc...\n}\n```\n\nNotice a few disadvantages with this setup:\n- Each provider (component/factory) needs context awareness of what angular module they belong to\n- The module those providers belong to needs to be declared on the global angular instance before the providers are loaded\n- The external dependency on ui-bootstrap's datepicker is declared in the entry, so it's not obvious that the dependency is used specifically in components\n- There is no way to know which providers depend on each other without following the injection list\n- Because of all this, testing the component or factory has become more difficult, requiring mocking all the injections and modules or alternatively building and loading the entire bundle through webpack just to run a unit test\n\nBut if we structured things into a dependency tree, we can put the responsibility on each file (ES module) to tell us what it needs and do away with the old angular module concept.\n\n```js\n/* components/date-picker.js */\n\n// External module dependency for this component\nimport datepicker from 'angular-ui-bootstrap/src/datepicker'\nexport $moduleDeps = [datePicker]\n\n// Injections\nimport * as dateFormatFactory from '../factories/date-format'\nexport const $deps = [dateFormatFactory]\n\nexport const $component = {\n  name: 'dateRangePicker',\n  controller: controller\n}\n\nfunction controller(dateFormat) {\n  'ngInject' // using angularjs-annotate here to get rid of the redundant $inject array\n  // etc...\n```\n\n\n```js\n/* factories/date-format.js */\nexport const $factory = dateFormat() {\n  // etc...\n}\n```\n\nAssuming you declare all the angular filters and child components used by your top level component and so on, then importing the top level component you will import the entire app.\n\n## Caveats\n\nUnlike modern frameworks like Vue or React, you won't get a warning if you declare a directive or component in your template that was never imported/registered. Angular will just not render anything and not give you a warning.\nThis is something you can only avoid with unit tests, or even better, snapshot tests that will catch when you try to reference a directive you forgot to register.\n\n## Provider API\n\n### Components\n\nYou can export the component object directly and provide a `name` property to give the component a name:\n\n```js\nexport const $component = {\n  name: 'myComponentName',\n  bindings: {},\n  controller,\n  template: `\u003cdiv\u003e\u003c/div\u003e`,\n}\n\nfunction controller() {}\n```\n\n### Directives\n\nSince directives are declared as functions, you export the function directly and the function's `name` property will be use in this case as well:\n\n```js\nexport const $directive = function myDirectiveName() {\n  return {\n    link,\n    restrict: 'A',\n    scope: false\n  }\n\n  function link() {}\n}\n```\n\n### Configs and Run files\n\nConfigs and Run files don't have names, but you can still provide a named function to improve the quality of your stack traces.\n\n- `export const $run = function run() {}`\n- `export const $config = function config() {}`\n\n### Factories, Services, and Providers\n\nExporting other providers types you export a named constant with that provider type prefixed with a \"$\" like so:\n\n- `export const $factory = function myFactoryName(myInjection) {}`\n- `export const $service = function myServiceName(myInjection) {}`\n- `export const $provider = function myProviderName(myInjection) {}`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjaythomas%2Fangular-initializer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjaythomas%2Fangular-initializer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjaythomas%2Fangular-initializer/lists"}