Skip to content

Commit debf726

Browse files
committed
Move LoaderFactory decorator to data-loader/ & use new metadata abstraction
1 parent dd5eb22 commit debf726

File tree

6 files changed

+62
-57
lines changed

6 files changed

+62
-57
lines changed

src/components/file/media/media-by-file-version.loader.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {
33
type DataLoaderStrategy,
44
} from '@seedcompany/data-loader';
55
import { type ID } from '~/common';
6-
import { LoaderFactory } from '~/core/resources';
6+
import { LoaderFactory } from '~/core/data-loader';
77
import { type AnyMedia } from './media.dto';
88
import { MediaRepository } from './media.repository';
99

src/components/file/media/media.loader.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { type DataLoaderStrategy } from '@seedcompany/data-loader';
22
import { type ID } from '~/common';
3-
import { LoaderFactory } from '~/core/resources';
3+
import { LoaderFactory } from '~/core/data-loader';
44
import { type AnyMedia, Media } from './media.dto';
55
import { MediaRepository } from './media.repository';
66

src/core/data-loader/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export {
66
} from '@seedcompany/data-loader';
77

88
export * from './options.type';
9+
export { LoaderFactory } from './loader-factory.decorator';
910
export * from './session-aware-loader.strategy';
1011
export * from './ordered-data-loader.strategy';
1112
export * from './single-item-loader.strategy';
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { Injectable, Scope, type Type } from '@nestjs/common';
2+
import type { DataLoaderStrategy } from '@seedcompany/data-loader';
3+
import { createMetadataDecorator } from '@seedcompany/nest';
4+
import type { ValueOf } from 'type-fest';
5+
import type { Many } from '~/common';
6+
import { type ResourceMap } from '~/core/resources';
7+
import { ObjectViewAwareLoader } from './object-view-aware-loader.strategy';
8+
9+
type SomeResource = ValueOf<ResourceMap>;
10+
11+
type DataLoaderCtor = Type<DataLoaderStrategy<any, any>>;
12+
13+
export interface LoaderOptions {
14+
/**
15+
* Whether the loader is aware of ObjectViews.
16+
*
17+
* This means the loader key needs to be in the shape of
18+
* {@link import('../data-loader/object-view-aware-loader.strategy').Key Key}
19+
*
20+
* This defaults to true if the class extends ObjectViewAwareLoader.
21+
*/
22+
objectViewAware?: boolean;
23+
}
24+
25+
export const LoaderFactoryMetadata = createMetadataDecorator({
26+
types: ['class'],
27+
setter: (resource?: () => Many<SomeResource>, options?: LoaderOptions) => ({
28+
resource,
29+
...options,
30+
}),
31+
});
32+
33+
/**
34+
* Register this class as a DataLoader for the given resource(s)
35+
*
36+
* @param resource Connect this loader to this resource, so it can be accessed dynamically.
37+
* @param options
38+
*/
39+
export const LoaderFactory =
40+
(
41+
resource?: () => Many<SomeResource>,
42+
options?: LoaderOptions,
43+
): (<LoaderCtor extends DataLoaderCtor>(target: LoaderCtor) => void) =>
44+
(target) => {
45+
Injectable({ scope: Scope.REQUEST })(target);
46+
47+
LoaderFactoryMetadata(resource, {
48+
...options,
49+
objectViewAware:
50+
options?.objectViewAware ??
51+
Object.getPrototypeOf(target) === ObjectViewAwareLoader,
52+
})(target);
53+
};

src/core/resources/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
export * from './resource-resolver.service';
2-
export { LoaderFactory } from './loader.registry';
32
export * from './resource.loader';
43
export * from './resources.host';
54
export * from './resource-name.types';

src/core/resources/loader.registry.ts

Lines changed: 6 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2,61 +2,16 @@ import {
22
Injectable,
33
type OnModuleInit,
44
Scope,
5-
SetMetadata,
65
type Type,
76
} from '@nestjs/common';
87
import { ModulesContainer } from '@nestjs/core';
98
import { type DataLoaderStrategy } from '@seedcompany/data-loader';
10-
import type { ValueOf } from 'type-fest';
11-
import { many, type Many } from '~/common';
9+
import { many } from '~/common';
1210
import { type ResourceMap } from '~/core';
13-
import { ObjectViewAwareLoader } from '../data-loader';
14-
15-
type SomeResource = ValueOf<ResourceMap>;
16-
17-
const LOADER_OF_RESOURCE = Symbol('LOADER_OF_RESOURCE');
18-
19-
interface MetadataShape extends LoaderOptions {
20-
resource?: () => Many<SomeResource>;
21-
}
22-
23-
interface LoaderOptions {
24-
/**
25-
* Whether the loader is aware of ObjectViews.
26-
*
27-
* This means the loader key needs to be in the shape of
28-
* {@link import('../data-loader/object-view-aware-loader.strategy').Key Key}
29-
*
30-
* This defaults to true if the class extends ObjectViewAwareLoader.
31-
*/
32-
objectViewAware?: boolean;
33-
}
34-
35-
type DataLoaderCtor = Type<DataLoaderStrategy<any, any>>;
36-
37-
/**
38-
* Register this class as a DataLoader for the given resource(s)
39-
*
40-
* @param resource Connect this loader to this resource, so it can be accessed dynamically.
41-
* @param options
42-
*/
43-
export const LoaderFactory =
44-
(
45-
resource?: () => Many<SomeResource>,
46-
options?: LoaderOptions,
47-
): (<LoaderCtor extends DataLoaderCtor>(target: LoaderCtor) => void) =>
48-
(target) => {
49-
Injectable({ scope: Scope.REQUEST })(target);
50-
51-
const metadata: MetadataShape = {
52-
resource,
53-
...options,
54-
objectViewAware:
55-
options?.objectViewAware ??
56-
Object.getPrototypeOf(target) === ObjectViewAwareLoader,
57-
};
58-
SetMetadata(LOADER_OF_RESOURCE, metadata)(target);
59-
};
11+
import {
12+
LoaderFactoryMetadata,
13+
type LoaderOptions,
14+
} from '../data-loader/loader-factory.decorator';
6015

6116
@Injectable()
6217
export class ResourceLoaderRegistry implements OnModuleInit {
@@ -75,10 +30,7 @@ export class ResourceLoaderRegistry implements OnModuleInit {
7530
if (!provider.metatype) {
7631
return [];
7732
}
78-
const metadata = Reflect.getMetadata(
79-
LOADER_OF_RESOURCE,
80-
provider.metatype,
81-
) as MetadataShape | undefined;
33+
const metadata = LoaderFactoryMetadata.get(provider.metatype as Type);
8234
return metadata ? { ...metadata, provider } : [];
8335
});
8436
for (const { resource, provider, ...options } of loaderFactories) {

0 commit comments

Comments
 (0)