Skip to content

Commit

Permalink
feat(cordis): support @Inject decorator
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Aug 25, 2024
1 parent ead7215 commit 1f9da98
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 1 deletion.
20 changes: 19 additions & 1 deletion packages/core/src/registry.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,32 @@
import { defineProperty, Dict } from 'cosmokit'
import { Context } from './context.ts'
import { ForkScope, MainScope } from './scope.ts'
import { resolveConfig, symbols } from './utils.ts'
import { resolveConfig, symbols, withProps } from './utils.ts'

function isApplicable(object: Plugin) {
return object && typeof object === 'object' && typeof object.apply === 'function'
}

export type Inject = string[] | Dict<Inject.Meta>

export function Inject(inject: Inject) {
return function (value: any, ctx: ClassDecoratorContext<any> | ClassMethodDecoratorContext<any>) {
if (ctx.kind === 'class') {
value.inject = inject
} else if (ctx.kind === 'method') {
ctx.addInitializer(function () {
const property = this[symbols.tracker]?.property
if (!property) throw new Error('missing context tracker')
;(this[property] as Context).inject(inject, (ctx) => {
value.call(withProps(this, { [property]: ctx }))
})
})
} else {
throw new Error('@Inject can only be used on class or class methods')
}
}
}

export namespace Inject {
export interface Meta {
required: boolean
Expand Down
39 changes: 39 additions & 0 deletions packages/core/tests/decorator.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Context, Inject, Service } from '../src'
import { expect } from 'chai'
import { mock } from 'node:test'

describe('Decorator', () => {
it('@Inject on class method', () => {
const callback = mock.fn()
const dispose = mock.fn()

class Foo extends Service {
constructor(ctx: Context) {
super(ctx, 'foo', true)
}
}

class Bar extends Service {
constructor(ctx: Context) {
super(ctx, 'bar', true)
}

@Inject(['foo'])
method() {
callback()
this.ctx.on('dispose', dispose)
}
}

const root = new Context()
root.plugin(Bar)
expect(callback.mock.calls).to.have.length(0)
expect(dispose.mock.calls).to.have.length(0)
const fork = root.plugin(Foo)
expect(callback.mock.calls).to.have.length(1)
expect(dispose.mock.calls).to.have.length(0)
fork.dispose()
expect(callback.mock.calls).to.have.length(1)
expect(dispose.mock.calls).to.have.length(1)
})
})

0 comments on commit 1f9da98

Please sign in to comment.