Chisle
코딩 에이전트 플러그인, 20개 실시간 작업에서 기본 모델 52% 활용, 간결한 페르소나와 출력 압축 제공
Import YAML, TOML, JSON5, INI and .env files into TypeScript with full type inference
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Typed, validated application config for TypeScript.
import config from './app.config.yaml' gives you the config for the current environment: the base file merged with
app.<env>.config.yaml and your local overrides, ${PLACEHOLDERS} filled in from .env files and the real environment, and
the result deep-frozen. The type comes from the file through a TypeScript 7.1 content mapper that runs inside tsc and the
editor, so there is no codegen step, and a wrong key or value in any layer is reported at its line in the config file. Add a
Standard Schema (Zod, Valibot, ArkType, …) or an Effect Schema when you need ranges, URLs, enums or required variables.
Read the documentation at tyfigo.vercel.app.
tyfigo needs TypeScript 7.1, the first release with content mappers, and Node 24 or later (or Bun).
npm i tyfigo
npm i -D [email protected]
// tsconfig.json
{
"compilerOptions": {
"module": "nodenext",
"strict": true,
"noEmit": true,
"allowImportingTsExtensions": true,
"skipLibCheck": true,
"types": ["node"],
},
"contentMappers": [
{
"package": "tyfigo",
"extensions": [
".config.yaml",
".config.yml",
".config.toml",
".config.jsonc",
".config.json5",
".config.ini",
".config.properties",
".config.xml",
],
},
],
"include": ["src", "config"],
}
tsc runs content mappers only with --runExternalCode:
{
"scripts": {
"typecheck": "tsc --noEmit --runExternalCode"
}
}
Including config makes tsc check environment and local files even when no code imports them directly. TypeScript 7 defaults types to [], so list node (or bun) yourself. skipLibCheck keeps tsc from checking the bundler types that the plugin declarations reference, which you only have installed for the bundler you use.
# config/app.config.yaml
server:
host: localhost
port: ${PORT:-3000}
database:
url: ${DATABASE_URL}
pool:
max: 5
features: [search]
# config/app.production.config.yaml
server:
port: 8080
hostname: 0.0.0.0
database:
pool:
max: twenty
features: [search, 42]
// src/main.ts
import config from '../config/app.config.yaml';
const port: string = config.server.port;
The type of config comes from the base file, widened so other environments can change values:
// const config: {
// readonly server: { readonly host: string; readonly port: number };
// readonly database: { readonly url: string; readonly pool: { readonly max: number } };
// readonly features: readonly string[];
// }
and tsc --noEmit --runExternalCode reports each mistake at its line in the YAML or the code:
config/app.production.config.yaml(3,5): error TS2353: Object literal may only specify known properties, and 'hostname' does not exist in type '{ readonly host?: string | undefined; readonly port?: number | undefined; }'.
config/app.production.config.yaml(6,9): error TS2322: Type 'string' is not assignable to type 'number'.
config/app.production.config.yaml(7,20): error TS2322: Type 'number' is not assignable to type 'string'.
src/main.ts(3,7): error TS2322: Type 'number' is not assignable to type 'string'.
Without a schema, the types are strict and widened: an environment file can't add a key (so there are no optional sections),
logLevel: info is string rather than 'info' | 'debug', a placeholder without a default is string, and a loadConfig
mismatch is reported at the call rather than on the YAML line. A schema handles each of these; see
What tsc checks without a schema.
database.url has no default, so set DATABASE_URL (in .env or the environment) before you run the example. Without it, the import fails
with Environment variable 'DATABASE_URL' is not set (missing-variable).
Layers are read in this order, each one winning over the last: app.config.yaml, app.<env>.config.yaml,
app.local.config.yaml, app.<env>.local.config.yaml. The environment is NODE_ENV unless you pass environment.
Placeholders (${VAR}, ${VAR:-default}, ${VAR:?message}) read .env, .env.local, .env.<env> and .env.<env>.local,
with real environment variables on top. tyfigo never writes process.env.
loadConfig validates a config import and loadEnv validates environment variables, with any Standard Schema or an Effect
Schema. Errors list every issue with the file:line:column the value came from.
import { loadConfig, loadEnv } from 'tyfigo';
import { z } from 'zod';
import config from '../config/app.config.yaml';
const Config = z.object({
server: z.object({ host: z.string(), port: z.number().int().positive() }),
database: z.object({ url: z.url({ protocol: /^postgres$/ }) }),
});
const settings = loadConfig(config, Config);
const env = loadEnv(z.object({ NODE_ENV: z.enum(['development', 'production', 'test']).default('development') }));
loadConfigAsync and loadEnvAsync take async schemas.
tyfigo/effect has the same loaders returning Effects that fail with a typed ConfigError, plus ConfigService, layers and a
ConfigProvider that reads a config file. See Effect.
여기까지가 README 앞부분입니다. 나머지는 원문에서 읽을 수 있습니다. README 전문 보기 ↗