1 | // Copyright IBM Corp. and LoopBack contributors 2018,2019. All Rights Reserved.
|
2 | // Node module: @loopback/boot
|
3 | // This file is licensed under the MIT License.
|
4 | // License text available at https://opensource.org/licenses/MIT
|
5 |
|
6 | import {Constructor} from '@loopback/core';
|
7 | import debugFactory from 'debug';
|
8 | import path from 'path';
|
9 | import {glob} from 'glob';
|
10 |
|
11 | const debug = debugFactory('loopback:boot:booter-utils');
|
12 |
|
13 | /**
|
14 | * Returns all files matching the given glob pattern relative to root
|
15 | *
|
16 | * @param pattern - A glob pattern
|
17 | * @param root - Root folder to start searching for matching files
|
18 | * @returns Array of discovered files
|
19 | */
|
20 | export async function discoverFiles(
|
21 | pattern: string,
|
22 | root: string,
|
23 | ): Promise<string[]> {
|
24 | return glob(pattern, {root: root});
|
25 | }
|
26 |
|
27 | /**
|
28 | * Given a function, returns true if it is a class, false otherwise.
|
29 | *
|
30 | * @param target - The function to check if it's a class or not.
|
31 | * @returns True if target is a class. False otherwise.
|
32 | */
|
33 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
34 | export function isClass(target: any): target is Constructor<any> {
|
35 | return (
|
36 | typeof target === 'function' && target.toString().indexOf('class') === 0
|
37 | );
|
38 | }
|
39 |
|
40 | /**
|
41 | * Returns an Array of Classes from given files. Works by requiring the file,
|
42 | * identifying the exports from the file by getting the keys of the file
|
43 | * and then testing each exported member to see if it's a class or not.
|
44 | *
|
45 | * @param files - An array of string of absolute file paths
|
46 | * @param projectRootDir - The project root directory
|
47 | * @returns An array of Class constructors from a file
|
48 | */
|
49 | export function loadClassesFromFiles(
|
50 | files: string[],
|
51 | projectRootDir: string,
|
52 | ): Constructor<{}>[] {
|
53 | const classes: Constructor<{}>[] = [];
|
54 | for (const file of files) {
|
55 | debug('Loading artifact file %j', path.relative(projectRootDir, file));
|
56 | const moduleObj = require(file);
|
57 | for (const k in moduleObj) {
|
58 | const exported = moduleObj[k];
|
59 | if (isClass(exported)) {
|
60 | debug(' add %s (class %s)', k, exported.name);
|
61 | classes.push(exported);
|
62 | } else {
|
63 | debug(' skip non-class %s', k);
|
64 | }
|
65 | }
|
66 | }
|
67 |
|
68 | return classes;
|
69 | }
|