15815213711
2024-08-26 67b8b6731811983447e053d4396b3708c14dfe3c
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getFunctionName = exports.getBaseClassDependencyCount = exports.getDependencies = void 0;
const lazy_service_identifier_1 = require("../annotation/lazy_service_identifier");
const ERROR_MSGS = __importStar(require("../constants/error_msgs"));
const literal_types_1 = require("../constants/literal_types");
const METADATA_KEY = __importStar(require("../constants/metadata_keys"));
const serialization_1 = require("../utils/serialization");
Object.defineProperty(exports, "getFunctionName", { enumerable: true, get: function () { return serialization_1.getFunctionName; } });
const target_1 = require("./target");
function getDependencies(metadataReader, func) {
    const constructorName = (0, serialization_1.getFunctionName)(func);
    return getTargets(metadataReader, constructorName, func, false);
}
exports.getDependencies = getDependencies;
function getTargets(metadataReader, constructorName, func, isBaseClass) {
    const metadata = metadataReader.getConstructorMetadata(func);
    const serviceIdentifiers = metadata.compilerGeneratedMetadata;
    if (serviceIdentifiers === undefined) {
        const msg = `${ERROR_MSGS.MISSING_INJECTABLE_ANNOTATION} ${constructorName}.`;
        throw new Error(msg);
    }
    const constructorArgsMetadata = metadata.userGeneratedMetadata;
    const keys = Object.keys(constructorArgsMetadata);
    const hasUserDeclaredUnknownInjections = (func.length === 0 && keys.length > 0);
    const hasOptionalParameters = keys.length > func.length;
    const iterations = (hasUserDeclaredUnknownInjections || hasOptionalParameters) ? keys.length : func.length;
    const constructorTargets = getConstructorArgsAsTargets(isBaseClass, constructorName, serviceIdentifiers, constructorArgsMetadata, iterations);
    const propertyTargets = getClassPropsAsTargets(metadataReader, func, constructorName);
    const targets = [
        ...constructorTargets,
        ...propertyTargets
    ];
    return targets;
}
function getConstructorArgsAsTarget(index, isBaseClass, constructorName, serviceIdentifiers, constructorArgsMetadata) {
    const targetMetadata = constructorArgsMetadata[index.toString()] || [];
    const metadata = formatTargetMetadata(targetMetadata);
    const isManaged = metadata.unmanaged !== true;
    let serviceIdentifier = serviceIdentifiers[index];
    const injectIdentifier = (metadata.inject || metadata.multiInject);
    serviceIdentifier = (injectIdentifier) ? (injectIdentifier) : serviceIdentifier;
    if (serviceIdentifier instanceof lazy_service_identifier_1.LazyServiceIdentifer) {
        serviceIdentifier = serviceIdentifier.unwrap();
    }
    if (isManaged) {
        const isObject = serviceIdentifier === Object;
        const isFunction = serviceIdentifier === Function;
        const isUndefined = serviceIdentifier === undefined;
        const isUnknownType = (isObject || isFunction || isUndefined);
        if (!isBaseClass && isUnknownType) {
            const msg = `${ERROR_MSGS.MISSING_INJECT_ANNOTATION} argument ${index} in class ${constructorName}.`;
            throw new Error(msg);
        }
        const target = new target_1.Target(literal_types_1.TargetTypeEnum.ConstructorArgument, metadata.targetName, serviceIdentifier);
        target.metadata = targetMetadata;
        return target;
    }
    return null;
}
function getConstructorArgsAsTargets(isBaseClass, constructorName, serviceIdentifiers, constructorArgsMetadata, iterations) {
    const targets = [];
    for (let i = 0; i < iterations; i++) {
        const index = i;
        const target = getConstructorArgsAsTarget(index, isBaseClass, constructorName, serviceIdentifiers, constructorArgsMetadata);
        if (target !== null) {
            targets.push(target);
        }
    }
    return targets;
}
function _getServiceIdentifierForProperty(inject, multiInject, propertyName, className) {
    const serviceIdentifier = (inject || multiInject);
    if (serviceIdentifier === undefined) {
        const msg = `${ERROR_MSGS.MISSING_INJECTABLE_ANNOTATION} for property ${String(propertyName)} in class ${className}.`;
        throw new Error(msg);
    }
    return serviceIdentifier;
}
function getClassPropsAsTargets(metadataReader, constructorFunc, constructorName) {
    const classPropsMetadata = metadataReader.getPropertiesMetadata(constructorFunc);
    let targets = [];
    const symbolKeys = Object.getOwnPropertySymbols(classPropsMetadata);
    const stringKeys = Object.keys(classPropsMetadata);
    const keys = stringKeys.concat(symbolKeys);
    for (const key of keys) {
        const targetMetadata = classPropsMetadata[key];
        const metadata = formatTargetMetadata(targetMetadata);
        const identifier = metadata.targetName || key;
        const serviceIdentifier = _getServiceIdentifierForProperty(metadata.inject, metadata.multiInject, key, constructorName);
        const target = new target_1.Target(literal_types_1.TargetTypeEnum.ClassProperty, identifier, serviceIdentifier);
        target.metadata = targetMetadata;
        targets.push(target);
    }
    const baseConstructor = Object.getPrototypeOf(constructorFunc.prototype).constructor;
    if (baseConstructor !== Object) {
        const baseTargets = getClassPropsAsTargets(metadataReader, baseConstructor, constructorName);
        targets = [
            ...targets,
            ...baseTargets
        ];
    }
    return targets;
}
function getBaseClassDependencyCount(metadataReader, func) {
    const baseConstructor = Object.getPrototypeOf(func.prototype).constructor;
    if (baseConstructor !== Object) {
        const baseConstructorName = (0, serialization_1.getFunctionName)(baseConstructor);
        const targets = getTargets(metadataReader, baseConstructorName, baseConstructor, true);
        const metadata = targets.map((t) => t.metadata.filter(m => m.key === METADATA_KEY.UNMANAGED_TAG));
        const unmanagedCount = [].concat.apply([], metadata).length;
        const dependencyCount = targets.length - unmanagedCount;
        if (dependencyCount > 0) {
            return dependencyCount;
        }
        else {
            return getBaseClassDependencyCount(metadataReader, baseConstructor);
        }
    }
    else {
        return 0;
    }
}
exports.getBaseClassDependencyCount = getBaseClassDependencyCount;
function formatTargetMetadata(targetMetadata) {
    const targetMetadataMap = {};
    targetMetadata.forEach((m) => {
        targetMetadataMap[m.key.toString()] = m.value;
    });
    return {
        inject: targetMetadataMap[METADATA_KEY.INJECT_TAG],
        multiInject: targetMetadataMap[METADATA_KEY.MULTI_INJECT_TAG],
        targetName: targetMetadataMap[METADATA_KEY.NAME_TAG],
        unmanaged: targetMetadataMap[METADATA_KEY.UNMANAGED_TAG]
    };
}
//# sourceMappingURL=reflection_utils.js.map