From cbb19a030de336cb3006e8ac2de12ccfbb33e864 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 8 Feb 2024 00:14:03 +0100 Subject: [PATCH] feat: `.jsonc` config support (#132) --- README.md | 7 ++++--- package.json | 1 + pnpm-lock.yaml | 9 ++++++--- src/loader.ts | 19 +++++++++++++++++-- test/fixture/.base/config.jsonc | 16 ++++++++++++++++ test/fixture/.base/config.ts | 15 --------------- test/index.test.ts | 4 ++-- 7 files changed, 46 insertions(+), 25 deletions(-) create mode 100644 test/fixture/.base/config.jsonc delete mode 100644 test/fixture/.base/config.ts diff --git a/README.md b/README.md index f6ad8e1..504d341 100644 --- a/README.md +++ b/README.md @@ -9,10 +9,11 @@ c12 (pronounced as /siːtwelv/, like c-twelve) is a smart configuration loader. ## Features -- JSON, CJS, Typescript, and ESM config loader with [unjs/jiti](https://github.com/unjs/jiti) -- RC config support with [unjs/rc9](https://github.com/unjs/rc9) -- Multiple sources merged with [unjs/defu](https://github.com/unjs/defu) +- `.json`, `.js`, `.ts`, and `.mjs` config loader with [unjs/jiti](https://github.com/unjs/jiti) +- `.jsonc` config support with [jsonc-parser](https://github.com/microsoft/node-jsonc-parser) +- `.rc` config support with [unjs/rc9](https://github.com/unjs/rc9) - `.env` support with [dotenv](https://www.npmjs.com/package/dotenv) +- Multiple sources merged with [unjs/defu](https://github.com/unjs/defu) - Reads config from the nearest `package.json` file - [Extends configurations](https://github.com/unjs/c12#extending-configuration) from multiple local or git sources - Overwrite with [environment-specific configuration](#environment-specific-configuration) diff --git a/package.json b/package.json index ccdce7f..7cf637c 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "dotenv": "^16.3.2", "giget": "^1.2.1", "jiti": "^1.21.0", + "jsonc-parser": "^3.2.1", "mlly": "^1.5.0", "ohash": "^1.1.3", "pathe": "^1.1.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e9997a5..b869877 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -20,6 +20,9 @@ dependencies: jiti: specifier: ^1.21.0 version: 1.21.0 + jsonc-parser: + specifier: ^3.2.1 + version: 3.2.1 mlly: specifier: ^1.5.0 version: 1.5.0 @@ -2965,8 +2968,8 @@ packages: hasBin: true dev: true - /jsonc-parser@3.2.0: - resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} + /jsonc-parser@3.2.1: + resolution: {integrity: sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==} /jsonfile@6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} @@ -3475,7 +3478,7 @@ packages: /pkg-types@1.0.3: resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==} dependencies: - jsonc-parser: 3.2.0 + jsonc-parser: 3.2.1 mlly: 1.5.0 pathe: 1.1.2 diff --git a/src/loader.ts b/src/loader.ts index 582eb15..5143857 100644 --- a/src/loader.ts +++ b/src/loader.ts @@ -1,5 +1,5 @@ import { existsSync } from "node:fs"; -import { rm } from "node:fs/promises"; +import { readFile, rm } from "node:fs/promises"; import { homedir } from "node:os"; import { resolve, extname, dirname, basename, join } from "pathe"; import createJiti from "jiti"; @@ -47,6 +47,16 @@ export async function loadConfig< interopDefault: true, requireCache: false, esmResolve: true, + extensions: [ + ".js", + ".mjs", + ".cjs", + ".ts", + ".mts", + ".cts", + ".json", + ".jsonc", + ], ...options.jitiOptions, }); @@ -316,7 +326,12 @@ async function resolveConfig< if (!existsSync(res.configFile!)) { return res; } - res.config = options.jiti!(res.configFile!); + if (res.configFile!.endsWith(".jsonc")) { + const { parse } = await import("jsonc-parser"); + res.config = parse(await readFile(res.configFile!, "utf8")); + } else { + res.config = options.jiti!(res.configFile!); + } if (res.config instanceof Function) { res.config = await res.config(); } diff --git a/test/fixture/.base/config.jsonc b/test/fixture/.base/config.jsonc new file mode 100644 index 0000000..6f3b45c --- /dev/null +++ b/test/fixture/.base/config.jsonc @@ -0,0 +1,16 @@ +{ + // jsonc can support comments! + "$meta": { + "name": "base", + "version": "1.0.0", + }, + "baseConfig": true, + "colors": { + "primary": "base_primary", + "text": "base_text", + }, + "array": ["b"], + "$env": { + "test": { "baseEnvConfig": true }, + }, +} diff --git a/test/fixture/.base/config.ts b/test/fixture/.base/config.ts deleted file mode 100644 index 85f0e37..0000000 --- a/test/fixture/.base/config.ts +++ /dev/null @@ -1,15 +0,0 @@ -export default { - $meta: { - name: "base", - version: "1.0.0", - }, - baseConfig: true, - colors: { - primary: "base_primary", - text: "base_text", - }, - array: ["b"], - $env: { - test: { baseEnvConfig: true }, - }, -}; diff --git a/test/index.test.ts b/test/index.test.ts index b7cee46..5805b6a 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -166,7 +166,7 @@ describe("c12", () => { "text": "base_text", }, }, - "configFile": "/fixture/.base/config.ts", + "configFile": "/fixture/.base/config.jsonc", "cwd": "/fixture/.base", "meta": { "name": "base", @@ -276,7 +276,7 @@ describe("c12", () => { expect(Object.keys(configLayer.config!)).toContain("$test"); const baseConfigLay = transformdLayers.find( - (layer) => layer.configFile === "/fixture/.base/config.ts", + (layer) => layer.configFile === "/fixture/.base/config.jsonc", )!; expect(Object.keys(baseConfigLay.config!)).toContain("$env"); });