@flink-app/flink 0.12.1-alpha.0 → 0.12.1-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/bin/flink.ts +6 -13
  2. package/dist/bin/flink.js +3 -10
  3. package/dist/cli/build.js +3 -3
  4. package/dist/cli/clean.js +2 -2
  5. package/dist/cli/cli-utils.js +1 -1
  6. package/dist/cli/run.js +2 -2
  7. package/dist/src/FlinkApp.d.ts +6 -3
  8. package/dist/src/FlinkApp.js +109 -78
  9. package/dist/src/FlinkErrors.d.ts +1 -1
  10. package/dist/src/FlinkErrors.js +5 -5
  11. package/dist/src/FlinkHttpHandler.d.ts +7 -7
  12. package/dist/src/FlinkHttpHandler.js +1 -1
  13. package/dist/src/FlinkJob.d.ts +2 -2
  14. package/dist/src/FlinkLog.d.ts +2 -2
  15. package/dist/src/FlinkRepo.d.ts +17 -8
  16. package/dist/src/FlinkRepo.js +44 -20
  17. package/dist/src/FlinkResponse.d.ts +2 -2
  18. package/dist/src/FsUtils.js +7 -7
  19. package/dist/src/TypeScriptCompiler.js +83 -68
  20. package/dist/src/TypeScriptUtils.js +11 -33
  21. package/dist/src/index.js +5 -1
  22. package/dist/src/mock-data-generator.js +1 -1
  23. package/dist/src/utils.js +6 -6
  24. package/package.json +7 -7
  25. package/spec/FlinkRepo.spec.ts +11 -0
  26. package/spec/mock-project/dist/src/handlers/GetCar.js +10 -12
  27. package/spec/mock-project/dist/src/handlers/GetCar2.js +11 -13
  28. package/spec/mock-project/dist/src/handlers/GetCarWithArraySchema.js +8 -10
  29. package/spec/mock-project/dist/src/handlers/GetCarWithArraySchema2.js +8 -10
  30. package/spec/mock-project/dist/src/handlers/GetCarWithArraySchema3.js +8 -10
  31. package/spec/mock-project/dist/src/handlers/GetCarWithLiteralSchema.js +10 -12
  32. package/spec/mock-project/dist/src/handlers/GetCarWithLiteralSchema2.js +10 -12
  33. package/spec/mock-project/dist/src/handlers/GetCarWithSchemaInFile.js +10 -12
  34. package/spec/mock-project/dist/src/handlers/GetCarWithSchemaInFile2.js +10 -12
  35. package/spec/mock-project/dist/src/handlers/ManuallyAddedHandler.js +10 -12
  36. package/spec/mock-project/dist/src/handlers/ManuallyAddedHandler2.js +10 -12
  37. package/spec/mock-project/dist/src/handlers/PostCar.js +10 -12
  38. package/spec/mock-project/dist/src/handlers/PostLogin.js +11 -13
  39. package/spec/mock-project/dist/src/handlers/PutCar.js +10 -12
  40. package/spec/mock-project/dist/src/index.js +6 -2
  41. package/src/FlinkApp.ts +33 -8
  42. package/src/FlinkRepo.ts +30 -11
  43. package/src/TypeScriptCompiler.ts +13 -2
  44. package/src/TypeScriptUtils.ts +110 -164
  45. package/cli/generate-schemas.ts +0 -153
package/src/FlinkApp.ts CHANGED
@@ -2,9 +2,9 @@ import Ajv, { ValidateFunction } from "ajv";
2
2
  import addFormats from "ajv-formats";
3
3
  import bodyParser, { OptionsJson } from "body-parser";
4
4
  import cors from "cors";
5
- import express, { Express, Request } from "express";
5
+ import express, { Express, Request, RequestHandler } from "express";
6
6
  import { JSONSchema7 } from "json-schema";
7
- import mongodb, { Db, MongoClient, ServerApiVersion } from "mongodb";
7
+ import { Db, MongoClient, ServerApiVersion } from "mongodb";
8
8
  import morgan from "morgan";
9
9
  import ms from "ms";
10
10
  import { AsyncTask, CronJob, SimpleIntervalJob, ToadScheduler } from "toad-scheduler";
@@ -217,6 +217,7 @@ export class FlinkApp<C extends FlinkContext> {
217
217
  public name: string;
218
218
  public expressApp?: Express;
219
219
  public db?: Db;
220
+ public dbClient?: MongoClient;
220
221
  public handlers: HandlerConfig[] = [];
221
222
  public port?: number;
222
223
  public started = false;
@@ -227,13 +228,14 @@ export class FlinkApp<C extends FlinkContext> {
227
228
  private onDbConnection?: FlinkOptions["onDbConnection"];
228
229
 
229
230
  private plugins: FlinkPlugin[] = [];
230
- private auth?: FlinkAuthPlugin;
231
+ public auth?: FlinkAuthPlugin;
231
232
  private corsOpts: FlinkOptions["cors"];
232
233
  private routingConfigured = false;
233
234
  private jsonOptions?: OptionsJson;
234
235
  private rawContentTypes?: string[];
235
236
  private schedulingOptions?: FlinkOptions["scheduling"];
236
237
  private disableHttpServer = false;
238
+ private expressServer: any; // for simplicity, we don't want to import types from express/node here
237
239
 
238
240
  private repos: { [x: string]: FlinkRepo<C, any> } = {};
239
241
 
@@ -303,14 +305,14 @@ export class FlinkApp<C extends FlinkContext> {
303
305
 
304
306
  if (this.rawContentTypes) {
305
307
  for (const type of this.rawContentTypes) {
306
- this.expressApp.use(express.raw({ type }));
308
+ this.expressApp.use(express.raw({ type }) as RequestHandler);
307
309
  }
308
310
  }
309
311
 
310
- this.expressApp.use(bodyParser.json(this.jsonOptions));
312
+ this.expressApp.use(bodyParser.json(this.jsonOptions) as RequestHandler);
311
313
 
312
314
  if (this.accessLog.enabled) {
313
- this.expressApp.use(morgan(this.accessLog.format));
315
+ this.expressApp.use(morgan(this.accessLog.format) as RequestHandler);
314
316
  }
315
317
 
316
318
  this.expressApp.use((req, res, next) => {
@@ -367,7 +369,7 @@ export class FlinkApp<C extends FlinkContext> {
367
369
  log.info("🚧 HTTP server is disabled, but flink app is running");
368
370
  this.started = true;
369
371
  } else {
370
- this.expressApp?.listen(this.port, () => {
372
+ this.expressServer = this.expressApp?.listen(this.port, () => {
371
373
  log.fontColorLog("magenta", `⚡️ HTTP server '${this.name}' is running and waiting for connections on ${this.port}`);
372
374
  this.started = true;
373
375
  });
@@ -376,6 +378,28 @@ export class FlinkApp<C extends FlinkContext> {
376
378
  return this;
377
379
  }
378
380
 
381
+ async stop() {
382
+ log.info("🛑 Stopping Flink app...");
383
+
384
+ if (this.scheduler) {
385
+ await this.scheduler.stop();
386
+ }
387
+
388
+ if (this.expressServer) {
389
+ return new Promise<void>((resolve, reject) => {
390
+ const int = setTimeout(() => {
391
+ reject("Failed to stop HTTP server in time");
392
+ }, 2000);
393
+
394
+ this.expressServer.close(() => {
395
+ clearInterval(int);
396
+ log.info("HTTP server stopped");
397
+ resolve();
398
+ });
399
+ });
400
+ }
401
+ }
402
+
379
403
  /**
380
404
  * Manually registers a handler.
381
405
  *
@@ -717,7 +741,7 @@ export class FlinkApp<C extends FlinkContext> {
717
741
  private async buildContext() {
718
742
  if (this.dbOpts) {
719
743
  for (const { collectionName, repoInstanceName, Repo } of autoRegisteredRepos) {
720
- const repoInstance: FlinkRepo<C, any> = new Repo(collectionName, this.db);
744
+ const repoInstance: FlinkRepo<C, any> = new Repo(collectionName, this.db, this.dbClient);
721
745
 
722
746
  this.repos[repoInstanceName] = repoInstance;
723
747
 
@@ -755,6 +779,7 @@ export class FlinkApp<C extends FlinkContext> {
755
779
  log.debug("Connecting to db");
756
780
  const client = await MongoClient.connect(this.dbOpts.uri, this.getMongoConnectionOptions());
757
781
  this.db = client.db();
782
+ this.dbClient = client;
758
783
  } catch (err) {
759
784
  log.error("Failed to connect to db: " + err);
760
785
  process.exit(1);
package/src/FlinkRepo.ts CHANGED
@@ -1,6 +1,12 @@
1
- import { Collection, Db, Document, InsertOneResult, ObjectId } from "mongodb";
1
+ import { Collection, Db, Document, InsertOneResult, MongoClient, ObjectId } from "mongodb";
2
2
  import { FlinkContext } from "./FlinkContext";
3
3
 
4
+ /**
5
+ * Partial model to have intellisense for partial updates but
6
+ * also allow any other properties to be set such as nested objects etc.
7
+ */
8
+ type PartialModel<Model> = Partial<Model> & { [x: string]: any };
9
+
4
10
  export abstract class FlinkRepo<C extends FlinkContext, Model extends Document> {
5
11
  collection: Collection;
6
12
 
@@ -15,23 +21,29 @@ export abstract class FlinkRepo<C extends FlinkContext, Model extends Document>
15
21
  return this._ctx;
16
22
  }
17
23
 
18
- constructor(private collectionName: string, private db: Db) {
24
+ constructor(public collectionName: string, public db: Db, public client?: MongoClient) {
19
25
  this.collection = db.collection(this.collectionName);
20
26
  }
21
27
 
22
28
  async findAll(query = {}): Promise<Model[]> {
23
29
  const res = await this.collection.find<Model>(query).toArray();
24
- return res.map(this.objectIdToString);
30
+ return res.map(this.objectIdToString) as Model[];
25
31
  }
26
32
 
27
33
  async getById(id: string | ObjectId) {
28
34
  const res = await this.collection.findOne<Model>({ _id: this.buildId(id) });
29
- return this.objectIdToString(res);
35
+ if (res) {
36
+ return this.objectIdToString(res) as Model;
37
+ }
38
+ return null;
30
39
  }
31
40
 
32
41
  async getOne(query = {}) {
33
42
  const res = await this.collection.findOne<Model>(query);
34
- return this.objectIdToString(res);
43
+ if (res) {
44
+ return this.objectIdToString(res) as Model;
45
+ }
46
+ return null;
35
47
  }
36
48
 
37
49
  async create<C = Omit<Model, "_id">>(model: C): Promise<C & { _id: string }> {
@@ -39,19 +51,26 @@ export abstract class FlinkRepo<C extends FlinkContext, Model extends Document>
39
51
  return { ...model, _id: result.insertedId.toString() };
40
52
  }
41
53
 
42
- async updateOne(id: string | ObjectId, model: Partial<Model>): Promise<Model | null> {
54
+ async updateOne(id: string | ObjectId, model: PartialModel<Model>): Promise<Model | null> {
43
55
  const oid = this.buildId(id);
44
56
 
45
- await this.collection.updateOne({ _id: oid }, { $set: model });
57
+ const { _id, ...modelWithoutId } = model;
58
+
59
+ await this.collection.updateOne({ _id: oid }, { $set: modelWithoutId });
46
60
 
47
61
  const res = await this.collection.findOne<Model>({ _id: oid });
48
62
 
49
- return this.objectIdToString(res);
63
+ if (res) {
64
+ return this.objectIdToString(res) as Model;
65
+ }
66
+ return null;
50
67
  }
51
68
 
52
- async updateMany<U = Partial<Model>>(query: any, model: U): Promise<number> {
69
+ async updateMany<U = PartialModel<Model>>(query: any, model: U): Promise<number> {
70
+ const { _id, ...modelWithoutId } = model as any;
71
+
53
72
  const { modifiedCount } = await this.collection.updateMany(query, {
54
- $set: model as any,
73
+ $set: modelWithoutId as any,
55
74
  });
56
75
  return modifiedCount;
57
76
  }
@@ -77,7 +96,7 @@ export abstract class FlinkRepo<C extends FlinkContext, Model extends Document>
77
96
  return oid;
78
97
  }
79
98
 
80
- private objectIdToString(doc: any & { _id?: any }) {
99
+ private objectIdToString<T>(doc: T & { _id?: any }) {
81
100
  if (doc && doc._id) {
82
101
  doc._id = doc._id.toString();
83
102
  }
@@ -2,7 +2,7 @@ import { promises as fsPromises } from "fs";
2
2
  import { JSONSchema7 } from "json-schema";
3
3
  import { join } from "path";
4
4
  import glob from "tiny-glob";
5
- import { Config, createFormatter, createParser, Schema, SchemaGenerator } from "ts-json-schema-generator";
5
+ import { CompletedConfig, Config, createFormatter, createParser, Schema, SchemaGenerator } from "ts-json-schema-generator";
6
6
  import {
7
7
  ArrayLiteralExpression,
8
8
  DiagnosticCategory,
@@ -437,9 +437,20 @@ import "..${appEntryScript.replace(/\.ts/g, "")}";
437
437
  }
438
438
 
439
439
  private initJsonSchemaGenerator() {
440
- const conf: Config = {
440
+ const conf: CompletedConfig = {
441
441
  expose: "none", // Do not create shared $ref definitions.
442
442
  topRef: false, // Removes the wrapper object around the schema.
443
+ additionalProperties: false,
444
+ jsDoc: "basic",
445
+ sortProps: false,
446
+ strictTuples: false,
447
+ minify: false,
448
+ markdownDescription: false,
449
+ skipTypeCheck: false,
450
+ encodeRefs: false,
451
+ extraTags: [],
452
+ functions: "fail",
453
+ discriminatorType: "json-schema",
443
454
  };
444
455
  const formatter = createFormatter(conf);
445
456
  const parser = createParser(this.project.getProgram().compilerObject, conf);
@@ -1,13 +1,4 @@
1
- import {
2
- ImportDeclarationStructure,
3
- Node,
4
- OptionalKind,
5
- SourceFile,
6
- Symbol,
7
- SyntaxKind,
8
- ts,
9
- Type,
10
- } from "ts-morph";
1
+ import { ImportDeclarationStructure, Node, OptionalKind, SourceFile, Symbol, SyntaxKind, ts, Type } from "ts-morph";
11
2
  import { getJsDocComment } from "./utils";
12
3
 
13
4
  /**
@@ -18,85 +9,66 @@ import { getJsDocComment } from "./utils";
18
9
  * Declared types of those are returned.
19
10
  */
20
11
  export function getTypesToImport(node: Node<ts.Node>) {
21
- const typeRefIdentifiers = node
22
- .getDescendantsOfKind(SyntaxKind.TypeReference)
23
- .filter(
24
- (typeRefNode) => !!typeRefNode.getFirstChildIfKind(SyntaxKind.Identifier)
25
- )
26
- .map((typeRefNode) =>
27
- typeRefNode.getFirstChildIfKindOrThrow(SyntaxKind.Identifier)
28
- );
12
+ const typeRefIdentifiers = node
13
+ .getDescendantsOfKind(SyntaxKind.TypeReference)
14
+ .filter((typeRefNode) => !!typeRefNode.getFirstChildIfKind(SyntaxKind.Identifier))
15
+ .map((typeRefNode) => typeRefNode.getFirstChildIfKindOrThrow(SyntaxKind.Identifier));
29
16
 
30
- const typesToImport: Type<ts.Type>[] = [];
17
+ const typesToImport: Type<ts.Type>[] = [];
31
18
 
32
- for (const typeRefIdentifier of typeRefIdentifiers) {
33
- const typeSymbol = typeRefIdentifier.getSymbolOrThrow();
19
+ for (const typeRefIdentifier of typeRefIdentifiers) {
20
+ const typeSymbol = typeRefIdentifier.getSymbolOrThrow();
34
21
 
35
- const declaredType = typeSymbol.getDeclaredType();
36
- const declaration = declaredType.getSymbol()?.getDeclarations()[0];
22
+ const declaredType = typeSymbol.getDeclaredType();
23
+ const declaration = declaredType.getSymbol()?.getDeclarations()[0];
37
24
 
38
- if (!declaration) {
39
- continue; // should not happen, right?
40
- }
25
+ if (!declaration) {
26
+ continue; // should not happen, right?
27
+ }
41
28
 
42
- if (declaration.getSourceFile() !== node.getSourceFile()) {
43
- typesToImport.push(declaration.getSymbolOrThrow().getDeclaredType());
44
- } else {
45
- typesToImport.push(...getTypesToImport(declaration));
29
+ if (declaration.getSourceFile() !== node.getSourceFile()) {
30
+ typesToImport.push(declaration.getSymbolOrThrow().getDeclaredType());
31
+ } else {
32
+ typesToImport.push(...getTypesToImport(declaration));
33
+ }
46
34
  }
47
- }
48
35
 
49
- return typesToImport;
36
+ return typesToImport;
50
37
  }
51
38
 
52
39
  export function addImport(toSourceFile: SourceFile, symbol: Symbol) {
53
- const symbolDeclaration = symbol.getDeclarations()[0];
54
-
55
- if (!symbolDeclaration) {
56
- throw new Error(
57
- "Missing declaration for symbol " + symbol.getFullyQualifiedName()
58
- );
59
- }
60
-
61
- const importName = symbol.getEscapedName();
62
- const symbolSourceFile = symbolDeclaration.getSourceFile();
40
+ const symbolDeclaration = symbol.getDeclarations()[0];
63
41
 
64
- const isDefaultExport = symbol
65
- .getDeclaredType()
66
- .getText()
67
- .endsWith(".default");
42
+ if (!symbolDeclaration) {
43
+ throw new Error("Missing declaration for symbol " + symbol.getFullyQualifiedName());
44
+ }
68
45
 
69
- const importDec = toSourceFile
70
- .getImportDeclarations()
71
- .find(
72
- (importDeclarataion) =>
73
- importDeclarataion.getModuleSpecifierSourceFile() === symbolSourceFile
74
- );
46
+ const importName = symbol.getEscapedName();
47
+ const symbolSourceFile = symbolDeclaration.getSourceFile();
75
48
 
76
- if (importDec) {
77
- // File already has import to file
78
- if (isDefaultExport) {
79
- if (!importDec.getDefaultImport()) {
80
- importDec.setDefaultImport(importName);
81
- }
49
+ const isDefaultExport = symbol.getDeclaredType().getText().endsWith(".default");
50
+
51
+ const importDec = toSourceFile.getImportDeclarations().find((importDeclarataion) => importDeclarataion.getModuleSpecifierSourceFile() === symbolSourceFile);
52
+
53
+ if (importDec) {
54
+ // File already has import to file
55
+ if (isDefaultExport) {
56
+ if (!importDec.getDefaultImport()) {
57
+ importDec.setDefaultImport(importName);
58
+ }
59
+ } else {
60
+ if (!importDec.getNamedImports().find((specifier) => specifier.getText() === importName)) {
61
+ importDec.addNamedImport(importName);
62
+ }
63
+ }
82
64
  } else {
83
- if (
84
- !importDec
85
- .getNamedImports()
86
- .find((specifier) => specifier.getText() === importName)
87
- ) {
88
- importDec.addNamedImport(importName);
89
- }
65
+ // Add new import declaration
66
+ toSourceFile.addImportDeclaration({
67
+ moduleSpecifier: toSourceFile.getRelativePathAsModuleSpecifierTo(symbolSourceFile),
68
+ defaultImport: isDefaultExport ? symbol.getEscapedName() : undefined,
69
+ namedImports: isDefaultExport ? undefined : [symbol.getEscapedName()],
70
+ });
90
71
  }
91
- } else {
92
- // Add new import declaration
93
- toSourceFile.addImportDeclaration({
94
- moduleSpecifier:
95
- toSourceFile.getRelativePathAsModuleSpecifierTo(symbolSourceFile),
96
- defaultImport: isDefaultExport ? symbol.getEscapedName() : undefined,
97
- namedImports: isDefaultExport ? undefined : [symbol.getEscapedName()],
98
- });
99
- }
100
72
  }
101
73
 
102
74
  /**
@@ -106,63 +78,47 @@ export function addImport(toSourceFile: SourceFile, symbol: Symbol) {
106
78
  * @param symbols
107
79
  */
108
80
  export function addImports(toSourceFile: SourceFile, symbols: Symbol[]) {
109
- const importsByModuleSpecifier = new Map<
110
- string,
111
- { defaultImportName?: string; namedImports: string[] }
112
- >();
81
+ const importsByModuleSpecifier = new Map<string, { defaultImportName?: string; namedImports: string[] }>();
113
82
 
114
- for (const symbol of symbols) {
115
- const symbolDeclaration = symbol.getDeclarations()[0];
83
+ for (const symbol of symbols) {
84
+ const symbolDeclaration = symbol.getDeclarations()[0];
116
85
 
117
- if (!symbolDeclaration) {
118
- throw new Error(
119
- "Missing declaration for symbol " + symbol.getFullyQualifiedName()
120
- );
121
- }
86
+ if (!symbolDeclaration) {
87
+ throw new Error("Missing declaration for symbol " + symbol.getFullyQualifiedName());
88
+ }
122
89
 
123
- const importName = symbol.getDeclaredType().isInterface()
124
- ? getInterfaceName(symbol)
125
- : symbol.getEscapedName();
90
+ const importName = symbol.getDeclaredType().isInterface() ? getInterfaceName(symbol) : symbol.getEscapedName();
126
91
 
127
- const symbolSourceFile = symbolDeclaration.getSourceFile();
128
- const isDefaultExport = symbol
129
- .getDeclaredType()
130
- .getText()
131
- .endsWith(".default");
92
+ const symbolSourceFile = symbolDeclaration.getSourceFile();
93
+ const isDefaultExport = symbol.getDeclaredType().getText().endsWith(".default");
132
94
 
133
- const moduleSpecifier =
134
- toSourceFile.getRelativePathAsModuleSpecifierTo(symbolSourceFile);
95
+ const moduleSpecifier = toSourceFile.getRelativePathAsModuleSpecifierTo(symbolSourceFile);
135
96
 
136
- let aImport = importsByModuleSpecifier.get(moduleSpecifier);
97
+ let aImport = importsByModuleSpecifier.get(moduleSpecifier);
137
98
 
138
- if (!aImport) {
139
- importsByModuleSpecifier.set(moduleSpecifier, {
140
- defaultImportName: isDefaultExport ? importName : undefined,
141
- namedImports: isDefaultExport ? [] : [importName],
142
- });
143
- } else {
144
- if (isDefaultExport) {
145
- aImport.defaultImportName = importName;
146
- } else if (!aImport.namedImports.includes(importName)) {
147
- aImport.namedImports.push(importName);
148
- }
99
+ if (!aImport) {
100
+ importsByModuleSpecifier.set(moduleSpecifier, {
101
+ defaultImportName: isDefaultExport ? importName : undefined,
102
+ namedImports: isDefaultExport ? [] : [importName],
103
+ });
104
+ } else {
105
+ if (isDefaultExport) {
106
+ aImport.defaultImportName = importName;
107
+ } else if (!aImport.namedImports.includes(importName)) {
108
+ aImport.namedImports.push(importName);
109
+ }
110
+ }
149
111
  }
150
- }
151
-
152
- toSourceFile.addImportDeclarations(
153
- Array.from(importsByModuleSpecifier.entries()).map(
154
- ([
155
- moduleSpecifier,
156
- aImport,
157
- ]): OptionalKind<ImportDeclarationStructure> => ({
158
- moduleSpecifier,
159
- defaultImport: aImport.defaultImportName,
160
- namedImports: aImport.namedImports.length
161
- ? aImport.namedImports
162
- : undefined,
163
- })
164
- )
165
- );
112
+
113
+ toSourceFile.addImportDeclarations(
114
+ Array.from(importsByModuleSpecifier.entries()).map(
115
+ ([moduleSpecifier, aImport]): OptionalKind<ImportDeclarationStructure> => ({
116
+ moduleSpecifier,
117
+ defaultImport: aImport.defaultImportName,
118
+ namedImports: aImport.namedImports.length ? aImport.namedImports : undefined,
119
+ })
120
+ )
121
+ );
166
122
  }
167
123
 
168
124
  /**
@@ -171,21 +127,17 @@ export function addImports(toSourceFile: SourceFile, symbols: Symbol[]) {
171
127
  * @returns
172
128
  */
173
129
  export function getDefaultExport(sf: SourceFile) {
174
- const exportAssignment = sf.getFirstDescendantByKind(
175
- SyntaxKind.ExportAssignment
176
- );
130
+ const exportAssignment = sf.getFirstDescendantByKind(SyntaxKind.ExportAssignment);
177
131
 
178
- if (exportAssignment) {
179
- const identifier = exportAssignment.getFirstChildByKind(
180
- SyntaxKind.Identifier
181
- );
132
+ if (exportAssignment) {
133
+ const identifier = exportAssignment.getFirstChildByKind(SyntaxKind.Identifier);
182
134
 
183
- if (identifier) {
184
- return identifier.getSymbolOrThrow().getDeclarations()[0];
185
- } else {
186
- return exportAssignment.getFirstChild();
135
+ if (identifier) {
136
+ return identifier.getSymbolOrThrow().getDeclarations()[0];
137
+ } else {
138
+ return exportAssignment.getFirstChild();
139
+ }
187
140
  }
188
- }
189
141
  }
190
142
 
191
143
  /**
@@ -195,48 +147,42 @@ export function getDefaultExport(sf: SourceFile) {
195
147
  * @returns
196
148
  */
197
149
  export function getInterfaceName(symbol: Symbol) {
198
- const declaration = symbol.getDeclarations()[0];
150
+ const declaration = symbol.getDeclarations()[0];
199
151
 
200
- if (!declaration) {
201
- throw new Error("Missing declaration of interface symbol");
202
- }
152
+ if (!declaration) {
153
+ throw new Error("Missing declaration of interface symbol");
154
+ }
203
155
 
204
- return declaration
205
- .getFirstChildByKindOrThrow(SyntaxKind.Identifier)
206
- .getText();
156
+ return declaration.getFirstChildByKindOrThrow(SyntaxKind.Identifier).getText();
207
157
  }
208
158
 
209
159
  export function getSymbolOrAlias(type: Type<ts.Type>) {
210
- return type.getAliasSymbol() || type.getSymbol();
160
+ return type.getAliasSymbol() || type.getSymbol();
211
161
  }
212
162
 
213
163
  export function getTypeMetadata(type: Type<ts.Type>) {
214
- if (["void", "any"].includes(type.getText())) {
215
- return [];
216
- }
164
+ if (!type || ["void", "any"].includes(type.getText())) {
165
+ return [];
166
+ }
217
167
 
218
- const symbol = getSymbolOrAlias(type);
168
+ const symbol = getSymbolOrAlias(type);
219
169
 
220
- if (!symbol) {
221
- throw new Error("Could not get type symbol for type: " + type.getText());
222
- }
170
+ if (!symbol) {
171
+ throw new Error("Could not get type symbol for type: " + type.getText());
172
+ }
223
173
 
224
- const [declaration] = symbol.getDeclarations();
174
+ const [declaration] = symbol.getDeclarations();
225
175
 
226
- if (!declaration) {
227
- throw new Error("Could not get declaration for type: " + type.getText());
228
- }
176
+ if (!declaration) {
177
+ throw new Error("Could not get declaration for type: " + type.getText());
178
+ }
229
179
 
230
- return declaration
231
- .getDescendantsOfKind(SyntaxKind.PropertySignature)
232
- .map((prop) => {
233
- const description = getJsDocComment(
234
- prop.getLeadingCommentRanges()[0]?.getText() || ""
235
- );
180
+ return declaration.getDescendantsOfKind(SyntaxKind.PropertySignature).map((prop) => {
181
+ const description = getJsDocComment(prop.getLeadingCommentRanges()[0]?.getText() || "");
236
182
 
237
- return {
238
- description,
239
- name: prop.getName(),
240
- };
183
+ return {
184
+ description,
185
+ name: prop.getName(),
186
+ };
241
187
  });
242
188
  }