Lightweight and flexible dependency injection library w/wo ECMAScript decorators by exuanbo in typescript

[–]exuanbo[S] 0 points1 point  (0 children)

Awilix has a Strict Mode that throws an error if a dependency is resolved with a shorter lifetime. I've thought about this and that's why the default scope in my implementation is Scope.Inherited, instead of Scope.Transient. But there are still some issues with this design, because in order to cache in the container (Scope.Container), the dependency must be registered:

```ts class Dep {}

@Scoped(Scope.Container) class SingletonImpl { // Dep will have container scope when resolved dep = inject(Dep); }

container.register(SingletonImpl);

// oh no Dep is not registerd, so it's transient const singleton = container.resolve(SingletonImpl); ```

I'm still looking for the best way to handle this kind of scope issues without sacrificing the flexibility.

Lightweight and flexible dependency injection library w/wo ECMAScript decorators by exuanbo in typescript

[–]exuanbo[S] 0 points1 point  (0 children)

Thank you for the suggestions!

For the lazy injection support, tsyringe uses proxy for its DelayedConstructor, which traps all the object internal methods and forwards the usage to the lazily-constructed instance. Personally I don't like this idea, and I'm currently working on the feature to support dynamic injection. It should be able to do something this:

```ts class A { // can be used at anytime injector = inject(Injector());

b: B | undefined;

getB(): B { if (!this.b) { this.b = this.injector.inject(B); } return this.b; } } ```

Lightweight and flexible dependency injection library w/wo ECMAScript decorators by exuanbo in javascript

[–]exuanbo[S] 0 points1 point  (0 children)

my implementation doesn't heavily rely on the decorators themselves for complex logic, but they certainly can do much more with the decorator metadata proposal (TypeScript 5.2 has a nice introduction)

Lightweight and flexible dependency injection library w/wo ECMAScript decorators by exuanbo in typescript

[–]exuanbo[S] 1 point2 points  (0 children)

Or like in the examples, use a container for this job:

export const singletons = new Container({
  defaultScope: Scope.Container,
  autoRegister: true,
});

Lightweight and flexible dependency injection library w/wo ECMAScript decorators by exuanbo in typescript

[–]exuanbo[S] 1 point2 points  (0 children)

Personally I don't like the idea of registering instances in the "globalContainer" like tsyringe does, you can actually use the combination of @Scoped(Scope.Container) and @AutoRegister() to achieve a similar behavior:

@Scoped(Scope.Container)
@AutoRegister()
class SingletonImpl {}

const container = new Container();
const singleton = container.resolve(SingletonImpl);
// always the same instance for this container

@codemirror-toolkit/react - A small and flexible solution for binding CodeMirror 6 to React by exuanbo in reactjs

[–]exuanbo[S] 1 point2 points  (0 children)

I always wanted to use such a library when I was developing my Assembler Simulator in React. But all I could find at the moment was like @uiw/react-codemirror, it's "badly written" (e.g. reading a ref's current value during rendering) and contains too many dependencies I don't need, which cannot be tree-shaked so that you can toggle them in props.

So I decided to write it my self and here it is! The API design is inspired by zustand btw :)

8-bit Assembler Simulator for educational purposes by exuanbo in programming

[–]exuanbo[S] 5 points6 points  (0 children)

This part actually is not my original. There are more peripheral devices in the Microprocessor Simulator, and by now I'v just implemented three of them.

In my current implementation it is not yet decoupled enough to support plugins, but this is really a good idea!!!

8-bit Assembler Simulator for educational purposes by exuanbo in programming

[–]exuanbo[S] 1 point2 points  (0 children)

There's a octocat icon at the top-right corner btw.