1 | ;
|
2 | /*
|
3 | * @adonisjs/fold
|
4 | *
|
5 | * (c) Harminder Virk <virk@adonisjs.com>
|
6 | *
|
7 | * For the full copyright and license information, please view the LICENSE
|
8 | * file that was distributed with this source code.
|
9 | */
|
10 | Object.defineProperty(exports, "__esModule", { value: true });
|
11 | exports.IocResolver = void 0;
|
12 | /**
|
13 | * Exposes the API to resolve and call bindings from the IoC container. The resolver
|
14 | * internally caches the IoC container lookup nodes to boost performance.
|
15 | */
|
16 | class IocResolver {
|
17 | constructor(container, fallbackMethod, rcNamespaceKey, fallbackNamespace) {
|
18 | this.container = container;
|
19 | this.fallbackMethod = fallbackMethod;
|
20 | this.rcNamespaceKey = rcNamespaceKey;
|
21 | this.fallbackNamespace = fallbackNamespace;
|
22 | this.lookupCache = {};
|
23 | /**
|
24 | * The namespace that will be used as a prefix when resolving
|
25 | * bindings
|
26 | */
|
27 | this.prefixNamespace = this.getPrefixNamespace();
|
28 | }
|
29 | /**
|
30 | * Returns the prefix namespace by giving preference to the
|
31 | * `.adonisrc.json` file
|
32 | */
|
33 | getPrefixNamespace() {
|
34 | /**
|
35 | * Use fallback namespace, when lookup inside rcFile is not required
|
36 | */
|
37 | if (!this.rcNamespaceKey) {
|
38 | return this.fallbackNamespace;
|
39 | }
|
40 | /**
|
41 | * If container doesn't have `Application` binding, then there is no
|
42 | * way for us to read rcFile namespaces and hence we use the fallback
|
43 | * namespace
|
44 | */
|
45 | if (!this.container.hasBinding('Adonis/Core/Application')) {
|
46 | return this.fallbackNamespace;
|
47 | }
|
48 | /**
|
49 | * Attempt to resolve the rcNamespace key from the rcFile
|
50 | * For example: The rc file has following namespaces
|
51 | * {
|
52 | * "controllers": "App/Controllers/Http"
|
53 | * }
|
54 | * We will use the value next to the `controllers` key
|
55 | */
|
56 | const application = this.container.use('Adonis/Core/Application');
|
57 | return application.namespacesMap.get(this.rcNamespaceKey) || this.fallbackNamespace;
|
58 | }
|
59 | /**
|
60 | * Resolves the namespace and returns it's lookup node
|
61 | */
|
62 | resolve(namespace, prefixNamespace = this.prefixNamespace) {
|
63 | const cacheKey = prefixNamespace ? `${prefixNamespace}/${namespace}` : namespace;
|
64 | /**
|
65 | * Return from cache, when the node exists
|
66 | */
|
67 | const cacheNode = this.lookupCache[cacheKey];
|
68 | if (cacheNode) {
|
69 | return cacheNode;
|
70 | }
|
71 | let method = this.fallbackMethod || 'handle';
|
72 | /**
|
73 | * Split the namespace to lookup the method on it. If method isn't
|
74 | * defined, we will use the conventional `handle` method.
|
75 | */
|
76 | const tokens = namespace.split('.');
|
77 | if (tokens.length > 1) {
|
78 | method = tokens.pop();
|
79 | }
|
80 | const lookupNode = this.container.lookupOrFail(tokens.join('.'), prefixNamespace);
|
81 | this.lookupCache[cacheKey] = { ...lookupNode, method };
|
82 | return this.lookupCache[cacheKey];
|
83 | }
|
84 | /**
|
85 | * Calls the namespace.method expression with any arguments that needs to
|
86 | * be passed. Also supports type-hinting dependencies.
|
87 | */
|
88 | async call(namespace, prefixNamespace, args) {
|
89 | const lookupNode = typeof namespace === 'string' ? this.resolve(namespace, prefixNamespace) : namespace;
|
90 | const instance = await this.container.makeAsync(lookupNode.namespace);
|
91 | args = typeof args === 'function' ? args(instance) : args;
|
92 | return this.container.callAsync(instance, lookupNode.method, args);
|
93 | }
|
94 | }
|
95 | exports.IocResolver = IocResolver;
|