[Typescript] Configuration
最近開始使用 Typescript 跟 Nodejs 在新公司的新專案上面,碰上的問題之一就是,該怎麼寫設定檔。
寫設定檔不外乎幾種方式
- .env
key=value
- JSON
{ "env": "test", "database": { "host": "db.example.com" } }
- YAML
env: test # comment database: host: "db.example.com"
- HOCON
env: test database: host: "..." database.port: 5678
前兩者的缺點很明顯,從 Scala typesafe config (使用 HOCON) 的轉過來我,自然無法接受前三種格式。
.env 的缺點是只支援 key=value 的格式,所有東西都是平的,沒有階層的觀念,也不支援矩陣 a,b,c
等複雜一點的資料型態。
json 的缺點是,雖然支源了複雜一點的資料型態,但是不能寫註解,跟本不能用啊,專案多人共同進行,怎麼知道為什麼某個欄位在不同的環境為什麼要用不同的值。
yaml 跟 HOCON 沒有上述的缺點,甚至還可以寫 schema 檔,來做格式驗證,但是不知道為什麼在 nodejs 這邊不怎麼流行。
後來想一想,在 Typescript 這邊,似乎不用什麼複雜的方案,直接用 Ts 的內建功能就夠了
/*
* This approach supports:
* - complex types
* - schema validation through type checking.
* - comments
* - dynamic reloading !!
*/
export type Config = {
env: "dev" | "stg" | "prod" | "test",
db: DBConfig
}
export type DBConfig = {
host: string,
username: string,
password: string,
database: string
}
export const devConfig: Config = {
env: "dev",
db: {
host: process.env.DB_HOST || "localhost",
username: process.env.DB_USERNAME || "user",
password: process.env.DB_PASSWORD || "p@ssword",
database: process.env.DB_DATABASE || "db"
}
}
export function getConfig(env: string = process.env.NODE_ENV || "test"): Config {
switch (env) {
case 'test':
return devConfig;
case 'dev':
return devConfig;
case 'stg':
return stagingConfig;
case 'prod':
return prodConfig;
default:
throw new Error(`unsupported environment ${env}`)
}
}
這個方式可以直接寫程式控制設定檔,而且還支援動態載入,修改設定檔,可以透過 nodemon ,不用手動重開 node ,可以自動重新載入新的設定檔,提高工程師的生產力。