-
Notifications
You must be signed in to change notification settings - Fork 5
/
configuration.ts
93 lines (74 loc) · 3.09 KB
/
configuration.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import { validateDecoratorOptions } from '../common/validators.js';
import { configuration } from '../singletons/configuration.js';
import { logger } from '../singletons/logger.js';
import type { ClassDecorator, ClassDecoratorTarget } from '../types.js';
/**
* Customizes odin's behavior.
*/
interface ConfigurationOptions {
/**
* Enables strict mode.
* If {@link true}, injectable names will be case-sensitive.
*/
strict: boolean;
}
const knownConfigurationOptions: (keyof ConfigurationOptions)[] = [
'strict',
];
/**
* Decorates a class to initialize the configuration before decorating other classes.
* The class won't be registered or used for anything.
*
* @param options the configuration.
*
* @throws Error if decorating something other than a class.
* @throws Error if called with too few or too many arguments.
* @throws Error if used more than once per project.
*/
function Configuration(options: ConfigurationOptions): ClassDecorator;
function Configuration<Target extends ClassDecoratorTarget>(target: ConfigurationOptions | Target, context?: ClassDecoratorContext<Target>): ClassDecorator | ReturnType<ClassDecorator> {
logger.decorators.debug('Configuration:', { target, context });
logger.notifyDeprecation({
name: '@Configuration decorator',
nameExample: '@Configuration({ ...configuration })',
since: 'v3.0.0',
use: 'explicit and exact-case names in @Injectable and @Inject decorators',
whatWillHappen: 'All configuration will be removed and strict mode will be the default',
});
if (arguments.length <= 0) {
throw new Error(logger.createMessage(`The @Configuration decorator cannot be called without any arguments. Add an argument or remove the ().`));
}
// @ts-expect-error: TS2741, yes the type doesn't like it but necessary for consistency and validation
let options: ConfigurationOptions = {};
if (typeof target === 'function' && context) {
return ConfigurationDecorator(target, context);
}
if (arguments.length > 1) {
throw new Error(logger.createMessage(`The @Configuration decorator cannot be called with more than one argument.`));
}
options = { ...target } as ConfigurationOptions;
return ConfigurationDecorator;
function ConfigurationDecorator<Target extends ClassDecoratorTarget>(target: Target, context: ClassDecoratorContext<Target>): Target | undefined {
logger.decorators.debug('ConfigurationDecorator:', { target, context, options });
if (context.kind !== 'class') {
throw new Error(logger.createMessage(`The @Configuration decorator can only decorate a class. Check the ${String(context.kind)} named '${String(context.name)}'.`));
}
validateDecoratorOptions(options, {
allowUnknown: false,
known: knownConfigurationOptions,
required: knownConfigurationOptions,
});
if (configuration.isInitialized()) {
throw new Error(logger.createMessage('The @Configuration decorator can only be used once.'));
}
configuration.setStrict(options.strict);
configuration.setInitialized(true);
return;
}
}
export {
Configuration,
};
export type {
ConfigurationOptions,
};