Skip to main content
Deno 2 is finally here πŸŽ‰οΈ
Learn more

Tuner

deno.land/x/tuner JSR Score

Tuner - ΠΌΠΎΠ΄ΡƒΠ»ΡŒ для управлСния конфигурациями ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°. Π”Π°Π½Π½Ρ‹Π΅ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ ΠΎΠΏΠΈΡΡ‹Π²Π°ΡŽΡ‚ΡΡ Π² Π²ΠΈΠ΄Π΅Β .tsΒ Ρ„Π°ΠΉΠ»Π° с экспортируСмым ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠΌ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ содСрТит пСрСчислСниС envΒ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… ΠΈ ΠΏΠΎΠ»Π΅ΠΉ ΠΊΠΎΠ½Ρ„ΠΈΠ³Π°. ΠšΠΎΠ½Ρ„ΠΈΠ³ΠΈ ΠΌΠΎΠ³ΡƒΡ‚ ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ ΠΈΠ΅Ρ€Π°Ρ€Ρ…ΠΈΡŽ, Π½Π°ΡΠ»Π΅Π΄ΡƒΡΡΡŒ ΠΎΡ‚ Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΈΡ… ΠΈ ΠΏΠ΅Ρ€Π΅Π·Π°ΠΏΠΈΡΡ‹Π²Π°ΡΡΡŒ Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠΌΠΈ.


ОглавлСниС

ΠŸΡ€ΠΎΡΡ‚Π΅ΠΉΡˆΠΈΠΉ ΠΊΠΎΠ½Ρ„ΠΈΠ³

Минимально ΠΊΠΎΠ½Ρ„ΠΈΠ³ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ описан Ρ‚Π°ΠΊ:

// ./config/myConfig.tuner.ts
import Tuner from 'jsr:@artpani/tuner';

export default Tuner.tune(
  {
    data: {
      field1: 'value1',
      field2: 100,
      field3: true,
      field4: ['минималистично', 'ΡƒΠ΄ΠΎΠ±Π½ΠΎ', 'Π½Π΅ ΠΏΡ€Π°Π²Π΄Π° Π»ΠΈ?'],
    },
  },
);

export default myCfg;
export type MyCFGType = typeof myCfg;

Ѐункция tune Π·Π°Π±ΠΎΡ‚Π»ΠΈΠ²ΠΎ подскаТСт структуру ΠΎΠΆΠΈΠ΄Π°Π΅ΠΌΠΎΠ³ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°

Π—Π°Π³Ρ€ΡƒΠ·ΠΊΠ° ΠΊΠΎΠ½Ρ„ΠΈΠ³Π° ΠΈ использованиС происходит Ρ‚Π°ΠΊ:

// ./main.ts
import Tuner from 'jsr:@artpani/tuner';
import { MyCFGType } from '../config/myConfig.tuner.ts';
const cfg = await Tuner.use.loadConfig<MyCFGType>({
  configDirPath: 'config',
});
console.log(cfg.data.field2); // 100

ΠŸΡ€ΠΈ запускС ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ Π½Π°Π»ΠΈΡ‡ΠΈΠ΅ env ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ CONFIG, Π΅Π΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ - Π½Π°Π·Π²Π°Π½ΠΈΠ΅ Ρ„Π°ΠΉΠ»Π° ΠΊΠΎΠ½Ρ„ΠΈΠ³Π° Π΄ΠΎ .tuner.ts, Π² Π΄Π°Π½Π½ΠΎΠΌ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ это myConfig.

CONFIG=myConfig deno run --allow-all main.ts

ΠšΠΎΠ½Ρ„ΠΈΠ³ с описаниСм env-ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ…

Π’ Tuner имССтся Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ ΠΎΠΏΠΈΡΠ°Ρ‚ΡŒ Ρ‚ΠΈΠΏΡ‹ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… окруТСния ΠΈ повСдСния ΠΏΡ€ΠΈ ΠΈΡ… отсутствии:

  • Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ
  • Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠ΅ процСсса
  • гСнСрация ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ
  • вычислСниС Π½Π° Π»Π΅Ρ‚Ρƒ

НапримСр, Ρ‚Π°ΠΊ:

// ./config/myConfig.tuner.ts
import Tuner from 'jsr:@artpani/tuner';
export default Tuner.tune(
  {
    env: {
      // Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π—Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ
      env1: Tuner.Env.getString.orDefault('defalut value1'),
      env2: Tuner.Env.getNumber.orDefault(100),
      env3: Tuner.Env.getBoolean.orDefault(true),
      // ΠŸΡ€ΠΎΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ отсуствиС ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ(Π±ΡƒΠ΄Π΅Ρ‚ ΠΈΠΌΠ΅Ρ‚ΡŒ Ρ‚ΠΈΠΏ значСния + undefined)
      env4: Tuner.Env.getString.orNothing(),
      env5: Tuner.Env.getNumber.orNothing(),
      env6: Tuner.Env.getBoolean.orNothing(),
      // Π—Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ‚ΡŒ процСсс
      env7: Tuner.Env.getString.orExit(
        'сообщСниС ΠΎΠ± ошибкС, Π½Π΅ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ',
      ),
      env8: Tuner.Env.getNumber.orExit(
        'Π²Ρ‹Π²Π΅Π΄Π΅Ρ‚ Π² консоль ΠΏΠ΅Ρ€Π΅Π΄ Π²Ρ‹Ρ…ΠΎΠ΄ΠΎΠΌ',
      ),
      env9: Tuner.Env.getBoolean.orExit(),
      // Π‘Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅
      env10: Tuner.Env.getString.orThrow(new Error('ошибка')),
      env11: Tuner.Env.getNumber.orThrow(new Error()),
      env12: Tuner.Env.getBoolean.orThrow(new Error()),
      // Π’Ρ‹Ρ‡ΠΈΡΠ»Π΅Π½ΠΈΡ‚ΡŒ Π΄Π°Π½Π½Ρ‹Ρ… ΠΏΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½ΠΎΠΌΡƒ колбэку
      //(ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ асинхронным, Ссли Π΄Π°Π½Π½Ρ‹Π΅ Π½ΡƒΠΆΠ½ΠΎ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ с диска ΠΈΠ»ΠΈ ΡƒΠ΄Π°Π»Π΅Π½Π½ΠΎ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€)
      env13: Tuner.Env.getString.orCompute(() => 'computed value1'),
      env14: Tuner.Env.getNumber.orAsyncCompute(() =>
        new Promise(() => 100)
      ),
    },
    data: {
      field1: 'value1',
      field2: 100,
      field3: true,
      field4: ['минималистично', 'ΡƒΠ΄ΠΎΠ±Π½ΠΎ', 'Π½Π΅ ΠΏΡ€Π°Π²Π΄Π° Π»ΠΈ?'],
    },
  },
);

РазумССтся, ΠΌΠΎΠΆΠ½ΠΎ просто ΡƒΠΊΠ°Π·Π°Ρ‚ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅-ΠΏΡ€ΠΈΠΌΠΈΡ‚ΠΈΠ², Π²Ρ€ΠΎΠ΄Π΅ env1: 100

ОбъСдинСниС ΠΊΠΎΠ½Ρ„ΠΈΠ³ΠΎΠ²

Tuner позволяСт β€œΡΠΎΠ±Ρ€Π°Ρ‚ΡŒβ€ ΠΊΠΎΠ½Ρ„ΠΈΠ³, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΠΈ, Π½ΡƒΠΆΠ½ΠΎ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π²Ρ‹ΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ ΠΈΠ· Π½ΠΈΡ… Ρ†Π΅ΠΏΠΎΡ‡ΠΊΡƒ:

  • Π’Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΠΊΠΎΠ½Ρ„ΠΈΠ³ дополнится всСми полями Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ, ΠΏΡ€ΠΈ этом сохранит свои значСния
  • Π’Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΠΊΠΎΠ½Ρ„ΠΈΠ³ дополнится всСми полями Π΄ΠΎΡ‡Π΅Ρ€Π½Π΅Π³ΠΎ, ΠΏΡ€ΠΈ этом ΡΠΎΠ²ΠΏΠ°Π΄Π°ΡŽΡ‰ΠΈΠ΅ поля Π±ΡƒΠ΄ΡƒΡ‚ пСрСписаны значСниями ΠΈΠ· Π΄ΠΎΡ‡Π΅Ρ€Π½Π΅Π³ΠΎ ΠΊΠΎΠ½Ρ„ΠΈΠ³Π°
  • ЗначСния-Ρ„ΡƒΠΊΠ½Ρ†ΠΈΠΈ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Π΅ для описания env-ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… Ρ‚Π°ΠΊΠΆΠ΅ ΠΏΠΎΠ΄Ρ‡ΠΈΠ½ΡΡŽΡ‚ΡΡ этим ΠΏΡ€Π°Π²ΠΈΠ»Π°ΠΌ

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ наслСдования

ΠŸΡ€ΠΈ этом, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΊΠΎΠ½Ρ„ΠΈΠ³Ρƒ Π’ Π½Π΅ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ А Π² качСствС Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ.

РСализация:

// config/develop.tuner.ts
import Tuner from 'jsr:@artpani/tuner';
import { ACfgType } from './a.tuner.ts';

const developCfg = Tuner.tune({
  parent: Tuner.Load.local.configDir<ACfgType>('a.tuner.ts'),
  data: {
    a: 300,
    b: 301,
  },
});

export default developCfg;
export type DevelopCFGType = typeof developCfg;

// config/base.tuner.ts
import Tuner from 'jsr:@artpani/tuner';

const baseCfg = Tuner.tune({
  data: {
    a: 400,
    b: 401,
    c: 402,
  },
});

export default baseCfg;
export type BaseCFGType = typeof baseCfg;

// config/a.tuner.ts
import Tuner from 'jsr:@artpani/tuner';
import { BaseCFGType } from './base.tuner.ts';

const aCfg = Tuner.tune({
  parent: Tuner.Load.local.configDir<BaseCFGType>('base.tuner.ts'),
  child: Tuner.Load.local.configDir('b.tuner.ts'),
  data: {
    b: 200,
    e: 201,
  },
});

export default aCfg;
export type ACfgType = typeof aCfg;

// config/b.tuner.ts
import Tuner from 'jsr:@artpani/tuner';

const bCfg = Tuner.tune({
  data: {
    a: 100,
    d: 101,
  },
});

export default bCfg;
export type BCfgType = typeof bCfg;

// main.ts
import { DevelopCFGType } from './config/develop.tuner.ts';
import Tuner from 'jsr:@artpani/tuner';

const config = await Tuner.use.loadConfig<DevelopCFGType>({
  configDirPath: './config',
});

console.log(config.data);
// { a: 300, b: 301, c: 402, e: 201, d: 101 }

ΠžΠΏΡ†ΠΈΠΈ ΠΏΡ€ΠΈ Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ΅

ΠŸΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅ loadConfig, ΠΏΠ΅Ρ€Π΅Π΄Π°ΠΉΡ‚Π΅ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ с опциями, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π°ΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ процСсс Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΉ:

  • configDirName: Имя Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΈ, Π³Π΄Π΅ хранятся ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΎΠ½Π½Ρ‹Π΅ Ρ„Π°ΠΉΠ»Ρ‹. По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ config. Π£ΠΊΠ°ΠΆΠΈΡ‚Π΅ это Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, Ссли Ρƒ вас другая структура ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³ΠΎΠ².

  • configDirPath: ΠŸΡƒΡ‚ΡŒ ΠΊ Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΈ, содСрТащСй ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΎΠ½Π½Ρ‹Π΅ Ρ„Π°ΠΉΠ»Ρ‹. По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ это тСкущая рабочая дирСктория (./). Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ эту ΠΎΠΏΡ†ΠΈΡŽ, Ссли ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΎΠ½Π½Ρ‹Π΅ Ρ„Π°ΠΉΠ»Ρ‹ находятся Π² Π΄Ρ€ΡƒΠ³ΠΎΠΌ мСстС.