@izumisy-tailor/omakase-modules 0.6.0 → 0.6.1
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 +1 -1
- package/src/config/sdk/paths.test.ts +111 -0
- package/src/config/sdk/paths.ts +50 -5
package/package.json
CHANGED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { pathToFileURL } from "node:url";
|
|
4
|
+
import { resolveBasePath } from "./paths";
|
|
5
|
+
|
|
6
|
+
// =============================================================================
|
|
7
|
+
// resolveBasePath Tests
|
|
8
|
+
// =============================================================================
|
|
9
|
+
|
|
10
|
+
describe("resolveBasePath", () => {
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
vi.spyOn(process, "cwd").mockReturnValue("/mocked/cwd");
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
vi.restoreAllMocks();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe("when basePath is undefined", () => {
|
|
20
|
+
it("should return process.cwd()", () => {
|
|
21
|
+
const result = resolveBasePath(undefined);
|
|
22
|
+
expect(result).toBe("/mocked/cwd");
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
describe("when basePath is an empty string", () => {
|
|
27
|
+
it("should return process.cwd()", () => {
|
|
28
|
+
const result = resolveBasePath("");
|
|
29
|
+
expect(result).toBe("/mocked/cwd");
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe("when basePath is a file:// URL (import.meta.url format)", () => {
|
|
34
|
+
it("should convert to directory path on Unix-like systems", () => {
|
|
35
|
+
const fileUrl = "file:///path/to/project/config.ts";
|
|
36
|
+
const result = resolveBasePath(fileUrl);
|
|
37
|
+
expect(result).toBe("/path/to/project");
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("should handle nested directory paths", () => {
|
|
41
|
+
const fileUrl = "file:///Users/developer/projects/my-app/src/config.ts";
|
|
42
|
+
const result = resolveBasePath(fileUrl);
|
|
43
|
+
expect(result).toBe("/Users/developer/projects/my-app/src");
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("should handle pathToFileURL output", () => {
|
|
47
|
+
// Simulate what import.meta.url would look like
|
|
48
|
+
const absolutePath = "/some/absolute/path/to/file.ts";
|
|
49
|
+
const fileUrl = pathToFileURL(absolutePath).href;
|
|
50
|
+
const result = resolveBasePath(fileUrl);
|
|
51
|
+
expect(result).toBe("/some/absolute/path/to");
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("should handle file URLs with spaces (encoded)", () => {
|
|
55
|
+
const fileUrl = "file:///path/to/my%20project/config.ts";
|
|
56
|
+
const result = resolveBasePath(fileUrl);
|
|
57
|
+
expect(result).toBe("/path/to/my project");
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe("when basePath is an absolute directory path", () => {
|
|
62
|
+
it("should return the path as-is", () => {
|
|
63
|
+
const absolutePath = "/path/to/project";
|
|
64
|
+
const result = resolveBasePath(absolutePath);
|
|
65
|
+
expect(result).toBe("/path/to/project");
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("should not modify paths with trailing slash", () => {
|
|
69
|
+
const absolutePath = "/path/to/project/";
|
|
70
|
+
const result = resolveBasePath(absolutePath);
|
|
71
|
+
expect(result).toBe("/path/to/project/");
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
describe("when basePath is a relative path", () => {
|
|
76
|
+
it("should return the relative path as-is (caller responsibility to resolve)", () => {
|
|
77
|
+
const relativePath = "./relative/path";
|
|
78
|
+
const result = resolveBasePath(relativePath);
|
|
79
|
+
expect(result).toBe("./relative/path");
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// =============================================================================
|
|
85
|
+
// Integration behavior documentation tests
|
|
86
|
+
// =============================================================================
|
|
87
|
+
|
|
88
|
+
describe("resolveBasePath integration scenarios", () => {
|
|
89
|
+
it("should work with typical import.meta.url usage pattern", () => {
|
|
90
|
+
// This simulates: { basePath: import.meta.url }
|
|
91
|
+
// where import.meta.url is something like "file:///path/to/tailor.config.ts"
|
|
92
|
+
const importMetaUrl = pathToFileURL(
|
|
93
|
+
"/projects/my-app/tailor.config.ts",
|
|
94
|
+
).href;
|
|
95
|
+
const result = resolveBasePath(importMetaUrl);
|
|
96
|
+
|
|
97
|
+
// Should return the directory containing tailor.config.ts
|
|
98
|
+
expect(result).toBe("/projects/my-app");
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it("should allow resolving relative module paths from the resolved base", () => {
|
|
102
|
+
const importMetaUrl = pathToFileURL(
|
|
103
|
+
"/projects/my-app/tailor.config.ts",
|
|
104
|
+
).href;
|
|
105
|
+
const basePath = resolveBasePath(importMetaUrl);
|
|
106
|
+
|
|
107
|
+
// User can then do: path.resolve(basePath, "./modules.ts")
|
|
108
|
+
const modulesPath = path.resolve(basePath, "./modules.ts");
|
|
109
|
+
expect(modulesPath).toBe("/projects/my-app/modules.ts");
|
|
110
|
+
});
|
|
111
|
+
});
|
package/src/config/sdk/paths.ts
CHANGED
|
@@ -1,11 +1,35 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import { pathToFileURL } from "node:url";
|
|
2
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
3
3
|
import type { DefinedModule, DependencyModules } from "../../builder/helpers";
|
|
4
4
|
import type { LoadedModules } from "../module-loader";
|
|
5
5
|
import { loadModuleForDev } from "./dev-context";
|
|
6
6
|
import { generateWrapperFiles } from "./wrapper/generator";
|
|
7
7
|
import { OMAKASE_WRAPPER_DIR } from "./wrapper/base";
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Resolve basePath from various input formats.
|
|
11
|
+
*
|
|
12
|
+
* Accepts:
|
|
13
|
+
* - `import.meta.url` (e.g., "file:///path/to/file.ts") - converted to directory path
|
|
14
|
+
* - Absolute directory path (e.g., "/path/to/dir")
|
|
15
|
+
* - `undefined` - falls back to `process.cwd()`
|
|
16
|
+
*
|
|
17
|
+
* @internal Exported for testing purposes
|
|
18
|
+
*/
|
|
19
|
+
export const resolveBasePath = (basePath: string | undefined): string => {
|
|
20
|
+
if (!basePath) {
|
|
21
|
+
return process.cwd();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Handle file:// URLs (from import.meta.url)
|
|
25
|
+
if (basePath.startsWith("file://")) {
|
|
26
|
+
const filePath = fileURLToPath(basePath);
|
|
27
|
+
return path.dirname(filePath);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return basePath;
|
|
31
|
+
};
|
|
32
|
+
|
|
9
33
|
/**
|
|
10
34
|
* Check if the imported module is a DefinedModule (from defineModule)
|
|
11
35
|
* rather than a LoadedModules (from loadModules)
|
|
@@ -32,9 +56,17 @@ const isDefinedModule = (
|
|
|
32
56
|
*
|
|
33
57
|
* @example
|
|
34
58
|
* ```typescript
|
|
35
|
-
* // With
|
|
59
|
+
* // With import.meta.url (recommended)
|
|
36
60
|
* const moduleReference = await getModules("./modules.ts", {
|
|
37
|
-
*
|
|
61
|
+
* basePath: import.meta.url,
|
|
62
|
+
* });
|
|
63
|
+
* ```
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* // With explicit directory path
|
|
68
|
+
* const moduleReference = await getModules("./modules.ts", {
|
|
69
|
+
* basePath: "/path/to/project",
|
|
38
70
|
* });
|
|
39
71
|
* ```
|
|
40
72
|
*/
|
|
@@ -42,7 +74,19 @@ export type GetModulesOptions = {
|
|
|
42
74
|
/**
|
|
43
75
|
* Base path for resolving relative modulesPath and generating wrapper files.
|
|
44
76
|
*
|
|
45
|
-
*
|
|
77
|
+
* Accepts:
|
|
78
|
+
* - `import.meta.url` - Automatically converted to the directory containing the caller file (recommended)
|
|
79
|
+
* - An absolute directory path
|
|
80
|
+
* - `undefined` - Falls back to `process.cwd()`
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```typescript
|
|
84
|
+
* // Using import.meta.url (recommended)
|
|
85
|
+
* await getModules("./modules.ts", { basePath: import.meta.url });
|
|
86
|
+
*
|
|
87
|
+
* // Using explicit path
|
|
88
|
+
* await getModules("./modules.ts", { basePath: "/path/to/project" });
|
|
89
|
+
* ```
|
|
46
90
|
*
|
|
47
91
|
* @default process.cwd()
|
|
48
92
|
*/
|
|
@@ -130,7 +174,8 @@ export const getModules = async (
|
|
|
130
174
|
modulesPath: string,
|
|
131
175
|
options: GetModulesOptions = {},
|
|
132
176
|
) => {
|
|
133
|
-
const { basePath
|
|
177
|
+
const { basePath: rawBasePath, log = false } = options;
|
|
178
|
+
const basePath = resolveBasePath(rawBasePath);
|
|
134
179
|
|
|
135
180
|
// Resolve modules path to absolute path
|
|
136
181
|
const absoluteModulesPath = path.isAbsolute(modulesPath)
|