Code Monkey home page Code Monkey logo

auto_injector's Introduction

Auto Injector - Automatic Dependency injection system without build_runner.


Logo

A simple way to inject dependencies in your project.
Explore the docs »

Report Bug · Request Feature


Version Pub Points Flutterando Analysis

Pub Publisher



Table of Contents
  1. About The Project
  2. Sponsors
  3. Getting Started
  4. How to Use
    1. Dispose Singleton
    2. Modularization
    3. Param Transform
  5. Features
  6. Contributing
  7. Contact
  8. Acknowledgements


About The Project

Auto Injector is a Dart package that was created to make the developer's life easier, making the method of how to do dependency injection simpler and more practical. Just create the class that will be injected and declare it within some of the available "add" methods and that's it, you already have your dependency injection ready to use.

This project is distributed under the MIT License. See LICENSE.txt for more information.

(back to top)

Sponsors

Logo

(back to top)


Getting Started

To get Auto Injector in your project follow either of the instructions below:

a) Add your_package as a dependency in your Pubspec.yaml:

  dependencies:
    auto_injector: ^1.0.2

b) Use Dart Pub:

   dart pub add auto_injector

How to Use

Register instances:

final autoInjector = AutoInjector();

void main(){


    // factory
    autoInjector.add(Controller.new);
    // Singleton
    autoInjector.addSingleton(Datasource.new);
    // lazySingleton
    autoInjector.addLazySingleton(Repository.new);
    // instance
    autoInjector.instance('Instance');

    // Inform that you have finished adding instances
    autoInjector.commit();

}


class Controller {
    final Repository repository;

    Controller(this.repository);
}

class Repository {
    final Datasource datasource;

    Repository({required this.datasource});
}

class Datasource {}

Register instances with Key:

autoInjector.add(Controller.new, key: 'MyCustomName');

Get instance:

  // fetch
  final controller = autoInjector.get<Controller>();
  print(controller); // Instance of 'Controller'.

  // or use calleble function (withless .get())
  final datasource = autoInjector<Datasource>();
  print(datasource); // Instance of 'Datasource'.

Get instance by key

  // fetch
  final controller = autoInjector.get<Controller>(key: 'CustomController');
  print(controller); // Instance of 'Controller'.

Try get instance:

  // use tryGet that returns null if exception.
  final datasource = autoInjector.tryGet<Datasource>() ?? Datasource();
  print(datasource); // Instance of 'Datasource'.

Get instance and transform params. This can be used for example to replace an instance with a mock in tests.

  final datasource = autoInjector.get<Datasource>(transform: changeParam(DataSourceMock()));
  print(datasource); // Instance of 'Datasource'.

Dispose Singleton

Singletons can be terminated on request using the disposeSingleton method returning the instance for executing the dispose routine.

final deadInstance = autoInjector.disposeSingleton<MyController>();
deadInstance.close();

Modularization

For projects with multiple scopes, try uniting the instances by naming them Module or Container. With this, you can register specific instances for each module.

// app_module.dart
final appModule = AutoInjector(
  tag: 'AppModule',
  on: (i) {
    i.addInjector(productModule);
    i.addInjector(userModule);
    i.commit();
  },
);

...

// product_module.dart
final productModule = AutoInjector(
  tag: 'ProductModule',
  on: (i) {
    i.addInstance(1);
  },
);

...

// user_module.dart
final userModule = AutoInjector(
  tag: 'UserModule',
  on: (i) {
    i.addInstance(true);
  },
);

...

void main() {
  print(appModule.get<int>());
  print(appModule.get<bool>());
}

It is also possible to remove all singletons from a specific tag using the method disposeSingletonsByTag which reports each instance removed via an anonymous function:

autoInjector.disposeSingletonsByTag('ProductModule', (instance){
  // individual dispose routine
});

Param Transform

There is the possibility to listen and transform all the parameters that are being analyzed when there is an instance request (AutoInject.get()). Add transformers on the main instance:

final homeModule = AutoInjector(
  paramTransforms: [
    (param) {
    if(param is NamedParam){
        return param;
    } else if(param is PositionalParam) {
        return param;
    }
  ],
);

###
BindConfig

If there is a need to configure the dispose and notifier of the bind, use the BindConfig<T> property. This is very useful if you want to automate class disposes like BLoC or Triple Store:

final injector = AutoInjector();

final config = BindConfig<Bloc>(
  onDispose: (bloc) => bloc.close(),
  onNotifier: (bloc) => bloc.stream,
);

injector.addSingleton(ProductBloc.new, config: config);

For more examples, please refer to the Documentation

(back to top)

Features

  • ✅ Auto Dependency Injection
  • ✅ Factory Injection
  • ✅ Singleton Injection
  • ✅ Lazy Singleton Injection
  • ✅ Instance Injection

Right now this package has concluded all his intended features. If you have any suggestions or find something to report, see below how to contribute to it.

(back to top)

Contributing

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the appropriate tag. Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

Remember to include a tag, and to follow Conventional Commits and Semantic Versioning when uploading your commit and/or creating the issue.

(back to top)

Contact

Flutterando Community

(back to top)

Acknowledgements

Thank you to all the people who contributed to this project, whithout you this project would not be here today.


(back to top)

Maintaned by


Built and maintained by Flutterando.

auto_injector's People

Contributors

davidsdearaujo avatar jacobaraujo7 avatar joao-fialho avatar luanbatistadev avatar samuelgadiel avatar tauamendonca avatar thkali avatar ygcoutinho avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

auto_injector's Issues

Binds type factory are not disposed

In the example below, the ClassFactory is not disposed when the injector is disposed

import 'dart:async';
import 'package:auto_injector/auto_injector.dart';

class ClassFactory {
  late StreamSubscription<String> _subscription;
  final Stream<String> _controller = Stream.periodic(
    const Duration(seconds: 1),
    (i) => 'Stream: $i',
  );

  ClassFactory() {
    _subscription = _controller.listen(print);
  }

  void dispose() {
    _subscription.cancel();
  }
}

Future<void> main() async {
  final injector = AutoInjector(
    on: (i) {
      i.add<ClassFactory>(
        ClassFactory.new,
        config: BindConfig(
          onDispose: (obj) => obj.dispose(),
        ),
      );
      i.commit();
    },
  );
  injector<ClassFactory>();
  injector.dispose();

  await Future.delayed(const Duration(seconds: 20));
}

Can't run on web with --release or --profile

After runApp using ModularApp I got the error:
"Expected symbol ":" but found "AutoInjectorImpl_addInstance_closure" at line 1 column 46."

When run as debug all works fine.

Flutter version: 3.13.1

Dependency versions:
auto_injector: 2.0.0+2
flutter_modular: 6.0.1+1
modular_core: 3.1.0

*I was able to caught this error only using sentry, there is no log or exception.

Annotations please!

Greetings,

auto_injector is great. Do you have any plans to support annotations like injectable?

Can't find Dependencies when using named parameters in constructor

Describe the bug
When we use a constructor with the new modular injector, e.g
ProductsControllerBase({required ProductsRepository productsRepository}) : _productsRepository = productsRepository;
it can't find the required ProductsRepository dependency.
BUT if we use a non-named parameter, e.g ProductsControllerBase(this._productsRepository); it works.
Wasn't it supposed to work with both of the constructors?

Environment
Add your flutter doctor -v

[✓] Flutter (Channel stable, 3.10.6, on Microsoft Windows [Version 10.0.22621.2070], locale en-US)
    • Flutter version 3.10.6 on channel stable at C:\src\flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision f468f3366c (3 weeks ago), 2023-07-12 15:19:05 -0700
    • Engine revision cdbeda788a
    • Dart version 3.0.6
    • DevTools version 2.23.1

[✓] Windows Version (Installed version of Windows is version 10 or higher)

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
    • Android SDK at C:\Users\gabri\AppData\Local\Android\sdk
    • Platform android-33, build-tools 33.0.0
    • Java binary at:
      C:\Users\gabri\AppData\Local\JetBrains\Toolbox\apps\AndroidStudio\ch-0\223.8836.35.2231.10406996\jbr\bin\java
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-b2043.56-10027231)
    • All Android licenses accepted.

[✓] Chrome - develop for the web
    • Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe

[✓] Visual Studio - develop for Windows (Visual Studio Community 2022 17.6.5)
    • Visual Studio at C:\Program Files\Microsoft Visual Studio\2022\Community
    • Visual Studio Community 2022 version 17.6.33829.357
    • Windows 10 SDK version 10.0.22621.0

[✓] Android Studio (version 2022.2)
    • Android Studio at C:\Users\gabri\AppData\Local\JetBrains\Toolbox\apps\AndroidStudio\ch-0\222.4459.24.2221.10121639
    • Flutter plugin version 74.0.2
    • Dart plugin version 222.4582
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-b2043.56-9586694)

[✓] Android Studio (version 2022.3)
    • Android Studio at C:\Users\gabri\AppData\Local\JetBrains\Toolbox\apps\AndroidStudio\ch-0\223.8836.35.2231.10406996
    • Flutter plugin version 74.0.3
    • Dart plugin version 223.8950
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-b2043.56-10027231)

[✓] IntelliJ IDEA Ultimate Edition (version 2023.2)
    • IntelliJ at C:\Users\gabri\AppData\Local\JetBrains\Toolbox\apps\IDEA-U\ch-0\232.8660.185
    • Flutter plugin version 74.0.5
    • Dart plugin version 232.8660.129

[✓] VS Code (version 1.81.0)
    • VS Code at C:\Users\gabri\AppData\Local\Programs\Microsoft VS Code
    • Flutter extension version 3.70.0

[✓] Connected device (4 available)
    • sdk gphone64 x86 64 (mobile) • emulator-5554 • android-x64    • Android 13 (API 33) (emulator)
    • Windows (desktop)            • windows       • windows-x64    • Microsoft Windows [Version 10.0.22621.2070]
    • Chrome (web)                 • chrome        • web-javascript • Google Chrome 115.0.5790.111
    • Edge (web)                   • edge          • web-javascript • Microsoft Edge 115.0.1901.188

[✓] Network resources
    • All expected network resources are available.

• No issues found!

Add your pubspec.yaml

name: delivery_backoffice_dw10
description: A new Flutter project.

publish_to: "none"

version: 1.0.0+1

environment:
  sdk: ^3.0.6

dependencies:
  awesome_snackbar_content: ^0.1.3
  brasil_fields: ^1.13.1
  dio: ^5.3.1
  flutter:
    sdk: flutter
  flutter_dotenv: ^5.1.0
  flutter_mobx: ^2.0.6+5
  flutter_modular: ^6.0.1
  flutter_web_plugins:
    sdk: flutter
  loading_animation_widget: ^1.2.0+4
  mobx: ^2.2.0
  url_strategy: ^0.2.0
  validatorless: ^1.2.3

dev_dependencies:
  build_runner: ^2.4.6
  dart_code_metrics: ^5.7.6
  flutter_test:
    sdk: flutter
  mobx_codegen: ^2.3.0

flutter:
  uses-material-design: true

  assets:
    - .env
    - assets/images/
    - assets/images/icons/

  fonts:
    - family: mplus1
      fonts:
        - asset: assets/fonts/MPLUS1p-Light.ttf
          weight: 300
        - asset: assets/fonts/MPLUS1p-Regular.ttf
          style: normal
        - asset: assets/fonts/MPLUS1p-Medium.ttf
          weight: 500
        - asset: assets/fonts/MPLUS1p-Bold.ttf
          weight: 700
        - asset: assets/fonts/MPLUS1p-ExtraBold.ttf
          weight: 800

To Reproduce
ProductsControllerBase({required ProductsRepository productsRepository}) : _productsRepository = productsRepository; -> Doesn't work
ProductsControllerBase(this._productsRepository); -> Works

Expected behavior
Should work with both constructors

Screenshots
image
image

Package stuck in 1.2.0 because of Flutter pinned version

Flutter still does not use meta: 1.11.0, even on the latest version.

This forces us to either use version 1.2.0 or override the dependency.

Isn't it possible to widen the meta dependency so it will be compatible with most developers?
Example: change to meta: >=1.10.0 <= 1.11.0.

Resolving dependencies...
Note: meta is pinned to version 1.10.0 by flutter_test from the flutter SDK.
See https://dart.dev/go/sdk-version-pinning for details.


Because every version of flutter_test from sdk depends on meta 1.10.0 and auto_injector >=2.0.3 depends on meta ^1.11.0, flutter_test from sdk is incompatible with auto_injector >=2.0.3.

[Modularization] Shouldn't injector look for binds up the tree?

Greetings, I'm having a problem to find a bind that is declared into another module.

Deps

  • auto_injector: ^2.0.2
  • dart: 3.1.5
  • flutter: 3.13.9

Summary:

code_module.dart
...
/// Core dependency injection
final coreModule = AutoInjector(
  tag: 'CoreModule',
  on: (i) {
    i.addLazySingleton<IContentService>(HttpContentService.new);
  },
);
pokedex_module.dart
...
/// Pokedex dependency injection
final pokedexModule = AutoInjector(
  tag: 'PokedexModule',
  on: (i) {
    i.addLazySingleton<IPokemonRemoteDs>(GraphPokemonRemoteDs.new);
    i.addLazySingleton<IPokemonRepository>(PokemonRepository.new);
    i.addSingleton<PokemonReducer>(PokemonReducer.new);
  },
);
app_module.dart
...
final appModule = AutoInjector(
  tag: 'AppModule',
  on: (i) {
    i.addInjector(coreModule);
    i.addInjector(pokedexModule);
    i.commit();
  },
);

When I run the project with those modules, the pokedex module fails to look for core module binds.

Console error
Error: UnregisteredInstance: IContentService not registered.
GraphPokemonRemoteDs => IContentService
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 294:49      throw_
packages/auto_injector/src/auto_injector_base.dart 515:7                          [_resolveBind]
packages/auto_injector/src/auto_injector_base.dart 496:43                         [_resolveInstanceByKey]
dart-sdk/lib/core/iterable.dart 347:35                                            forEach
packages/auto_injector/src/auto_injector_base.dart 402:72                         startSingletons
packages/auto_injector/src/auto_injector_base.dart 394:5                          commit
packages/auto_injector/src/auto_injector_base.dart 391:17                         <fn>
packages/auto_injector/src/layers_graph.dart 102:15                               executeInAllInjectors
packages/auto_injector/src/auto_injector_base.dart 388:17                         commit
packages/pokedx/app/app_module.dart 10:6                                          <fn>
packages/auto_injector/src/auto_injector_base.dart 232:9                          new
packages/auto_injector/src/auto_injector_base.dart 135:12                         new
packages/pokedx/app/app_module.dart 5:19                                          get appModule
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 1220:8  get
packages/pokedx/main.dart 22:17                                                   main

Working solution

Declaring the content service along with the child module it works well.

working structure
// app_module.dart
final appModule = AutoInjector(
  tag: 'AppModule',
  on: (i) {
    i.addInjector(pokedexModule);
    i.commit();
  },
);

// pokedex_module.dart
final pokedexModule = AutoInjector(
  tag: 'PokedexModule',
  on: (i) {
    i.addLazySingleton<IContentService>(HttpContentService.new);
    i.addLazySingleton<IPokemonRemoteDs>(GraphPokemonRemoteDs.new);
    i.addLazySingleton<IPokemonRepository>(PokemonRepository.new);
    i.addSingleton<PokemonReducer>(PokemonReducer.new);
  },
);

Thanks.

Lazy Singleton + Inversion of Control

When we try to register a lazy singleton class with inversion of control, it doesn't works.
Look this example:

abstract class InversionOfControlInterface {}
class Implementation implements InversionOfControlInterface {} 

void main() {
  final injector = AutoInjector();
  injector.addLazySingleton<InversionOfControlInterface>(Implementation.new);
  injector.commit();

  final instance = injector.get<InversionOfControlInterface>();
}

It throws an error at the last line: InversionOfControlInterface unregistered.

AutoInjector breaks when calling .new and the parameters have generics

Describe the bug

When we use auto_injector .new it breaks in types that have generics, such as Map<String, dynamic>

Environment

Add your flutter doctor -v

[✓] Flutter (Channel stable, 3.13.0, on macOS 13.4.1 22F770820d darwin-arm64, locale en-BR)
• Flutter version 3.13.0 on channel stable at /Users/luanrafaelbatistaramos/development/flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision efbf63d9c6 (7 days ago), 2023-08-15 21:05:06 -0500
• Engine revision 1ac611c64e
• Dart version 3.1.0
• DevTools version 2.25.0

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.1)
• Android SDK at /Users/luanrafaelbatistaramos/Library/Android/sdk
• Platform android-33, build-tools 33.0.1
• Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b829.9-10027231)
• All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 14.3.1)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Build 14E300c
• CocoaPods version 1.12.1

[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2022.1)
• Android Studio at /Applications/Android Studio TIMWE.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 11.0.15+0-b2043.56-8887301)

[✓] Android Studio (version 2022.3)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b829.9-10027231)

[✓] VS Code (version 1.81.1)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.70.0

[✓] Connected device (3 available)
• sdk gphone64 arm64 (mobile) • emulator-5554 • android-arm64 • Android 13 (API 33) (emulator)
• macOS (desktop) • macos • darwin-arm64 • macOS 13.4.1 22F770820d darwin-arm64
• Chrome (web) • chrome • web-javascript • Google Chrome 116.0.5845.96
• No issues found!

Add your pubspec.yaml

name: cimed
description: Cimed - Portal dos Representantes
publish_to: "none"

version: 17.2.0+112
environment:
sdk: ">=3.0.0 <4.0.0"
flutter: ">=3.10.0"

flutter_icons:
image_path_android: "lib/assets/images/logo.png"
image_path_ios: "lib/assets/images/logo.png"
android: true
ios: true

dependencies:
animate_do: ^3.0.2
auto_injector:
bloc: ^8.1.2
brasil_fields: ^1.14.0
cached_network_image: ^3.2.3
cloud_firestore: ^4.8.5
collection: ^1.17.2
connectivity_plus: ^4.0.2
dartz: ^0.10.1
detectable_text_field: ^2.1.0
dio: ^5.3.2
document_file_save_plus: ^2.0.0
encrypt: ^5.0.1
equatable: ^2.0.5
expandable_page_view: ^1.0.17
extended_masked_text: ^2.3.1
file_picker: ^5.3.3
firebase_analytics: ^10.4.5
firebase_core: ^2.15.1
firebase_crashlytics: ^3.3.5
flutter:
sdk: flutter
flutter_archive: ^5.0.0
flutter_bloc: ^8.1.3
flutter_keyboard_visibility: ^5.4.1
flutter_localizations:
sdk: flutter
flutter_modular: ^6.0.4+1
flutter_svg: ^2.0.7
google_fonts: ^5.1.0
hexcolor: ^3.0.1
hive: ^2.2.3
horizontal_data_table: ^4.3.1
http: ^1.1.0
image_picker: ^1.0.2
in_app_update: ^4.1.4
intl: ^0.18.1
jiffy: ^6.2.1
jwt_decoder: ^2.0.1
line_icons: ^2.0.3
mask_text_input_formatter: ^2.5.0
new_version_plus: ^0.0.11
open_filex: ^4.3.2
package_info_plus: ^4.1.0
path: ^1.8.3
path_provider: ^2.1.0
percent_indicator: ^4.2.3
pinch_zoom_image_last: ^0.4.1 #Discontinuado
pretty_dio_logger: ^1.3.1
qr_code_scanner:
git:
url: https://github.com/xeinebiu/qr_code_scanner.git
ref: fix_break_changes_platform
rx_notifier: ^2.3.0
rxdart: ^0.27.7
share_plus: ^7.1.0
skeleton_animation: ^0.1.4
snack: ^2.0.0
sp_util: ^2.0.3
url_launcher: ^6.1.12
uuid: ^3.0.7
workmanager: ^0.5.1

dependency_overrides:
auto_injector:
path: ../flutterando/auto_injector

dev_dependencies:
flutter_driver:
sdk: flutter
flutter_lints: ^2.0.2
flutter_test:
sdk: flutter
integration_test:
sdk: flutter
test: any

flutter:
fonts:
- family: Roboto
fonts:
- asset: lib/assets/fonts/Roboto-Regular.ttf
uses-material-design: true
assets:
- lib/assets/images/
- lib/assets/fonts/
- lib/assets/json/
- assets/images/
- assets/version.txt

To Reproduce

class TestComplexNamed {
final Map<String, dynamic>? value;
final Map<String, List<Map<String, dynamic>>>? map;

TestComplexNamed({this.value, this.map});
}

TestComplexNamed.new

Expected behavior

Should find exactly bind

Screenshots

Screenshot 2023-08-22 at 13 31 07
Screenshot 2023-08-22 at 13 31 48
Screenshot 2023-08-22 at 13 32 32

Unregistered instance

Even after i'm using the commit method te package return this error

UnregisteredInstance (UnregisteredInstance: LocationStore unregistered.)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.