-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Introduce strongly-typed metadata key #1240
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
shimks
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Had a quick overview, and most of it looked good. A couple of points though:
MetadataAccessorneeds it own test, similar to howBindingKeyhad its own test in that other PR- Couple packages had been missed out when the others' keys were converted to use
MetadataAccessor- authentication
- repository-json-schema (feel free to separate out the key to its own file for this one (didn't do this when I created the package :p))
- there might be others, so I'd check other packages just to be sure
- did you check for potential changes in the docs that would use this feature?
| const TEST_META = MetadataAccessor.create<object, ClassDecorator>('test'); | ||
|
|
||
| it('inspects metadata of a base class', () => { | ||
| const meta = MetadataInspector.getClassMetadata('test', BaseController); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why isn't test being replaced with TEST_META here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to test string keys too.
| const myClassDecorator = ClassDecoratorFactory.createDecorator(CLASS_KEY); | ||
|
|
||
| // Inspect a class with the key | ||
| const myClassMeta = MetadataInspector.getClassMetaData(CLASS_KEY, MyController); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we include a comment here insinuating that myClassMeta will have its type set to MyClassMetadata?
shimks
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, make sure that the new file is mentioned in docs.json
4549518 to
8433547
Compare
|
@shimks PTAL |
8433547 to
2dd8b81
Compare
| import {MetadataInspector, MetadataAccessor} from '@loopback/context'; | ||
|
|
||
| export const JSON_SCHEMA_KEY = 'loopback:json-schema'; | ||
| export const JSON_SCHEMA_KEY = MetadataAccessor.create<JsonDefinition>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is there no decorator type passed here in the <>?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If missing, any decorator type is fine. There are valid cases that the same string is used for both class and member decorators.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't realize it still works with just key strings. :)
| export class MetadataAccessor<T, D extends DecoratorType = DecoratorType> { | ||
| private constructor(public readonly key: string) {} | ||
|
|
||
| toString() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't it cleaner and easier to access the .key property directly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please note toString() works for both MetadataAccessor and string so that we don't to test if the key is a string or not.
| options && options.ownMetadataOnly | ||
| ? Reflector.getOwnMetadata(key, target) | ||
| : Reflector.getMetadata(key, target); | ||
| ? Reflector.getOwnMetadata(key.toString(), target) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a blocker but using .toString() is messy imo. Wouldn't it be better to do key.key or key.name with us storing the key as the name property?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See my explanation above.
shimks
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but please wait on merging this until @bajtos's review since the PR itself had been inspired by the PR he authored.
| ).to.equal('bar'); | ||
| }); | ||
|
|
||
| it('can be used to create decorator', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be nitpicky, but I think this test should live in a separate integration folder
2dd8b81 to
1bcb9b4
Compare
| import {BindingKey} from '@loopback/context'; | ||
| import {AuthenticateFn, UserProfile} from './providers/authentication.provider'; | ||
| import {AuthenticationMetadata} from './decorators/authenticate.decorator'; | ||
| import {BindingKey, MetadataAccessor} from '@loopback/context'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't MetadataAccessor be imported from @loopback/metadata? Actually I'm not even sure how this is working since I didn't see a re-export of MetadataAccessor from @loopback/context and this class is defined in @loopback/metadata.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| * @typeparam T Type of the metadata value | ||
| * @typeparam D Type of the decorator | ||
| */ | ||
| export class MetadataAccessor<T, D extends DecoratorType = DecoratorType> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The class shouldn't be in a types.ts file. Should have it's own file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we move MetadataAccessor to its own file, it will create a circular deps:
- MetadataAccessor --> DecoratorType (metadata-accessor.ts)
- MetadataKey --> MetadataAccessor (types.ts)
BTW, a class plays dual roles of typing and implementing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know a class serves as a type but just thought types.ts for was types / interfaces not classes.
Didn't see the circular dependency. Good enough reason to keep it here.
bajtos
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I quickly skimmed through the patch and don't see any major issues.
Is there any additional documentation (either as API docs or in /docs/site) that should be updated to reflect these changes?
I have updated the README, which is the docs we pull into loopback.io for metadata. |
This PR introduces a strong-typed MetadataKey for metadata access via reflection. It's inspired by #1169.
Checklist
npm testpasses on your machinepackages/cliwere updatedexamples/*were updated