@truelab/trueserver 0.1.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.2.0] - 2026-07-06
10
+
11
+ ### Breaking
12
+
13
+ - Удалена опция `new Application({ envPath })` и тип `TApplicationOptions`. Приоритетный env-файл теперь задаётся CLI-флагом `--env` при запуске процесса (см. Added). В проде `envPath` использовала только battle-rage, уже переведённая на штатный вариант, поэтому удаление безопасно. Рекомендуется minor-релиз **0.2.0**. См. [MIGRATION](MIGRATION.md#migration-014--020).
14
+
15
+ ### Added
16
+
17
+ - CLI-флаг `--env <path>` | `--env=<path>` (аргумент приложения, парсится из `process.argv`) — загружает указанный `.env` **с приоритетом** (`override: true`) поверх `./.env` из cwd и уже присутствующих `process.env`. Флаг обрабатывается на верхнем уровне `env.helper` (при импорте), т.е. **до** вычисления `loggerOptions` в `logger.helper`, поэтому влияет и на `LOG_LEVEL` (раньше `envPath` применялся позже и `LOG_LEVEL` терялся). Относительный путь резолвится от cwd процесса; несуществующий файл → `console.warn` без падения. Разбор аргумента — через `minimist`.
18
+
9
19
  ## [0.1.4] - 2026-07-06
10
20
 
11
21
  ### Changed
package/MIGRATION.md CHANGED
@@ -1,12 +1,54 @@
1
1
  # Migration
2
2
 
3
- - [0.0.7 → 0.1.0](#migration-007--010) (последнее)
3
+ - [0.1.4 → 0.2.0](#migration-014--020) (последнее)
4
+ - [0.0.7 → 0.1.0](#migration-007--010)
4
5
  - [0.0.6 → 0.0.7](#migration-006--007)
5
6
  - [0.0.5 → 0.0.6](#migration-005--006)
6
7
  - [0.0.4 → 0.0.5](#migration-004--005)
7
8
 
8
9
  ---
9
10
 
11
+ ## Migration: 0.1.4 → 0.2.0
12
+
13
+ Единственное ломающее изменение — удалена опция `new Application({ envPath })` (вместе с типом `TApplicationOptions`). Приоритетный env-файл теперь задаётся CLI-флагом `--env` при запуске процесса.
14
+
15
+ > **TL;DR:**
16
+ > - Использовали `new Application({ envPath })` — уберите опцию: `new Application()`.
17
+ > - Конкретный env-файл теперь передавайте флагом `--env <path>` в команде запуска. Он не зависит от cwd и применяется **до** создания логгера, поэтому влияет и на `LOG_LEVEL`.
18
+ > - Ничего не передавали в `Application()` — менять нечего.
19
+
20
+ ### 1. `new Application({ envPath })` → `new Application()`
21
+
22
+ ```diff
23
+ -const app = new Application({ envPath: './server/.env' })
24
+ +const app = new Application()
25
+ ```
26
+
27
+ Передачу конкретного env-файла перенесите в команду запуска процесса:
28
+
29
+ ```sh
30
+ pm2 start ./server/dist/index.js --name <proc> --cwd ${FOLDER_PATH} -- --env ./server/.env
31
+ ```
32
+
33
+ Флаг `--env`:
34
+ - поддерживает формы `--env <path>` и `--env=<path>`;
35
+ - применяет файл с `override: true` — он перекрывает и `./.env` из cwd, и уже выставленные `process.env`;
36
+ - резолвит относительный путь от cwd процесса (абсолютный — как есть);
37
+ - на несуществующий файл пишет `console.warn` и не роняет процесс.
38
+
39
+ ### Почему
40
+
41
+ `envPath` применялся в конструкторе `Application` — уже **после** того, как `logger.helper` на этапе импорта прочитал `LOG_LEVEL`. Поэтому `PORT/HOST/API_KEY` из переданного файла применялись, а `LOG_LEVEL` — нет: сервер, запущенный не из корня воркспейса, молча терял `info`/startup-логи. Флаг `--env` парсится на верхнем уровне `env.helper`, гарантированно раньше чтения `LOG_LEVEL`, поэтому логи и env корректны из любого cwd.
42
+
43
+ ### Чек-лист
44
+
45
+ 1. `npm install @truelab/trueserver@0.2.0`.
46
+ 2. Убрать аргумент из `new Application({ envPath })` → `new Application()`.
47
+ 3. Если нужен конкретный env-файл на деплое — добавить `-- --env <path>` в команду запуска (pm2/systemd/докер-entrypoint).
48
+ 4. Прогнать тесты и проверить, что startup-логи присутствуют.
49
+
50
+ ---
51
+
10
52
  ## Migration: 0.0.7 → 0.1.0
11
53
 
12
54
  Ломающий релиз. Приводит пакет в полное соответствие контракту Game Server API v1.0.0.
package/README.md CHANGED
@@ -181,7 +181,19 @@ import {
181
181
  | `SENTRY_RATE` | `0.01` | Sentry traces sample rate |
182
182
  | `GAME_ID` | `0001` | Sentry `game.id` tag fallback |
183
183
 
184
- The environment helper imports `dotenv/config`, so `.env` is loaded automatically.
184
+ `.env` is loaded automatically from the process working directory (`dotenv.config()` runs at import time).
185
+
186
+ To load a specific `.env` **with priority** — independent of the working directory and early enough to affect `LOG_LEVEL` — pass the `--env` flag as an application argument:
187
+
188
+ ```sh
189
+ node ./dist/index.js --env ./path/to/.env # or --env=./path/to/.env
190
+ ```
191
+
192
+ The file is applied with `override: true` (it wins over the cwd `.env` and any already-set `process.env`), a relative path resolves against the process cwd, and a missing file only logs a `console.warn` without crashing. This is useful when the process starts outside the workspace root, e.g. pm2 with a custom `--cwd`:
193
+
194
+ ```sh
195
+ pm2 start ./server/dist/index.js --name <proc> --cwd ${FOLDER_PATH} -- --env ./server/.env
196
+ ```
185
197
 
186
198
  ## Swagger
187
199
 
@@ -1,11 +1,7 @@
1
1
  import { FastifyTypebox } from './helpers/fastify.helper';
2
- export type TApplicationOptions = {
3
- /** Optional env file to load (overriding the default ./.env), e.g. a per-version file at deploy time */
4
- envPath?: string;
5
- };
6
2
  export default class Application {
7
3
  server: FastifyTypebox;
8
- constructor(options?: TApplicationOptions);
4
+ constructor();
9
5
  build(): Promise<FastifyTypebox>;
10
6
  }
11
7
  //# sourceMappingURL=application.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"application.d.ts","sourceRoot":"","sources":["../application.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAAkB,MAAM,0BAA0B,CAAA;AAGzE,MAAM,MAAM,mBAAmB,GAAG;IAC9B,wGAAwG;IACxG,OAAO,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,MAAM,CAAC,OAAO,OAAO,WAAW;IAC5B,MAAM,EAAE,cAAc,CAAA;gBAEV,OAAO,GAAE,mBAAwB;IAcvC,KAAK,IAAI,OAAO,CAAC,cAAc,CAAC;CAuBzC"}
1
+ {"version":3,"file":"application.d.ts","sourceRoot":"","sources":["../application.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,cAAc,EAAkB,MAAM,0BAA0B,CAAA;AAGzE,MAAM,CAAC,OAAO,OAAO,WAAW;IAC5B,MAAM,EAAE,cAAc,CAAA;;IAchB,KAAK,IAAI,OAAO,CAAC,cAAc,CAAC;CAuBzC"}
@@ -6,12 +6,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const autoload_1 = __importDefault(require("@fastify/autoload"));
7
7
  const fastify_1 = __importDefault(require("fastify"));
8
8
  const path_1 = __importDefault(require("path"));
9
- const env_helper_1 = require("./helpers/env.helper");
10
9
  const fastify_helper_1 = require("./helpers/fastify.helper");
11
10
  const logger_helper_1 = require("./helpers/logger.helper");
12
11
  class Application {
13
- constructor(options = {}) {
14
- (0, env_helper_1.loadEnv)(options.envPath);
12
+ constructor() {
15
13
  this.server = (0, fastify_1.default)({
16
14
  ajv: {
17
15
  customOptions: {
@@ -1 +1 @@
1
- {"version":3,"file":"application.js","sourceRoot":"","sources":["../application.ts"],"names":[],"mappings":";;;;;AAAA,iEAA+C;AAE/C,sDAA6B;AAC7B,gDAAuB;AAEvB,qDAA8C;AAC9C,6DAAyE;AACzE,2DAAuD;AAOvD,MAAqB,WAAW;IAG5B,YAAY,UAA+B,EAAE;QACzC,IAAA,oBAAO,EAAC,OAAO,CAAC,OAAO,CAAC,CAAA;QAExB,IAAI,CAAC,MAAM,GAAG,IAAA,iBAAO,EAAC;YAClB,GAAG,EAAE;gBACD,aAAa,EAAE;oBACX,QAAQ,EAAE,CAAC,YAAY,CAAC;iBAC3B;aACJ;YACD,MAAM,EAAE,6BAAa;YACrB,qBAAqB,EAAE,IAAI;SAC9B,CAAC,CAAC,gBAAgB,EAAuB,CAAA;IAC9C,CAAC;IAED,KAAK,CAAC,KAAK;QACP,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAe,EAAE;YACxC,GAAG,EAAE,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC;SACvC,CAAC,CAAA;QAEF,MAAM,MAAM,GAAG,IAAA,+BAAc,GAAE,CAAA;QAE/B,wCAAwC;QACxC,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAe,EAAE;YACxC,GAAG,EAAE,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC;YAC1C,OAAO,EAAE,EAAE,MAAM,EAAE;YACnB,kBAAkB,EAAE,KAAK;SAC5B,CAAC,CAAA;QAEF,mEAAmE;QACnE,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAe,EAAE;YACxC,GAAG,EAAE,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC;YACnC,OAAO,EAAE,EAAE,MAAM,EAAE,GAAG,MAAM,cAAc,EAAE;YAC5C,kBAAkB,EAAE,KAAK;SAC5B,CAAC,CAAA;QAEF,OAAO,IAAI,CAAC,MAAM,CAAA;IACtB,CAAC;CACJ;AAxCD,8BAwCC"}
1
+ {"version":3,"file":"application.js","sourceRoot":"","sources":["../application.ts"],"names":[],"mappings":";;;;;AAAA,iEAA+C;AAE/C,sDAA6B;AAC7B,gDAAuB;AAEvB,6DAAyE;AACzE,2DAAuD;AAEvD,MAAqB,WAAW;IAG5B;QACI,IAAI,CAAC,MAAM,GAAG,IAAA,iBAAO,EAAC;YAClB,GAAG,EAAE;gBACD,aAAa,EAAE;oBACX,QAAQ,EAAE,CAAC,YAAY,CAAC;iBAC3B;aACJ;YACD,MAAM,EAAE,6BAAa;YACrB,qBAAqB,EAAE,IAAI;SAC9B,CAAC,CAAC,gBAAgB,EAAuB,CAAA;IAC9C,CAAC;IAED,KAAK,CAAC,KAAK;QACP,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAe,EAAE;YACxC,GAAG,EAAE,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC;SACvC,CAAC,CAAA;QAEF,MAAM,MAAM,GAAG,IAAA,+BAAc,GAAE,CAAA;QAE/B,wCAAwC;QACxC,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAe,EAAE;YACxC,GAAG,EAAE,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC;YAC1C,OAAO,EAAE,EAAE,MAAM,EAAE;YACnB,kBAAkB,EAAE,KAAK;SAC5B,CAAC,CAAA;QAEF,mEAAmE;QACnE,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAe,EAAE;YACxC,GAAG,EAAE,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC;YACnC,OAAO,EAAE,EAAE,MAAM,EAAE,GAAG,MAAM,cAAc,EAAE;YAC5C,kBAAkB,EAAE,KAAK;SAC5B,CAAC,CAAA;QAEF,OAAO,IAAI,CAAC,MAAM,CAAA;IACtB,CAAC;CACJ;AAtCD,8BAsCC"}
@@ -1,5 +1,3 @@
1
- /** Load an additional env file, overriding already-defined vars. */
2
- export declare function loadEnv(path?: string): void;
3
1
  export declare function getenv<T = string>(name: string, def: T): T;
4
2
  /** Вариации значений в зависимости от окружения */
5
3
  export declare function variation<T>(devBranch: T, releaseBranch: T, masterBranch: T): T;
@@ -1 +1 @@
1
- {"version":3,"file":"env.helper.d.ts","sourceRoot":"","sources":["../../helpers/env.helper.ts"],"names":[],"mappings":"AAMA,oEAAoE;AACpE,wBAAgB,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAI3C;AAED,wBAAgB,MAAM,CAAC,CAAC,GAAG,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAY1D;AAED,mDAAmD;AACnD,wBAAgB,SAAS,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,GAAG,CAAC,CAY/E"}
1
+ {"version":3,"file":"env.helper.d.ts","sourceRoot":"","sources":["../../helpers/env.helper.ts"],"names":[],"mappings":"AAsBA,wBAAgB,MAAM,CAAC,CAAC,GAAG,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAY1D;AAED,mDAAmD;AACnD,wBAAgB,SAAS,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,GAAG,CAAC,CAY/E"}
@@ -3,17 +3,24 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.loadEnv = loadEnv;
7
6
  exports.getenv = getenv;
8
7
  exports.variation = variation;
8
+ const node_path_1 = __importDefault(require("node:path"));
9
9
  const dotenv_1 = __importDefault(require("dotenv"));
10
- // Load the default ./.env (relative to the process cwd). A game that needs a specific env file
11
- // can pass it at startup via `new Application({ envPath })`, which calls loadEnv() below.
10
+ const minimist_1 = __importDefault(require("minimist"));
11
+ // 1) Default: load ./.env relative to the process cwd (unchanged behaviour).
12
12
  dotenv_1.default.config();
13
- /** Load an additional env file, overriding already-defined vars. */
14
- function loadEnv(path) {
15
- if (path) {
16
- dotenv_1.default.config({ path, override: true });
13
+ // 2) Priority override via the CLI flag `--env <path>` | `--env=<path>`.
14
+ // Applied HERE, on module import — before logger.helper reads LOG_LEVEL. This is intentionally
15
+ // an app-level flag parsed from process.argv (not Node's `--env-file`), which gives us control
16
+ // over both the timing and `override` across all supported Node versions.
17
+ const cliEnvPath = (0, minimist_1.default)(process.argv.slice(2)).env;
18
+ if (typeof cliEnvPath === 'string' && cliEnvPath) {
19
+ // Relative paths resolve against the process cwd; absolute paths are used as-is.
20
+ const { error } = dotenv_1.default.config({ path: node_path_1.default.resolve(cliEnvPath), override: true });
21
+ if (error) {
22
+ // The logger is not created yet — write straight to stderr.
23
+ console.warn(`[trueserver] --env "${cliEnvPath}" not loaded: ${error.message}`);
17
24
  }
18
25
  }
19
26
  function getenv(name, def) {
@@ -1 +1 @@
1
- {"version":3,"file":"env.helper.js","sourceRoot":"","sources":["../../helpers/env.helper.ts"],"names":[],"mappings":";;;;;AAOA,0BAIC;AAED,wBAYC;AAGD,8BAYC;AAxCD,oDAA2B;AAE3B,+FAA+F;AAC/F,0FAA0F;AAC1F,gBAAM,CAAC,MAAM,EAAE,CAAA;AAEf,oEAAoE;AACpE,SAAgB,OAAO,CAAC,IAAa;IACjC,IAAI,IAAI,EAAE,CAAC;QACP,gBAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;IAC3C,CAAC;AACL,CAAC;AAED,SAAgB,MAAM,CAAa,IAAY,EAAE,GAAM;IACnD,IAAI,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QACtB,MAAM,KAAK,GAAY,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QAExC,QAAQ,KAAK,EAAE,CAAC;YACZ,KAAK,MAAM,CAAC,CAAC,OAAO,IAAoB,CAAA;YACxC,KAAK,OAAO,CAAC,CAAC,OAAO,KAAqB,CAAA;YAC1C,OAAO,CAAC,CAAC,OAAO,KAAU,CAAA;QAC9B,CAAC;IACL,CAAC;IAED,OAAO,GAAG,CAAA;AACd,CAAC;AAED,mDAAmD;AACnD,SAAgB,SAAS,CAAI,SAAY,EAAE,aAAgB,EAAE,YAAe;IACxE,MAAM,UAAU,GAAyB;QACrC,GAAG,EAAE,SAAS;QACd,OAAO,EAAE,aAAa;QACtB,MAAM,EAAE,YAAY;KACvB,CAAA;IAED,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,UAAU,EAAE,CAAC;QAC3D,OAAO,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IAC1C,CAAC;IAED,OAAO,YAAY,CAAA;AACvB,CAAC"}
1
+ {"version":3,"file":"env.helper.js","sourceRoot":"","sources":["../../helpers/env.helper.ts"],"names":[],"mappings":";;;;;AAsBA,wBAYC;AAGD,8BAYC;AAjDD,0DAA4B;AAE5B,oDAA2B;AAC3B,wDAA+B;AAE/B,6EAA6E;AAC7E,gBAAM,CAAC,MAAM,EAAE,CAAA;AAEf,yEAAyE;AACzE,kGAAkG;AAClG,kGAAkG;AAClG,6EAA6E;AAC7E,MAAM,UAAU,GAAY,IAAA,kBAAQ,EAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;AAC/D,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,EAAE,CAAC;IAC/C,iFAAiF;IACjF,MAAM,EAAE,KAAK,EAAE,GAAG,gBAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,mBAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;IACnF,IAAI,KAAK,EAAE,CAAC;QACR,4DAA4D;QAC5D,OAAO,CAAC,IAAI,CAAC,uBAAuB,UAAU,iBAAiB,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;IACnF,CAAC;AACL,CAAC;AAED,SAAgB,MAAM,CAAa,IAAY,EAAE,GAAM;IACnD,IAAI,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QACtB,MAAM,KAAK,GAAY,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QAExC,QAAQ,KAAK,EAAE,CAAC;YACZ,KAAK,MAAM,CAAC,CAAC,OAAO,IAAoB,CAAA;YACxC,KAAK,OAAO,CAAC,CAAC,OAAO,KAAqB,CAAA;YAC1C,OAAO,CAAC,CAAC,OAAO,KAAU,CAAA;QAC9B,CAAC;IACL,CAAC;IAED,OAAO,GAAG,CAAA;AACd,CAAC;AAED,mDAAmD;AACnD,SAAgB,SAAS,CAAI,SAAY,EAAE,aAAgB,EAAE,YAAe;IACxE,MAAM,UAAU,GAAyB;QACrC,GAAG,EAAE,SAAS;QACd,OAAO,EAAE,aAAa;QACtB,MAAM,EAAE,YAAY;KACvB,CAAA;IAED,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,UAAU,EAAE,CAAC;QAC3D,OAAO,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IAC1C,CAAC;IAED,OAAO,YAAY,CAAA;AACvB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truelab/trueserver",
3
- "version": "0.1.4",
3
+ "version": "0.2.0",
4
4
  "description": "TrueLab Fastify server package: routes, schemas, and plugins for TrueLab game backends",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -74,11 +74,13 @@
74
74
  "dotenv": "^16.6.1",
75
75
  "fastify": "^4.29.1",
76
76
  "fastify-plugin": "^4.5.1",
77
+ "minimist": "^1.2.8",
77
78
  "pino": "^8.21.0",
78
79
  "pino-pretty": "^10.3.1"
79
80
  },
80
81
  "devDependencies": {
81
82
  "@types/big.js": "^6.2.2",
83
+ "@types/minimist": "^1.2.5",
82
84
  "@types/node": "^16.18.126",
83
85
  "typescript": "^5.9.3",
84
86
  "vitest": "^4.1.9"