diff --git a/packages/compiler/src/core/source-file.ts b/packages/compiler/src/core/source-file.ts index 756964c278d..6c7b55195f4 100644 --- a/packages/compiler/src/core/source-file.ts +++ b/packages/compiler/src/core/source-file.ts @@ -40,7 +40,7 @@ export function createSourceFile(text: string, path: string): SourceFile { export function getSourceFileKindFromExt(path: string): SourceFileKind | undefined { const ext = getAnyExtensionFromPath(path); - if (ext === ".js" || ext === ".mjs") { + if (ext === ".js" || ext === ".mjs" || ext === ".ts") { return "js"; } else if (ext === ".tsp") { return "typespec"; diff --git a/packages/compiler/test/checker/imports.test.ts b/packages/compiler/test/checker/imports.test.ts index e01a47705de..48fa9e33703 100644 --- a/packages/compiler/test/checker/imports.test.ts +++ b/packages/compiler/test/checker/imports.test.ts @@ -68,6 +68,29 @@ describe("compiler: imports", () => { expectFileLoaded(program, { typespec: ["proj/main.tsp"], js: ["blue.js"] }); }); + it("import relative TS file", async () => { + const { program } = await Tester.files({ + "blue.ts": mockFile.js({ $blue() {} }), + }).compile(` + import "./blue.ts"; + @blue + model A {} + `); + expectFileLoaded(program, { typespec: ["main.tsp"], js: ["blue.ts"] }); + }); + + it("import relative TS file in parent folder", async () => { + const { program } = await Tester.files({ + "blue.ts": mockFile.js({ $blue() {} }), + "proj/main.tsp": ` + import "../blue.ts"; + @blue + model A {} + `, + }).compile(`import "./proj/main.tsp";`); + expectFileLoaded(program, { typespec: ["proj/main.tsp"], js: ["blue.ts"] }); + }); + it("import directory with main.tsp", async () => { const { program } = await Tester.files({ "test/main.tsp": `model C { }`, diff --git a/packages/compiler/test/e2e/scenarios/import-relative-ts/decorators.ts b/packages/compiler/test/e2e/scenarios/import-relative-ts/decorators.ts new file mode 100644 index 00000000000..b5d5208dc20 --- /dev/null +++ b/packages/compiler/test/e2e/scenarios/import-relative-ts/decorators.ts @@ -0,0 +1,4 @@ +export function $blue(context: unknown, target: unknown): void { + void context; + void target; +} diff --git a/packages/compiler/test/e2e/scenarios/import-relative-ts/main.tsp b/packages/compiler/test/e2e/scenarios/import-relative-ts/main.tsp new file mode 100644 index 00000000000..507a5b7c601 --- /dev/null +++ b/packages/compiler/test/e2e/scenarios/import-relative-ts/main.tsp @@ -0,0 +1,4 @@ +import "./decorators.ts"; + +@blue +model A {} diff --git a/packages/compiler/test/e2e/scenarios/scenarios.e2e.ts b/packages/compiler/test/e2e/scenarios/scenarios.e2e.ts index ff0c2cd32c7..1a1b2783147 100644 --- a/packages/compiler/test/e2e/scenarios/scenarios.e2e.ts +++ b/packages/compiler/test/e2e/scenarios/scenarios.e2e.ts @@ -130,6 +130,11 @@ describe("compiler: entrypoints", () => { expectDiagnosticEmpty(program.diagnostics); }); + it("succeed with relative .ts module import", async () => { + const program = await compileScenario("import-relative-ts"); + expectDiagnosticEmpty(program.diagnostics); + }); + it("succeed if loading different install of the same library at the same version", async () => { const program = await compileScenario("same-library-same-version", { emit: ["@typespec/lib2"], diff --git a/website/src/content/docs/docs/language-basics/imports.md b/website/src/content/docs/docs/language-basics/imports.md index 163b0b0633e..9819bf404da 100644 --- a/website/src/content/docs/docs/language-basics/imports.md +++ b/website/src/content/docs/docs/language-basics/imports.md @@ -7,7 +7,7 @@ llmstxt: true Imports are used to include files or libraries into your TypeSpec program. When compiling a TypeSpec file, you specify the path to your root TypeSpec file, typically named "main.tsp". From this root file, any imported files are added to your program. If a directory is imported, TypeSpec will search for a `main.tsp` file within that directory. -The path specified in the import must either start with `"./"` or `"../"`, or be an absolute path. The path should either point to a directory, or have an extension of either ".tsp" or ".js". The examples below illustrate how to use imports to assemble a TypeSpec program from multiple files: +The path specified in the import must either start with `"./"` or `"../"`, or be an absolute path. The path should either point to a directory, or have an extension of either ".tsp", ".js", or ".ts". The examples below illustrate how to use imports to assemble a TypeSpec program from multiple files: ## Importing a TypeSpec file