{"id":37023052,"url":"https://github.com/david-sledge/scalaioc","last_synced_at":"2026-01-14T02:45:46.130Z","repository":{"id":57732961,"uuid":"122108521","full_name":"david-sledge/scalaioc","owner":"david-sledge","description":"IoC/DI Framework Written in Scala","archived":false,"fork":false,"pushed_at":"2021-03-01T00:50:47.000Z","size":843,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2023-07-04T02:13:02.655Z","etag":null,"topics":["dependency-injection","ioc-framework","scala"],"latest_commit_sha":null,"homepage":null,"language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/david-sledge.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}},"created_at":"2018-02-19T19:14:01.000Z","updated_at":"2021-03-01T00:50:49.000Z","dependencies_parsed_at":"2022-09-26T22:11:09.342Z","dependency_job_id":null,"html_url":"https://github.com/david-sledge/scalaioc","commit_stats":null,"previous_names":[],"tags_count":4,"template":null,"template_full_name":null,"purl":"pkg:github/david-sledge/scalaioc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/david-sledge%2Fscalaioc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/david-sledge%2Fscalaioc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/david-sledge%2Fscalaioc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/david-sledge%2Fscalaioc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/david-sledge","download_url":"https://codeload.github.com/david-sledge/scalaioc/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/david-sledge%2Fscalaioc/sbom","scorecard":{"id":325913,"data":{"date":"2025-08-11","repo":{"name":"github.com/david-sledge/scalaioc","commit":"f4f46a52779041d8a3474773f1c8313c86342287"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.7,"checks":[{"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":"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":"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":"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":"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":"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":"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":"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":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v1.0.0-alpha.3 not signed: https://api.github.com/repos/david-sledge/scalaioc/releases/21374543","Warn: release artifact v1.0.0-alpha.2 not signed: https://api.github.com/repos/david-sledge/scalaioc/releases/20690939","Warn: release artifact v1.0.0-alpha.1 not signed: https://api.github.com/repos/david-sledge/scalaioc/releases/16517943","Warn: release artifact v1.0.0-alpha not signed: https://api.github.com/repos/david-sledge/scalaioc/releases/15466762","Warn: release artifact v1.0.0-alpha.3 does not have provenance: https://api.github.com/repos/david-sledge/scalaioc/releases/21374543","Warn: release artifact v1.0.0-alpha.2 does not have provenance: https://api.github.com/repos/david-sledge/scalaioc/releases/20690939","Warn: release artifact v1.0.0-alpha.1 does not have provenance: https://api.github.com/repos/david-sledge/scalaioc/releases/16517943","Warn: release artifact v1.0.0-alpha does not have provenance: https://api.github.com/repos/david-sledge/scalaioc/releases/15466762"],"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: GNU General Public License v3.0: 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-18T02:28:52.461Z","repository_id":57732961,"created_at":"2025-08-18T02:28:52.461Z","updated_at":"2025-08-18T02:28:52.461Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28408737,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T01:52:23.358Z","status":"online","status_checked_at":"2026-01-14T02:00:06.678Z","response_time":107,"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","ioc-framework","scala"],"created_at":"2026-01-14T02:45:45.280Z","updated_at":"2026-01-14T02:45:46.118Z","avatar_url":"https://github.com/david-sledge.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"# scalaioc\nIoC/DI Framework Written in Scala\n\n[![Build Status](https://travis-ci.org/david-sledge/scalaioc.svg?branch=master)](https://travis-ci.org/david-sledge/scalaioc)\n\n## Goals\n\n* First and foremost support IoC and DI for Scala and Java applications.\n  - Facilitate unit testing by allowing components to be instantiated with mock dependencies or inject test implementations.\n  - Eliminate the need for global static state.\n* Non-invasive: Do not require imports from the framework's library in application code in order to configure the application.\n  - Allow configuration to be fully external to application code.\n  - Eliminate the need for annotation-based configuration.\n  - Eliminate the need to extend framework classes and interfaces in application code.\n* Allow the framework to be extended using the framework. Developers can define their own constructs within the framework.\n\n## Setup\n\nAdd the following dependency to your `build.sbt` file:\n\n```scala\nlibraryDependencies += \"io.github.david-sledge\" % \"scalaioc_2.13\" % \"1.0.0-alpha.3\"\n```\n\n## Simple Tutorial\n\nLet's start with a plain-ol'-scala-object. (The following example can be found [here](https://github.com/david-sledge/scalaioc/tree/master/examples/simple/ \"simple example\").)\n\n`HelloWorld.scala`:\n\n```scala\npackage com.example.hello\n\nclass HelloWorld(message: String)\n{\n  def printMessage = {\n    println(s\"Your Message : $message\")\n  }\n}\n\nobject HelloWorld {\n  def apply(message: String) = new HelloWorld(message)\n}\n```\n\nConfiguration file; factory staff plan.\n\n`staff.fsp`:\n\n```\n`namespace|scalaioc`\n\n// this is a factory manager\n\"helloWorld\" `#=` com.example.hello.HelloWorld(\"Hello World!\")\n```\n\nMain entry point to the application (`MainApp.scala`).\n\n```scala\npackage com.example.hello\n\nimport scala.ioc.ppm._\nimport scala.ioc.Factory\n\nobject MainApp extends App {\n\n  // build the factory and staff it\n  val (factory, _) = staffFactoryFromResource(\"staff.fsp\")\n  // put the \"helloWorld\" manager to work and get the fruits of her labor\n  val obj = factory.putToWork(\"helloWorld\").asInstanceOf[HelloWorld]\n  obj.printMessage\n}\n```\n\n### Factory managers\n\nFactory managers are specified using `` `#=` `` (lazy) and `` `#=\u003e` `` (productive). Factories contain workers that provide a service and/or produce a product. Managers are workers that can be referenced by name.\n\n* `` `#=` `` executes the first time and caches the result for later calls.\n* `` `#=\u003e` `` executes without caching every time.\n\n`staff.fsp`:\n\n```\n`namespace|scalaioc`\n\n...\n\n// Simple (lazy) factory manager\n// the first time a lazy manager is put to work, their result is stored.\n// On subsequent requests for the manager to do some work, they just give you\n// what's stored from the first time.\n// This manager is so lazy they're having another manager do all the work.\n\"lazyManager\" `#=` `#ref`(\"eagerManager\")\n\n// Simple (way-too-eager) factory managers\n// produce a new result each time they're put to work (even if their work\n// results in the exact same thing they produced last time).\n\"eagerManager\" `#=\u003e` java.time.ZonedDateTime.now\n```\n\n`MainApp.scala`:\n\n```scala\n...\n\nimport java.time.ZonedDateTime\n\nobject MainApp extends App {\n\n  // build the factory and staff it\n  val (factory, _) = staffFactoryFromResource(\"staff.fsp\")\n  ...\n\n  // gimme the time, ya lazy bum!\n  val dateTime = factory.putToWork(\"lazyManager\").asInstanceOf[ZonedDateTime]\n  // you, people-pleaser, gimme the time, too.\n  val anotherDateTime = factory.putToWork(\"eagerManager\").asInstanceOf[ZonedDateTime]\n\n  // let's wait half a second\n  Thread sleep 500\n\n  // who will give the same ol', and who will give something new?\n  println(s\"Will the lazy manager produce the same as before?\"\n      + s\" ${if (factory.putToWork(\"lazyManager\").equals(dateTime)) \"Yes\" else \"No\"}\")\n  println(s\"Will the eager manager produce the same as before?\"\n      + s\" ${if (factory.putToWork(\"eagerManager\").equals(anotherDateTime)) \"Yes\" else \"No\"}\")\n}\n```\n\n### Managers referencing other managers\n\nManagers can task other managers with `` `#ref` `` and `` `#ref!` ``. Both operate the same except that latter will force the lazy (caching) managers to produce something new instead of a cached result. The new product will be cached in place of the old.\n\n`DateTimeHelloWorld.scala`:\n\n```scala\npackage com.example.hello\n\nimport java.time.ZonedDateTime\n\nclass DateTimeHelloWorld(message: String, val dateTime: ZonedDateTime)\n{\n  def printMessage = {\n    println(s\"Your Message : $message\\nI was given the specific time of $dateTime.\")\n  }\n}\n\nobject DateTimeHelloWorld {\n  def apply(message: String, dateTime: ZonedDateTime) = new DateTimeHelloWorld(message, dateTime)\n}\n```\n\n`staff.fsp`:\n\n```\n`namespace|scalaioc`\n\n...\n\n// This guy's such a workhorse, even other managers are more productive.\n\"productiveSeniorManager\" `#=\u003e`\n  com.example.hello.DateTimeHelloWorld(\n    \"Hello World!\",\n    `#ref!`(\"lazyManager\"),\n  )\n```\n\n`MainApp.scala`:\n\n```scala\n...\n\n  // build the factory and staff it\n  val (factory, _) = staffFactoryFromResource(\"staff.fsp\")\n\n  ...\n\n  // The productive senior manager puts the lazy one to work.\n  val dateTimeHelloWorld =\n    factory.putToWork(\"productiveSeniorManager\").asInstanceOf[DateTimeHelloWorld]\n  dateTimeHelloWorld.printMessage\n  // Will the lazy manager give the productive one the same ol'?\n  println(\"The senior manager will make even the lazy manager perform some work.\")\n  println(s\"Will the lazy manager give senior manager the same as before?\"\n      + s\" ${if (dateTimeHelloWorld.dateTime.equals(dateTime)) \"Yes\" else \"No\"}\")\n```\n\n## Context parameters/variables\n\nObjects and values can be passed to managers when they're put to work.\n\n### Command-Line Arguments\n\nIf the application utilizes command line arguments they can be past to a worker to be processed. The framework is packaged with a main class [scala.ioc.cli.Main](https://github.com/david-sledge/scalaioc/blob/master/src/main/scala/scala/ioc/cli/Main.scala \"main class\") that will pass on the command-line arguments to an initialization manager.\n\nBy default the main class reads the file name `staff.fsp` from the working directory, and instantiates a factory from the file. Then it puts the manager named `init` to work passing the command-line arguments. (The following example can be found [here](https://github.com/david-sledge/scalaioc/tree/master/examples/cli/ \"CLI example\"). There is also a [Java version of this example](https://github.com/david-sledge/scalaioc/tree/master/examples/java/ \"Java CLI example\").)\n\n`staff.fsp`:\n\n```\n`namespace|scalaioc`\n\n\"init\" `#=\u003e`\n  com.example.cli.parseOptions(\n    `#$`(\"args\"),\n  )\n```\n\nIn the `init` manager, the arguments are retrieved using `` `#$` `` with the string `\"args\"` and passed to `parseOptions`. This example uses [jopt-simple](http://jopt-simple.github.io/jopt-simple/ \"JOpt Simple\") to parse command line arguments. However, any other arg-parser library could be used, or the arguments could be processed without the aid of a third-party library.\n\n`package.scala`:\n\n```scala\npackage com.example\n\nimport joptsimple._\n\npackage object cli {\n  val parseOptions = (args: Array[String]) =\u003e {\n\n    val parser = new OptionParser( \"s:a:\" )\n\n    val options = parser.parse(args:_*)\n\n    val salutation = if (options.has(\"s\")) {\n        options.valueOf(\"s\")\n    }\n    else {\n        \"Hello\"\n    }\n\n    val addressee = if (options.has(\"a\")) {\n        options.valueOf(\"a\")\n    }\n    else {\n        \"World\"\n    }\n\n    println(s\"$salutation, $addressee!\")\n\n  }\n}\n```\n\nOther .fsp files can be specified using the flag `--If` followed by the file name. The main class will not pass these arguments to the initializing manager, nor any other argument starting with `--I` and any following associated arguments. The name of the initialization manager can be specified with `--Ii` followed by the manager's name.\n\nThe example has an alternative staff.fsp and an initialization manager that can be invoked using:\n\n```sh\n$ sbt \"run --If src/main/resources/staff.fsp --Ii startup\"\n```\n\nMultiple .fsp files can be specified by passing in multiple `--If \u003cfilename\u003e` arguments.\n\n### Passing Context Variables between Workers\n\n*TBD*\n\n`` `#let`(\u003ckey0\u003e -\u003e \u003cvalue0\u003e, \u003ckey1\u003e -\u003e \u003cvalue1\u003e, ... \u003ckeyN\u003e -\u003e \u003cvalueN\u003e, \u003cworker\u003e)``\n\n## Namespaces\n\n### Namespace Declarations\n\n* `` `namespace|scalaioc` `` assigns the namespace name \"scalaioc\" as the default. All the example .fsp files thus far have started with this declaration, so all worker definitions presented have been in the \"scalaioc\" namespace.\n* `` `namespace i|scalaioc` `` assigns the namespace name \"scalaioc\" to the prefix \"i\".\n\n### Namespaced Workers\n\n* `` `#ref` `` references the worker named \"ref\" in the default namespace.\n* `` `#i|let` `` references the worker named \"let\" in the namespace whose name assigned to the prefix \"i\".\n* `` `#scalaioc#=` `` references the worker named \"=\" in the namespace whose name is \"scalaioc\".\n* `` `#|myWorker` `` references the worker named \"myWorker\" that's in the nameless namespace.\n\n### Workers in \"scalaioc\" Namespace\n\n*work-in-progress*\n\n* `` `#=` ``\n* `` `#=\u003e` ``\n* `` `#ref` ``\n* `` `#ref!` ``\n* `` `#let` ``\n* `` `#$` ``\n* `` `#def` ``\n* `` `#resource` ``\n* `` `#embed` ``\n\n## Multiple Factory Configuration Files\n\n*TBD*\n\n## Extending the Framework (unstable)\n\n*work-in-progress*\n\n`` `#def`([[\u003cnamespace name\u003e, ]\u003clocal name\u003e, ]\u003cworker definition\u003e)``\n\nWorker definition must be functions with the follow signature:\n\n```scala\n(\n  Option[String], // namespace name of invoking worker\n  String,         // local name of invoking worker\n) =\u003e (\n  scala.ppm.MacroArgs(\n    Option[scala.reflect.runtime.universe.Tree],  // LHS value\n    List[scala.reflect.runtime.universe.Tree],    // Type arguments\n    List[scala.reflect.runtime.universe.Tree],    // arguments\n    ToolBox[scala.reflect.runtime.universe.type], // Toolbox instance\n    Option[String],                               // description of the source of the trees\n  )\n) =\u003e scala.reflect.runtime.universe.Tree // resulting tree\n```\n\n## Packaged Extensions\n\n*work-in-progress*\n\n* Servlet extension: [servlet example](https://github.com/david-sledge/scalaioc/tree/master/examples/servlet/ \"Servlet example\") (enable with `` `#embed`(\"scala/ioc/servlet/http/macroDefs.fsp\")``)\n* XML writer (enable with `` `#embed`(\"scala/ioc/xml/macroDefs.fsp\")``)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavid-sledge%2Fscalaioc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavid-sledge%2Fscalaioc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavid-sledge%2Fscalaioc/lists"}