@alacard-project/config-sdk 1.0.3 → 1.0.5

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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # @alacard/config-sdk
1
+ # @alacard-project/config-sdk
2
2
 
3
3
  **Alacard Config SDK** — это клиентская библиотека для взаимодействия с централизованным микросервисом конфигураций (CCS) через gRPC. SDK обеспечивает строго типизированный доступ к настройкам, поддерживает горячую перезагрузку через Kafka и имеет встроенный fallback на `.env` файлы.
4
4
 
@@ -8,14 +8,12 @@
8
8
  - 🛡️ **Строгая типизация**: Автоматическая генерация TypeScript-интерфейсов из Protocol Buffers (`ts-proto`).
9
9
  - ⚡ **Hot-Reloading**: Мгновенное обновление параметров в памяти приложения при изменении в базе (через Kafka).
10
10
  - 📂 **.env Fallback**: Поддержка локальных `.env.<environment>` файлов для разработки и как резервный вариант.
11
- - 🏗️ **Instance-based**: Поддержка нескольких экземпляров клиента в одном процессе (подготовлено для сложной архитектуры 2026 года).
11
+ - 🏗️ **Instance-based**: Поддержка нескольких экземпляров клиента в одном процессе.
12
12
 
13
13
  ## Установка
14
14
 
15
- Так как пакет является приватным, убедитесь, что ваш `.npmrc` настроен для доступа к соответствующему реестру.
16
-
17
15
  ```bash
18
- npm install @alacard/config-sdk
16
+ npm install @alacard-project/config-sdk
19
17
  ```
20
18
 
21
19
  ## Быстрый старт
@@ -25,83 +23,31 @@ npm install @alacard/config-sdk
25
23
  Инициализируйте клиент при запуске вашего приложения (например, в `main.ts` или `bootstrap.ts`):
26
24
 
27
25
  ```typescript
28
- import { ConfigClient } from '@alacard/config-sdk';
26
+ import { ConfigClient } from '@alacard-project/config-sdk';
29
27
 
30
28
  async function bootstrap() {
31
29
  const config = await ConfigClient.initialize({
32
30
  serviceName: 'auth-service',
33
31
  environment: process.env.NODE_ENV || 'development',
34
- grpcUrl: process.env.GRPC_CONFIG_URL || 'localhost:50055',
35
- internalKey: process.env.INTERNAL_CONFIG_KEY, // Ключ для ConfigGrpcGuard
36
-
37
- // Опционально: Интеграция с Vault (KV + PKI)
38
- vault: {
39
- address: 'https://vault.prod.alacard.local:8200',
40
- roleId: process.env.VAULT_ROLE_ID!,
41
- secretId: process.env.VAULT_SECRET_ID!,
42
- pkiPath: 'pki/issue/config-service', // Путь для динамических сертификатов
43
- },
44
-
45
- // Опционально: Ручная настройка mTLS (если не используется Vault PKI)
46
- /*
47
- tls: {
48
- rootCert: fs.readFileSync('./certs/ca.crt'),
49
- clientCert: fs.readFileSync('./certs/client.crt'),
50
- clientKey: fs.readFileSync('./certs/client.key'),
51
- },
52
- */
53
-
54
- kafkaBrokers: ['localhost:9092'],
55
- useDotenvFallback: true,
32
+ grpcUrl: process.env.GRPC_CONFIG_URL || 'config-microservice:50055',
33
+ kafkaBrokers: ['kafka:9092'],
34
+ useDotenvFallback: true, // Использовать .env если gRPC недоступен
56
35
  });
57
36
 
58
37
  const dbUrl = config.get('DATABASE_URL');
38
+ console.log('Config loaded!');
59
39
  }
60
40
  ```
61
41
 
62
- ## Как это работает (Порядок загрузки)
63
-
64
- 1. **.env Fallback**: SDK пробует прочитать локальный `.env.<env>` файл (если `useDotenvFallback: true`).
65
- 2. **Vault KV**: Если настроен `vault`, SDK логинится через AppRole и забирает секреты из `secret/data/config-service/<serviceName>`.
66
- 3. **Vault PKI (mTLS)**: Если в `vault` указан `pkiPath`, SDK получает динамические сертификаты для защиты gRPC соединения.
67
- 4. **gRPC Config Service**: SDK запрашивает финальный конфиг через зашифрованное соединение с микросервиса конфигураций.
68
- 5. **Kafka Watch**: Запускается подписка на изменения для обновления параметров "на лету".
42
+ ### Использование в NestJS
69
43
 
70
- // Получение настроек
71
- const port = config.getInt('PORT', 3000);
72
- const dbUrl = config.get('DATABASE_URL');
44
+ Рекомендуется создать `ConfigService` обертку или использовать `ConfigModule` (если он реализован в вашем проекте), который внутри вызывает `ConfigClient.initialize`.
73
45
 
74
- console.log(`Сервис запущен на порту ${port}`);
75
- }
76
- ```
77
-
78
- ### Использование в других частях кода
79
-
80
- После инициализации вы можете получить доступ к инстансу в любом месте приложения:
81
-
82
- ```typescript
83
- import { ConfigClient } from '@alacard/config-sdk';
84
-
85
- const config = ConfigClient.getInstance();
86
- const apiKey = config.get('EXTERNAL_API_KEY');
87
- ```
88
-
89
- ## Доступные методы
90
-
91
- - `get(key: string, defaultValue?: string): string` — получить строковое значение.
92
- - `getInt(key: string, defaultValue?: number): number` — получить целое число.
93
- - `getAll(): Record<string, string>` — получить все загруженные настройки.
94
-
95
- ## Команды для разработки
96
-
97
- Если вы вносите правки в сам SDK:
98
-
99
- - `npm run gen:proto` — перегенерировать TypeScript-код из `.proto` файлов.
100
- - `npm run build` — скомпилировать TypeScript в JavaScript для публикации.
101
-
102
- ## Структура конфигурации (gRPC)
46
+ ## Как это работает (Порядок загрузки)
103
47
 
104
- SDK использует `config.proto` для связи. Запросы отправляются методом `GetConfig`, включая `serviceName`, `environment` и `version`.
48
+ 1. **.env Fallback**: SDK пробует прочитать локальный `.env.<env>` файл (если `useDotenvFallback: true`).
49
+ 2. **gRPC Config Service**: SDK запрашивает финальный конфиг через gRPC.
50
+ 3. **Kafka Watch**: Запускается подписка на изменения для обновления параметров "на лету".
105
51
 
106
52
  ---
107
53
  © 2026 Alacard Team
@@ -0,0 +1,27 @@
1
+ // @ts-check
2
+ import eslint from '@eslint/js';
3
+ import tseslint from 'typescript-eslint';
4
+ import globals from 'globals';
5
+
6
+ export default tseslint.config(
7
+ {
8
+ ignores: ['dist/**'],
9
+ },
10
+ eslint.configs.recommended,
11
+ ...tseslint.configs.recommended,
12
+ {
13
+ languageOptions: {
14
+ globals: {
15
+ ...globals.node,
16
+ ...globals.jest,
17
+ },
18
+ },
19
+ rules: {
20
+ '@typescript-eslint/interface-name-prefix': 'off',
21
+ '@typescript-eslint/explicit-function-return-type': 'off',
22
+ '@typescript-eslint/explicit-module-boundary-types': 'off',
23
+ '@typescript-eslint/no-explicit-any': 'off', // Relaxed for SDK flexibility
24
+ '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
25
+ },
26
+ },
27
+ );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alacard-project/config-sdk",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "engines": {
5
5
  "node": ">=24.0.0"
6
6
  },
@@ -8,23 +8,53 @@
8
8
  "description": "Standalone gRPC-based Configuration SDK for Alacard microservices",
9
9
  "main": "dist/index.js",
10
10
  "types": "dist/index.d.ts",
11
+ "exports": {
12
+ ".": "./dist/index.js"
13
+ },
11
14
  "scripts": {
12
15
  "build": "tsc",
13
16
  "gen:proto": "protoc --plugin=./node_modules/.bin/protoc-gen-ts_proto --ts_proto_out=src/proto --proto_path=proto proto/config.proto --ts_proto_opt=outputServices=grpc-js,env=node,useOptionals=messages,exportCommonSymbols=false,esModuleInterop=true",
17
+ "lint": "eslint \"src/**/*.ts\" --fix",
18
+ "test": "jest",
19
+ "test:cov": "jest --coverage",
14
20
  "prepublishOnly": "npm run build"
15
21
  },
16
22
  "dependencies": {
17
23
  "@alacard-project/shared": "^1.0.4",
18
- "@bufbuild/protobuf": "^2.11.0",
19
- "@grpc/grpc-js": "^1.14.3",
20
- "@grpc/proto-loader": "^0.8.0",
24
+ "@bufbuild/protobuf": "^2.2.3",
25
+ "@grpc/grpc-js": "^1.12.5",
26
+ "@grpc/proto-loader": "^0.7.13",
21
27
  "axios": "^1.7.9",
22
- "dotenv": "^16.4.6",
28
+ "dotenv": "^16.4.7",
23
29
  "kafkajs": "^2.2.4"
24
30
  },
25
31
  "devDependencies": {
26
- "@types/node": "^24.10.0",
32
+ "@eslint/js": "^9.18.0",
33
+ "@types/jest": "^29.5.14",
34
+ "@types/node": "^22.10.7",
35
+ "eslint": "^9.18.0",
36
+ "globals": "^15.14.0",
37
+ "jest": "^29.7.0",
38
+ "ts-jest": "^29.2.5",
27
39
  "ts-proto": "^2.6.1",
28
- "typescript": "^5.9.3"
40
+ "typescript": "^5.7.3",
41
+ "typescript-eslint": "^8.20.0"
42
+ },
43
+ "jest": {
44
+ "moduleFileExtensions": [
45
+ "js",
46
+ "json",
47
+ "ts"
48
+ ],
49
+ "rootDir": "src",
50
+ "testRegex": ".*\\.spec\\.ts$",
51
+ "transform": {
52
+ "^.+\\.(t|j)s$": "ts-jest"
53
+ },
54
+ "collectCoverageFrom": [
55
+ "**/*.(t|j)s"
56
+ ],
57
+ "coverageDirectory": "../coverage",
58
+ "testEnvironment": "node"
29
59
  }
30
- }
60
+ }
@@ -0,0 +1,34 @@
1
+ import { ConfigClient } from '../src/config-client';
2
+
3
+ // Mock gRPC and Kafka dependencies
4
+ jest.mock('@grpc/grpc-js', () => ({
5
+ credentials: { createInsecure: jest.fn() },
6
+ ServiceClient: jest.fn(),
7
+ loadPackageDefinition: jest.fn(),
8
+ }));
9
+ jest.mock('@grpc/proto-loader', () => ({
10
+ loadSync: jest.fn(),
11
+ }));
12
+
13
+ describe('ConfigClient', () => {
14
+ let client: ConfigClient;
15
+
16
+ beforeEach(() => {
17
+ // Reset mocks if needed
18
+ jest.clearAllMocks();
19
+ });
20
+
21
+ it('should be defined', () => {
22
+ expect(ConfigClient).toBeDefined();
23
+ });
24
+
25
+ // Add more tests for initialization and fetching
26
+ it('should handle environment variables gracefully if remote fails', async () => {
27
+ // Simulation of fallback
28
+ process.env.TEST_VAR = 'fallback_value';
29
+
30
+ // This test would ideally mock the static initialize logic
31
+ // But for now we just verify structural integrity
32
+ expect(process.env.TEST_VAR).toBe('fallback_value');
33
+ });
34
+ });