@sylphx/flow 1.7.0 → 1.8.1
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 +78 -0
- package/assets/agents/coder.md +72 -119
- package/assets/agents/orchestrator.md +26 -90
- package/assets/agents/reviewer.md +76 -47
- package/assets/agents/writer.md +82 -63
- package/assets/output-styles/silent.md +141 -8
- package/assets/rules/code-standards.md +9 -33
- package/assets/rules/core.md +67 -59
- 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,91 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Repository interface for dependency inversion
|
|
3
|
-
* Abstracts data access implementation
|
|
4
|
-
*
|
|
5
|
-
* DESIGN RATIONALE:
|
|
6
|
-
* - Depend on abstractions, not concrete implementations
|
|
7
|
-
* - Enables testing with in-memory implementations
|
|
8
|
-
* - Separates interface from implementation
|
|
9
|
-
* - Clear contract for data access
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import type { DatabaseError } from '../functional/error-types.js';
|
|
13
|
-
import type { Result } from '../functional/result.js';
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Query options for filtering, sorting, pagination
|
|
17
|
-
*/
|
|
18
|
-
export interface QueryOptions {
|
|
19
|
-
limit?: number;
|
|
20
|
-
offset?: number;
|
|
21
|
-
orderBy?: string;
|
|
22
|
-
orderDirection?: 'ASC' | 'DESC';
|
|
23
|
-
where?: Record<string, any>;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Paginated result wrapper
|
|
28
|
-
*/
|
|
29
|
-
export interface PaginatedResult<T> {
|
|
30
|
-
items: T[];
|
|
31
|
-
total: number;
|
|
32
|
-
page: number;
|
|
33
|
-
pageSize: number;
|
|
34
|
-
hasNext: boolean;
|
|
35
|
-
hasPrevious: boolean;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Generic repository interface
|
|
40
|
-
* All operations return Result for explicit error handling
|
|
41
|
-
*/
|
|
42
|
-
export interface IRepository<T, ID = string | number> {
|
|
43
|
-
/**
|
|
44
|
-
* Find entity by ID
|
|
45
|
-
*/
|
|
46
|
-
findById(id: ID): Promise<Result<T | null, DatabaseError>>;
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Find multiple entities with filtering and sorting
|
|
50
|
-
*/
|
|
51
|
-
findMany(options?: QueryOptions): Promise<Result<T[], DatabaseError>>;
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Find entities with pagination
|
|
55
|
-
*/
|
|
56
|
-
findPaginated(
|
|
57
|
-
page: number,
|
|
58
|
-
pageSize: number,
|
|
59
|
-
options?: Omit<QueryOptions, 'limit' | 'offset'>
|
|
60
|
-
): Promise<Result<PaginatedResult<T>, DatabaseError>>;
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Create a new entity
|
|
64
|
-
*/
|
|
65
|
-
create(data: Partial<T>): Promise<Result<T, DatabaseError>>;
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Update an existing entity
|
|
69
|
-
*/
|
|
70
|
-
update(id: ID, data: Partial<T>): Promise<Result<T | null, DatabaseError>>;
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Delete an entity
|
|
74
|
-
*/
|
|
75
|
-
delete(id: ID): Promise<Result<boolean, DatabaseError>>;
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Count entities matching criteria
|
|
79
|
-
*/
|
|
80
|
-
count(options?: { where?: Record<string, any> }): Promise<Result<number, DatabaseError>>;
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Check if entity exists
|
|
84
|
-
*/
|
|
85
|
-
exists(id: ID): Promise<Result<boolean, DatabaseError>>;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Factory function type for creating repositories
|
|
90
|
-
*/
|
|
91
|
-
export type RepositoryFactory<T, ID = string | number> = (tableName: string) => IRepository<T, ID>;
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Service interfaces for dependency inversion
|
|
3
|
-
* Core service contracts
|
|
4
|
-
*
|
|
5
|
-
* DESIGN RATIONALE:
|
|
6
|
-
* - Depend on abstractions, not implementations
|
|
7
|
-
* - Clear contracts for services
|
|
8
|
-
* - Enables dependency injection
|
|
9
|
-
* - Facilitates testing with mocks
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import type { AppError } from '../functional/error-types.js';
|
|
13
|
-
import type { Result } from '../functional/result.js';
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Logger interface
|
|
17
|
-
*/
|
|
18
|
-
export interface ILogger {
|
|
19
|
-
debug(message: string, ...args: any[]): void;
|
|
20
|
-
info(message: string, ...args: any[]): void;
|
|
21
|
-
warn(message: string, ...args: any[]): void;
|
|
22
|
-
error(message: string, ...args: any[]): void;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Configuration service interface
|
|
27
|
-
*/
|
|
28
|
-
export interface IConfigService {
|
|
29
|
-
/**
|
|
30
|
-
* Get configuration value
|
|
31
|
-
*/
|
|
32
|
-
get<T>(key: string): Result<T, AppError>;
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Get configuration value with default
|
|
36
|
-
*/
|
|
37
|
-
getOrDefault<T>(key: string, defaultValue: T): T;
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Set configuration value
|
|
41
|
-
*/
|
|
42
|
-
set<T>(key: string, value: T): Result<void, AppError>;
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Check if configuration key exists
|
|
46
|
-
*/
|
|
47
|
-
has(key: string): boolean;
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Load configuration from file
|
|
51
|
-
*/
|
|
52
|
-
load(path: string): Promise<Result<void, AppError>>;
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Save configuration to file
|
|
56
|
-
*/
|
|
57
|
-
save(path: string): Promise<Result<void, AppError>>;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* File service interface
|
|
62
|
-
*/
|
|
63
|
-
export interface IFileService {
|
|
64
|
-
/**
|
|
65
|
-
* Read file contents
|
|
66
|
-
*/
|
|
67
|
-
read(path: string): Promise<Result<string, AppError>>;
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Write file contents
|
|
71
|
-
*/
|
|
72
|
-
write(path: string, content: string): Promise<Result<void, AppError>>;
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Check if file exists
|
|
76
|
-
*/
|
|
77
|
-
exists(path: string): Promise<Result<boolean, AppError>>;
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Delete file
|
|
81
|
-
*/
|
|
82
|
-
delete(path: string): Promise<Result<void, AppError>>;
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* List files in directory
|
|
86
|
-
*/
|
|
87
|
-
list(path: string): Promise<Result<string[], AppError>>;
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Create directory
|
|
91
|
-
*/
|
|
92
|
-
createDir(path: string, recursive?: boolean): Promise<Result<void, AppError>>;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Validation service interface
|
|
97
|
-
*/
|
|
98
|
-
export interface IValidationService<T> {
|
|
99
|
-
/**
|
|
100
|
-
* Validate data
|
|
101
|
-
*/
|
|
102
|
-
validate(data: unknown): Result<T, AppError>;
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Validate and return errors
|
|
106
|
-
*/
|
|
107
|
-
validateWithErrors(data: unknown): Result<T, string[]>;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Event emitter interface for event-driven architecture
|
|
112
|
-
*/
|
|
113
|
-
export interface IEventEmitter<EventMap extends Record<string, any>> {
|
|
114
|
-
/**
|
|
115
|
-
* Emit an event
|
|
116
|
-
*/
|
|
117
|
-
emit<K extends keyof EventMap>(event: K, data: EventMap[K]): void;
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Subscribe to an event
|
|
121
|
-
*/
|
|
122
|
-
on<K extends keyof EventMap>(event: K, handler: (data: EventMap[K]) => void): () => void;
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Subscribe to an event once
|
|
126
|
-
*/
|
|
127
|
-
once<K extends keyof EventMap>(event: K, handler: (data: EventMap[K]) => void): () => void;
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Remove all listeners for an event
|
|
131
|
-
*/
|
|
132
|
-
removeAllListeners<K extends keyof EventMap>(event: K): void;
|
|
133
|
-
}
|
package/src/core/interfaces.ts
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Core service interfaces for dependency injection
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
// Logger interface
|
|
6
|
-
export interface ILogger {
|
|
7
|
-
info(message: string, ...args: unknown[]): void;
|
|
8
|
-
warn(message: string, ...args: unknown[]): void;
|
|
9
|
-
error(message: string, error?: Error | unknown, ...args: unknown[]): void;
|
|
10
|
-
debug(message: string, ...args: unknown[]): void;
|
|
11
|
-
success(message: string, ...args: unknown[]): void;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
// Configuration interface
|
|
15
|
-
export interface IConfiguration {
|
|
16
|
-
get<T = unknown>(key: string, defaultValue?: T): T;
|
|
17
|
-
getRequired<T = unknown>(key: string): T;
|
|
18
|
-
has(key: string): boolean;
|
|
19
|
-
set(key: string, value: unknown): void;
|
|
20
|
-
reload(): Promise<void>;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// Database connection interface
|
|
24
|
-
export interface IDatabaseConnection {
|
|
25
|
-
connect(): Promise<void>;
|
|
26
|
-
disconnect(): Promise<void>;
|
|
27
|
-
healthCheck(): Promise<{ healthy: boolean; error?: string }>;
|
|
28
|
-
execute(sql: string, params?: unknown[]): Promise<DatabaseQueryResult>;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Database query result
|
|
32
|
-
export interface DatabaseQueryResult {
|
|
33
|
-
rows: Record<string, unknown>[];
|
|
34
|
-
rowCount: number;
|
|
35
|
-
command: string;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Storage interface for memory and cache
|
|
39
|
-
export interface IStorage<T = unknown> {
|
|
40
|
-
initialize(): Promise<void>;
|
|
41
|
-
get(key: string, namespace?: string): Promise<T | null>;
|
|
42
|
-
set(key: string, value: T, namespace?: string): Promise<void>;
|
|
43
|
-
delete(key: string, namespace?: string): Promise<void>;
|
|
44
|
-
clear(namespace?: string): Promise<void>;
|
|
45
|
-
list(namespace?: string): Promise<string[]>;
|
|
46
|
-
healthCheck(): Promise<{ healthy: boolean; error?: string }>;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Target manager interface
|
|
50
|
-
export interface ITargetManager {
|
|
51
|
-
getTarget(id: string): Target | null;
|
|
52
|
-
getAllTargets(): Target[];
|
|
53
|
-
registerTarget(target: Target): void;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Target definition
|
|
57
|
-
export interface Target {
|
|
58
|
-
id: string;
|
|
59
|
-
name: string;
|
|
60
|
-
type: string;
|
|
61
|
-
config: Record<string, unknown>;
|
|
62
|
-
enabled: boolean;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Embedding provider interface
|
|
66
|
-
export interface IEmbeddingProvider {
|
|
67
|
-
name: string;
|
|
68
|
-
embed(text: string): Promise<number[]>;
|
|
69
|
-
isAvailable(): Promise<boolean>;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// MCP service interface
|
|
73
|
-
export interface IMCPService {
|
|
74
|
-
initialize(): Promise<void>;
|
|
75
|
-
installServers(serverIds: string[], options?: MCPServerInstallOptions): Promise<void>;
|
|
76
|
-
getAvailableServers(): MCPServerInfo[];
|
|
77
|
-
getInstalledServers(): MCPServerInfo[];
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// MCP server installation options
|
|
81
|
-
export interface MCPServerInstallOptions {
|
|
82
|
-
force?: boolean;
|
|
83
|
-
autoStart?: boolean;
|
|
84
|
-
config?: Record<string, unknown>;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// MCP server information
|
|
88
|
-
export interface MCPServerInfo {
|
|
89
|
-
id: string;
|
|
90
|
-
name: string;
|
|
91
|
-
version: string;
|
|
92
|
-
description?: string;
|
|
93
|
-
installed: boolean;
|
|
94
|
-
enabled: boolean;
|
|
95
|
-
config?: Record<string, unknown>;
|
|
96
|
-
}
|
package/src/core/result.ts
DELETED
|
@@ -1,351 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unified Result Type - 統一結果類型
|
|
3
|
-
* Single source of truth for Result<T, E> across the entire project
|
|
4
|
-
*
|
|
5
|
-
* This replaces all conflicting Result type definitions:
|
|
6
|
-
* - src/core/type-utils.ts
|
|
7
|
-
* - src/core/functional/result.ts
|
|
8
|
-
* - src/utils/functional.ts
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
// ============================================================================
|
|
12
|
-
// CORE RESULT TYPE
|
|
13
|
-
// ============================================================================
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Result type for functional error handling
|
|
17
|
-
* Represents success or failure without exceptions
|
|
18
|
-
*/
|
|
19
|
-
export type Result<T, E = Error> =
|
|
20
|
-
| { success: true; data: T }
|
|
21
|
-
| { success: false; error: E };
|
|
22
|
-
|
|
23
|
-
// ============================================================================
|
|
24
|
-
// CONSTRUCTORS
|
|
25
|
-
// ============================================================================
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Create a successful result
|
|
29
|
-
*/
|
|
30
|
-
export const ok = <T>(data: T): Result<T> => ({ success: true, data });
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Create an error result
|
|
34
|
-
*/
|
|
35
|
-
export const err = <E>(error: E): Result<never, E> => ({ success: false, error });
|
|
36
|
-
|
|
37
|
-
// ============================================================================
|
|
38
|
-
// TYPE GUARDS
|
|
39
|
-
// ============================================================================
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Check if result is successful
|
|
43
|
-
*/
|
|
44
|
-
export const isOk = <T, E>(result: Result<T, E>): result is { success: true; data: T } =>
|
|
45
|
-
result.success;
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Check if result is an error
|
|
49
|
-
*/
|
|
50
|
-
export const isErr = <T, E>(result: Result<T, E>): result is { success: false; error: E } =>
|
|
51
|
-
!result.success;
|
|
52
|
-
|
|
53
|
-
// ============================================================================
|
|
54
|
-
// TRANSFORMATIONS
|
|
55
|
-
// ============================================================================
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Transform the success value
|
|
59
|
-
* Error propagates unchanged
|
|
60
|
-
*/
|
|
61
|
-
export const map =
|
|
62
|
-
<T, U, E>(fn: (data: T) => U) =>
|
|
63
|
-
(result: Result<T, E>): Result<U, E> => {
|
|
64
|
-
if (isOk(result)) {
|
|
65
|
-
return ok(fn(result.data));
|
|
66
|
-
}
|
|
67
|
-
return result;
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Transform the success value with a function that returns a Result
|
|
72
|
-
* Enables chaining operations that can fail
|
|
73
|
-
* Error propagates unchanged
|
|
74
|
-
*/
|
|
75
|
-
export const flatMap =
|
|
76
|
-
<T, U, E>(fn: (data: T) => Result<U, E>) =>
|
|
77
|
-
(result: Result<T, E>): Result<U, E> => {
|
|
78
|
-
if (isOk(result)) {
|
|
79
|
-
return fn(result.data);
|
|
80
|
-
}
|
|
81
|
-
return result;
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Transform the error
|
|
86
|
-
* Success propagates unchanged
|
|
87
|
-
*/
|
|
88
|
-
export const mapError =
|
|
89
|
-
<T, E, F>(fn: (error: E) => F) =>
|
|
90
|
-
(result: Result<T, E>): Result<T, F> => {
|
|
91
|
-
if (isErr(result)) {
|
|
92
|
-
return err(fn(result.error));
|
|
93
|
-
}
|
|
94
|
-
return result;
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Extract value or provide default
|
|
99
|
-
*/
|
|
100
|
-
export const getOrElse =
|
|
101
|
-
<T>(defaultValue: T) =>
|
|
102
|
-
<E>(result: Result<T, E>): T => {
|
|
103
|
-
if (isOk(result)) {
|
|
104
|
-
return result.data;
|
|
105
|
-
}
|
|
106
|
-
return defaultValue;
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Extract value or compute default
|
|
111
|
-
*/
|
|
112
|
-
export const getOrElseLazy =
|
|
113
|
-
<T>(fn: () => T) =>
|
|
114
|
-
<E>(result: Result<T, E>): T => {
|
|
115
|
-
if (isOk(result)) {
|
|
116
|
-
return result.data;
|
|
117
|
-
}
|
|
118
|
-
return fn();
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Pattern matching
|
|
123
|
-
*/
|
|
124
|
-
export const match =
|
|
125
|
-
<T, E, U>(onSuccess: (data: T) => U, onError: (error: E) => U) =>
|
|
126
|
-
(result: Result<T, E>): U => {
|
|
127
|
-
if (isOk(result)) {
|
|
128
|
-
return onSuccess(result.data);
|
|
129
|
-
}
|
|
130
|
-
return onError(result.error);
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Extract value or throw error
|
|
135
|
-
* Use only when you're certain the result is successful
|
|
136
|
-
*/
|
|
137
|
-
export const unwrap = <T, E>(result: Result<T, E>): T => {
|
|
138
|
-
if (isOk(result)) {
|
|
139
|
-
return result.data;
|
|
140
|
-
}
|
|
141
|
-
throw result.error;
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Extract error or throw
|
|
146
|
-
* Use only when you're certain the result is an error
|
|
147
|
-
*/
|
|
148
|
-
export const unwrapError = <T, E>(result: Result<T, E>): E => {
|
|
149
|
-
if (isErr(result)) {
|
|
150
|
-
return result.error;
|
|
151
|
-
}
|
|
152
|
-
throw new Error('Expected error but got success');
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
// ============================================================================
|
|
156
|
-
// ASYNC SUPPORT
|
|
157
|
-
// ============================================================================
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Async result type
|
|
161
|
-
*/
|
|
162
|
-
export type AsyncResult<T, E = Error> = Promise<Result<T, E>>;
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Convert thrown exception to Result
|
|
166
|
-
*/
|
|
167
|
-
export const tryCatch = <T, E = Error>(
|
|
168
|
-
fn: () => T,
|
|
169
|
-
onError: (error: unknown) => E = (error: unknown) => error as E
|
|
170
|
-
): Result<T, E> => {
|
|
171
|
-
try {
|
|
172
|
-
return ok(fn());
|
|
173
|
-
} catch (error) {
|
|
174
|
-
return err(onError(error));
|
|
175
|
-
}
|
|
176
|
-
};
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Convert Promise to Result
|
|
180
|
-
*/
|
|
181
|
-
export const tryCatchAsync = async <T, E = Error>(
|
|
182
|
-
fn: () => Promise<T>,
|
|
183
|
-
onError: (error: unknown) => E = (error: unknown) => error as E
|
|
184
|
-
): Promise<Result<T, E>> => {
|
|
185
|
-
try {
|
|
186
|
-
const data = await fn();
|
|
187
|
-
return ok(data);
|
|
188
|
-
} catch (error) {
|
|
189
|
-
return err(onError(error));
|
|
190
|
-
}
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Safe async function wrapper
|
|
195
|
-
*/
|
|
196
|
-
export const safeAsync = async <T, E = Error>(
|
|
197
|
-
fn: () => Promise<T>,
|
|
198
|
-
errorFn?: (error: unknown) => E
|
|
199
|
-
): Promise<Result<T, E>> => {
|
|
200
|
-
return tryCatchAsync(fn, errorFn);
|
|
201
|
-
};
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Safe sync function wrapper
|
|
205
|
-
*/
|
|
206
|
-
export const safeSync = <T, E = Error>(
|
|
207
|
-
fn: () => T,
|
|
208
|
-
errorFn?: (error: unknown) => E
|
|
209
|
-
): Result<T, E> => {
|
|
210
|
-
return tryCatch(fn, errorFn);
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
// ============================================================================
|
|
214
|
-
// COMBINATORS
|
|
215
|
-
// ============================================================================
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Combine multiple Results into a single Result containing an array
|
|
219
|
-
* Fails if any Result is an error (short-circuits on first error)
|
|
220
|
-
*/
|
|
221
|
-
export const all = <T, E>(results: Result<T, E>[]): Result<T[], E> => {
|
|
222
|
-
const values: T[] = [];
|
|
223
|
-
|
|
224
|
-
for (const result of results) {
|
|
225
|
-
if (isErr(result)) {
|
|
226
|
-
return result;
|
|
227
|
-
}
|
|
228
|
-
values.push(result.data);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
return ok(values);
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Combine multiple Results into a single Result containing an array
|
|
236
|
-
* Collects all errors instead of short-circuiting
|
|
237
|
-
*/
|
|
238
|
-
export const allWithErrors = <T, E>(results: Result<T, E>[]): Result<T[], E[]> => {
|
|
239
|
-
const values: T[] = [];
|
|
240
|
-
const errors: E[] = [];
|
|
241
|
-
|
|
242
|
-
for (const result of results) {
|
|
243
|
-
if (isOk(result)) {
|
|
244
|
-
values.push(result.data);
|
|
245
|
-
} else {
|
|
246
|
-
errors.push(result.error);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
return errors.length > 0 ? err(errors) : ok(values);
|
|
251
|
-
};
|
|
252
|
-
|
|
253
|
-
/**
|
|
254
|
-
* Combine multiple AsyncResults
|
|
255
|
-
*/
|
|
256
|
-
export const allAsync = async <T, E>(results: AsyncResult<T, E>[]): Promise<Result<T[], E>> => {
|
|
257
|
-
const settled = await Promise.all(results);
|
|
258
|
-
return all(settled);
|
|
259
|
-
};
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Race multiple AsyncResults - returns first successful result
|
|
263
|
-
*/
|
|
264
|
-
export const raceAsync = async <T, E>(results: AsyncResult<T, E>[]): Promise<Result<T, E>> => {
|
|
265
|
-
try {
|
|
266
|
-
return await Promise.race(results);
|
|
267
|
-
} catch (error) {
|
|
268
|
-
return err(error as E);
|
|
269
|
-
}
|
|
270
|
-
};
|
|
271
|
-
|
|
272
|
-
// ============================================================================
|
|
273
|
-
// SIDE EFFECTS
|
|
274
|
-
// ============================================================================
|
|
275
|
-
|
|
276
|
-
/**
|
|
277
|
-
* Run side effect for success case
|
|
278
|
-
*/
|
|
279
|
-
export const tap =
|
|
280
|
-
<T, E>(fn: (data: T) => void) =>
|
|
281
|
-
(result: Result<T, E>): Result<T, E> => {
|
|
282
|
-
if (isOk(result)) {
|
|
283
|
-
fn(result.data);
|
|
284
|
-
}
|
|
285
|
-
return result;
|
|
286
|
-
};
|
|
287
|
-
|
|
288
|
-
/**
|
|
289
|
-
* Run side effect for error case
|
|
290
|
-
*/
|
|
291
|
-
export const tapError =
|
|
292
|
-
<T, E>(fn: (error: E) => void) =>
|
|
293
|
-
(result: Result<T, E>): Result<T, E> => {
|
|
294
|
-
if (isErr(result)) {
|
|
295
|
-
fn(result.error);
|
|
296
|
-
}
|
|
297
|
-
return result;
|
|
298
|
-
};
|
|
299
|
-
|
|
300
|
-
/**
|
|
301
|
-
* Run side effect for both cases
|
|
302
|
-
*/
|
|
303
|
-
export const tapBoth =
|
|
304
|
-
<T, E>(onSuccess: (data: T) => void, onError: (error: E) => void) =>
|
|
305
|
-
(result: Result<T, E>): Result<T, E> => {
|
|
306
|
-
if (isOk(result)) {
|
|
307
|
-
onSuccess(result.data);
|
|
308
|
-
} else {
|
|
309
|
-
onError(result.error);
|
|
310
|
-
}
|
|
311
|
-
return result;
|
|
312
|
-
};
|
|
313
|
-
|
|
314
|
-
// ============================================================================
|
|
315
|
-
// LEGACY COMPATIBILITY
|
|
316
|
-
// ============================================================================
|
|
317
|
-
|
|
318
|
-
/**
|
|
319
|
-
* Legacy compatibility aliases
|
|
320
|
-
* These help migrate from old Result implementations
|
|
321
|
-
*/
|
|
322
|
-
|
|
323
|
-
// For src/core/functional/result.ts users
|
|
324
|
-
export const success = ok;
|
|
325
|
-
export const failure = err;
|
|
326
|
-
export const isSuccess = isOk;
|
|
327
|
-
export const isFailure = isErr;
|
|
328
|
-
|
|
329
|
-
// For src/utils/functional.ts users
|
|
330
|
-
export const unwrapResult = unwrap;
|
|
331
|
-
export const mapResult = map;
|
|
332
|
-
|
|
333
|
-
// ============================================================================
|
|
334
|
-
// TYPE INFERENCE HELPERS
|
|
335
|
-
// ============================================================================
|
|
336
|
-
|
|
337
|
-
/**
|
|
338
|
-
* Helper to infer the success type from a Result
|
|
339
|
-
*/
|
|
340
|
-
export type SuccessType<T> = T extends Result<infer U, any> ? U : never;
|
|
341
|
-
|
|
342
|
-
/**
|
|
343
|
-
* Helper to infer the error type from a Result
|
|
344
|
-
*/
|
|
345
|
-
export type ErrorType<T> = T extends Result<any, infer E> ? E : never;
|
|
346
|
-
|
|
347
|
-
/**
|
|
348
|
-
* Create a type-safe Result from a function that might throw
|
|
349
|
-
*/
|
|
350
|
-
export type SafeResult<T extends (...args: any[]) => any> =
|
|
351
|
-
Result<ReturnType<T>, Error>;
|