Skip to content

Commit

Permalink
Merge pull request #149 from peopledoc/modernise-service-embedded
Browse files Browse the repository at this point in the history
Modernise Service `embedded` + accept a generic type parameter
  • Loading branch information
MrChocolatine authored Oct 19, 2021
2 parents d415f4c + ab20708 commit 331e543
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 16 deletions.
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,54 @@ if (environment === 'test') {
```


### TypeScript support

If your consuming application relies TypeScript, you can make you life a bit easier by using the
included types:

**File `/types/my-project/index.d.ts`**

```ts
import type BaseEmbeddedService from 'ember-cli-embedded/services/embedded';

declare global {

type EmbeddedService = BaseEmbeddedService<{
one: string;
two?: string;
}>;

}

export {};
```

**File `/app/components/my-component.ts`**

```ts
import Component from '@glimmer/component';
import { inject as service } from '@ember/service';

export default class MyComponent extends Component {
/**
* To know why the modifier `declare` should be used when injecting a Service:
* https://github.com/typed-ember/ember-cli-typescript/issues/1406#issuecomment-778660505
*/
@service
declare embedded: EmbeddedService;

get one() { // Return type inferred: `string | undefined`
return this.embedded.get('one');
}

get two() {
// TypeScript returns an error as `twoo` is not a recognised key
return this.embedded.get('twoo');
}
}
```


## Contributing

See the [Contributing](./CONTRIBUTING.md) guide for details.
Expand Down
38 changes: 27 additions & 11 deletions addon/services/embedded.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,32 @@
import ObjectProxy from '@ember/object/proxy'
import { getOwner } from '@ember/application'
import { assert } from '@ember/debug'

// eslint-disable-next-line ember/no-classic-classes
const configService = ObjectProxy.extend({
init(...args: Array<Record<string, unknown>>): void {
this.content = getOwner(this).factoryFor('config:embedded').class
this._super(...args)
},
})
type AnyObject = Record<string, unknown>

configService.reopenClass({
isServiceFactory: true,
})
export default class EmbeddedService<
EmbeddedOptions extends AnyObject = AnyObject
> extends ObjectProxy<EmbeddedOptions> {

export default configService
constructor() {
super(...arguments) // eslint-disable-line prefer-rest-params

const factoryName = 'config:embedded'
const factory: { class: EmbeddedOptions } | undefined = getOwner(this).factoryFor(factoryName)

assert(
`The factory "${factoryName}" could not be found.`,
typeof factory === 'object'
)

this.content = factory.class
}

}

// DO NOT DELETE: this is how TypeScript knows how to look up your services.
declare module '@ember/service' {
interface Registry {
embedded: EmbeddedService;
}
}
18 changes: 13 additions & 5 deletions tests/unit/services/embedded-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,20 @@ module('Unit | Service | embedded', function (hooks) {
setupTest(hooks)

test('it fetches data from the config as a proxy', function (assert) {
// We can access the raw config with `config:embedded`
const config = this.owner.resolveRegistration('config:embedded')
config.myKey = 'myValue'
this.owner.register('config:embedded', {
myKey: 'myValue',
})

const service = this.owner.lookup('service:embedded')
assert.equal(service.get('myKey'), 'myValue')
assert.equal(service.get('doesNotExist'), undefined)

assert.strictEqual(
service.get('myKey'),
'myValue'
)

assert.strictEqual(
service.get('doesNotExist'),
undefined
)
})
})

0 comments on commit 331e543

Please sign in to comment.