UNPKG

9.3 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const ts_morph_1 = require("ts-morph");
4// FILE HELPERS
5/**
6 * Retrieve all local dependencies of a file recursively including itself.
7 *
8 * @param file the source file
9 * @param visitedFiles visisted files
10 */
11function getSelfAndLocalDependencies(file, visitedFiles = []) {
12 return (file
13 .getImportDeclarations()
14 // We only care about local imports.
15 .filter(id => id.isModuleSpecifierRelative())
16 // will throw on file with no import/export statements
17 // TODO: provide a warning
18 .map(id => id.getModuleSpecifierSourceFileOrThrow())
19 .reduce((acc, curr) => {
20 if (acc.some(f => f.getFilePath() === curr.getFilePath())) {
21 return acc;
22 }
23 else {
24 return getSelfAndLocalDependencies(curr, acc);
25 }
26 }, visitedFiles.concat(file)));
27}
28exports.getSelfAndLocalDependencies = getSelfAndLocalDependencies;
29/**
30 * Retrieve a class from a file with a particular decorator or throw.
31 *
32 * @param file the source file
33 * @param decoratorName name of decorator to search for
34 */
35function getClassWithDecoratorOrThrow(file, decoratorName) {
36 const matchingKlasses = file
37 .getClasses()
38 .filter(k => k.getDecorator(decoratorName) !== undefined);
39 if (matchingKlasses.length !== 1) {
40 throw new Error(`expected a decorator @${decoratorName} to be used once, found ${matchingKlasses.length} usages`);
41 }
42 return matchingKlasses[0];
43}
44exports.getClassWithDecoratorOrThrow = getClassWithDecoratorOrThrow;
45// CLASS HELPERS
46/**
47 * Retrieve a property from a class declaration with a particular decorator.
48 *
49 * @param klass class declaration
50 * @param decoratorName name of decorator to search for
51 */
52function getPropertyWithDecorator(klass, decoratorName) {
53 const matchingProps = klass
54 .getProperties()
55 .filter(p => p.getDecorator(decoratorName) !== undefined);
56 if (matchingProps.length > 1) {
57 throw new Error(`expected a decorator @${decoratorName} to be used only once, found ${matchingProps.length} usages`);
58 }
59 return matchingProps.length === 1 ? matchingProps[0] : undefined;
60}
61exports.getPropertyWithDecorator = getPropertyWithDecorator;
62/**
63 * Retrieve a method from a class declaration with a particular decorator.
64 *
65 * @param klass class declaration
66 * @param decoratorName name of the decorator to search for
67 */
68function getMethodWithDecorator(klass, decoratorName) {
69 const matchingMethods = klass
70 .getMethods()
71 .filter(m => m.getDecorator(decoratorName) !== undefined);
72 if (matchingMethods.length > 1) {
73 throw new Error(`expected a decorator @${decoratorName} to be used only once, found ${matchingMethods.length} usages`);
74 }
75 return matchingMethods.length === 1 ? matchingMethods[0] : undefined;
76}
77exports.getMethodWithDecorator = getMethodWithDecorator;
78// METHOD HELPERS
79/**
80 * Retrieve a parameter from a method declaration with a particular decorator.
81 *
82 * @param method method declaration
83 * @param decoratorName name of decorator to search for
84 */
85function getParamWithDecorator(method, decoratorName) {
86 const matchingParams = method
87 .getParameters()
88 .filter(p => p.getDecorator(decoratorName) !== undefined);
89 if (matchingParams.length > 1) {
90 throw new Error(`expected a decorator @${decoratorName} to be used only once, found ${matchingParams.length} usages`);
91 }
92 return matchingParams.length === 1 ? matchingParams[0] : undefined;
93}
94exports.getParamWithDecorator = getParamWithDecorator;
95// PARAMETER HELPERS
96/**
97 * Retrieve a parameter's type as a type literal or throw.
98 *
99 * @param parameter a parameter declaration
100 */
101function getParameterTypeAsTypeLiteralOrThrow(parameter) {
102 const typeNode = parameter.getTypeNodeOrThrow();
103 if (!ts_morph_1.TypeGuards.isTypeLiteralNode(typeNode)) {
104 throw new Error("expected parameter value to be an type literal object");
105 }
106 return typeNode;
107}
108exports.getParameterTypeAsTypeLiteralOrThrow = getParameterTypeAsTypeLiteralOrThrow;
109// DECORATOR HELPERS
110/**
111 * Retrieve a decorator factory's configuration. The configuration is
112 * the first parameter of the decorator and is expected to be an object
113 * literal.
114 *
115 * @param decorator the source decorator
116 */
117function getDecoratorConfigOrThrow(decorator) {
118 // expect a decorator factory
119 if (!decorator.isDecoratorFactory()) {
120 throw new Error("expected decorator factory");
121 }
122 // expect a single argument
123 const decoratorArgs = decorator.getArguments();
124 if (decoratorArgs.length !== 1) {
125 throw new Error(`expected exactly one argument, got ${decoratorArgs.length}`);
126 }
127 // expect the argument to be an object literal expression
128 const decoratorArg = decoratorArgs[0];
129 if (!ts_morph_1.TypeGuards.isObjectLiteralExpression(decoratorArg)) {
130 throw new Error(`expected decorator factory configuration argument to be an object literal`);
131 }
132 return decoratorArg;
133}
134exports.getDecoratorConfigOrThrow = getDecoratorConfigOrThrow;
135// EXPRESSION HELPERS
136/**
137 * Retrieves a property from an object literal expression. If provided,
138 * the generic parameter will narrow down the available property names
139 * allowed.
140 *
141 * @param objectLiteral a ts-morph object literal expression
142 * @param propertyName name of the property
143 */
144function getObjLiteralProp(objectLiteral, propertyName) {
145 const property = objectLiteral.getProperty(propertyName);
146 if (!property) {
147 return undefined;
148 }
149 if (!ts_morph_1.TypeGuards.isPropertyAssignment(property)) {
150 throw new Error("expected property assignment");
151 }
152 return property;
153}
154exports.getObjLiteralProp = getObjLiteralProp;
155/**
156 * Retrieves a property from an object literal expression or error. If
157 * provided, the generic parameter will narrow down the available
158 * property names allowed.
159 *
160 * @param objectLiteral a ts-morph object literal expression
161 * @param propertyName name of the property
162 */
163function getObjLiteralPropOrThrow(objectLiteral, propertyName) {
164 const property = objectLiteral.getPropertyOrThrow(propertyName);
165 if (!ts_morph_1.TypeGuards.isPropertyAssignment(property)) {
166 throw new Error("expected property assignment");
167 }
168 return property;
169}
170exports.getObjLiteralPropOrThrow = getObjLiteralPropOrThrow;
171// PROPERTY ASSIGNMENT HELPERS
172/**
173 * Retrieve a property's value as a string or error.
174 *
175 * @param property the source property
176 */
177function getPropValueAsStringOrThrow(property) {
178 return property.getInitializerIfKindOrThrow(ts_morph_1.ts.SyntaxKind.StringLiteral);
179}
180exports.getPropValueAsStringOrThrow = getPropValueAsStringOrThrow;
181/**
182 * Retrieve a property's value as a number or error.
183 *
184 * @param property the source property
185 */
186function getPropValueAsNumberOrThrow(property) {
187 return property.getInitializerIfKindOrThrow(ts_morph_1.ts.SyntaxKind.NumericLiteral);
188}
189exports.getPropValueAsNumberOrThrow = getPropValueAsNumberOrThrow;
190/**
191 * Retrieve a property's value as an array or error.
192 *
193 * @param property the source property
194 */
195function getPropValueAsArrayOrThrow(property) {
196 return property.getInitializerIfKindOrThrow(ts_morph_1.ts.SyntaxKind.ArrayLiteralExpression);
197}
198exports.getPropValueAsArrayOrThrow = getPropValueAsArrayOrThrow;
199/**
200 * Retrieve a property's value as an object or error.
201 *
202 * @param property the source property
203 */
204function getPropValueAsObjectOrThrow(property) {
205 return property.getInitializerIfKindOrThrow(ts_morph_1.ts.SyntaxKind.ObjectLiteralExpression);
206}
207exports.getPropValueAsObjectOrThrow = getPropValueAsObjectOrThrow;
208// PROPERTY SIGNATURE/DECLARATION HELPERS
209/**
210 * Retrieve a property's name. This will remove any quotes surrounding the name.
211 *
212 * @param property property signature
213 */
214function getPropertyName(property) {
215 return property.getNameNode().getSymbolOrThrow().getEscapedName();
216}
217exports.getPropertyName = getPropertyName;
218// JSDOC HELPERS
219/**
220 * Retrieve a JSDoc for a ts-morph node. The node is expected
221 * to have no more than one JSDoc.
222 *
223 * @param node a JSDocable ts-morph node
224 */
225function getJsDoc(node) {
226 const jsDocs = node.getJsDocs();
227 if (jsDocs.length > 1) {
228 throw new Error(`expected at most 1 jsDoc node, got ${jsDocs.length}`);
229 }
230 else if (jsDocs.length === 1) {
231 return jsDocs[0];
232 }
233 return undefined;
234}
235exports.getJsDoc = getJsDoc;
236// TYPE GUARDS
237/**
238 * Determine if a HTTP method is a supported HttpMethod.
239 *
240 * @param method the method to check
241 */
242function isHttpMethod(method) {
243 switch (method) {
244 case "GET":
245 case "POST":
246 case "PUT":
247 case "PATCH":
248 case "DELETE":
249 return true;
250 default:
251 return false;
252 }
253}
254exports.isHttpMethod = isHttpMethod;
255/**
256 * Determine if a query param array strategy is a supported QueryParamArrayStrategy.
257 *
258 * @param strategy the strategy to check
259 */
260function isQueryParamArrayStrategy(strategy) {
261 switch (strategy) {
262 case "ampersand":
263 case "comma":
264 return true;
265 default:
266 return false;
267 }
268}
269exports.isQueryParamArrayStrategy = isQueryParamArrayStrategy;