Skip to content

Commit 8463249

Browse files
authored
Merge pull request #100 from dolittle/module-loading-registration
Register all decorated types in the imported files automatically
2 parents f84c7f3 + d018d1c commit 8463249

32 files changed

Lines changed: 259 additions & 46 deletions

Samples/Tutorials/GettingStarted/index.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,11 @@
66
import { DolittleClient } from '@dolittle/sdk';
77
import { TenantId } from '@dolittle/sdk.execution';
88
import { DishPrepared } from './DishPrepared';
9-
import { DishHandler } from './DishHandler';
9+
import './DishHandler';
1010

1111
(async () => {
1212
const client = await DolittleClient
13-
.setup(builder => builder
14-
.withEventTypes(eventTypes =>
15-
eventTypes.register(DishPrepared))
16-
.withEventHandlers(builder =>
17-
builder.registerEventHandler(DishHandler)))
13+
.setup()
1814
.connect();
1915

2016
const preparedTaco = new DishPrepared('Bean Blaster Taco', 'Mr. Taco');

Source/aggregates/_exports.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,5 @@ export { IAggregateRootTypes } from './IAggregateRootTypes';
2121
export { MissingAggregateRootDecoratorFor } from './MissingAggregateRootDecoratorFor';
2222
export { OnDecoratedMethod } from './OnDecoratedMethod';
2323
export { OnMethodSignature } from './OnMethodSignature';
24-
export { aggregateRoot, getDecoratedAggregateRootType } from './aggregateRootDecorator';
24+
export { aggregateRoot, isDecoratedAggregateRootType, getDecoratedAggregateRootType } from './aggregateRootDecorator';
2525
export { on } from './onDecorator';

Source/aggregates/aggregateRootDecorator.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,15 @@ export function aggregateRoot(aggregateRootId: AggregateRootIdLike, options: Agg
2828
});
2929
}
3030

31+
/**
32+
* Checks whether the specified class is decorated with an aggregate root type.
33+
* @param {Constructor<any>} type - The class to check the decorated aggregate root type for.
34+
* @returns {boolean} True if the decorator is applied, false if not.
35+
*/
36+
export function isDecoratedAggregateRootType(type: Constructor<any>): boolean {
37+
return getMetadata(type, false, false) !== undefined;
38+
}
39+
3140
/**
3241
* Gets the decorated aggregate root type of the specified class.
3342
* @param {Constructor<any>} type - The class to get the decorated aggregate root type for.

Source/common/Decorators/_exports.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export { createMetadataDecorator } from './createMetadataDecorator';
66
export { Decorator } from './Decorator';
77
export { DecoratorAppliedMultipleTimes } from './DecoratorAppliedMultipleTimes';
88
export { DecoratorTarget } from './DecoratorTarget';
9-
export { ensureDecoratorMetadataMap } from './ensureDecoratorMetadataMap';
9+
export { hasDecoratorMetadataMap, ensureDecoratorMetadataMap } from './decoratorMetadataMap';
1010
export { getAppliedDecorators } from './getAppliedDecorators';
1111
export { getDecoratedTarget } from './getDecoratedTarget';
1212
export { getDecoratorMetadata } from './getDecoratorMetadata';

Source/common/Decorators/createMetadataDecorator.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ import { RequiredDecoratorNotApplied } from './RequiredDecoratorNotApplied';
1313
import { setDecoratorMetadata } from './setDecoratorMetadata';
1414

1515
type GetMetadataValue<TData> =
16-
((type: Constructor<any>, required?: false) => TData | undefined) &
17-
((type: Constructor<any>, required: true, reason: string) => TData);
16+
((type: Constructor<any>, required?: false, createMetadata?: boolean) => TData | undefined) &
17+
((type: Constructor<any>, required: true, reason: string, createMetadata?: boolean) => TData);
1818

1919
type Decorator<TCallback> = (callback: TCallback) => (target: Function | Object, propertyKey?: string | symbol, descriptorOrIndex?: PropertyDescriptor | number) => void;
2020

@@ -55,7 +55,7 @@ export function createMetadataDecorator<TData>(name: string, displayName: string
5555
throw new DecoratorAppliedMultipleTimes(displayName, decoratedTarget, constructor, target, propertyKey, descriptorOrIndex);
5656
}
5757

58-
const value = getDecoratorMetadata<TData>(name, constructor);
58+
const value = getDecoratorMetadata<TData>(name, constructor, true);
5959
const newValue = callback(decoratedTarget, constructor, propertyKey, descriptorOrIndex, value);
6060
setDecoratorMetadata<TData>(name, constructor, newValue);
6161

@@ -64,11 +64,16 @@ export function createMetadataDecorator<TData>(name: string, displayName: string
6464
}
6565
};
6666
},
67-
function (type: Constructor<any>, required?: boolean, reason?: string) {
68-
const value = getDecoratorMetadata<TData>(name, type);
67+
function (type: Constructor<any>, required?: boolean, maybeRasonOrCreateMetadata?: string | boolean, maybeCreateMetadata?: boolean) {
68+
const createMetadata =
69+
typeof maybeCreateMetadata === 'boolean' ? maybeCreateMetadata :
70+
typeof maybeRasonOrCreateMetadata === 'boolean' ? maybeRasonOrCreateMetadata :
71+
true;
6972

70-
if (value === undefined && required) {
71-
throw new RequiredDecoratorNotApplied(displayName, validTargets, type, reason!);
73+
const value = getDecoratorMetadata<TData>(name, type, createMetadata);
74+
75+
if (value === undefined && required === true) {
76+
throw new RequiredDecoratorNotApplied(displayName, validTargets, type, maybeRasonOrCreateMetadata as string);
7277
}
7378

7479
return value;

Source/common/Decorators/ensureDecoratorMetadataMap.ts renamed to Source/common/Decorators/decoratorMetadataMap.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@ import { Constructor } from '@dolittle/types';
55

66
const DECORATOR_METADATA_KEY = '@dolittle/sdk.common/Decorators';
77

8+
/**
9+
* Checks whether or not the decorator metadata map exists on the provided type.
10+
* @param {Constructor<any>} type - The type to check if the map exists on.
11+
* @returns {boolean} True if the type has the decorator metadata map, false if not.
12+
*/
13+
export function hasDecoratorMetadataMap(type: Constructor<any>): boolean {
14+
const descriptor = Object.getOwnPropertyDescriptor(type, DECORATOR_METADATA_KEY);
15+
return descriptor !== undefined && descriptor.value instanceof Map;
16+
}
17+
818
/**
919
* Ensures that the decorator metadata map exists on the provided type.
1020
* @param {Constructor<any>} type - The type to ensure the map exists on.

Source/common/Decorators/getAppliedDecorators.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export type AppliedDecorator = {
2525
* @returns {AppliedDecorator[]} The applied decorators.
2626
*/
2727
export function getAppliedDecorators(type: Constructor<any>): AppliedDecorator[] {
28-
let decorators = getDecoratorMetadata<AppliedDecorator[]>(APPLIED_DECORATORS_NAME, type);
28+
let decorators = getDecoratorMetadata<AppliedDecorator[]>(APPLIED_DECORATORS_NAME, type, true);
2929

3030
if (decorators === undefined) {
3131
decorators = [];

Source/common/Decorators/getDecoratorMetadata.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,22 @@
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

44
import { Constructor } from '@dolittle/types';
5-
import { ensureDecoratorMetadataMap } from './ensureDecoratorMetadataMap';
5+
6+
import { ensureDecoratorMetadataMap, hasDecoratorMetadataMap } from './decoratorMetadataMap';
67

78
/**
89
* Gets the named data in the metadata of the specified type.
910
* @param {string} name - The metadata name to get.
1011
* @param {Constructor<any>} type - The type to get metadata on.
12+
* @param {boolean} [createMetadata] - An optional boolean to specify whether or not to create the metadata map if it doesn't exist.
1113
* @returns {T | undefined} The value of the named data.
12-
* @template T The type of the metadata value.
14+
* @template T The Type of the metadata value.
1315
*/
14-
export function getDecoratorMetadata<T>(name: string, type: Constructor<any>): T | undefined {
16+
export function getDecoratorMetadata<T>(name: string, type: Constructor<any>, createMetadata?: boolean): T | undefined {
17+
if (createMetadata === false && !hasDecoratorMetadataMap(type)) {
18+
return undefined;
19+
}
20+
1521
const metadata = ensureDecoratorMetadataMap(type);
1622
return metadata.get(name);
1723
}

Source/common/Decorators/hasDecoratorMetadata.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,20 @@
33

44
import { Constructor } from '@dolittle/types';
55

6-
import { ensureDecoratorMetadataMap } from './ensureDecoratorMetadataMap';
6+
import { ensureDecoratorMetadataMap, hasDecoratorMetadataMap } from './decoratorMetadataMap';
77

88
/**
99
* Checks whether or not the metadata of the specified type has the named data.
1010
* @param {string} name - The metadata name to check for.
1111
* @param {Constructor<any>} type - The type to check metadata on.
12+
* @param {boolean} [createMetadata] - An optional boolean to specify whether or not to create the metadata map if it doesn't exist.
1213
* @returns {boolean} True if it is set, false if not.
1314
*/
14-
export function hasDecoratorMetadata(name: string, type: Constructor<any>): boolean {
15+
export function hasDecoratorMetadata(name: string, type: Constructor<any>, createMetadata?: boolean): boolean {
16+
if (createMetadata === false && !hasDecoratorMetadataMap(type)) {
17+
return false;
18+
}
19+
1520
const metadata = ensureDecoratorMetadataMap(type);
1621
return metadata.has(name);
1722
}

Source/common/Decorators/setDecoratorMetadata.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

44
import { Constructor } from '@dolittle/types';
5-
import { ensureDecoratorMetadataMap } from './ensureDecoratorMetadataMap';
5+
import { ensureDecoratorMetadataMap } from './decoratorMetadataMap';
66

77
/**
88
* Sets the named data in the metadata of the specified type.

0 commit comments

Comments
 (0)