@tsed/components-scan 8.0.0 → 8.0.2

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.
package/package.json CHANGED
@@ -2,13 +2,14 @@
2
2
  "name": "@tsed/components-scan",
3
3
  "description": "Components scan utilities for Ts.ED Framework",
4
4
  "type": "module",
5
- "version": "8.0.0",
5
+ "version": "8.0.2",
6
6
  "source": "./src/index.ts",
7
7
  "main": "./lib/esm/index.js",
8
8
  "module": "./lib/esm/index.js",
9
9
  "typings": "./lib/types/index.d.ts",
10
10
  "exports": {
11
11
  ".": {
12
+ "@tsed/source": "./src/index.ts",
12
13
  "types": "./lib/types/index.d.ts",
13
14
  "import": "./lib/esm/index.js",
14
15
  "default": "./lib/esm/index.js"
@@ -22,21 +23,21 @@
22
23
  "test:ci": "vitest run --coverage.thresholds.autoUpdate=true"
23
24
  },
24
25
  "dependencies": {
25
- "@tsed/normalize-path": "8.0.0",
26
+ "@tsed/normalize-path": "8.0.2",
26
27
  "globby": "^14.0.2",
27
28
  "tslib": "2.7.0"
28
29
  },
29
30
  "devDependencies": {
30
- "@tsed/barrels": "8.0.0",
31
- "@tsed/core": "8.0.0",
32
- "@tsed/di": "8.0.0",
33
- "@tsed/typescript": "8.0.0",
31
+ "@tsed/barrels": "8.0.2",
32
+ "@tsed/core": "8.0.2",
33
+ "@tsed/di": "8.0.2",
34
+ "@tsed/typescript": "8.0.2",
34
35
  "eslint": "9.12.0",
35
36
  "typescript": "5.4.5",
36
37
  "vitest": "2.1.2"
37
38
  },
38
39
  "peerDependencies": {
39
- "@tsed/core": "8.0.0"
40
+ "@tsed/core": "8.0.2"
40
41
  },
41
42
  "peerDependenciesMeta": {
42
43
  "@tsed/core": {
@@ -0,0 +1,32 @@
1
+ import {cleanGlobPatterns} from "./cleanGlobPatterns.js";
2
+ import {isTsEnv} from "./isTsEnv.js";
3
+
4
+ vi.mock("./isTsEnv");
5
+
6
+ describe("cleanGlobPatterns()", () => {
7
+ describe("when haven't typescript compiler", () => {
8
+ beforeAll(() => {
9
+ (isTsEnv as any).mockReturnValue(false);
10
+ });
11
+
12
+ it("should return file.js", () => {
13
+ expect(cleanGlobPatterns("file.ts", ["!**.spec.ts"])[0]).toContain("file.js");
14
+ });
15
+
16
+ it("should return file.ts,js", () => {
17
+ expect(cleanGlobPatterns("file{.ts,.js}", ["!**.spec.ts"])[0]).toContain("file.js");
18
+ });
19
+
20
+ it("should return file.ts.js and manipulate only the file extension", () => {
21
+ expect(cleanGlobPatterns("file.ts.ts", ["!**.spec.ts"])[0]).toContain("file.ts.js");
22
+ });
23
+ });
24
+ describe("when have typescript compiler", () => {
25
+ beforeAll(() => {
26
+ (isTsEnv as any).mockReturnValue(true);
27
+ });
28
+ it("should return file.ts", () => {
29
+ expect(cleanGlobPatterns("file.ts", ["!**.spec.ts"])[0]).toContain("file.ts");
30
+ });
31
+ });
32
+ });
@@ -0,0 +1,26 @@
1
+ // @ts-ignore
2
+ import {normalizePath} from "@tsed/normalize-path";
3
+ import {resolve} from "path";
4
+
5
+ import {isTsEnv} from "./isTsEnv.js";
6
+
7
+ function mapExcludes(excludes: string[]) {
8
+ return excludes.map((s: string) => `!${s.replace(/!/gi, "")}`);
9
+ }
10
+
11
+ function mapExtensions(file: string): string {
12
+ if (!isTsEnv()) {
13
+ file = file.replace(/\.ts$/i, ".js").replace(/{\.ts,\.js}$/i, ".js");
14
+ }
15
+
16
+ return file;
17
+ }
18
+
19
+ export function cleanGlobPatterns(files: string | string[], excludes: string[]): string[] {
20
+ return []
21
+ .concat(files as never)
22
+ .map((s: string) => resolve(s))
23
+ .concat(mapExcludes(excludes) as never)
24
+ .map(mapExtensions)
25
+ .map((s: string) => normalizePath(s));
26
+ }
@@ -0,0 +1,21 @@
1
+ import {join} from "path";
2
+
3
+ import {Test1} from "./__mock__/Test1.js";
4
+ import {Test2} from "./__mock__/Test2.js";
5
+ import {importFiles} from "./importFiles.js";
6
+
7
+ const rootDir = import.meta.dirname; // automatically replaced by import.meta.dirname on build
8
+
9
+ describe("importFiles", () => {
10
+ it("should import symbols", async () => {
11
+ const symbols = await importFiles([join(rootDir, "__mock__/*.ts")], []);
12
+
13
+ expect(symbols.sort()).toEqual(["value", Test1, "value", Test2].sort());
14
+ });
15
+
16
+ it("should import symbols without excluded files", async () => {
17
+ const symbols = await importFiles([join(rootDir, "__mock__/*.ts")], [join(rootDir, "__mock__/Test2.ts")]);
18
+
19
+ expect(symbols.sort()).toEqual(["value", Test1].sort());
20
+ });
21
+ });
@@ -0,0 +1,18 @@
1
+ import {cleanGlobPatterns} from "./cleanGlobPatterns.js";
2
+
3
+ export async function importFiles(patterns: string | string[], exclude: string[]): Promise<any[]> {
4
+ const {globby} = await import("globby");
5
+
6
+ const files = await globby(cleanGlobPatterns(patterns, exclude));
7
+ const symbols: any[] = [];
8
+
9
+ for (const file of files.sort((a, b) => (a < b ? -1 : 1))) {
10
+ if (!file.endsWith(".d.ts")) {
11
+ // prevent .d.ts import if the global pattern isn't correctly configured
12
+ const exports = await import(file);
13
+ Object.keys(exports).forEach((key) => symbols.push(exports[key]));
14
+ }
15
+ }
16
+
17
+ return symbols;
18
+ }
@@ -0,0 +1,41 @@
1
+ import {nameOf} from "@tsed/core";
2
+ import {resolveControllers} from "@tsed/platform-http";
3
+
4
+ import {importProviders} from "./importProviders.js";
5
+
6
+ const rootDir = import.meta.dirname; // automatically replaced by import.meta.dirname on build
7
+
8
+ describe("importProviders", () => {
9
+ it("should load providers and merge configuration", async () => {
10
+ const configuration = {
11
+ mount: {
12
+ "/rest": [`${rootDir}/__mock__/controllers/**/*.ts`]
13
+ },
14
+ imports: [`${rootDir}/__mock__/**/Module*.ts`]
15
+ };
16
+
17
+ const result = await importProviders(configuration);
18
+
19
+ expect(result.imports?.map(nameOf)).toEqual(["Module1", "Module2"]);
20
+ expect(result.mount!["/rest"].map(nameOf)).toEqual(["TestCtrl"]);
21
+
22
+ const result2 = resolveControllers(result);
23
+
24
+ const routes = result2.map((item) => ({...item, token: nameOf(item.token)}));
25
+
26
+ expect(routes).toEqual([
27
+ {
28
+ route: "/m1",
29
+ token: "M1Ctrl1"
30
+ },
31
+ {
32
+ route: "/mod2",
33
+ token: "M2Ctrl"
34
+ },
35
+ {
36
+ route: "/rest",
37
+ token: "TestCtrl"
38
+ }
39
+ ]);
40
+ });
41
+ });
@@ -0,0 +1,57 @@
1
+ import {isArray, isClass, isString} from "@tsed/core";
2
+ import {GlobalProviders, ProviderType} from "@tsed/di";
3
+
4
+ import {importFiles} from "./importFiles.js";
5
+
6
+ const lookup = ["imports", "componentsScan", "mount"];
7
+
8
+ async function resolveRecursively(items: any[], exclude: string[], rootDir: string) {
9
+ for (const index in items) {
10
+ if (isString(items[index])) {
11
+ items[index] = await importFiles(items[index].replace("${rootDir}", rootDir), exclude);
12
+ }
13
+ }
14
+
15
+ const providers = items.flat().filter(isClass);
16
+
17
+ for (const token of providers) {
18
+ const provider = GlobalProviders.get(token);
19
+
20
+ if (provider?.type === ProviderType.MODULE && provider.configuration) {
21
+ provider.configuration.exclude = exclude;
22
+ provider.configuration.rootDir = provider.configuration.rootDir || rootDir;
23
+
24
+ provider.configuration = await importProviders(provider.configuration);
25
+ }
26
+ }
27
+
28
+ return providers;
29
+ }
30
+
31
+ /**
32
+ * Lookup settings and replace glob pattern by the resolved providers
33
+ *
34
+ * @param settings
35
+ */
36
+ export async function importProviders(settings: Record<string, any>): Promise<Partial<TsED.Configuration>> {
37
+ const {exclude = [], rootDir} = settings;
38
+
39
+ for (const property of lookup) {
40
+ if (settings[property]) {
41
+ if (!isArray(settings[property])) {
42
+ const current = settings[property];
43
+ const promises = Object.entries(current).map(async ([key, items]: [string, any]) => {
44
+ current[key] = await resolveRecursively([].concat(items), exclude, rootDir);
45
+ });
46
+
47
+ await Promise.all(promises);
48
+ } else {
49
+ settings[property] = await resolveRecursively(settings[property], exclude, rootDir);
50
+ }
51
+ }
52
+ }
53
+
54
+ settings.disableComponentsScan = true;
55
+
56
+ return settings;
57
+ }
package/src/index.ts ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @file Automatically generated by @tsed/barrels.
3
+ */
4
+ export * from "./cleanGlobPatterns.js";
5
+ export * from "./importFiles.js";
6
+ export * from "./importProviders.js";
7
+ export * from "./isTsEnv.js";
package/src/isTsEnv.ts ADDED
@@ -0,0 +1,9 @@
1
+ export function isTsEnv() {
2
+ return (
3
+ process.env["TS_NODE_DEV"] ||
4
+ process.env["_"]?.includes("ts-node") ||
5
+ process.env["TS_TEST"] ||
6
+ process.env.JEST_WORKER_ID !== undefined ||
7
+ process.env.NODE_ENV === "test"
8
+ );
9
+ }