Skip to content
This repository has been archived by the owner on Jul 16, 2024. It is now read-only.

Add proposal for upper case mapping #202

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@
"@vitejs/plugin-react": "^3.0.1",
"@vitest/coverage-c8": "^0.27.2",
"babel-plugin-annotate-pure-calls": "^0.4.0",
"camel-case": "^4.1.2",
"concurrently": "^7.6.0",
"constant-case": "^3.0.4",
"cpx": "^1.5.0",
"docs-ts": "0.6.10",
"eslint": "^8.32.0",
Expand Down
45 changes: 45 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions src/Config/Provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ export declare namespace ConfigProvider {
export interface FromEnvConfig {
readonly pathDelim: string
readonly seqDelim: string
readonly conversion: (k: string) => string
readonly reverseConversion: (k: string) => string
}
}

Expand Down
16 changes: 13 additions & 3 deletions src/internal/configProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,19 @@ export const fromFlat = (flat: ConfigProvider.ConfigProvider.Flat): ConfigProvid
export const fromEnv = (
config: Partial<ConfigProvider.ConfigProvider.FromEnvConfig> = {}
): ConfigProvider.ConfigProvider => {
const { pathDelim, seqDelim } = Object.assign({}, { pathDelim: "_", seqDelim: "," }, config)
const makePathString = (path: Chunk.Chunk<string>): string => pipe(path, Chunk.join(pathDelim))
const unmakePathString = (pathString: string): ReadonlyArray<string> => pathString.split(pathDelim)
const { conversion, pathDelim, reverseConversion, seqDelim } = Object.assign(
{},
{
pathDelim: "_",
seqDelim: ",",
conversion: (k) => k,
reverseConversion: (k) => k
} as ConfigProvider.ConfigProvider.FromEnvConfig,
config
)
const makePathString = (path: Chunk.Chunk<string>): string => pipe(path, Chunk.map(conversion), Chunk.join(pathDelim))
const unmakePathString = (pathString: string): ReadonlyArray<string> =>
pathString.split(pathDelim).map(reverseConversion)

const getEnv = () =>
typeof process !== "undefined" && "env" in process && typeof process.env === "object" ? process.env : {}
Expand Down
56 changes: 56 additions & 0 deletions test/ConfigProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import * as Chunk from "@fp-ts/data/Chunk"
import { pipe } from "@fp-ts/data/Function"
import * as HashMap from "@fp-ts/data/HashMap"
import * as HashSet from "@fp-ts/data/HashSet"
import { camelCase } from "camel-case"
import { constantCase } from "constant-case"
import { assert, describe } from "vitest"

interface HostPort {
Expand Down Expand Up @@ -323,3 +325,57 @@ describe.concurrent("ConfigProvider", () => {
assert.strictEqual(result, "value1")
}))
})

const makeEnvProvider = () =>
ConfigProvider.fromEnv({ pathDelim: "__", conversion: constantCase, reverseConversion: camelCase, seqDelim: "," })

describe.concurrent("EnvProvider", () => {
it.effect("capitalisation", () => {
return Effect.gen(function*($) {
// current in comments
process.env["HOST" /* "host" */] = "localhost"
process.env["PORT" /* "port" */] = "8080"
const provider = makeEnvProvider()
const result = yield* $(provider.load(hostPortConfig))
assert.deepStrictEqual(result, {
host: "localhost",
port: 8080
})
})
})

it.effect("capitalisation, word separation should use _, and nesting __", () => {
return Effect.gen(function*($) {
// current in comments
process.env["HOST_PORT__HOST" /* "hostPort_host" */] = "localhost"
process.env["HOST_PORT__PORT" /* "hostPort_port" */] = "8080"
process.env["TIMEOUT" /* "timeout" */] = "1000"
const provider = makeEnvProvider()
const result = yield* $(provider.load(serviceConfigConfig))
assert.deepStrictEqual(result, {
hostPort: {
host: "localhost",
port: 8080
},
timeout: 1000
})
})
})

it.effect("default", () => {
return Effect.gen(function*($) {
process.env["hostPort_host"] = "localhost"
process.env["hostPort_port"] = "8080"
process.env["timeout"] = "1000"
const provider = ConfigProvider.fromEnv()
const result = yield* $(provider.load(serviceConfigConfig))
assert.deepStrictEqual(result, {
hostPort: {
host: "localhost",
port: 8080
},
timeout: 1000
})
})
})
})