@kibibit/configit 1.0.0-beta.26 → 1.0.0-beta.27

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.
Files changed (98) hide show
  1. package/README.md +419 -0
  2. package/lib/scripts/test-vault-comprehensive.d.ts +2 -0
  3. package/lib/scripts/test-vault-comprehensive.d.ts.map +1 -0
  4. package/lib/scripts/test-vault-comprehensive.js +422 -0
  5. package/lib/scripts/test-vault-comprehensive.js.map +1 -0
  6. package/lib/scripts/test-vault-dynamic.d.ts +2 -0
  7. package/lib/scripts/test-vault-dynamic.d.ts.map +1 -0
  8. package/lib/scripts/test-vault-dynamic.js +193 -0
  9. package/lib/scripts/test-vault-dynamic.js.map +1 -0
  10. package/lib/scripts/test-vault-gcp-ttl.d.ts +3 -0
  11. package/lib/scripts/test-vault-gcp-ttl.d.ts.map +1 -0
  12. package/lib/scripts/test-vault-gcp-ttl.js +218 -0
  13. package/lib/scripts/test-vault-gcp-ttl.js.map +1 -0
  14. package/lib/scripts/test-vault.d.ts +2 -0
  15. package/lib/scripts/test-vault.d.ts.map +1 -0
  16. package/lib/scripts/test-vault.js +167 -0
  17. package/lib/scripts/test-vault.js.map +1 -0
  18. package/lib/src/config.errors.d.ts.map +1 -0
  19. package/lib/src/config.errors.js.map +1 -0
  20. package/lib/src/config.model.d.ts.map +1 -0
  21. package/lib/src/config.model.js.map +1 -0
  22. package/lib/{config.service.d.ts → src/config.service.d.ts} +10 -1
  23. package/lib/src/config.service.d.ts.map +1 -0
  24. package/lib/{config.service.js → src/config.service.js} +75 -9
  25. package/lib/src/config.service.js.map +1 -0
  26. package/lib/src/environment.service.d.ts.map +1 -0
  27. package/lib/src/environment.service.js.map +1 -0
  28. package/lib/{index.d.ts → src/index.d.ts} +1 -0
  29. package/lib/src/index.d.ts.map +1 -0
  30. package/lib/{index.js → src/index.js} +1 -0
  31. package/lib/src/index.js.map +1 -0
  32. package/lib/src/json-schema.validator.d.ts.map +1 -0
  33. package/lib/src/json-schema.validator.js.map +1 -0
  34. package/lib/src/vault/__tests__/vault-integration.test.d.ts +2 -0
  35. package/lib/src/vault/__tests__/vault-integration.test.d.ts.map +1 -0
  36. package/lib/src/vault/__tests__/vault-integration.test.js +190 -0
  37. package/lib/src/vault/__tests__/vault-integration.test.js.map +1 -0
  38. package/lib/src/vault/decorators.d.ts +17 -0
  39. package/lib/src/vault/decorators.d.ts.map +1 -0
  40. package/lib/src/vault/decorators.js +149 -0
  41. package/lib/src/vault/decorators.js.map +1 -0
  42. package/lib/src/vault/index.d.ts +7 -0
  43. package/lib/src/vault/index.d.ts.map +1 -0
  44. package/lib/src/vault/index.js +42 -0
  45. package/lib/src/vault/index.js.map +1 -0
  46. package/lib/src/vault/secret-refresh-manager.d.ts +23 -0
  47. package/lib/src/vault/secret-refresh-manager.d.ts.map +1 -0
  48. package/lib/src/vault/secret-refresh-manager.js +149 -0
  49. package/lib/src/vault/secret-refresh-manager.js.map +1 -0
  50. package/lib/src/vault/types.d.ts +149 -0
  51. package/lib/src/vault/types.d.ts.map +1 -0
  52. package/lib/src/vault/types.js +4 -0
  53. package/lib/src/vault/types.js.map +1 -0
  54. package/lib/src/vault/vault-cache.d.ts +20 -0
  55. package/lib/src/vault/vault-cache.d.ts.map +1 -0
  56. package/lib/src/vault/vault-cache.js +139 -0
  57. package/lib/src/vault/vault-cache.js.map +1 -0
  58. package/lib/src/vault/vault-integration.d.ts +27 -0
  59. package/lib/src/vault/vault-integration.d.ts.map +1 -0
  60. package/lib/src/vault/vault-integration.js +211 -0
  61. package/lib/src/vault/vault-integration.js.map +1 -0
  62. package/lib/src/vault/vault-provider.d.ts +37 -0
  63. package/lib/src/vault/vault-provider.d.ts.map +1 -0
  64. package/lib/src/vault/vault-provider.js +354 -0
  65. package/lib/src/vault/vault-provider.js.map +1 -0
  66. package/lib/tsconfig.tsbuildinfo +1 -1
  67. package/package.json +5 -65
  68. package/src/config.service.ts +155 -10
  69. package/src/config.service.vault.spec.ts +859 -0
  70. package/src/index.ts +1 -0
  71. package/src/vault/__tests__/vault-integration.test.ts +226 -0
  72. package/src/vault/decorators.ts +228 -0
  73. package/src/vault/index.ts +31 -0
  74. package/src/vault/secret-refresh-manager.ts +241 -0
  75. package/src/vault/types.ts +487 -0
  76. package/src/vault/vault-cache.ts +240 -0
  77. package/src/vault/vault-integration.ts +332 -0
  78. package/src/vault/vault-provider.ts +576 -0
  79. package/lib/config.errors.d.ts.map +0 -1
  80. package/lib/config.errors.js.map +0 -1
  81. package/lib/config.model.d.ts.map +0 -1
  82. package/lib/config.model.js.map +0 -1
  83. package/lib/config.service.d.ts.map +0 -1
  84. package/lib/config.service.js.map +0 -1
  85. package/lib/environment.service.d.ts.map +0 -1
  86. package/lib/environment.service.js.map +0 -1
  87. package/lib/index.d.ts.map +0 -1
  88. package/lib/index.js.map +0 -1
  89. package/lib/json-schema.validator.d.ts.map +0 -1
  90. package/lib/json-schema.validator.js.map +0 -1
  91. /package/lib/{config.errors.d.ts → src/config.errors.d.ts} +0 -0
  92. /package/lib/{config.errors.js → src/config.errors.js} +0 -0
  93. /package/lib/{config.model.d.ts → src/config.model.d.ts} +0 -0
  94. /package/lib/{config.model.js → src/config.model.js} +0 -0
  95. /package/lib/{environment.service.d.ts → src/environment.service.d.ts} +0 -0
  96. /package/lib/{environment.service.js → src/environment.service.js} +0 -0
  97. /package/lib/{json-schema.validator.d.ts → src/json-schema.validator.d.ts} +0 -0
  98. /package/lib/{json-schema.validator.js → src/json-schema.validator.js} +0 -0
package/src/index.ts CHANGED
@@ -3,3 +3,4 @@ export * from './config.errors';
3
3
  export * from './config.model';
4
4
  export * from './json-schema.validator';
5
5
  export * from './environment.service';
6
+ export * from './vault';
@@ -0,0 +1,226 @@
1
+ /**
2
+ * Vault Integration Tests
3
+ * These tests require a local Vault instance and are skipped in CI.
4
+ * To run locally:
5
+ * docker compose -f docker-compose.vault.yml up -d
6
+ * bash scripts/vault-setup.sh
7
+ * VAULT_INTEGRATION_TESTS=true npm test
8
+ */
9
+
10
+ import { IsString } from 'class-validator';
11
+
12
+ import { VaultKey, VaultPath } from '../decorators';
13
+ import { IVaultConfigOptions } from '../types';
14
+ import { VaultIntegration } from '../vault-integration';
15
+
16
+ import 'reflect-metadata';
17
+
18
+ // Skip these tests unless explicitly enabled (requires running Vault)
19
+ const SKIP_VAULT_TESTS = !process.env.VAULT_INTEGRATION_TESTS;
20
+
21
+ /**
22
+ * Test configuration class with Vault secrets
23
+ * Note: VaultPath should use logical paths (without engine-specific prefix)
24
+ * The engine prefix (secret/data/ for kv-v2) is added automatically
25
+ */
26
+ class TestVaultConfig {
27
+ @VaultPath('configit/api')
28
+ @VaultKey('api_key')
29
+ @IsString()
30
+ API_KEY!: string;
31
+
32
+ @VaultPath('configit/api')
33
+ @VaultKey('api_secret')
34
+ @IsString()
35
+ API_SECRET!: string;
36
+
37
+ @VaultPath('configit/database')
38
+ @VaultKey('host')
39
+ @IsString()
40
+ DB_HOST!: string;
41
+
42
+ @VaultPath('configit/database')
43
+ @VaultKey('port')
44
+ @IsString()
45
+ DB_PORT!: string;
46
+
47
+ @VaultPath('configit/database')
48
+ @VaultKey('username')
49
+ @IsString()
50
+ DB_USERNAME!: string;
51
+
52
+ @VaultPath('configit/database')
53
+ @VaultKey('password')
54
+ @IsString()
55
+ DB_PASSWORD!: string;
56
+
57
+ @VaultPath('configit/features')
58
+ @VaultKey('enable_beta')
59
+ @IsString()
60
+ ENABLE_BETA!: string;
61
+
62
+ @VaultPath('configit/features')
63
+ @VaultKey('max_connections')
64
+ @IsString()
65
+ MAX_CONNECTIONS!: string;
66
+ }
67
+
68
+ const VAULT_CONFIG: IVaultConfigOptions = {
69
+ endpoint: 'http://127.0.0.1:8200',
70
+ auth: {
71
+ methods: [
72
+ {
73
+ type: 'token',
74
+ config: {
75
+ token: process.env.VAULT_TOKEN || 'configit-dev-token'
76
+ }
77
+ }
78
+ ]
79
+ },
80
+ tls: {
81
+ enabled: false,
82
+ verifyCertificate: false
83
+ }
84
+ };
85
+
86
+ // Use describe.skip when Vault is not available
87
+ const describeVault = SKIP_VAULT_TESTS ? describe.skip : describe;
88
+
89
+ describeVault('VaultIntegration (requires running Vault)', () => {
90
+ let vaultIntegration: VaultIntegration;
91
+
92
+ afterEach(() => {
93
+ if (vaultIntegration) {
94
+ vaultIntegration.shutdown();
95
+ }
96
+ });
97
+
98
+ describe('when Vault is available', () => {
99
+ beforeEach(() => {
100
+ vaultIntegration = new VaultIntegration(VAULT_CONFIG);
101
+ });
102
+
103
+ it('should initialize successfully', async () => {
104
+ await vaultIntegration.initialize();
105
+ expect(vaultIntegration.isInitialized()).toBe(true);
106
+ });
107
+
108
+ it('should load secrets for a config class', async () => {
109
+ await vaultIntegration.initialize();
110
+ await vaultIntegration.loadSecrets(TestVaultConfig);
111
+
112
+ // Verify secrets are cached
113
+ expect(vaultIntegration.getSecret('API_KEY')).toBe('test-api-key-123');
114
+ expect(vaultIntegration.getSecret('API_SECRET')).toBe('test-api-secret-xyz');
115
+ expect(vaultIntegration.getSecret('DB_HOST')).toBe('localhost');
116
+ expect(vaultIntegration.getSecret('DB_PORT')).toBe('5432');
117
+ expect(vaultIntegration.getSecret('DB_USERNAME')).toBe('testuser');
118
+ expect(vaultIntegration.getSecret('DB_PASSWORD')).toBe('testpassword');
119
+ expect(vaultIntegration.getSecret('ENABLE_BETA')).toBe('true');
120
+ expect(vaultIntegration.getSecret('MAX_CONNECTIONS')).toBe('100');
121
+ });
122
+
123
+ it('should report healthy status after initialization', async () => {
124
+ await vaultIntegration.initialize();
125
+ await vaultIntegration.loadSecrets(TestVaultConfig);
126
+
127
+ const health = vaultIntegration.getHealth();
128
+ expect(health.connected).toBe(true);
129
+ expect(health.authenticated).toBe(true);
130
+ expect(health.cacheSize).toBeGreaterThan(0);
131
+ });
132
+
133
+ it('should invalidate cache entries', async () => {
134
+ await vaultIntegration.initialize();
135
+ await vaultIntegration.loadSecrets(TestVaultConfig);
136
+
137
+ // Verify secret is cached
138
+ expect(vaultIntegration.getSecret('API_KEY')).toBe('test-api-key-123');
139
+
140
+ // Invalidate
141
+ vaultIntegration.invalidateProperty('API_KEY');
142
+
143
+ // Should be null after invalidation
144
+ expect(vaultIntegration.getSecret('API_KEY')).toBeNull();
145
+ });
146
+ });
147
+
148
+ describe('error handling', () => {
149
+ it('should throw error when not initialized', async () => {
150
+ vaultIntegration = new VaultIntegration(VAULT_CONFIG);
151
+
152
+ await expect(vaultIntegration.loadSecrets(TestVaultConfig))
153
+ .rejects
154
+ .toThrow('VaultIntegration not initialized');
155
+ });
156
+
157
+ it('should throw error with invalid token', async () => {
158
+ const invalidConfig: IVaultConfigOptions = {
159
+ ...VAULT_CONFIG,
160
+ auth: {
161
+ methods: [
162
+ {
163
+ type: 'token',
164
+ config: {
165
+ token: 'invalid-token'
166
+ }
167
+ }
168
+ ]
169
+ }
170
+ };
171
+
172
+ vaultIntegration = new VaultIntegration(invalidConfig);
173
+
174
+ await expect(vaultIntegration.initialize())
175
+ .rejects
176
+ .toThrow(/authentication.*failed/i);
177
+ });
178
+ });
179
+ });
180
+
181
+ /**
182
+ * Run this file directly to test Vault integration:
183
+ * npx ts-node src/vault/__tests__/vault-integration.test.ts
184
+ */
185
+ if (require.main === module) {
186
+ (async () => {
187
+ console.log('Testing Vault Integration...\n');
188
+
189
+ const integration = new VaultIntegration(VAULT_CONFIG);
190
+
191
+ try {
192
+ console.log('1. Initializing...');
193
+ await integration.initialize();
194
+ console.log(' ✓ Initialized\n');
195
+
196
+ console.log('2. Loading secrets...');
197
+ await integration.loadSecrets(TestVaultConfig);
198
+ console.log(' ✓ Secrets loaded\n');
199
+
200
+ console.log('3. Reading secrets:');
201
+ console.log(` API_KEY: ${ integration.getSecret('API_KEY') }`);
202
+ console.log(` API_SECRET: ${ integration.getSecret('API_SECRET') }`);
203
+ console.log(` DB_HOST: ${ integration.getSecret('DB_HOST') }`);
204
+ console.log(` DB_PORT: ${ integration.getSecret('DB_PORT') }`);
205
+ console.log(` DB_USERNAME: ${ integration.getSecret('DB_USERNAME') }`);
206
+ console.log(` DB_PASSWORD: ${ integration.getSecret('DB_PASSWORD') }`);
207
+ console.log(` ENABLE_BETA: ${ integration.getSecret('ENABLE_BETA') }`);
208
+ console.log(` MAX_CONNECTIONS: ${ integration.getSecret('MAX_CONNECTIONS') }\n`);
209
+
210
+ console.log('4. Health status:');
211
+ const health = integration.getHealth();
212
+ console.log(` Connected: ${ health.connected }`);
213
+ console.log(` Authenticated: ${ health.authenticated }`);
214
+ console.log(` Cache size: ${ health.cacheSize }`);
215
+ console.log(` Errors: ${ health.errors.length }\n`);
216
+
217
+ console.log('✓ All tests passed!\n');
218
+ } catch (error) {
219
+ console.error('✗ Test failed:', error);
220
+ process.exit(1);
221
+ } finally {
222
+ integration.shutdown();
223
+ }
224
+ })();
225
+ }
226
+
@@ -0,0 +1,228 @@
1
+ /**
2
+ * Vault Decorators
3
+ * Composable decorators for marking configuration properties as Vault secrets
4
+ */
5
+
6
+ import { kebabCase } from 'lodash';
7
+
8
+ import { VaultEngineType, VaultPropertyMetadata } from './types';
9
+
10
+ import 'reflect-metadata';
11
+
12
+ /**
13
+ * Symbols for storing individual decorator metadata
14
+ */
15
+ const VAULT_PATH_SYMBOL = Symbol('configit:vault:path');
16
+ const VAULT_ENGINE_SYMBOL = Symbol('configit:vault:engine');
17
+ const VAULT_KEY_SYMBOL = Symbol('configit:vault:key');
18
+ const VAULT_REFRESH_BUFFER_SYMBOL = Symbol('configit:vault:refreshBuffer');
19
+ const VAULT_OPTIONAL_SYMBOL = Symbol('configit:vault:optional');
20
+ const VAULT_PROPERTIES_SYMBOL = Symbol('configit:vault:properties');
21
+
22
+ /**
23
+ * Register a property as having Vault metadata (for discovery)
24
+ */
25
+ function registerVaultProperty(target: unknown, propertyKey: string): void {
26
+ const constructor = (target as object).constructor;
27
+ const existingProperties: string[] = Reflect.getMetadata(VAULT_PROPERTIES_SYMBOL, constructor) || [];
28
+ if (!existingProperties.includes(propertyKey)) {
29
+ Reflect.defineMetadata(VAULT_PROPERTIES_SYMBOL, [ ...existingProperties, propertyKey ], constructor);
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Get all registered Vault property names for a class
35
+ */
36
+ export function getVaultPropertyNames(target: unknown): string[] {
37
+ const constructor = typeof target === 'function' ? target : (target as object).constructor;
38
+ return Reflect.getMetadata(VAULT_PROPERTIES_SYMBOL, constructor) || [];
39
+ }
40
+
41
+ /**
42
+ * Specifies the Vault path for a property (required for Vault secrets)
43
+ * @param path Full Vault path (e.g., 'secret/data/myapp/db_password' or 'database/creds/my-role')
44
+ */
45
+ export function VaultPath(path: string): PropertyDecorator {
46
+ return function(target: unknown, propertyKey: string | symbol) {
47
+ const key = String(propertyKey);
48
+ Reflect.defineMetadata(VAULT_PATH_SYMBOL, path, target, key);
49
+ // Register this property for discovery
50
+ registerVaultProperty(target, key);
51
+ };
52
+ }
53
+
54
+ /**
55
+ * Specifies the Vault secrets engine type (optional, auto-detected from path)
56
+ * @param engine Engine type
57
+ */
58
+ export function VaultEngine(engine: VaultEngineType): PropertyDecorator {
59
+ return function(target: unknown, propertyKey: string | symbol) {
60
+ const key = String(propertyKey);
61
+ Reflect.defineMetadata(VAULT_ENGINE_SYMBOL, engine, target, key);
62
+ };
63
+ }
64
+
65
+ /**
66
+ * Specifies the key name within the secret (optional, defaults to property name in kebab-case)
67
+ * Only used for KV v1/v2 engines
68
+ * @param key Key name
69
+ */
70
+ export function VaultKey(key: string): PropertyDecorator {
71
+ return function(target: unknown, propertyKey: string | symbol) {
72
+ const keyName = String(propertyKey);
73
+ Reflect.defineMetadata(VAULT_KEY_SYMBOL, key, target, keyName);
74
+ };
75
+ }
76
+
77
+ /**
78
+ * Override default refresh buffer (optional)
79
+ * @param seconds Refresh buffer in seconds (default: 300s or 10% of TTL, whichever is smaller)
80
+ */
81
+ export function VaultRefreshBuffer(seconds: number): PropertyDecorator {
82
+ return function(target: unknown, propertyKey: string | symbol) {
83
+ const key = String(propertyKey);
84
+ Reflect.defineMetadata(VAULT_REFRESH_BUFFER_SYMBOL, seconds, target, key);
85
+ };
86
+ }
87
+
88
+ /**
89
+ * Mark secret as optional - fallback to environment variable if Vault unavailable
90
+ * Without this decorator, Vault secrets are required by default
91
+ */
92
+ export function VaultOptional(): PropertyDecorator {
93
+ return function(target: unknown, propertyKey: string | symbol) {
94
+ const key = String(propertyKey);
95
+ Reflect.defineMetadata(VAULT_OPTIONAL_SYMBOL, true, target, key);
96
+ };
97
+ }
98
+
99
+ /**
100
+ * Get Vault path for a property
101
+ */
102
+ export function getVaultPath(target: any, propertyKey: string): string | undefined {
103
+ return Reflect.getMetadata(VAULT_PATH_SYMBOL, target, propertyKey);
104
+ }
105
+
106
+ /**
107
+ * Get Vault engine for a property
108
+ */
109
+ export function getVaultEngine(target: any, propertyKey: string): VaultEngineType | undefined {
110
+ return Reflect.getMetadata(VAULT_ENGINE_SYMBOL, target, propertyKey);
111
+ }
112
+
113
+ /**
114
+ * Get Vault key for a property
115
+ */
116
+ export function getVaultKey(target: any, propertyKey: string): string | undefined {
117
+ return Reflect.getMetadata(VAULT_KEY_SYMBOL, target, propertyKey);
118
+ }
119
+
120
+ /**
121
+ * Get Vault refresh buffer for a property
122
+ */
123
+ export function getVaultRefreshBuffer(target: any, propertyKey: string): number | undefined {
124
+ return Reflect.getMetadata(VAULT_REFRESH_BUFFER_SYMBOL, target, propertyKey);
125
+ }
126
+
127
+ /**
128
+ * Check if Vault secret is optional for a property
129
+ */
130
+ export function isVaultOptional(target: any, propertyKey: string): boolean {
131
+ return Reflect.getMetadata(VAULT_OPTIONAL_SYMBOL, target, propertyKey) === true;
132
+ }
133
+
134
+ /**
135
+ * Detect engine type from Vault path
136
+ */
137
+ export function detectEngineFromPath(path: string): VaultEngineType {
138
+ // Common path patterns
139
+ if (path.startsWith('secret/data/')) {
140
+ return 'kv-v2';
141
+ }
142
+ if (path.startsWith('secret/') && !path.includes('/data/')) {
143
+ return 'kv-v1';
144
+ }
145
+ if (path.startsWith('database/creds/')) {
146
+ return 'database';
147
+ }
148
+ if (path.startsWith('aws/creds/')) {
149
+ return 'aws';
150
+ }
151
+ if (path.startsWith('azure/creds/')) {
152
+ return 'azure';
153
+ }
154
+ if (path.startsWith('gcp/')) {
155
+ return 'gcp';
156
+ }
157
+ if (path.startsWith('transit/')) {
158
+ return 'transit';
159
+ }
160
+ if (path.startsWith('pki/')) {
161
+ return 'pki';
162
+ }
163
+
164
+ // Default to kv-v2 (most common)
165
+ return 'kv-v2';
166
+ }
167
+
168
+ /**
169
+ * Get property type from metadata (basic implementation)
170
+ */
171
+ function getPropertyType(target: any, propertyKey: string): string {
172
+ // Try to get type from reflect-metadata
173
+ const type = Reflect.getMetadata('design:type', target, propertyKey);
174
+ if (type) {
175
+ return type.name || 'unknown';
176
+ }
177
+ return 'unknown';
178
+ }
179
+
180
+ /**
181
+ * Build complete Vault metadata for a property from individual decorators
182
+ */
183
+ export function buildVaultMetadata(
184
+ target: any,
185
+ propertyKey: string
186
+ ): VaultPropertyMetadata | undefined {
187
+ const path = getVaultPath(target, propertyKey);
188
+ if (!path) {
189
+ return undefined; // Not a Vault property
190
+ }
191
+
192
+ const engine = getVaultEngine(target, propertyKey) || detectEngineFromPath(path);
193
+ const key = getVaultKey(target, propertyKey) || kebabCase(propertyKey);
194
+ const refreshBuffer = getVaultRefreshBuffer(target, propertyKey);
195
+ const optional = isVaultOptional(target, propertyKey);
196
+ const propertyType = getPropertyType(target, propertyKey);
197
+
198
+ return {
199
+ path,
200
+ engine,
201
+ key,
202
+ refreshBuffer,
203
+ required: !optional,
204
+ propertyName: propertyKey,
205
+ propertyType
206
+ };
207
+ }
208
+
209
+ /**
210
+ * Get all Vault metadata for a class
211
+ */
212
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
213
+ export function getAllVaultMetadata(target: any): Record<string, VaultPropertyMetadata> {
214
+ const metadata: Record<string, VaultPropertyMetadata> = {};
215
+
216
+ // Get registered Vault properties
217
+ const propertyKeys = getVaultPropertyNames(target);
218
+ const prototype = target.prototype || target;
219
+
220
+ for (const key of propertyKeys) {
221
+ const vaultMetadata = buildVaultMetadata(prototype, key);
222
+ if (vaultMetadata) {
223
+ metadata[key] = vaultMetadata;
224
+ }
225
+ }
226
+
227
+ return metadata;
228
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Vault Integration Module
3
+ * Exports for HashiCorp Vault integration
4
+ */
5
+
6
+ // Types
7
+ export * from './types';
8
+
9
+ // Decorators
10
+ export {
11
+ VaultPath,
12
+ VaultEngine,
13
+ VaultKey,
14
+ VaultRefreshBuffer,
15
+ VaultOptional,
16
+ getVaultPath,
17
+ getVaultEngine,
18
+ getVaultKey,
19
+ getVaultRefreshBuffer,
20
+ isVaultOptional,
21
+ detectEngineFromPath,
22
+ buildVaultMetadata,
23
+ getAllVaultMetadata,
24
+ getVaultPropertyNames
25
+ } from './decorators';
26
+
27
+ // Components
28
+ export { VaultProvider } from './vault-provider';
29
+ export { VaultCache } from './vault-cache';
30
+ export { SecretRefreshManager } from './secret-refresh-manager';
31
+ export { VaultIntegration } from './vault-integration';