Giter Club home page Giter Club logo

di-compiler's Introduction

Logo

A Custom Transformer for Typescript that enables compile-time Dependency Injection

Downloads per month NPM version Dependencies Contributors code style: prettier License: MIT Support on Patreon

Description

This library enables you to use the DI library by providing several ways to transform your source code into a representation that it expects. You can use it as a Node.js loader, as an API, and even as a Custom Transformer for Typescript.

Integration with popular tools such as Webpack, esbuild, Rollup, or something else is easy, and this README provides several examples of ways it can be achieved.

It is optimized for performance, but how fast it can go depends on your setup. Please see the Optimization section for details on how to tweak DI-Compiler so that it works most efficiently.

Features

  • Really lightweight
  • Really fast
  • Low-level implementation that can be used as the foundation for other tools such as Loaders, Plugins, and others.
  • It doesn't ask you to reflect metadata or to annotate your classes with decorators. "It just works".
  • Works without a TypeScript program, so you can use it with tools like babel, esbuild, and SWC for the best possible performance.

Backers

Trent Raymond scrubtheweb
Trent Raymond scrubtheweb

Patreon

Patrons on Patreon

Table of Contents

Install

npm

$ npm install @wessberg/di-compiler

Yarn

$ yarn add @wessberg/di-compiler

pnpm

$ pnpm add @wessberg/di-compiler

Peer Dependencies

@wessberg/di-compiler depends on typescript, so you need to manually install this as well.

Usage

There are multiple ways you can use DI-compiler, depending on your setup:

Usage as an API

The simplest possible way to use DI-Compiler is with its transform function:

import {transform} from "@wessberg/di-compiler";
const {code} = transform(`\
	import {DIContainer} from "@wessberg/di";
	const container = new DIContainer();
	class Foo {}
	container.registerSingleton<Foo>();
`);

In this example, the compiler knows that container is an instance of DIContainer based on the source text. However, you may be importing an instance of DIContainer from another file, in which case the compiler may not be able to statically infer that an identifier is an instance of DIContainer. For example:

transform(`\
	import {container} from "./services";
	// There may not be a way to statically determine whether or
	// not \`container\` is an instance of DIContainer at this point
	container.get<Foo>();
`);

To help the compiler out, and to improve performance, you can pass in one or more identifiers in the source text that should be considered instances of DIContainer:

transform(
	`\
	import {container} from "./services";
	container.get<Foo>();
`,
	{
		// Treat identifiers named `container` as instances of DIContainer
		identifier: "container"
	}
);

If you want a source map to be generated, make sure to pass that option in as a TypeScript CompilerOption:

const {code, map} = transform(`...`, {
	compilerOptions: {
		sourceMap: true
	}
});

You can pass in a cache to use as an option. This must be a data structure that conforms to that of a standard JavaScript Map data structure:

import {transform, type TransformResult} from "@wessberg/di-compiler";
const cache = new Map<string, TransformResult>();

transform(`...`, {
	cache
});

Usage as a Node.js loader

A very convenient way to use DI-Compiler is as a loader directly with Node.js.

If your codebase is based on native ESM, and if you use Node.js v.18.6.0 or newer, pass it as a loader via the command line

node --loader @wessberg/di-compiler/loader

This is not enough on its own to teach Node.js to understand TypeScript syntax, so you'll still need to couple it with a loader like ts-node, tsx or esm-loader.

For example, here's how to use it with the native ESM loader for ts-node:

node --loader @wessberg/di-compiler/loader --loader ts-node/esm

And, here's how to use it with tsx:

node --loader @wessberg/di-compiler/loader --loader tsx

Finally, here's how you can use it with esm-loader:

node --loader @wessberg/di-compiler/loader --loader @esbuild-kit/esm-loader

Alternatively, if you don't use ESM in your project, or if you're running an older version of Node.js, DI-Compiler can be used as a loader too. For example, here's how to use it in combination with ts-node in a CommonJS project:

node -r @wessberg/di-compiler/loader -r ts-node

In all of the above configurations, for both ESM and CommonJS loaders, there is no TypeScript Program context, nor is there a Type checker, so DI-Compiler will attempt to determinate programmatically whether or not the identifiers across your files reference instances of DIContainer or not, by performing partial evaluation on compile time. Please see the Optimization section for details on how this process can be optimized.

A convenience loader is exposed that combines ts-node and DI-Compiler in a single loader for CommonJS projects, which also exposes a TypeScript Program to DI-Compiler, which is the most robust way to use it as a loader, at the expense of slower performance:

node -r @wessberg/di-compiler/ts-node-loader

Note: You must install ts-node yourself for this configuration to work, as it is not listed as a dependency of DI-Compiler.

Loader SourceMaps

By default, SourceMaps will be generated and inlined inside the loaded modules if the sourceMap option is true inside the resolved tsconfig.

Loader caching

By default, DI-Compiler maintains a disk cache of transformation results from previously evaluated files. That means that successive loads of the same files will be extremely fast.

Customizing DI-Compiler when used as a loader

You can pass in a few options to DI-Compiler via command line options:

Environment Variable Description
DI_COMPILER_TSCONFIG_PATH The path to the tsconfig.json file to use
DI_COMPILER_IDENTIFIER A comma-separated list of identifiers that should be considered instances of DIContainer when transforming the source files
DI_COMPILER_DISABLE_CACHE If set, no disk caching will be used.

Alternatively, you can add a di property to your tsconfig where you can customize its behavior without setting environment variables:

// Inside your tsconfig.json
{
	"di": {
		"identifier": "container",
		"disableCache": false
	},
	"compilerOptions": {
		// ...
	}
}

Usage as a TypeScript Custom Transformer

You can use the DI-Compiler anywhere TypeScript Custom Transformers can be used. One advantage of this approach is that you often have access to a TypeScript Program, which can be leveraged by the DI-Compiler to fully understand the structure of your program and specifically the type hierarchy and whether or not an identifier is an instance of DIContainer, for example.

A few examples of ways to use DI-Compiler as a Custom Transformer include:

Usage with TypeScript's Compiler APIs

There's several ways to do this, but here's a simple example:

import {createProgram, getDefaultCompilerOptions, createCompilerHost} from "typescript";
import {di} from "@wessberg/di-compiler";

const compilerOptions = getDefaultCompilerOptions();
const compilerHost = createCompilerHost(compilerOptions);

// Create a Typescript program
const program = createProgram(["my-file-1.ts", "my-file-2.ts"], compilerOptions, compilerHost);

// Transform the SourceFiles within the program, and pass them through the 'di' transformer
program.emit(undefined, undefined, undefined, undefined, di({program}));

Usage with ts-nodes programmatic API

ts-node can also be used programmatically. Here's an example of how you may combine it with DI-Compiler:

import {di} from "@wessberg/di-compiler";

require("ts-node").register({
	transformers: program => di({program})
});

Usage with ttypescript

To use DI-compiler with ttypescript, create a file that wraps the invocation of di:

import type { Program } from 'typescript'
import { di } from "@wessberg/di-compiler";

const transformer = (program: Program) => di({ program })

export default transformer

Then add a record to the plugins array of your tsconfig.json that maps a key named transform to the relative path to the file you just created:

{
	"compilerOptions": {
		"plugins": [{"transform": "path/to/transformer.ts"}]
	}
}

Usage with Rollup

There are a few TypeScript plugins for Rollup that support Custom Transformers, and DI-Compiler can be easily integrated with them:

Usage with rollup-plugin-ts

To use DI-Compiler with rollup-plugin-ts, all you have to do is pass it to the list of transformers given as a plugin option:

import ts from "rollup-plugin-ts";
import {di} from "@wessberg/di-compiler";

export default {
	input: "...",
	output: [
		/* ... */
	],
	plugins: [
		ts({
			transformers: [di]
		})
	]
};

Usage with rollup-plugin-typescript2

Here's how you may integrate DI-Compiler with rollup-plugin-typescript2:

import ts from "rollup-plugin-typescript2";
import {di} from "@wessberg/di-compiler";

export default {
	input: "...",
	output: [
		/* ... */
	],
	plugins: [
		ts({
			transformers: [service => di({program: service.getProgram()})]
		})
	]
};

Usage with Webpack

There are two popular TypeScript loaders for Webpack that support Custom Transformers, and you can use DI-Compiler with both of them:

Usage with awesome-typescript-loader

Here's how it can be used with awesome-typescript-loader:

import {di} from "@wessberg/di-compiler";
const config = {
	// ...
	module: {
		rules: [
			{
				// Match .mjs, .js, .jsx, and .tsx files
				test: /(\.mjs)|(\.[jt]sx?)$/,
				loader: "awesome-typescript-loader",
				options: {
					// ...
					getCustomTransformers: program => di({program})
				}
			}
		]
	}
	// ...
};

Usage with ts-loader

ts-loader can be used in exactly the same way as awesome-typescript-loader:

import {di} from "@wessberg/di";
const config = {
	// ...
	module: {
		rules: [
			{
				// Match .mjs, .js, .jsx, and .tsx files
				test: /(\.mjs)|(\.[jt]sx?)$/,
				loader: "ts-loader",
				options: {
					// ...
					getCustomTransformers: program => di({program})
				}
			}
		]
	}
	// ...
};

Usage with ava

You can also use DI-compiler with the ava test runner by using DI-Compiler as a loader. See this section for more details on how to configure it.

For a CommonJS project, you can use the require property in the ava configuration. For example:

{
	"ava": {
		// Other options...
		"extensions": ["ts"],
		"require": [
			"@wessberg/di-compiler/loader",
			// For teaching Node.js about TypeScript specific syntax and extensions
			"ts-node"
		]
	}
}

Whereas for an ESM project, the syntax is a little different:

{
	"ava": {
		// Other options...
		"extensions": {
			"ts": "module"
		},
		"nodeArguments": [
			"--loader=@wessberg/di-compiler/loader",
			// For teaching Node.js about TypeScript specific syntax and extensions.
			"--loader=ts-node/esm"
		]
	}
}

Note, we use ts-node in this example, but we could have used other tools like tsx or esm-loader just as well.

Options

The transform function, as well as the di Custom Transformer takes the same set of base options to configure tehir behavior. All of these options are optional:

Option Type Description
program TypeScript Program A full TypeScript program. When given, a Typechecker will be used to understand the type hierarchy of the application and to determine whether or not identifiers are instances of DIContainer.
typescript TypeScript module If given, the TypeScript version to use internally for all operations.
identifier string[] or string One or more identifiers in the source text that should be considered instances of DIContainer. Note: If a Program is passed, this option will be ignored.
compilerOptions TypeScript CompilerOptions A TypeScript Compiler Options record. Note: If a Program is passed, this option will be ignored.

Optimization

Even though DI-Compiler is built for speed, there are ways you can speed it up significantly.

Optimization 1: Activate preserveValueImports in your tsconfig CompilerOptions

By default, TypeScript will discard imported bindings of value types that are unused. This means that the following example:

import {Foo} from "./foo";
container.registerSingleton<Foo>();

Would actually compile into code that would crash on runtime:

// Error: Foo is not defined
container.registerSingleton(undefined, {identifier: "Foo", implementation: Foo});

To work around this, DI-Compiler has to track the imports of the files, and add them back in after transpilation, which comes at a cost.

You can optimize this by activating the preserveValueImports option in your tsconfig:

{
	"compilerOptions": {
		"preserveValueImports": true
	}
}

By doing that, you instruct TypeScript to leave unused value imports be. DI-Compiler will recognize this and opt out of all the internal logic for adding imported bindings back in.

Optimization 2: Pass in one or more identifiers to consider instances of DIContainer instead of relying on partial evaluation

Note: This optimization is irrelevant if a Typescript Program is passed to DI-Compiler.

As described here, it may not always be possible to statically infer whether or not an identifier is in fact an instance of DIContainer when DI-Compiler does not have access to a Typechecker. Or, it may simply be slow, in case a lot of Nodes have to be visited in order to determine it.

To make it more robust and much faster simultaneously, pass in one or more identifiers as the identifier option that should be considered instances of DIContainer:

import {di, transform} from "@wessberg/di-compiler";

// Example when using the transform function
transform(
	`\
	import {container} from "./services";
	container.get<Foo>();
`,
	{
		// Treat identifiers named `container` as instances of DIContainer
		identifier: "container"
	}
);

See this section for details on how to pass the option when DI-Compiler is used as a loader.

Contributing

Do you want to contribute? Awesome! Please follow these recommendations.

Maintainers

Frederik Wessberg
Frederik Wessberg
Twitter: @FredWessberg
Github: @wessberg
Lead Developer

FAQ

DI-Compiler doesn't correctly update all my calls to the DIContainer methods

If you pass a Program to DI-Compiler (such as you typically do when you use it as a Custom Transformer), this means that the Typechecker wasn't able to determine that one or more identifiers in your code was in fact instances of DIContainer. Please verify that TypeScript correctly tracks the type of the objects on which you invoke the relevant DIContainer methods.

If you don't pass a Program to DI-Compiler, then you're relying on DI-Compiler being able to statically infer whether or not identifiers are instances of DIContainer without having access to multiple files inside your application. This will very often lead to problems if you reference an instance of DIContainer from another file inside your application. To fix it, pass one or more identifiers that should be considered instances of DIContainer as an option. Please see this section for details on how you can do that.

How does it work, exactly?

First, classes that are discovered as part of your Typescript program/bundle will be parsed for their constructor argument types and positions. Then, instances of the DIContainer will be discovered and their expressions will be upgraded. For example, an expression such as:

import {DIContainer} from "@wessberg/di";
import {MyInterface} from "./my-interface.js";
import {MyImplementation} from "./my-implementation.js";

const container = new DIContainer();
container.registerSingleton<MyInterface, MyImplementation>();

Will be compiled into:

// ...
container.registerSingleton(undefined, {
	identifier: `MyInterface`,
	implementation: MyImplementation
});

License

MIT ยฉ Frederik Wessberg (@FredWessberg) (Website)

di-compiler's People

Contributors

cmidgley avatar m-shaka avatar wessberg 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  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

di-compiler's Issues

Is there any special compiler options required?

Hello @wessberg
Thanks for the awesome package ๐Ÿ™

I'm probably missing something trivial but I can't get it to work ๐Ÿ˜ž

sample ts file

import { DIContainer } from "@wessberg/di";
import { LoggerServiceContract } from "../domain/contracts/services/logger.service-contract";
import { LoggerService } from "../services/logger.service";

export function registerServices(injector: DIContainer): void {
    injector.registerSingleton<LoggerServiceContract, LoggerService>();
}

package usage

import { di } from "@wessberg/di-compiler";
import {
    createProgram,
    getDefaultCompilerOptions,
    createCompilerHost,
    ImportsNotUsedAsValues,
} from "typescript";

const compilerOptions = getDefaultCompilerOptions();
compilerOptions.outDir = 'lib';
compilerOptions.importsNotUsedAsValues = ImportsNotUsedAsValues.Preserve;
const compilerHost = createCompilerHost(compilerOptions);

const program = createProgram(
    ["./src/index.ts"],
    compilerOptions,
    compilerHost
);

program.emit(undefined, undefined, undefined, undefined, di({ program }));

result

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.registerServices = void 0;
require("@wessberg/di");
require("../domain/contracts/services/logger.service-contract");
require("../services/logger.service");
function registerServices(injector) {
/* HERE */    injector.registerSingleton(undefined, { identifier: "LoggerServiceContract", implementation: LoggerService });
}
exports.registerServices = registerServices;

when I run the app I get the following error during this call injector.registerSingleton

ReferenceError: LoggerService is not defined

Do you have any hints on what am I doing wrong?
Thanks

Esbuild plugin support

Hello, this project seems very interesting as the .NET reflection pattern is something I look for, tho it seems not easily doable to add this compiler as a build step process of an esbuild build process.

The readme says that it's possible, but I only see typescript programms solutions, I would gladly use this library and recommend it if you could give some examples on how to integrate it with esbuild

Support for async service factories

Hi, this library looks like a dream come true to me, I hate decorator-based DI libraries with a passion and I've wanted to get around to writing a compile-time DI implementation for literally years (in fact I tried, several times, but always fell short). So first of all, thank you from the bottom of my heart for writing and releasing this library!

I'm using MikroORM in most of my backend NodeJS apps. It's a pretty neat ORM library, I like it a lot. But its initialisation is asynchronous - and so if I want to register it as a service in a DIC, I need to either initialise it first and then register the resolved instance (which means the ORM is always initialised, even when it's not needed), or I have to type the service as a promise for the correct type. But then I want to inject this service into other services. Either I could inject the typed promise (which the dependent services cannot await in their constructor, so they would have to store a reference to the promise instead of the actual resolved service, and await that promise each time they want to access the dependency), or I have to wrap all the dependent services in a promise as well and write an async factory function for each of those services, which would do something like return new DependentService(await container.get('async-service')). This is, in fact, what I'm doing right now, because it feels like the "cleanest" solution in terms of separating the actual services from the DI implementation or the fact that some services are initialised asynchronously.

My current DI implementation is basically a lot of handwritten factories which mostly do exactly what your DI library does at runtime, except it allows for services to be async. I'm not sure how the support for generics currently works in this library - from the linked issue it seems I can use generics, but maybe the generic part of the registration is ignored..? (based on the last comment from @cmidgley, which seems to suggest that stripping the type parameter is the intended behaviour?). So if this library does support generic services, then that would probably also mean promises for services (since a promise is just a generic from this point of view). Is that a correct assumption?

And, well, further on the topic, I think that one amazing feature this library could include would be support for async services out of the box - that is, I'd like to do something like this:

container.registerSingleton<Promise<ServiceOne>>(async () => createServiceOneSomehow());
container.registerSingleton<Promise<ServiceTwo>>();

class ServiceTwo {
  constructor(private readonly one: ServiceOne) {}
}

// the transformer can now detect that "ServiceOne" is wrapped in a promise, so it should be possible to generate factory code for "ServiceTwo" which awaits the container.get() call in order to autowire the unwrapped ServiceOne instance instead of the promise

Maybe the container.register* methods might not even need the type parameter wrapped in a promise - the transformer should be able to detect that the service is async based on either the passed-in factory function, or on the fact that the service depends on other services which are async. When one wants to access such a service, the transformer could detect that container.get<ServiceTwo>() is attempting to access an async service without specifying the Promise wrapper and throw an error (since this would break at runtime)..

I'm not sure if all of this is perhaps already supported - I can't find it anywhere in the docs or issues. If it is, then that's amazing! And if it's not: is this something you'd consider adding to the library? I would very much like to offer my help in case you would.

Thanks in any case!

ReferenceError: 1 argument required, but only 0 present

Hi. I followed you docs, but anyway keep getting this exception: ReferenceError: 1 argument required, but only 0 present. Note: You must use DI-Compiler (https://github.com/wessberg/di-compiler) for this library to work correctly. Please consult the readme for instructions on how to install and configure it for your project.

Here is my little test project setup:
package.json

{
  "name": "di-test-ts",
  "version": "1.0.0",
  "description": "",
  "main": "index.ts",
  "type": "module",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@wessberg/di": "^2.1.0",
    "@wessberg/di-compiler": "^3.3.0",
    "tsx": "^3.12.10",
    "typescript": "^5.2.2"
  },
  "devDependencies": {
    "@types/node": "^20.6.0"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",

    "module": "esnext",

    "preserveValueImports": true,

    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,

    "strict": true,

    "skipLibCheck": true
  }
}

di.ts

import { DIContainer } from "@wessberg/di";

export interface IMyService {
  testMyService: (str: string) => void;
}
export class MyService implements IMyService {
  testMyService(str: string) {
    console.log("testMyService", str);
  }
}

export const container = new DIContainer();
container.registerSingleton<IMyService, MyService>();
container.get<IMyService>().testMyService("from di.ts");

index.ts

import { container, type IMyService } from "./di";

container.get<IMyService>().testMyService("from index.ts");

Note
If i run node --loader @wessberg/di-compiler/loader --loader tsx di.ts - everything works as expected
But, if i try to use container from another file, i get that exception:
node --loader @wessberg/di-compiler/loader --loader tsx index.ts
image

Is this issue on your side or something wrong with my configs? Ty for help!

p.s. I am sure this tool is absolutely underrated, and i think this is partly due to problems with setting it up to be working , to play with it and make some tests.
p.s.2. I hope it is still maintained)

DI-compiler fails to build due to change in TypeScript and @wessberg/ts-config

In a somewhat recent release of TypeScript (I believe in some version around 5.2 but not sure) the rules for module/moduleResolution were tightened up. This causes DI-compiler to fail a build (pnpm build) with an error that module must be nodenext when moduleResolution is nodenext when using a fresh install of DI-compiler (latest TypeScript). The root cause is in @wessberg/ts-config where the following is set:

"moduleResolution": "nodenext",
"module": "esnext",

A workaround that resolves this build issue for just DI-compiler (though perhaps this is best resolved with some change to @wessberg/di-config) is to edit tsconfig.build.json and add moduleResolution: "node" to the compilerOptions:

{
	"extends": "./tsconfig.json",
	"include": [
		"src/**/*.*"
	],
	"compilerOptions": {
		"declaration": true,
		"declarationMap": false,
		"moduleResolution": "node"
	}
}

Jest example

Thank you for library its awesome. But i ran into issue cant configure with jest. Can you please provide example how to setup with jest ts-jest

Issues with derived classes transpiled by Typescript

When typescript transpiles a constructor-less derived class, it compiles it into:

// super class
class A {
    constructor (fooService)
}

// derived class
class B {
     constructor () {
        super(...arguments);
     }
}

This breaks.

ttypescript deprecated and replaced with ts-patch

I have been trying to get the DI transformer working with ts-patch. Have raised an issue in that repository also
nonara/ts-patch#120

After quite a few hours trying to work out why its not working I am at a loss. I think I may have to create a new transformer from the examples in the ts-patch project. Thought I would check in there before I go down this path in case the solution is something that I am missing.

JSX support for transform() API method

I am trying to use the proposed approach from the docs with direct usage of transform(code, filename, options).

Unfortunately, this does not work when running TSX files as transform() is hardcoding the script type to ScriptKind.TS.

From a quick test it would be sufficient to simply remove this parameter, TS seems to figure it out implicitly. Alternatively, using a factory method like used in the tests would be possible as well I guess.

Is there any chance to get TSX for the transform() method? It would be super helpful as it's a tremendous performance improvement compared to using the rollup TS plugin.

Thanks for any response and the awesome work on this piece of code!

Does this work with @rollup/plugin-typescript ?

Asking this since the @rollup/plugin-typescript plugin supports transformers option for typescript.

I tried but getting this error:

TypeError: Cannot read property 'getTypeChecker' of undefined

Bindings not generated with Parcel

Hello,

First I want to say that I am very glad you made this compile time DI library for TS! It does not have many features, it just contains what is necessary, that is perfect :)

I am trying to make the di-compiler work with Parcel (I use Parcel to set up "easily" a React project with di-compiler after that). Almost everything is working (it correctly generates the constructors data), however for some reason the bindings are not generated.
Everything works fine if I write:

container.registerSingleton(undefined, {identifier:'ServiceA', implementation:ServiceA});
container.registerSingleton(undefined, {identifier:'ServiceB', implementation:ServiceB});
const serviceB = container.get<ServiceB>({identifier: 'ServiceB'});

However, if I try to use the standard syntax:

container.registerSingleton<ServiceA>();
container.registerSingleton<ServiceB>();
const serviceB = container.get<ServiceB>();

I get a Uncaught ReferenceError: DIContainer could not get service: No arguments were given! for the registerSingleton calls and a Uncaught ReferenceError: DIContainer could not get service: No options was given! for the get call.

Do you have any idea of what is wrong or what is missing?

To make the integration work, I use parcel-plugin-ttypescript that enables me to specify some TS transformers in the tsconfig.json file. After that, I needed to make a small adapter between this parcel plugin and di-compiler:

import { di } from "@wessberg/di-compiler";
import * as ts from 'typescript';

export default function(program: ts.Program) {
  return di({ program });
}

I created a repository with a minimal project to reproduce the issue: https://github.com/amanteaux/poc-parcel-di-compiler
The two ways of writing the bindings are in src/index.ts.

Thank you for any help/hints to make the integration works!
Cheers

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.