diff --git a/README.md b/README.md index 969c27d..2a57969 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,8 @@ It will check these files and return config file if found it. - `.your-applicationrc.yml` - `.your-applicationrc.yaml` - `.your-applicationrc.js` +- `.your-applicationrc.cjs` +- `.your-applicationrc.ts` - [optional] `package.json` - if `packageJSON` option is enabled diff --git a/package.json b/package.json index a592b1d..dc7b7e7 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,8 @@ "debug": "^4.3.4", "js-yaml": "^4.1.0", "json5": "^2.2.1", - "require-from-string": "^2.0.2" + "require-from-string": "^2.0.2", + "typescript": "^4.8.4" }, "devDependencies": { "@types/mocha": "^9.1.0", @@ -70,7 +71,6 @@ "mocha": "^9.2.2", "prettier": "^2.6.2", "ts-node": "^10.7.0", - "ts-node-test-register": "^10.0.0", - "typescript": "^4.6.3" + "ts-node-test-register": "^10.0.0" } } diff --git a/src/rc-config-loader.ts b/src/rc-config-loader.ts index 9bcfa0f..ddcd3f4 100644 --- a/src/rc-config-loader.ts +++ b/src/rc-config-loader.ts @@ -5,11 +5,13 @@ import path from "path"; import fs from "fs"; import requireFromString from "require-from-string"; import JSON5 from "json5"; +import ts from "typescript"; const debug = require("debug")("rc-config-loader"); const defaultLoaderByExt = { ".cjs": loadJSConfigFile, ".js": loadJSConfigFile, + ".ts": loadTSConfigFile, ".json": loadJSONConfigFile, ".yaml": loadYAMLConfigFile, ".yml": loadYAMLConfigFile @@ -19,7 +21,7 @@ const defaultOptions = { // does look for `package.json` packageJSON: false, // treat default(no ext file) as some extension - defaultExtension: [".json", ".yaml", ".yml", ".js", ".cjs"], + defaultExtension: [".json", ".yaml", ".yml", ".ts", ".js", ".cjs"], cwd: process.cwd() }; @@ -192,6 +194,26 @@ function loadJSConfigFile(filePath: string, suppress: boolean) { } } +function loadTSConfigFile(filePath: string, supperes: boolean) { + debug(`Loading TypeScript config file: ${filePath}`); + + try { + const code = fs.readFileSync(filePath, "utf-8"); + const content = ts.transpile(code, { + module: ts.ModuleKind.Node16, + target: ts.ScriptTarget.ES5 + }); + + return requireFromString(content, filePath).default; + } catch (error: any) { + debug(`Error reading TypeScript file: ${filePath}`); + if (!supperes) { + error.message = `Cannot read config file: ${filePath}\nError: ${error.message}`; + throw error; + } + } +} + function loadJSONConfigFile(filePath: string, suppress: boolean) { debug(`Loading JSON config file: ${filePath}`); diff --git a/test/fixtures/.tsrc.ts b/test/fixtures/.tsrc.ts new file mode 100644 index 0000000..7de299a --- /dev/null +++ b/test/fixtures/.tsrc.ts @@ -0,0 +1,7 @@ +type Config = { + foo: "foo"; +}; + +export default { + foo: "foo" +}; diff --git a/test/rc-config-loader-test.ts b/test/rc-config-loader-test.ts index acd0268..ce57167 100644 --- a/test/rc-config-loader-test.ts +++ b/test/rc-config-loader-test.ts @@ -43,6 +43,16 @@ describe("rc-config-loader", () => { assert.deepStrictEqual(config, { bar: "bar" }); }); + it("should read ts config in current directory", () => { + const results = rcFile("ts", { cwd: path.join(__dirname, "fixtures") }); + + if (!results) { + throw new Error("not found"); + } + const { config } = results; + assert.deepStrictEqual(config, { foo: "foo" }); + }); + it("should read cjs config in current directory", () => { const results = rcFile("baz", { cwd: path.join(__dirname, "fixtures") }); if (!results) {