Dependency Injection framework for Swift (iOS/macOS/Linux)

Overview

logo

Declarative, easy-to-use and safe Dependency Injection framework for Swift (iOS/macOS/Linux)

Build Status codecov Gitter

Watch the video

Features

  • Dependency declaration via property wrappers or comments
  • DI Containers auto-generation
  • Dependency Graph compile time validation
  • ObjC support
  • Non-optional dependency resolution
  • Type safety
  • Injection with arguments
  • Registration Scopes
  • DI Container hierarchy
  • Thread safe

Talks

Tutorials

If you're looking for a step by step tutorial, check out these links.

Dependency Injection

Dependency Injection basically means "giving an object its instance variables" ¹. It seems like it's not such a big deal, but as soon as a project gets bigger, it gets tricky. Initializers become too complex, passing down dependencies through several layers becomes time consuming and just figuring out where to get a dependency from can be hard enough to give up and finally use a singleton.

However, Dependency Injection is a fundamental aspect of software architecture, and there is no good reason not to do it properly. That's where Weaver can help.

What is Weaver?

Weaver is a declarative, easy-to-use and safe Dependency Injection framework for Swift.

  • Declarative because it allows developers to declare dependencies via annotations directly in the Swift code.
  • Easy-to-use because it generates the necessary boilerplate code to inject dependencies into Swift types.
  • Safe because it's all happening at compile time. If it compiles, it works.

How does Weaver work?

                                                                         |-> validate() -> valid/invalid 
swift files -> scan() -> [Token] -> parse() -> AST -> link() -> Graph -> | 
                                                                         |-> generate() -> source code 

Weaver scans the Swift sources of the project, looking for annotations, and generates an AST (abstract syntax tree). It uses SourceKitten which is backed by Apple's SourceKit.

The AST then goes through a linking phase, which outputs a dependency graph.

Some safety checks are then performed on the dependency graph in order to ensure that the generated code won't crash at runtime. Issues are friendly reported in Xcode to make their correction easier.

Finally, Weaver generates the boilerplate code which can directly be used to make the dependency injections happen.

Installation

(1) - Weaver command

Weaver can be installed using Homebrew, CocodaPods or manually.

Binary form

Download the latest release with the prebuilt binary from release tab. Unzip the archive into the desired destination and run bin/weaver

Homebrew

$ brew install weaver

CocoaPods

Add the following to your Podfile:

pod 'WeaverDI'

This will download the Weaver binaries and dependencies in Pods/ during your next pod install execution and will allow you to invoke it via ${PODS_ROOT}/WeaverDI/weaver/bin/weaver in your Script Build Phases.

This is the best way to install a specific version of Weaver since Homebrew cannot automatically install a specific version.

Mint

To use Weaver via Mint, prefix the normal usage with mint run scribd/Weaver like so:

mint run scribd/Weaver version

To use a specific version of Weaver, add the release tag like so:

mint run scribd/[email protected] version

Building from source

Download the latest release source code from the release tab or clone the repository.

In the project directory, run brew update && brew bundle && make install to build and install the command line tool.

Check installation

Run the following to check if Weaver has been installed correctly.

$ weaver swift --help

Usage:

    $ weaver swift

Options:
    --project-path - Project's directory.
    --config-path - Configuration path.
    --main-output-path - Where the swift code gets generated.
    --tests-output-path - Where the test helpers gets generated.
    --input-path - Paths to input files.
    --ignored-path - Paths to ignore.
    --cache-path - Where the cache gets stored.
    --recursive-off
    --tests - Activates the test helpers' generation.
    --testable-imports - Modules to imports in the test helpers.
    --swiftlint-disable-all - Disables all swiftlint rules.

(2) - Weaver build phase

In Xcode, add the following command to a command line build phase:

weaver swift --project-path $PROJECT_DIR/$PROJECT_NAME --main-output-path output/relative/path

Important - Move this build phase above the Compile Source phase so that Weaver can generate the boilerplate code before compilation happens.

Basic Usage

For a more complete usage example, please check out the sample project.

Let's implement a simple app displaying a list of movies. It will be composed of three noticeable objects:

  • AppDelegate where the dependencies are registered.
  • MovieManager providing the movies.
  • MoviesViewController showing a list of movies at the screen.

Let's get into the code.

AppDelegate with comment annotations:

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    private let dependencies = MainDependencyContainer.appDelegateDependencyResolver()
    
    // weaver: movieManager = MovieManager <- MovieManaging
    // weaver: movieManager.scope = .container
    
    // weaver: moviesViewController = MoviesViewController <- UIViewController
    // weaver: moviesViewController.scope = .container
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        
        window = UIWindow()

        let rootViewController = dependencies.moviesViewController
        window?.rootViewController = UINavigationController(rootViewController: rootViewController)
        window?.makeKeyAndVisible()
        
        return true
    }
}

AppDelegate registers two dependencies:

  • // weaver: movieManager = MovieManager <- MovieManaging
  • // weaver: moviesViewController = MoviesViewController <- UIViewController

These dependencies are made accessible to any object built from AppDelegate because their scope is set to container:

  • // weaver: movieManager.scope = .container
  • // weaver: moviesViewController.scope = .container

A dependency registration automatically generates the registration code and one accessor in AppDelegateDependencyContainer, which is why the rootViewController can be built:

  • let rootViewController = dependencies.moviesViewController.

AppDelegate with property wrapper annotations:

Since Weaver 1.0.1, you can use property wrappers instead of annotations in comments.

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    
    // Must be declared first!
    private let dependencies = MainDependencyContainer.appDelegateDependencyResolver()

    @Weaver(.registration, type: MovieManager.self, scope: .container)
    private var movieManager: MovieManaging
	
    @Weaver(.registration, type: MoviesViewController.self, scope: .container)
    private var moviesViewController: UIViewController
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        
        window = UIWindow()

        window?.rootViewController = UINavigationController(rootViewController: moviesViewController)
        window?.makeKeyAndVisible()
        
        return true
    }
}
  • Note how dependencies can be accessed from the self instance directly.

  • Also note that the dependencies object must be declared and created prior to any other Weaver annotation. Not doing so would immediately crash the application.

  • It is possible to use comment and property wrapper annotations in the same type.

MovieManager:

protocol MovieManaging {
    
    func getMovies(_ completion: @escaping (Result<Page<Movie>, MovieManagerError>) -> Void)
}

final class MovieManager: MovieManaging {

    func getMovies(_ completion: @escaping (Result<Page<Movie>, MovieManagerError>) -> Void) {
        // fetches movies from the server...
        completion(.success(movies))        
    }
}

MoviesViewController with comment annotations:

final class MoviesViewController: UIViewController {
    
    private let dependencies: MoviesViewControllerDependencyResolver
    
    private var movies = [Movie]()
    
    // weaver: movieManager <- MovieManaging
    
    required init(injecting dependencies: MoviesViewControllerDependencyResolver) {
        self.dependencies = dependencies
        super.init(nibName: nil, bundle: nil)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // Setups the tableview... 
        
        // Fetches the movies
        dependencies.movieManager.getMovies { result in
            switch result {
            case .success(let page):
                self.movies = page.results
                self.tableView.reloadData()
                
            case .failure(let error):
                self.showError(error)
            }
        }
    }

    // ... 
}

MoviesViewController declares a dependency reference:

  • // weaver: movieManager <- MovieManaging

This annotation generates an accessor in MoviesViewControllerDependencyResolver, but no registration, which means MovieManager is not stored in MoviesViewControllerDependencyContainer, but in its parent (the container from which it was built). In this case, AppDelegateDependencyContainer.

MoviesViewController also needs to declare a specific initializer:

  • required init(injecting dependencies: MoviesViewControllerDependencyResolver)

This initializer is used to inject the DI Container. Note that MoviesViewControllerDependencyResolver is a protocol, which means a fake version of the DI Container can be injected when testing.

MoviesViewController with property wrapper annotations:

final class MoviesViewController: UIViewController {
    
    private var movies = [Movie]()

    @Weaver(.reference)
    private var movieManager: MovieManaging
    
    required init(injecting _: MoviesViewControllerDependencyResolver) {
        super.init(nibName: nil, bundle: nil)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // Setups the tableview... 
        
        // Fetches the movies
        movieManager.getMovies { result in
            switch result {
            case .success(let page):
                self.movies = page.results
                self.tableView.reloadData()
                
            case .failure(let error):
                self.showError(error)
            }
        }
    }

    // ... 
}

API

Code Annotations

Weaver allows you to declare dependencies by annotating the code with comments like // weaver: ... or property wrappers like @Weaver(...) var ...

It currently supports the following annotations:

- Registration

  • Adds the dependency builder to the container.

  • Adds an accessor for the dependency to the container's resolver protocol.

Example:

// weaver: dependencyName = DependencyConcreteType <- DependencyProtocol

@Weaver(.registration, type: DependencyConcreteType.self) 
var dependencyName: DependencyProtocol

or

// weaver: dependencyName = DependencyConcreteType

@Weaver(.registration) 
var dependencyName: DependencyConcreteType
  • dependencyName: Dependency's name. Used to make reference to the dependency in other objects and/or annotations.

  • DependencyConcreteType: Dependency's implementation type. Can be a struct or a class.

  • DependencyProtocol: Dependency's protocol if any. Optional, you can register a dependency with its concrete type only.

- Reference

Adds an accessor for the dependency to the container's protocol.

Example:

// weaver: dependencyName <- DependencyType

@Weaver(.reference) 
var dependencyName: DependencyType

DependencyType: Either the concrete or abstract type of the dependency. This also defines the type the dependency's accessor returns.

- Parameter

Adds a parameter to the container's resolver protocol. This means that the generated container needs to take these parameter at initialisation. It also means that all the concerned dependency accessors need to take this parameter.

Example:

// weaver: parameterName <= ParameterType

@Weaver(.parameter) 
var parameterName: ParameterType

- Scope

Sets the scope of a dependency. The default scope being container. Only works for registrations or weak parameters.

The scope defines a dependency lifecycle. Four scopes are available:

  • transient: Always creates a new instance when resolved.

  • container: Builds an instance at initialization of its container and lives as long as its container lives.

  • weak: A new instance is created when resolved the first time and then lives as long as its strong references are living.

  • lazy: A new instance is created when resolved the first time with the same lifetime than its container.

Example:

// weaver: dependencyName.scope = .scopeValue

@Weaver(.registration, scope: .scopeValue)
var dependencyName: DependencyType

scopeValue: Value of the scope. It can be one of the values described above.

- Custom Builder

Overrides a dependency's default initialization code.

Works for registration annotations only.

Example:

// weaver: dependencyName.builder = DependencyType.make

@Weaver(.registration, builder: DependencyType.make) 
var dependencyName: DependencyType

DependencyType.make: Code overriding the dependency's initialization code taking DependencyTypeInputDependencyResolver as a parameter and returning DependencyType (e.g. make's signature could be static func make(_ dependencies: DependencyTypeInputDependencyResolver) -> DependencyType).

Warning - Make sure you don't do anything unsafe with the DependencyResolver parameter passed down in this method since it won't be caught by the dependency graph validator.

- Configuration

Sets a configuration attribute to the concerned object.

Example:

// weaver: dependencyName.attributeName = aValue

@Weaver(..., attributeName: aValue, ...) 
var dependencyName: DependencyType
Configuration Attributes:
  • isIsolated: Bool (default: false): any object setting this to true is considered by Weaver as an object which isn't used in the project. An object flagged as isolated can only have isolated dependents. This attribute is useful to develop a feature wihout all the dependencies setup in the project.

  • setter: Bool (default: false): generates a setter (setDependencyName(dependency)) in the dependency container. Note that a dependency using a setter has to be set manually before being accessed through a dependency resolver or it will crash.

  • objc: Bool (default: false): generates an ObjC compliant resolver for a given dependency, allowing it be accessed from ObjC code.

  • escaping: Bool (default: true when applicable): asks Weaver to use @escaping when declaring a closure parameter.

  • platforms: [Platform] (default: []): List of platforms for which Weaver is allowed to use the dependency. An empty list means any platform is allowed.

Using protperty wrappers with parameters:

Types using parameter annotations need to take the said parameters as an input when being registered or referenced. This is particularly true when using property wrappers, because the signature of the annotation won't compile if not done correctly.

For example, the following shows how a type taking two parameters at initialization can be annotated:

final class MovieViewController {

   @Weaver(.parameter) private var movieID: Int
   
   @Weaver(.parameter) private var movieTitle: String
}

And how that same type can be registered and referenced:

@WeaverP2(.registration)
private var movieViewController: (Int, String) -> MovieViewController

@WeaverP2(.reference)
private var moviewViewController: (Int, String) -> MovieViewController

Note that Weaver generates one property wrapper per amount of input parameters, so if a type takes one parameter WeaverP1 shall be used, for two parameters, WeaverP2, and so on.

Writing tests:

Weaver can also generate a dependency container stub which can be used for testing. This feature is accessible by adding the option --tests to the command (e.g. weaver swift --tests).

To compile, the stub expects certain type doubles to be implemented.

For example, given the following code:

final class MovieViewController {
   @Weaver(.reference) private var movieManager: MovieManaging
}

The generated stub expects MovieManagingDouble to be implemented in order to compile.

Testing MoviewViewController can then be written like the following:

final class MovieViewControllerTests: XCTestCase {

	func test_view_controller() {
		let dependencies = MainDependencyResolverStub()
		let viewController = dependencies.buildMovieViewController()
		
		viewController.viewDidLoad()
		
		XCTAssertEqual(dependencies.movieManagerDouble.didRequestMovies, true)
	}
}

Generate Swift Files

To generate the boilerplate code, the swift command shall be used.

$ weaver swift --help

Usage:

    $ weaver swift

Options:
    --project-path - Project's directory.
    --config-path - Configuration path.
    --main-output-path - Where the swift code gets generated.
    --tests-output-path - Where the test helpers gets generated.
    --input-path - Paths to input files.
    --ignored-path - Paths to ignore.
    --cache-path - Where the cache gets stored.
    --recursive-off
    --tests - Activates the test helpers' generation.
    --testable-imports - Modules to imports in the test helpers.
    --swiftlint-disable-all - Disables all swiftlint rules.
    --platform - Targeted platform.
    --included-imports - Included imports.
    --excluded-imports - Excluded imports.

Example:

weaver swift --project-path $PROJECT_DIR/$PROJECT_NAME --main-output-path Generated

Parameters:

  • --project-path: Acts like a base path for other relative paths like config-path, output-path, template-path, input-path and ignored-path. It defaults to the running directory.
  • --config-path: Path to a configuration file. By defaults, Weaver automatically detects .weaver.yaml and .weaver.json located at project-path.
  • --main-output-path: Path where the code will be generated. Defaults to project-path.
  • --tests-output-path: Path where the test utils code will be generated. Defaults to project-path.
  • --input-path: Path to the project's Swift code. Defaults to project-path. Variadic parameter, which means it can be set more than once. By default, Weaver recursively read any Swift file located under the input-path.
  • --ignored-path: Same than input-path but for ignoring files which shouldn't be parsed by Weaver.
  • --recursive-off: Deactivates recursivity for input-path and ignored-path.
  • --tests - Activates the test helpers' generation.
  • --testable-imports - Modules to imports in the test helpers. Variadic parameter, which means it can be set more than once.
  • --swiftlint-disable-all - Disables all swiftlint rules in generated files.
  • --platform - Platform for which the generated code will be compiled (iOS, watchOS, OSX, macOS or tvOS).
  • --included-imports - Modules which can be imported in generated files.
  • --excluded-imports - Modules which can't be imported in generated files.

Configuration File:

Weaver can read a configuration file rather than getting its parameters from the command line. It supports both json and yaml formats.

To configure Weaver with a file, write a file named .weaver.yaml or .weaver.json at the root of your project.

Parameters are named the same, but snakecased. They also work the same way with one exception, project_path cannot be defined in a configuration. Weaver automatically set its value to the configuration file location.

For example, the sample project configuration looks like:

main_output_path: Sample/Generated
input_paths:
  - Sample
ignored_paths:
  - Sample/Generated

Caching & Cleaning

In order to avoid parsing the same swift files over and over again, Weaver has a cache system built in. It means that Weaver won't reprocess files which haven't been changed since last time they got processed.

Using this functionality is great in a development environment because it makes Weaver's build phase much faster most of the time. However, on a CI it is preferable to let Weaver process the Swift files everytime for safety, for which the clean command can be used.

For example, the following always processes all of the swift code:

$ weaver clean
$ weaver swift 

Export Dependency Graph

Weaver can ouput a JSON representation of the dependency graph of a project.

$ weaver json --help
Usage:

    $ weaver json

Options:
    --project-path - Project's directory.
    --config-path - Configuration path.
    --pretty [default: false]
    --input-path - Paths to input files.
    --ignored-path - Paths to ignore.
    --cache-path - Cache path.
    --recursive-off
    --platform - Selected platform

For an output example, please check this Gist.

Migration guides

More content...

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

License

MIT license. See the LICENSE file for details.

Comments
  • DI Container Thread-safety

    DI Container Thread-safety

    As asked for help on issue #18, I built a basic thread-safe implementation for the BuilderStoring. Consist only on dispatching all the requests to be executed on a private Queue, this way avoiding parallel execution of the gets and sets. Please take a look and give me feedback. If you think that is necessary for the Cache, I can build a similar class for it.

    opened by BrunoMazzo 6
  • Instantiate lazy registrations on first usage

    Instantiate lazy registrations on first usage

    I don't really know how this feature fits the spirit of Weaver, but in our project we found it useful to instantiate lazy registration when we use it for the first time (deep inside in the dependency graph far away from this lazy registration). Actual Weaver version instantiates such registrations when intermediate dependency containers are being resolved.

    class A {
    	
    	// weaver: b = B
    	// weaver: b.scope = .lazy
    
    	// weaver: c = C
    	// weaver: c.scope = .lazy
    
    	func someMethod() {
    		let b = dependencies.b // prints "instantiated C" here
    		b.start() // but we want to instantiate C here
    	}
    }
    
    class B {
    	
    	// weaver: c <- C
    
    	init(injecting dependencies: ...) {
    		print("instantiated B")
    	} 
    
    	func start() {
    		dependencies.c.perform()
    	}
    }
    
    class C {
    	
    	init() {
    		print("instantiated C")
    	}
    
    	func perform() {}
    }
    
    opened by LorienMan 5
  • Bump addressable from 2.7.0 to 2.8.0

    Bump addressable from 2.7.0 to 2.8.0

    Bumps addressable from 2.7.0 to 2.8.0.

    Changelog

    Sourced from addressable's changelog.

    Addressable 2.8.0

    • fixes ReDoS vulnerability in Addressable::Template#match
    • no longer replaces + with spaces in queries for non-http(s) schemes
    • fixed encoding ipv6 literals
    • the :compacted flag for normalized_query now dedupes parameters
    • fix broken escape_component alias
    • dropping support for Ruby 2.0 and 2.1
    • adding Ruby 3.0 compatibility for development tasks
    • drop support for rack-mount and remove Addressable::Template#generate
    • performance improvements
    • switch CI/CD to GitHub Actions
    Commits
    • 6469a23 Updating gemspec again
    • 2433638 Merge branch 'main' of github.com:sporkmonger/addressable into main
    • e9c76b8 Merge pull request #378 from ashmaroli/flat-map
    • 56c5cf7 Update the gemspec
    • c1fed1c Require a non-vulnerable rake
    • 0d8a312 Adding note about ReDoS vulnerability
    • 89c7613 Merge branch 'template-regexp' into main
    • cf8884f Note about alias fix
    • bb03f71 Merge pull request #371 from charleystran/add_missing_encode_component_doc_entry
    • 6d1d809 Adding note about :compacted normalization
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 2
  • Update generated code so that transient builders always create a unique instance.

    Update generated code so that transient builders always create a unique instance.

    Problem statement:

    The core of the problem is that transient builders didn't always create unique instances.

    If you look at this class relationship:

    class App {
        // weaver: manager = Manager
        // weaver: manager.scope = .transient
    
        // weaver: object1 = Object1
    }
    
    class Object1 {
        // weaver: manager <- Manager
    
        // weaver: object2 = Object2
    }
    
    class Object2 {
        // weaver: manager <- Manager
    }
    
    class Manager { }
    

    in the existing implementation, you'd end up with these results:

    • App -> Manager instance A
    • Object1 -> Manager instance B
    • Object2 -> Manager instance B

    And the same instance (B) would be passed down from there on.

    The new implementation results in:

    • App -> Manager instance A
    • Object1 -> Manager instance B
    • Object2 -> Manager instance C

    And down the chain would create D, E, F, etc. Additionally any new calls to the builder by the same class would generate new unique instances.

    Architectural change

    The main issue is that we were storing builder object, but the first time the transient builder was fulfilled, we retained a reference to the returned object instead.

    To solve this, we now have a separate Provider class that holds a reference to the builders. Additionally, the Provider object has a weak reference to an owner.

    This moves the weak referencing out of the builder itself and into the Provider. The code change also ensures that builders do not hold a reference to the parent container object. The end result is this allows us to transfer ownership of builders down the chain so that they are bound to the memory lifecycle of the children nodes.

    This ultimately solves the problem of a transient dependency instantiating a container dependency that nodes down the tree expect to continue to exist. The lifecycle is no longer bound to the instantiating container, but also to children referencing it.

    opened by StephaneMagne 1
  • Fix grep error for empty dependencies

    Fix grep error for empty dependencies

    Hello! Thanks for the cool tool. I prepared a small pull request with improvement.

    Motivation: if I didn’t register or add any dependencies, now I get the error of the weaver swift command. In this case, I want to get the generated file with basic entities, for example @Weaver, so that you can use them

    opened by happynik 1
  • Bump rubyzip from 1.2.2 to 1.3.0

    Bump rubyzip from 1.2.2 to 1.3.0

    Bumps rubyzip from 1.2.2 to 1.3.0.

    Release notes

    Sourced from rubyzip's releases.

    v1.3.0

    Security

    • Add validate_entry_sizes option so that callers can trust an entry's reported size when using extract #403
      • This option defaults to false for backward compatibility in this release, but you are strongly encouraged to set it to true. It will default to true in rubyzip 2.0.

    New Feature

    • Add add_stored method to simplify adding entries without compression #366

    Tooling / Documentation

    • Add more gem metadata links #402

    v1.2.4

    • Do not rewrite zip files opened with open_buffer that have not changed #360

    Tooling / Documentation

    • Update example_recursive.rb in README #397
    • Hold CI at trusty for now, automatically pick the latest ruby patch version, use rbx-4 and hold jruby at 9.1 #399

    v1.2.3

    • Allow tilde in zip entry names #391 (fixes regression in 1.2.2 from #376)
    • Support frozen string literals in more files #390
    • Require pathname explicitly #388 (fixes regression in 1.2.2 from #376)

    Tooling / Documentation:

    • CI updates #392, #394
      • Bump supported ruby versions and add 2.6
      • JRuby failures are no longer ignored (reverts #375 / part of #371)
    • Add changelog entry that was missing for last release #387
    • Comment cleanup #385

    Since the GitHub release information for 1.2.2 is missing, I will also include it here:

    1.2.2

    NB: This release drops support for extracting symlinks, because there was no clear way to support this securely. See https://github-redirect.dependabot.com/rubyzip/rubyzip/pull/376#issue-210954555 for details.

    • Fix CVE-2018-1000544 #376 / #371
    • Fix NoMethodError: undefined method `glob' #363
    • Fix handling of stored files (i.e. files not using compression) with general purpose bit 3 set #358
    • Fix close on StringIO-backed zip file #353
    • Add Zip.force_entry_names_encoding option #340
    • Update rubocop, apply auto-fixes, and fix regressions caused by said auto-fixes #332, #355
    • Save temporary files to temporary directory (rather than current directory) #325

    Tooling / Documentation:

    ... (truncated)
    Changelog

    Sourced from rubyzip's changelog.

    1.3.0 (2019-09-25)

    Security

    • Add validate_entry_sizes option so that callers can trust an entry's reported size when using extract #403
      • This option defaults to false for backward compatibility in this release, but you are strongly encouraged to set it to true. It will default to true in rubyzip 2.0.

    New Feature

    • Add add_stored method to simplify adding entries without compression #366

    Tooling / Documentation

    • Add more gem metadata links #402

    1.2.4 (2019-09-06)

    • Do not rewrite zip files opened with open_buffer that have not changed #360

    Tooling / Documentation

    • Update example_recursive.rb in README #397
    • Hold CI at trusty for now, automatically pick the latest ruby patch version, use rbx-4 and hold jruby at 9.1 #399

    1.2.3

    • Allow tilde in zip entry names #391 (fixes regression in 1.2.2 from #376)
    • Support frozen string literals in more files #390
    • Require pathname explicitly #388 (fixes regression in 1.2.2 from #376)

    Tooling / Documentation:

    • CI updates #392, #394
      • Bump supported ruby versions and add 2.6
      • JRuby failures are no longer ignored (reverts #375 / part of #371)
    • Add changelog entry that was missing for last release #387
    • Comment cleanup #385
    Commits
    • e79d9ea Merge pull request #407 from rubyzip/v1-3-0
    • 7c65e1e Bump version to 1.3.0
    • d65fe7b Merge pull request #403 from rubyzip/check-size
    • 97cb6ae Warn when an entry size is invalid
    • 7849f73 Default validate_entry_sizes to false for 1.3 release
    • 4167f0c Validate entry sizes when extracting
    • 94b7fa2 [ci skip] Update changelog
    • 93505ca Check expected entry size in add_stored test
    • 6619bf3 Merge pull request #366 from hainesr/add-stored
    • ecb2776 Zip::File.add_stored() to add uncompressed files.
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot ignore this [patch|minor|major] version will close this PR and stop Dependabot creating any more for this minor/major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 1
  • Fix two bugs: runtime tree inspection and ignore paths.

    Fix two bugs: runtime tree inspection and ignore paths.

    This PR fixes two issues.

    1. The runtime parse of the tree would sometimes fail if two separate abstractions were backed by the same concrete type. Example below.
        // weaver: appLifecycleEventProvider = AppLifecycleEventController <- AppLifecycleEventProviding
        // weaver: appLifecycleEventProvider.builder = { _ in AppLifecycleEventController.shared }
        // weaver: appLifecycleEventProvider.scope = .container
    
        // weaver: appLifecycleEventConfiguration = AppLifecycleEventController <- AppLifecycleEventConfiguring
        // weaver: appLifecycleEventConfiguration.builder = { _ in AppLifecycleEventController.shared }
        // weaver: appLifecycleEventConfiguration.scope = .container
    
    1. A bug where the ignored_paths listed in the .yaml file weren't being properly filtered from the include list.
    opened by StephaneMagne 0
  • Fix parameter referencing

    Fix parameter referencing

    Previously there was an issue with a build hierarchy like this...

    First we have a dependency that takes in a parameter. This can only be built as an instance or itself be injected as a parameter into another container.

    final class Manager: Managing {
    
        // weaver: someValue <= Int
    }
    

    Look at this case where we do both. You'll see that AppDelegate creates Manager <- Managing, but its child Controller1 is handed that same object as a parameter. Additionally, the child class Controller2 expects Managing to exist as a reference.

    public final class AppDelegate {
    
        // weaver: manager = Manager <- Managing
        // weaver: manager.scope = .transient
    
        // weaver: controller1 = Controller1
        // weaver: controller1.scope = .transient
    }
    
    final class Controller1 {
    
        // weaver: manager <= Managing
    
        // weaver: controller2 = Controller2
        // weaver: controller2.scope = .transient
    }
    
    final class Controller2 {
    
        // weaver: manager <- Managing
    }
    

    Previously there was a bug where Controller1 would have access to the injected instance, but Controller2 would incorrectly attempt to inherit the transient builder even though it was marked as a reference.

    This change now allows Controller2 to correctly fetch the existing instance of Managing from the dependency container.

    opened by StephaneMagne 0
  • Add support to reference dependencies that have parameters and are transient.

    Add support to reference dependencies that have parameters and are transient.

    Add support for references to transient properties that take parameters.

    E.g. a structure like this:

                final class MovieViewController {
                    // weaver: movieManager = MovieManager
                    // weaver: movieManager.scope = .transient
    
                    // weaver: otherClass = OtherClass
                    // weaver: otherClass.scope = .container
                }
    
                final class OtherClass {
                    // weaver: movieManager <- MovieManager
                }
    
                final class MovieManager {
                    // weaver: movieID <= Int
                }
    

    In this case OtherClass should be able to inherit the transient builder for MovieManager since it will build a new instance every time.

    This should now work correctly with the previous fix for transient objects.

    opened by StephaneMagne 0
  • Add support for classes with nested scope

    Add support for classes with nested scope

    Previously, attempting to use weaver within classes of nested scope would introduce a number of problems:

    • Dependency resolvers would have names that quickly collided.
    • The static graph analysis could not properly match names.
    • Generated code would attempt to apply dot notation in both class and function names. Code would not compile.

    Approach

    The solution was to include the entire hierarchy (not including module name) into the class description of the static analyzer.

    Take a look at these two classes:

    class FirstClass { }
    
    enum Test {
        enum Code {
            class SecondClass { }
        }
    }
    

    Previously they would have been encoded as:

    • FirstClass
    • SecondClass

    This was causing issues with static analysis as it could not match the class name to its full hierarchy.

    After this change, this will now be encoded as:

    • FirstClass
    • Test.Code.SecondClass

    This makes class equality checks continue to work.

    In addition, I needed to add support to code gen to better support this change. We want to generate user friendly code using extensions, and not just forcing full length names all the time. This is detailed below.

    Code Example

    Here's an example of a class with nested scope:

    public enum ShareFeature {
    
        public enum Quotes {
    
            public final class Builder {
    
                // weaver: urlSession <- URLSession
    
                private let dependencies: BuilderDependencyResolver
    
                init(injecting dependencies: BuilderDependencyResolver) {
                    self.dependencies = dependencies
                    print("urlSession -> \(dependencies.urlSession)")
                }
            }
        }
    }
    

    As we can see, we should be able to reference the dependency resolver BuilderDependencyResolver.

    Here is the code now generated by weaver:

    extension ShareFeature.Quotes {
        typealias BuilderDependencyResolver = UrlSessionResolver
    }
    
    private func shareFeatureQuotesBuilderDependencyResolver() -> ShareFeature.Quotes.BuilderDependencyResolver {
        let _self = MainDependencyContainer()
        var _builders = Dictionary<String, Any>()
        _builders["urlSession"] = urlSessionBuilder
        _self.provider.addBuilders(_builders)
        return _self
    }
    
            ...
            _builders["shareBuilder"] = Provider.lazyBuilder(
                 { (_: Optional<Provider.ParametersCopier>) -> ShareFeature.Quotes.Builder in
                    let _inputContainer = MainDependencyContainer(provider: _inputProvider)
                    let __self = _inputContainer.shareFeatureQuotesBuilderDependencyResolver()
                    return ShareFeature.Quotes.Builder(injecting: __self)
                }
            )
            ...
    

    and across frameworks:

    extension ShareFeature.Quotes {
        typealias BuilderInputDependencyResolver = LoggerResolver & MovieAPIResolver & ShareBuilderResolver
    }
    
            ...
            _builders["shareBuilder"] = Provider.lazyBuilder(
                 { (_: Optional<Provider.ParametersCopier>) -> ShareFeature.Quotes.Builder in
                    let _inputContainer = MainDependencyContainer(provider: _inputProvider)
                    return ReviewManager.makeBuilder(_inputContainer as ShareFeature.Quotes.BuilderInputDependencyResolver)
                }
            )
            ...
    

    Cleanup

    I added a third commit to clean-up the indentation of string literals in tests.

    In any multi-line string using """ notation, the overall indentation is relative to the closing """ parameter. This means that these two strings will be equal:

    let string1 = """
    class Someone {
    
        let name: String
        let age: Int
    
        init(_ person: Person) {
            self.name = person.fullName
            self.age = person.age
        }
    }
    """
    
    let string2 = """
            class Someone {
    
                let name: String
                let age: Int
    
                init(_ person: Person) {
                    self.name = person.fullName
                    self.age = person.age
                }
            }
            """
    
    print(string1 == string2) // prints `true`
    

    Using this rule, I indented all multi-line strings. I find it easier to parse when the test name is the left-most value in the code.

    opened by StephaneMagne 0
  • Fix transient builders without requiring owner

    Fix transient builders without requiring owner

    This is an increment from the previous solution: https://github.com/scribd/Weaver/pull/158.

    The main change here is that we remove the owner property from the Provider class.

    I realized that by separating the Provider from MainDependencyContainer we had already given ourselves a way to maintain the memory graph without the weak references* (with one exception listed at the end).

    Instead, we can simply hold references to the Providers inside of our blocks and then release them naturally as the retaining objects are released. The owner reference was entirely unneeded!

    The one case where we will use a weak reference to the Provider object is in the case where the parent container has a setter = true dependency. In this case we need to make sure that we copy the Provider right as we instantiate the child to ensure that we're getting the proper object passed to the setter reference (this could have been set 1 or more times).

    Since only .container objects will have a setter = true dependency, then we can safely use the weak reference to the Provider is this specific situation.

    opened by StephaneMagne 0
  • Bump addressable from 2.7.0 to 2.8.1

    Bump addressable from 2.7.0 to 2.8.1

    Bumps addressable from 2.7.0 to 2.8.1.

    Changelog

    Sourced from addressable's changelog.

    Addressable 2.8.1

    • refactor Addressable::URI.normalize_path to address linter offenses (#430)
    • remove redundant colon in Addressable::URI::CharacterClasses::AUTHORITY regex (#438)
    • update gemspec to reflect supported Ruby versions (#466, #464, #463)
    • compatibility w/ public_suffix 5.x (#466, #465, #460)
    • fixes "invalid byte sequence in UTF-8" exception when unencoding URLs containing non UTF-8 characters (#459)
    • Ractor compatibility (#449)
    • use the whole string instead of a single line for template match (#431)
    • force UTF-8 encoding only if needed (#341)

    #460: sporkmonger/addressable#460 #463: sporkmonger/addressable#463 #464: sporkmonger/addressable#464 #465: sporkmonger/addressable#465 #466: sporkmonger/addressable#466

    Addressable 2.8.0

    • fixes ReDoS vulnerability in Addressable::Template#match
    • no longer replaces + with spaces in queries for non-http(s) schemes
    • fixed encoding ipv6 literals
    • the :compacted flag for normalized_query now dedupes parameters
    • fix broken escape_component alias
    • dropping support for Ruby 2.0 and 2.1
    • adding Ruby 3.0 compatibility for development tasks
    • drop support for rack-mount and remove Addressable::Template#generate
    • performance improvements
    • switch CI/CD to GitHub Actions
    Commits
    • 8657465 Update version, gemspec, and CHANGELOG for 2.8.1 (#474)
    • 4fc5bb6 CI: remove Ubuntu 18.04 job (#473)
    • 860fede Force UTF-8 encoding only if needed (#341)
    • 99810af Merge pull request #431 from ojab/ct-_do_not_parse_multiline_strings
    • 7ce0f48 Merge branch 'main' into ct-_do_not_parse_multiline_strings
    • 7ecf751 Merge pull request #449 from okeeblow/freeze_concatenated_strings
    • 41f12dd Merge branch 'main' into freeze_concatenated_strings
    • 068f673 Merge pull request #459 from jarthod/iso-encoding-problem
    • b4c9882 Merge branch 'main' into iso-encoding-problem
    • 08d27e8 Merge pull request #471 from sporkmonger/sporkmonger-enable-codeql
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Bump tzinfo from 1.2.5 to 1.2.10

    Bump tzinfo from 1.2.5 to 1.2.10

    Bumps tzinfo from 1.2.5 to 1.2.10.

    Release notes

    Sourced from tzinfo's releases.

    v1.2.10

    TZInfo v1.2.10 on RubyGems.org

    v1.2.9

    • Fixed an incorrect InvalidTimezoneIdentifier exception raised when loading a zoneinfo file that includes rules specifying an additional transition to the final defined offset (for example, Africa/Casablanca in version 2018e of the Time Zone Database). #123.

    TZInfo v1.2.9 on RubyGems.org

    v1.2.8

    • Added support for handling "slim" format zoneinfo files that are produced by default by zic version 2020b and later. The POSIX-style TZ string is now used calculate DST transition times after the final defined transition in the file. The 64-bit section is now always used regardless of whether Time has support for 64-bit times. #120.
    • Rubinius is no longer supported.

    TZInfo v1.2.8 on RubyGems.org

    v1.2.7

    • Fixed 'wrong number of arguments' errors when running on JRuby 9.0. #114.
    • Fixed warnings when running on Ruby 2.8. #112.

    TZInfo v1.2.7 on RubyGems.org

    v1.2.6

    • Timezone#strftime('%s', time) will now return the correct number of seconds since the epoch. #91.
    • Removed the unused TZInfo::RubyDataSource::REQUIRE_PATH constant.
    • Fixed "SecurityError: Insecure operation - require" exceptions when loading data with recent Ruby releases in safe mode.
    • Fixed warnings when running on Ruby 2.7. #106 and #111.

    TZInfo v1.2.6 on RubyGems.org

    Changelog

    Sourced from tzinfo's changelog.

    Version 1.2.10 - 19-Jul-2022

    Version 1.2.9 - 16-Dec-2020

    • Fixed an incorrect InvalidTimezoneIdentifier exception raised when loading a zoneinfo file that includes rules specifying an additional transition to the final defined offset (for example, Africa/Casablanca in version 2018e of the Time Zone Database). #123.

    Version 1.2.8 - 8-Nov-2020

    • Added support for handling "slim" format zoneinfo files that are produced by default by zic version 2020b and later. The POSIX-style TZ string is now used calculate DST transition times after the final defined transition in the file. The 64-bit section is now always used regardless of whether Time has support for 64-bit times. #120.
    • Rubinius is no longer supported.

    Version 1.2.7 - 2-Apr-2020

    • Fixed 'wrong number of arguments' errors when running on JRuby 9.0. #114.
    • Fixed warnings when running on Ruby 2.8. #112.

    Version 1.2.6 - 24-Dec-2019

    • Timezone#strftime('%s', time) will now return the correct number of seconds since the epoch. #91.
    • Removed the unused TZInfo::RubyDataSource::REQUIRE_PATH constant.
    • Fixed "SecurityError: Insecure operation - require" exceptions when loading data with recent Ruby releases in safe mode.
    • Fixed warnings when running on Ruby 2.7. #106 and #111.
    Commits
    • 0814dcd Fix the release date.
    • fd05e2a Preparing v1.2.10.
    • b98c32e Merge branch 'fix-directory-traversal-1.2' into 1.2
    • ac3ee68 Remove unnecessary escaping of + within regex character classes.
    • 9d49bf9 Fix relative path loading tests.
    • 394c381 Remove private_constant for consistency and compatibility.
    • 5e9f990 Exclude Arch Linux's SECURITY file from the time zone index.
    • 17fc9e1 Workaround for 'Permission denied - NUL' errors with JRuby on Windows.
    • 6bd7a51 Update copyright years.
    • 9905ca9 Fix directory traversal in Timezone.get when using Ruby data source
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Fix dependency resolver ordering

    Fix dependency resolver ordering

    This makes a change to how we manage the _dynamicResolvers array.

    The old code popped from the front:

        fileprivate static func _popDynamicResolver<Resolver>(_ resolverType: Resolver.Type) -> Resolver {
            guard let dynamicResolver = _dynamicResolvers.removeFirst() as? Resolver else {
                MainDependencyContainer.fatalError()
            }
            return dynamicResolver
        }
    

    And I've updated this to pop from the back:

        fileprivate static func _popDynamicResolver<Resolver>(_ resolverType: Resolver.Type) -> Resolver {
            guard let dynamicResolver = _dynamicResolvers.removeLast() as? Resolver else {
                MainDependencyContainer.fatalError()
            }
            return dynamicResolver
        }
    

    And to support this, I've inverted the ordering of how the dependencies are pushed.

    Here's the use case of the Repository class being built

            _builders["repository"] = Provider.lazyBuilder(
                 { (_: Optional<Provider.ParametersCopier>) -> RepositoryProtocol in
                    defer { MainDependencyContainer._dynamicResolversLock.unlock() }
                    MainDependencyContainer._dynamicResolversLock.lock()
                    let _inputContainer = MainDependencyContainer(provider: _inputProvider)
                    let __self = _inputContainer.repositoryDependencyResolver()
                    return Repository(injecting: __self)
                }
            )
    

    This calls the function repositoryDependencyResolver() which pushes the dependency resolvers. To make sure we pop these off the stack correctly, we push them on in reverse order (so the first one we attempt to access is on the end).

    Here's a look at the changes to the repositoryDependencyResolver() function...

    Old:

        private func repositoryDependencyResolver() -> RepositoryDependencyResolver {
            let _self = MainDependencyContainer()
            var _builders = Dictionary<String, Any>()
            _builders["repositoryExampleSubClass"] = repositoryExampleSubClassBuilder
            _builders["service"] = serviceBuilder
            _builders["service2"] = service2Builder
            _self.provider.addBuilders(_builders)
            MainDependencyContainer._pushDynamicResolver({ _self.service })
            MainDependencyContainer._pushDynamicResolver({ _self.service2 })
            MainDependencyContainer._pushDynamicResolver({ _self.repositoryExampleSubClass })
            return _self
        }
    

    New:

        private func repositoryDependencyResolver() -> RepositoryDependencyResolver {
            let _self = MainDependencyContainer()
            var _builders = Dictionary<String, Any>()
            _builders["repositoryExampleSubClass"] = repositoryExampleSubClassBuilder
            _builders["service"] = serviceBuilder
            _builders["service2"] = service2Builder
            _self.provider.addBuilders(_builders)
            MainDependencyContainer._pushDynamicResolver({ _self.repositoryExampleSubClass })
            MainDependencyContainer._pushDynamicResolver({ _self.service2 })
            MainDependencyContainer._pushDynamicResolver({ _self.service })
            return _self
        }
    
    opened by StephaneMagne 0
  • Bump cocoapods-downloader from 1.3.0 to 1.6.3

    Bump cocoapods-downloader from 1.3.0 to 1.6.3

    Bumps cocoapods-downloader from 1.3.0 to 1.6.3.

    Release notes

    Sourced from cocoapods-downloader's releases.

    1.6.3

    Enhancements
    • None.
    Bug Fixes
    • None.

    1.6.2

    Enhancements
    • None.
    Bug Fixes
    • None.

    1.6.1

    Enhancements
    • None.
    Bug Fixes
    • None.

    1.6.0

    Enhancements
    • None.
    Bug Fixes
    • Adds a check for command injections in the input for hg and git.
      orta #124

    1.5.1

    Enhancements
    • None.
    Bug Fixes
    • Fix "can't modify frozen string" errors when pods are integrated using the branch option
      buju77 #10920

    1.5.0

    ... (truncated)

    Changelog

    Sourced from cocoapods-downloader's changelog.

    1.6.3 (2022-04-01)

    Enhancements
    • None.
    Bug Fixes
    • None.

    1.6.2 (2022-03-28)

    Enhancements
    • None.
    Bug Fixes
    • None.

    1.6.1 (2022-03-23)

    Enhancements
    • None.
    Bug Fixes
    • None.

    1.6.0 (2022-03-22)

    Enhancements
    • None.
    Bug Fixes
    • Adds a check for command injections in the input for hg and git.
      orta #124

    1.5.1 (2021-09-07)

    Enhancements
    • None.

    ... (truncated)

    Commits
    • c03e2ed Release 1.6.3
    • f75bccc Disable Bazaar tests due to macOS 12.3 not including python2
    • 52a0d54 Merge pull request #128 from CocoaPods/validate_before_dl
    • d27c983 Ensure that the git pre-processor doesn't accidentally bail also
    • 3adfe1f [CHANGELOG] Add empty Master section
    • 591167a Release 1.6.2
    • d2564c3 Merge pull request #127 from CocoaPods/validate_before_dl
    • 99fec61 Switches where we check for invalid input, to move it inside the download fun...
    • 96679f2 [CHANGELOG] Add empty Master section
    • 3a7c54b Release 1.6.1
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 1
Releases(1.1.4)
  • 1.1.4(Nov 9, 2022)

    • Fixed a bug where the .platforms annotation was not always being respected. This would cause cross platform dependencies to show up in the testing container.
    • Fixed a bug with the command line parameter project-path not being applied to the output directories in the yaml file.
    Source code(tar.gz)
    Source code(zip)
  • 1.1.3(Sep 22, 2022)

    This fixes a few issues:

    • added a new configuration property product_name.
    • two (or more) dependencies that rely on the same concrete class that fulfills multiple abstractions.
    • a compile issue where dependency containers for a framework marked @objc would collide in the Xcode autogenerated bridging header.
    • fixed the ignored_paths configuration property.
    Source code(tar.gz)
    Source code(zip)
  • 1.1.2(Jun 22, 2022)

  • 1.1.0(Jun 8, 2022)

    • Weaver 1.1.0 adopts a new memory pattern in the dependency container from the original 1.0.0 design. It now relies on a private copied class object instead of weak referencing up the tree.

    Source code(tar.gz)
    Source code(zip)
  • 1.0.8(Apr 25, 2022)

    • Fixed transient dependencies. All inherited transient depenencies by child nodes will now always generate a unique instance of that object. Additionally, this fixes an over-retain issue inside of the dependency containers that was caused by transient dependencies. (4389561196f7246757315017b11bd5a943f9d186)
    Source code(tar.gz)
    Source code(zip)
  • 1.0.7(Jun 19, 2020)

  • 1.0.6(Jun 11, 2020)

    New features

    • Possibility to associate dependencies to one or more platforms in order to support multi platform compilation (#148).
    • Possibility to exclude or include modules to import in generated files (#148).

    Bug fixes

    • Parameter --input_paths was wrongly requiring whitespaces and slashes to be escaped (#148).
    • Cache was unable to save if the containing directory wouldn't exist (#148).
    • Cache was not invalidated when removing paths from the input paths list (#148).
    Source code(tar.gz)
    Source code(zip)
    weaver-1.0.6.zip(1.62 MB)
  • 1.0.5(May 18, 2020)

  • 1.0.4(May 11, 2020)

  • 1.0.3(Feb 24, 2020)

  • 1.0.2(Jan 27, 2020)

  • 1.0.1(Dec 20, 2019)

    New Features

    • Parameters can use weak or container scopes [#90]
    • Closure configuration attribute in order to handle dependency with a closure type [#108]

    Bug Fixes

    • Fixed input file listing which was blocking Weaver when trying to use (unsupported) wildcards.
    • Fixed type parser edge cases.
    Source code(tar.gz)
    Source code(zip)
    weaver-1.0.1.zip(1.60 MB)
  • 1.0.0(Dec 15, 2019)

    First stable version of Weaver 🎉

    Foundations rework

    • Dependency Graph: The dependency graph representation has been entirely reworked in order to allow for more flexibility at use. Basically, it is now linked using hash keys rather than direct object references.
    • Linker/Inspector: Since the dependency graph changed, the linker & Inspector naturally changed as well. Accessing to data through the graph can now throw, giving a more precise error handling. The visitor algorithm for resolving and building remains fairly the same, but now supports new features, which I will describe a bit below.
    • Generator: The generator has been entirely rewritten using Meta. It also supports new features which I will describe below.

    Optimizations

    • Lexer: A cache (LexerCache) has been added in order to avoid SourceKitten to parse the source files every time (~1s for ~30 files). This cache stores one token list per file. A token list is invalidated once its file has changed after it was stored. The format for storing is an optimized JSON where every key is only one or two characters.
    • Generator: The generated Swift code is now relying a lot more on runtime, which brings more flexibility for supporting new features, but also allows Weaver to generate one single dependency container per project instead of one per injectable type
    • Misc optimizations as a result of profiling the binary (~0.5s instead of ~2s for ~30 files when cache is complete).

    New Features

    • Property wrapper support. With Swift 5.1, Weaver is now able to detect property wrappers named @Weaver(...) as annotations.
    • Dependencies can now be resolved by name and/or by type.
    • Abstract types can be composite (eg. A & B) and still be resolved correctly as soon as a registration is declared up the tree with a super set abstract type (eg. A & B & C).
    • Some new (more specific) errors are now thrown. Eg. type mismatch, ambiguous type, ambiguous dependency name, etc...
    • Added generation of a stub implementation of the main dependency resolver to facilitate testing. The code is generated in a separated file WeaverTests.swift.
    • Added scope lazy which activates a lazy loading mechanism for a given dependency.
    • Added configuration attribute setter which makes Weaver generate a setter for a given dependency.
    • An injectable type can now reference itself. The stored reference is weak, avoiding retain cycles. The optionality of that reference is abstracted away by Weaver though.

    Breaking changes

    • Only one unique file per target (app/tests) can be generated while Weaver used to offer an option to generate multiple files.
    • Naturally, the xcfilelist command has been removed since its necessity was very limited by the fact that only one file is generated now.
    • Detailed resolvers are always on, which means the option doesn't exist anymore.
    • Custom stencil templates aren't supported anymore, since Stencil has been replaced by Meta.
    • The argument --output-path has been renamed to --main-output-path in order to go along with the --test-output-path.
    Source code(tar.gz)
    Source code(zip)
    weaver-1.0.0.zip(1.59 MB)
  • 0.12.3(Apr 12, 2019)

  • 0.12.2(Feb 21, 2019)

  • 0.12.1(Feb 21, 2019)

  • 0.12.0(Feb 16, 2019)

    • [x] No more duplicate module imports when using the flag --single-output (#80/#81).
    • [x] open types support (#83/#85).
    • [x] Renamed command generate to swift and new parameters (#86).
    • [x] YAML or JSON configuration file support (#86).
    • [x] New xcfilelist command to automatically generate input/output xcfilelist files (#84/#86).
    • [x] Fixed installation from archive (#87/#88, #92).
    • [x] CocoaPods support (#93/#95).

    This version breaks few elements of the command line tool API. Please refer to the migration guide for details.

    Source code(tar.gz)
    Source code(zip)
    weaver-0.12.0.zip(4.28 MB)
  • 0.11.1(Dec 14, 2018)

  • 0.11.0(Nov 14, 2018)

    • [x] Xcodeproj is no longer versioned. Use swift package generate-xcodeproj instead (#66).
    • [x] Better support of generic types (#47, #67).
    • [x] Added JSON export command (#68, #70).
    • [x] Renamed annotation customRef to builder (#72, #76)
    • [x] Bug fixes (#71, #74)

    This version breaks few elements of the API. Please refer to the migration guide for details.

    Source code(tar.gz)
    Source code(zip)
    weaver-0.11.0.zip(1.37 MB)
  • 0.10.2(Sep 25, 2018)

  • 0.10.1(Sep 24, 2018)

  • 0.10.0(Jul 26, 2018)

  • 0.9.12(Jul 17, 2018)

  • 0.9.10(Jun 26, 2018)

  • 0.9.9(May 31, 2018)

  • 0.9.5(May 26, 2018)

  • 0.9.4(May 23, 2018)

  • 0.9.3(May 21, 2018)

Owner
Scribd
Changing the way the world reads.
Scribd
Injection - Dependency injection using property wrappers

Dependency injection using property wrappers. Registering types: // injecting a

Alejandro Ramirez 3 Mar 14, 2022
CarbonGraph - A Swift dependency injection / lookup framework for iOS

CarbonGraph is a Swift dependency injection / lookup framework for iOS. You can

Baidu 244 Jan 4, 2023
Cleanse is a dependency injection framework for Swift.

Cleanse - Swift Dependency Injection Cleanse is a dependency injection framework for Swift. It is designed from the ground-up with developer experienc

Square 1.7k Dec 16, 2022
DIKit Dependency Injection Framework for Swift, inspired by KOIN.

DIKit Dependency Injection Framework for Swift, inspired by KOIN. Basically an implementation of service-locator pattern, living within the applicatio

null 95 Dec 22, 2022
Swinject is a lightweight dependency injection framework for Swift.

Swinject Swinject is a lightweight dependency injection framework for Swift. Dependency injection (DI) is a software design pattern that implements In

null 5.6k Dec 31, 2022
Swift Ultralight Dependency Injection / Service Locator framework

Swift Ultralight Dependency Injection / Service Locator framework

Michael Long 1.9k Jan 6, 2023
Needle - Compile-time safe Swift dependency injection framework

Needle is a dependency injection (DI) system for Swift. Unlike other DI frameworks, such as Cleanse, Swinject, Needle encourages hierarchical DI struc

Uber Open Source 1.4k Jan 3, 2023
Container is a lightweight dependency injection framework for Swift.

Container Container is a lightweight dependency injection framework for Swift. Installation is available in the Swift Package Manager. Swift Package M

Aleksei Artemev 17 Oct 13, 2022
ViperServices - Simple dependency injection container for services written for iOS in swift supporting boot order

ViperServices Introduction ViperServices is dependency injection container for iOS applications written in Swift. It is more lightweight and simple in

Siarhei Ladzeika 5 Dec 8, 2022
DIContainer Swift is an ultra-light dependency injection container made to help developers to handle dependencies easily. It works with Swift 5.1 or above.

?? DIContainer Swift It is an ultra-light dependency injection container made to help developers to handle dependencies easily. We know that handle wi

Victor Carvalho Tavernari 10 Nov 23, 2022
Injector - A Swift package for simple dependency injection that also supports Swift UI previews

A Swift package for simple dependency injection that also supports Swift UI prev

null 6 Aug 9, 2022
Tranquillity is a lightweight but powerful dependency injection library for swift.

DITranquillity Tranquillity is a lightweight but powerful dependency injection library for swift. The name "Tranquillity" laid the foundation in the b

Ivlev Alexander 393 Dec 24, 2022
Kraken - Simple Dependency Injection container for Swift. Use protocols to resolve dependencies with easy-to-use syntax!

Kraken Photo courtesy of www.krakenstudios.blogspot.com Introduction Kraken is a simple Dependency Injection Container. It's aimed to be as simple as

Syed Sabir Salman-Al-Musawi 1 Oct 9, 2020
Toledo - a dependency injection library for Swift that statically generates resolvers at compile-time.

Toledo Toledo is a dependency injection library for Swift that statically generates resolvers at compile-time. Index Features Installation Usage Licen

Valentin Radu 18 Nov 25, 2022
A new approach to Container-Based Dependency Injection for Swift and SwiftUI.

A new approach to Container-Based Dependency Injection for Swift and SwiftUI. Why do something new? Resolver was my first Dependency Injection system.

Michael Long 573 Jan 2, 2023
Effortless modular dependency injection for Swift.

Inject Effortless modular dependency injection for Swift. Sometimes during the app development process we need to replace instances of classes or acto

Maxim Bazarov 40 Dec 6, 2022
Corridor A Coreader-like Dependency Injection μFramework

Corridor A Coreader-like Dependency Injection μFramework Table of Contents Why | Examples | Usage | Installation | Credits & License | Why In order to

symentis GmbH 60 Nov 1, 2022
Deli is an easy-to-use Dependency Injection Container that creates DI containers

Deli is an easy-to-use Dependency Injection Container that creates DI containers with all required registrations and corresponding factories.

Jungwon An 134 Aug 10, 2022
Dip is a simple Dependency Injection Container.

Dip is a simple Dependency Injection Container. It's aimed to be as simple as possible yet p

Olivier Halligon 949 Jan 3, 2023