@sylphx/flow 1.8.0 → 1.8.2
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 +72 -0
- package/assets/output-styles/silent.md +145 -8
- package/assets/rules/core.md +19 -2
- package/package.json +2 -12
- package/src/commands/flow/execute.ts +470 -0
- package/src/commands/flow/index.ts +11 -0
- package/src/commands/flow/prompt.ts +35 -0
- package/src/commands/flow/setup.ts +312 -0
- package/src/commands/flow/targets.ts +18 -0
- package/src/commands/flow/types.ts +47 -0
- package/src/commands/flow-command.ts +18 -967
- package/src/commands/flow-orchestrator.ts +14 -5
- package/src/commands/hook-command.ts +1 -1
- package/src/commands/init-core.ts +12 -3
- package/src/commands/run-command.ts +1 -1
- package/src/config/rules.ts +1 -1
- package/src/core/error-handling.ts +1 -1
- package/src/core/loop-controller.ts +1 -1
- package/src/core/state-detector.ts +1 -1
- package/src/core/target-manager.ts +1 -1
- package/src/index.ts +1 -1
- package/src/shared/files/index.ts +1 -1
- package/src/shared/processing/index.ts +1 -1
- package/src/targets/claude-code.ts +3 -3
- package/src/targets/opencode.ts +3 -3
- package/src/utils/agent-enhancer.ts +2 -2
- package/src/utils/{mcp-config.ts → config/mcp-config.ts} +4 -4
- package/src/utils/{paths.ts → config/paths.ts} +1 -1
- package/src/utils/{settings.ts → config/settings.ts} +1 -1
- package/src/utils/{target-config.ts → config/target-config.ts} +5 -5
- package/src/utils/{target-utils.ts → config/target-utils.ts} +3 -3
- package/src/utils/display/banner.ts +25 -0
- package/src/utils/display/status.ts +55 -0
- package/src/utils/{file-operations.ts → files/file-operations.ts} +2 -2
- package/src/utils/files/jsonc.ts +36 -0
- package/src/utils/{sync-utils.ts → files/sync-utils.ts} +3 -3
- package/src/utils/index.ts +42 -61
- package/src/utils/version.ts +47 -0
- package/src/components/benchmark-monitor.tsx +0 -331
- package/src/components/reindex-progress.tsx +0 -261
- package/src/composables/functional/index.ts +0 -14
- package/src/composables/functional/useEnvironment.ts +0 -171
- package/src/composables/functional/useFileSystem.ts +0 -139
- package/src/composables/index.ts +0 -4
- package/src/composables/useEnv.ts +0 -13
- package/src/composables/useRuntimeConfig.ts +0 -27
- package/src/core/ai-sdk.ts +0 -603
- package/src/core/app-factory.ts +0 -381
- package/src/core/builtin-agents.ts +0 -9
- package/src/core/command-system.ts +0 -550
- package/src/core/config-system.ts +0 -550
- package/src/core/connection-pool.ts +0 -390
- package/src/core/di-container.ts +0 -155
- package/src/core/headless-display.ts +0 -96
- package/src/core/interfaces/index.ts +0 -22
- package/src/core/interfaces/repository.interface.ts +0 -91
- package/src/core/interfaces/service.interface.ts +0 -133
- package/src/core/interfaces.ts +0 -96
- package/src/core/result.ts +0 -351
- package/src/core/service-config.ts +0 -252
- package/src/core/session-service.ts +0 -121
- package/src/core/storage-factory.ts +0 -115
- package/src/core/stream-handler.ts +0 -288
- package/src/core/type-utils.ts +0 -427
- package/src/core/unified-storage.ts +0 -456
- package/src/core/validation/limit.ts +0 -46
- package/src/core/validation/query.ts +0 -20
- package/src/db/auto-migrate.ts +0 -322
- package/src/db/base-database-client.ts +0 -144
- package/src/db/cache-db.ts +0 -218
- package/src/db/cache-schema.ts +0 -75
- package/src/db/database.ts +0 -70
- package/src/db/index.ts +0 -252
- package/src/db/memory-db.ts +0 -153
- package/src/db/memory-schema.ts +0 -29
- package/src/db/schema.ts +0 -289
- package/src/db/session-repository.ts +0 -733
- package/src/domains/index.ts +0 -6
- package/src/domains/utilities/index.ts +0 -6
- package/src/domains/utilities/time/index.ts +0 -5
- package/src/domains/utilities/time/tools.ts +0 -291
- package/src/services/agent-service.ts +0 -273
- package/src/services/evaluation-service.ts +0 -271
- package/src/services/functional/evaluation-logic.ts +0 -296
- package/src/services/functional/file-processor.ts +0 -273
- package/src/services/functional/index.ts +0 -12
- package/src/services/memory.service.ts +0 -476
- package/src/types/api/batch.ts +0 -108
- package/src/types/api/errors.ts +0 -118
- package/src/types/api/index.ts +0 -55
- package/src/types/api/requests.ts +0 -76
- package/src/types/api/responses.ts +0 -180
- package/src/types/api/websockets.ts +0 -85
- package/src/types/benchmark.ts +0 -49
- package/src/types/database.types.ts +0 -510
- package/src/types/memory-types.ts +0 -63
- package/src/utils/advanced-tokenizer.ts +0 -191
- package/src/utils/ai-model-fetcher.ts +0 -19
- package/src/utils/async-file-operations.ts +0 -516
- package/src/utils/audio-player.ts +0 -345
- package/src/utils/codebase-helpers.ts +0 -211
- package/src/utils/console-ui.ts +0 -79
- package/src/utils/database-errors.ts +0 -140
- package/src/utils/debug-logger.ts +0 -49
- package/src/utils/file-scanner.ts +0 -259
- package/src/utils/help.ts +0 -20
- package/src/utils/immutable-cache.ts +0 -106
- package/src/utils/jsonc.ts +0 -158
- package/src/utils/memory-tui.ts +0 -414
- package/src/utils/models-dev.ts +0 -91
- package/src/utils/parallel-operations.ts +0 -487
- package/src/utils/process-manager.ts +0 -155
- package/src/utils/prompts.ts +0 -120
- package/src/utils/search-tool-builder.ts +0 -214
- package/src/utils/session-manager.ts +0 -168
- package/src/utils/session-title.ts +0 -87
- package/src/utils/simplified-errors.ts +0 -410
- package/src/utils/template-engine.ts +0 -94
- package/src/utils/test-audio.ts +0 -71
- package/src/utils/todo-context.ts +0 -46
- package/src/utils/token-counter.ts +0 -288
- /package/src/utils/{cli-output.ts → display/cli-output.ts} +0 -0
- /package/src/utils/{logger.ts → display/logger.ts} +0 -0
- /package/src/utils/{notifications.ts → display/notifications.ts} +0 -0
- /package/src/utils/{secret-utils.ts → security/secret-utils.ts} +0 -0
- /package/src/utils/{security.ts → security/security.ts} +0 -0
|
@@ -1,550 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Configuration System - 統一配置系統
|
|
3
|
-
* Feature-first, composable, functional configuration management
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { readFileSync, existsSync } from 'node:fs';
|
|
7
|
-
import { homedir } from 'node:os';
|
|
8
|
-
import { join, dirname } from 'node:path';
|
|
9
|
-
import { z } from 'zod';
|
|
10
|
-
import { Result, err, ok } from './result.js';
|
|
11
|
-
import { ConfigurationError, ValidationError } from './error-handling.js';
|
|
12
|
-
import { logger } from '../utils/logger.js';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Configuration source
|
|
16
|
-
*/
|
|
17
|
-
export type ConfigSource =
|
|
18
|
-
| { type: 'file'; path: string }
|
|
19
|
-
| { type: 'env'; prefix?: string }
|
|
20
|
-
| { type: 'object'; data: Record<string, unknown> }
|
|
21
|
-
| { type: 'memory'; data: Record<string, unknown> };
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Configuration schema
|
|
25
|
-
*/
|
|
26
|
-
export type ConfigSchema = z.ZodSchema;
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Configuration options
|
|
30
|
-
*/
|
|
31
|
-
export interface ConfigOptions {
|
|
32
|
-
schema?: ConfigSchema;
|
|
33
|
-
sources?: ConfigSource[];
|
|
34
|
-
defaults?: Record<string, unknown>;
|
|
35
|
-
transformers?: ConfigTransformer[];
|
|
36
|
-
validators?: ConfigValidator[];
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Configuration transformer
|
|
41
|
-
*/
|
|
42
|
-
export interface ConfigTransformer {
|
|
43
|
-
name: string;
|
|
44
|
-
transform(config: Record<string, unknown>): Record<string, unknown>;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Configuration validator
|
|
49
|
-
*/
|
|
50
|
-
export interface ConfigValidator {
|
|
51
|
-
name: string;
|
|
52
|
-
validate(config: Record<string, unknown>): Result<void, ValidationError>;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Configuration manager
|
|
57
|
-
*/
|
|
58
|
-
export class ConfigManager {
|
|
59
|
-
private config: Record<string, unknown> = {};
|
|
60
|
-
private schema?: ConfigSchema;
|
|
61
|
-
private sources: ConfigSource[] = [];
|
|
62
|
-
private transformers: ConfigTransformer[] = [];
|
|
63
|
-
private validators: ConfigValidator[] = [];
|
|
64
|
-
private watchCallbacks = new Set<() => void>();
|
|
65
|
-
|
|
66
|
-
constructor(options: ConfigOptions = {}) {
|
|
67
|
-
this.schema = options.schema;
|
|
68
|
-
this.sources = options.sources || [];
|
|
69
|
-
this.transformers = options.transformers || [];
|
|
70
|
-
this.validators = options.validators || [];
|
|
71
|
-
|
|
72
|
-
// Set defaults
|
|
73
|
-
if (options.defaults) {
|
|
74
|
-
this.config = { ...options.defaults };
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
logger.debug('ConfigManager initialized', {
|
|
78
|
-
sources: this.sources.length,
|
|
79
|
-
transformers: this.transformers.length,
|
|
80
|
-
validators: this.validators.length,
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Add configuration source
|
|
86
|
-
*/
|
|
87
|
-
addSource(source: ConfigSource): void {
|
|
88
|
-
this.sources.push(source);
|
|
89
|
-
logger.debug('Config source added', { type: source.type });
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Add transformer
|
|
94
|
-
*/
|
|
95
|
-
addTransformer(transformer: ConfigTransformer): void {
|
|
96
|
-
this.transformers.push(transformer);
|
|
97
|
-
logger.debug('Config transformer added', { name: transformer.name });
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Add validator
|
|
102
|
-
*/
|
|
103
|
-
addValidator(validator: ConfigValidator): void {
|
|
104
|
-
this.validators.push(validator);
|
|
105
|
-
logger.debug('Config validator added', { name: validator.name });
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Load configuration from all sources
|
|
110
|
-
*/
|
|
111
|
-
async load(): Promise<Result<void, Error>> {
|
|
112
|
-
logger.info('Loading configuration');
|
|
113
|
-
|
|
114
|
-
try {
|
|
115
|
-
// Load from sources in order
|
|
116
|
-
for (const source of this.sources) {
|
|
117
|
-
const result = await this.loadFromSource(source);
|
|
118
|
-
if (!result.success) {
|
|
119
|
-
return err(result.error);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// Merge configuration (later sources override earlier ones)
|
|
123
|
-
this.config = { ...this.config, ...result.data };
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Apply transformers
|
|
127
|
-
for (const transformer of this.transformers) {
|
|
128
|
-
this.config = transformer.transform(this.config);
|
|
129
|
-
logger.debug('Config transformer applied', { name: transformer.name });
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Apply schema validation
|
|
133
|
-
if (this.schema) {
|
|
134
|
-
const result = this.validateWithSchema(this.config);
|
|
135
|
-
if (!result.success) {
|
|
136
|
-
return err(result.error);
|
|
137
|
-
}
|
|
138
|
-
this.config = result.data;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// Apply custom validators
|
|
142
|
-
for (const validator of this.validators) {
|
|
143
|
-
const result = validator.validate(this.config);
|
|
144
|
-
if (!result.success) {
|
|
145
|
-
return err(result.error);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
logger.info('Configuration loaded successfully', {
|
|
150
|
-
keys: Object.keys(this.config),
|
|
151
|
-
sources: this.sources.length,
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
return ok(undefined);
|
|
155
|
-
|
|
156
|
-
} catch (error) {
|
|
157
|
-
const errorObj = error instanceof Error ? error : new Error(String(error));
|
|
158
|
-
logger.error('Failed to load configuration', { error: errorObj.message });
|
|
159
|
-
return err(errorObj);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* Get configuration value
|
|
165
|
-
*/
|
|
166
|
-
get<T = unknown>(key: string, defaultValue?: T): T {
|
|
167
|
-
const value = this.getNestedValue(this.config, key);
|
|
168
|
-
return value !== undefined ? (value as T) : defaultValue!;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Set configuration value
|
|
173
|
-
*/
|
|
174
|
-
set<T>(key: string, value: T): void {
|
|
175
|
-
this.setNestedValue(this.config, key, value);
|
|
176
|
-
this.notifyWatchers();
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Get all configuration
|
|
181
|
-
*/
|
|
182
|
-
getAll(): Record<string, unknown> {
|
|
183
|
-
// Return deep copy to ensure immutability
|
|
184
|
-
return JSON.parse(JSON.stringify(this.config));
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Check if key exists
|
|
189
|
-
*/
|
|
190
|
-
has(key: string): boolean {
|
|
191
|
-
return this.getNestedValue(this.config, key) !== undefined;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Get configuration as typed object
|
|
196
|
-
*/
|
|
197
|
-
as<T>(): T {
|
|
198
|
-
return this.config as T;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Watch for configuration changes
|
|
203
|
-
*/
|
|
204
|
-
watch(callback: () => void): () => void {
|
|
205
|
-
this.watchCallbacks.add(callback);
|
|
206
|
-
return () => this.watchCallbacks.delete(callback);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Reload configuration
|
|
211
|
-
*/
|
|
212
|
-
async reload(): Promise<Result<void, Error>> {
|
|
213
|
-
this.config = {};
|
|
214
|
-
return this.load();
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Load from specific source
|
|
219
|
-
*/
|
|
220
|
-
private async loadFromSource(source: ConfigSource): Promise<Result<Record<string, unknown>, Error>> {
|
|
221
|
-
switch (source.type) {
|
|
222
|
-
case 'file':
|
|
223
|
-
return this.loadFromFile(source.path);
|
|
224
|
-
case 'env':
|
|
225
|
-
return this.loadFromEnv(source.prefix);
|
|
226
|
-
case 'object':
|
|
227
|
-
return ok(source.data);
|
|
228
|
-
case 'memory':
|
|
229
|
-
return ok(source.data);
|
|
230
|
-
default:
|
|
231
|
-
return err(new ConfigurationError(`Unknown source type: ${(source as any).type}`));
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Load from file
|
|
237
|
-
*/
|
|
238
|
-
private loadFromFile(path: string): Result<Record<string, unknown>, Error> {
|
|
239
|
-
if (!existsSync(path)) {
|
|
240
|
-
logger.warn('Config file not found', { path });
|
|
241
|
-
return ok({});
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
try {
|
|
245
|
-
const content = readFileSync(path, 'utf-8');
|
|
246
|
-
const config = this.parseFileContent(content, path);
|
|
247
|
-
logger.debug('Config loaded from file', { path, keys: Object.keys(config) });
|
|
248
|
-
return ok(config);
|
|
249
|
-
} catch (error) {
|
|
250
|
-
const errorObj = error instanceof Error ? error : new Error(String(error));
|
|
251
|
-
return err(new ConfigurationError(`Failed to load config from ${path}: ${errorObj.message}`));
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* Load from environment variables
|
|
257
|
-
*/
|
|
258
|
-
private loadFromEnv(prefix = ''): Result<Record<string, unknown>, Error> {
|
|
259
|
-
const config: Record<string, unknown> = {};
|
|
260
|
-
const envPrefix = prefix ? `${prefix}_` : '';
|
|
261
|
-
|
|
262
|
-
for (const [key, value] of Object.entries(process.env)) {
|
|
263
|
-
if (key.startsWith(envPrefix)) {
|
|
264
|
-
const configKey = key.slice(envPrefix.length).toLowerCase();
|
|
265
|
-
config[configKey] = this.parseEnvValue(value);
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
logger.debug('Config loaded from environment', {
|
|
270
|
-
prefix,
|
|
271
|
-
keys: Object.keys(config),
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
return ok(config);
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
/**
|
|
278
|
-
* Parse file content based on extension
|
|
279
|
-
*/
|
|
280
|
-
private parseFileContent(content: string, path: string): Record<string, unknown> {
|
|
281
|
-
const ext = path.split('.').pop()?.toLowerCase();
|
|
282
|
-
|
|
283
|
-
switch (ext) {
|
|
284
|
-
case 'json':
|
|
285
|
-
return JSON.parse(content);
|
|
286
|
-
case 'js':
|
|
287
|
-
case 'ts':
|
|
288
|
-
// For JS/TS files, we'd need to use dynamic imports
|
|
289
|
-
// This is a simplified version
|
|
290
|
-
throw new Error(`JS/TS config files not yet supported: ${path}`);
|
|
291
|
-
default:
|
|
292
|
-
throw new Error(`Unsupported config file format: ${ext}`);
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
/**
|
|
297
|
-
* Parse environment variable value
|
|
298
|
-
*/
|
|
299
|
-
private parseEnvValue(value: string | undefined): unknown {
|
|
300
|
-
if (value === undefined) return undefined;
|
|
301
|
-
|
|
302
|
-
// Try JSON
|
|
303
|
-
try {
|
|
304
|
-
return JSON.parse(value);
|
|
305
|
-
} catch {
|
|
306
|
-
// Try common types
|
|
307
|
-
if (value === 'true') return true;
|
|
308
|
-
if (value === 'false') return false;
|
|
309
|
-
if (/^\d+$/.test(value)) return parseInt(value, 10);
|
|
310
|
-
if (/^\d+\.\d+$/.test(value)) return parseFloat(value);
|
|
311
|
-
|
|
312
|
-
return value;
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
/**
|
|
317
|
-
* Validate with schema
|
|
318
|
-
*/
|
|
319
|
-
private validateWithSchema(config: Record<string, unknown>): Result<Record<string, unknown>, ValidationError> {
|
|
320
|
-
try {
|
|
321
|
-
const result = this.schema!.parse(config);
|
|
322
|
-
return ok(result);
|
|
323
|
-
} catch (error) {
|
|
324
|
-
if (error instanceof z.ZodError && error.errors && Array.isArray(error.errors)) {
|
|
325
|
-
const message = error.errors.map(e => `${e.path.join('.')}: ${e.message}`).join(', ');
|
|
326
|
-
return err(new ValidationError(`Configuration validation failed: ${message}`));
|
|
327
|
-
}
|
|
328
|
-
const errorMessage = error instanceof Error ? error.message : 'Unknown validation error';
|
|
329
|
-
return err(new ValidationError(`Configuration validation failed: ${errorMessage}`));
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
/**
|
|
334
|
-
* Get nested value from object
|
|
335
|
-
*/
|
|
336
|
-
private getNestedValue(obj: Record<string, unknown>, path: string): unknown {
|
|
337
|
-
return path.split('.').reduce((current, key) => {
|
|
338
|
-
return current && typeof current === 'object' ? (current as any)[key] : undefined;
|
|
339
|
-
}, obj);
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
/**
|
|
343
|
-
* Set nested value in object
|
|
344
|
-
*/
|
|
345
|
-
private setNestedValue(obj: Record<string, unknown>, path: string, value: unknown): void {
|
|
346
|
-
const keys = path.split('.');
|
|
347
|
-
const lastKey = keys.pop()!;
|
|
348
|
-
|
|
349
|
-
let current = obj;
|
|
350
|
-
for (const key of keys) {
|
|
351
|
-
if (!(key in current) || typeof current[key] !== 'object') {
|
|
352
|
-
current[key] = {};
|
|
353
|
-
}
|
|
354
|
-
current = current[key] as Record<string, unknown>;
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
current[lastKey] = value;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
/**
|
|
361
|
-
* Notify watchers of changes
|
|
362
|
-
*/
|
|
363
|
-
private notifyWatchers(): void {
|
|
364
|
-
for (const callback of this.watchCallbacks) {
|
|
365
|
-
callback();
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
/**
|
|
371
|
-
* Configuration factory
|
|
372
|
-
*/
|
|
373
|
-
export const ConfigFactory = {
|
|
374
|
-
/**
|
|
375
|
-
* Create a new config manager
|
|
376
|
-
*/
|
|
377
|
-
create(options?: ConfigOptions): ConfigManager {
|
|
378
|
-
return new ConfigManager(options);
|
|
379
|
-
},
|
|
380
|
-
|
|
381
|
-
/**
|
|
382
|
-
* Create config manager with file source
|
|
383
|
-
*/
|
|
384
|
-
fromFile(path: string, options?: Omit<ConfigOptions, 'sources'>): ConfigManager {
|
|
385
|
-
return new ConfigManager({
|
|
386
|
-
...options,
|
|
387
|
-
sources: [{ type: 'file', path }],
|
|
388
|
-
});
|
|
389
|
-
},
|
|
390
|
-
|
|
391
|
-
/**
|
|
392
|
-
* Create config manager with environment source
|
|
393
|
-
*/
|
|
394
|
-
fromEnv(prefix?: string, options?: Omit<ConfigOptions, 'sources'>): ConfigManager {
|
|
395
|
-
return new ConfigManager({
|
|
396
|
-
...options,
|
|
397
|
-
sources: [{ type: 'env', prefix }],
|
|
398
|
-
});
|
|
399
|
-
},
|
|
400
|
-
|
|
401
|
-
/**
|
|
402
|
-
* Create config manager with multiple sources
|
|
403
|
-
*/
|
|
404
|
-
fromSources(sources: ConfigSource[], options?: Omit<ConfigOptions, 'sources'>): ConfigManager {
|
|
405
|
-
return new ConfigManager({
|
|
406
|
-
...options,
|
|
407
|
-
sources,
|
|
408
|
-
});
|
|
409
|
-
},
|
|
410
|
-
} as const;
|
|
411
|
-
|
|
412
|
-
/**
|
|
413
|
-
* Common configuration schemas
|
|
414
|
-
*/
|
|
415
|
-
export const ConfigSchemas = {
|
|
416
|
-
/**
|
|
417
|
-
* Application configuration
|
|
418
|
-
*/
|
|
419
|
-
app: z.object({
|
|
420
|
-
name: z.string(),
|
|
421
|
-
version: z.string(),
|
|
422
|
-
description: z.string().optional(),
|
|
423
|
-
environment: z.enum(['development', 'production', 'test']).default('development'),
|
|
424
|
-
debug: z.boolean().default(false),
|
|
425
|
-
}),
|
|
426
|
-
|
|
427
|
-
/**
|
|
428
|
-
* Server configuration
|
|
429
|
-
*/
|
|
430
|
-
server: z.object({
|
|
431
|
-
port: z.number().positive().default(3000),
|
|
432
|
-
host: z.string().default('localhost'),
|
|
433
|
-
cors: z.boolean().default(true),
|
|
434
|
-
}),
|
|
435
|
-
|
|
436
|
-
/**
|
|
437
|
-
* Database configuration
|
|
438
|
-
*/
|
|
439
|
-
database: z.object({
|
|
440
|
-
url: z.string(),
|
|
441
|
-
ssl: z.boolean().optional(),
|
|
442
|
-
pool: z.object({
|
|
443
|
-
min: z.number().min(0).default(0),
|
|
444
|
-
max: z.number().positive().default(10),
|
|
445
|
-
}).optional(),
|
|
446
|
-
}),
|
|
447
|
-
|
|
448
|
-
/**
|
|
449
|
-
* Logging configuration
|
|
450
|
-
*/
|
|
451
|
-
logging: z.object({
|
|
452
|
-
level: z.enum(['error', 'warn', 'info', 'debug']).default('info'),
|
|
453
|
-
format: z.enum(['json', 'text']).default('text'),
|
|
454
|
-
file: z.string().optional(),
|
|
455
|
-
}),
|
|
456
|
-
|
|
457
|
-
/**
|
|
458
|
-
* Cache configuration
|
|
459
|
-
*/
|
|
460
|
-
cache: z.object({
|
|
461
|
-
type: z.enum(['memory', 'redis']).default('memory'),
|
|
462
|
-
ttl: z.number().positive().default(3600),
|
|
463
|
-
maxSize: z.number().positive().optional(),
|
|
464
|
-
redis: z.object({
|
|
465
|
-
url: z.string(),
|
|
466
|
-
keyPrefix: z.string().optional(),
|
|
467
|
-
}).optional(),
|
|
468
|
-
}),
|
|
469
|
-
} as const;
|
|
470
|
-
|
|
471
|
-
/**
|
|
472
|
-
* Common transformers
|
|
473
|
-
*/
|
|
474
|
-
export const ConfigTransformers = {
|
|
475
|
-
/**
|
|
476
|
-
* Environment variable expansion
|
|
477
|
-
*/
|
|
478
|
-
envExpander: (): ConfigTransformer => ({
|
|
479
|
-
name: 'envExpander',
|
|
480
|
-
transform: (config): Record<string, unknown> => {
|
|
481
|
-
const expanded: Record<string, unknown> = {};
|
|
482
|
-
|
|
483
|
-
for (const [key, value] of Object.entries(config)) {
|
|
484
|
-
if (typeof value === 'string') {
|
|
485
|
-
expanded[key] = value.replace(/\$\{([^}]+)\}/g, (match, envVar) => {
|
|
486
|
-
return process.env[envVar] || match;
|
|
487
|
-
});
|
|
488
|
-
} else {
|
|
489
|
-
expanded[key] = value;
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
return expanded;
|
|
494
|
-
},
|
|
495
|
-
}),
|
|
496
|
-
|
|
497
|
-
/**
|
|
498
|
-
* Path resolution
|
|
499
|
-
*/
|
|
500
|
-
pathResolver: (basePath?: string): ConfigTransformer => ({
|
|
501
|
-
name: 'pathResolver',
|
|
502
|
-
transform: (config): Record<string, unknown> => {
|
|
503
|
-
const base = basePath || process.cwd();
|
|
504
|
-
const resolved: Record<string, unknown> = {};
|
|
505
|
-
|
|
506
|
-
for (const [key, value] of Object.entries(config)) {
|
|
507
|
-
if (typeof value === 'string' && (value.startsWith('./') || value.startsWith('../'))) {
|
|
508
|
-
resolved[key] = join(base, value);
|
|
509
|
-
} else {
|
|
510
|
-
resolved[key] = value;
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
return resolved;
|
|
515
|
-
},
|
|
516
|
-
}),
|
|
517
|
-
} as const;
|
|
518
|
-
|
|
519
|
-
/**
|
|
520
|
-
* Common validators
|
|
521
|
-
*/
|
|
522
|
-
export const ConfigValidators = {
|
|
523
|
-
/**
|
|
524
|
-
* Required fields validator
|
|
525
|
-
*/
|
|
526
|
-
required: (fields: string[]): ConfigValidator => ({
|
|
527
|
-
name: 'required',
|
|
528
|
-
validate: (config): Result<void, ValidationError> => {
|
|
529
|
-
const missing = fields.filter(field => !config[field]);
|
|
530
|
-
if (missing.length > 0) {
|
|
531
|
-
return err(new ValidationError(`Required fields missing: ${missing.join(', ')}`));
|
|
532
|
-
}
|
|
533
|
-
return ok(undefined);
|
|
534
|
-
},
|
|
535
|
-
}),
|
|
536
|
-
|
|
537
|
-
/**
|
|
538
|
-
* Port range validator
|
|
539
|
-
*/
|
|
540
|
-
portRange: (key = 'port'): ConfigValidator => ({
|
|
541
|
-
name: 'portRange',
|
|
542
|
-
validate: (config): Result<void, ValidationError> => {
|
|
543
|
-
const port = config[key];
|
|
544
|
-
if (port !== undefined && (typeof port !== 'number' || port < 1 || port > 65535)) {
|
|
545
|
-
return err(new ValidationError(`Invalid port number: ${port}`));
|
|
546
|
-
}
|
|
547
|
-
return ok(undefined);
|
|
548
|
-
},
|
|
549
|
-
}),
|
|
550
|
-
} as const;
|