@sylphx/flow 1.0.1 → 1.0.3

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 (229) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/package.json +10 -9
  3. package/src/commands/codebase-command.ts +168 -0
  4. package/src/commands/flow-command.ts +1137 -0
  5. package/src/commands/flow-orchestrator.ts +296 -0
  6. package/src/commands/hook-command.ts +444 -0
  7. package/src/commands/init-command.ts +92 -0
  8. package/src/commands/init-core.ts +322 -0
  9. package/src/commands/knowledge-command.ts +161 -0
  10. package/src/commands/run-command.ts +120 -0
  11. package/src/components/benchmark-monitor.tsx +331 -0
  12. package/src/components/reindex-progress.tsx +261 -0
  13. package/src/composables/functional/index.ts +14 -0
  14. package/src/composables/functional/useEnvironment.ts +171 -0
  15. package/src/composables/functional/useFileSystem.ts +139 -0
  16. package/src/composables/index.ts +5 -0
  17. package/src/composables/useEnv.ts +13 -0
  18. package/src/composables/useRuntimeConfig.ts +27 -0
  19. package/src/composables/useTargetConfig.ts +45 -0
  20. package/src/config/ai-config.ts +376 -0
  21. package/src/config/constants.ts +35 -0
  22. package/src/config/index.ts +27 -0
  23. package/src/config/rules.ts +43 -0
  24. package/src/config/servers.ts +371 -0
  25. package/src/config/targets.ts +126 -0
  26. package/src/core/agent-loader.ts +141 -0
  27. package/src/core/agent-manager.ts +174 -0
  28. package/src/core/ai-sdk.ts +603 -0
  29. package/src/core/app-factory.ts +381 -0
  30. package/src/core/builtin-agents.ts +9 -0
  31. package/src/core/command-system.ts +550 -0
  32. package/src/core/config-system.ts +550 -0
  33. package/src/core/connection-pool.ts +390 -0
  34. package/src/core/di-container.ts +155 -0
  35. package/src/core/error-handling.ts +519 -0
  36. package/src/core/formatting/bytes.test.ts +115 -0
  37. package/src/core/formatting/bytes.ts +64 -0
  38. package/src/core/functional/async.ts +313 -0
  39. package/src/core/functional/either.ts +109 -0
  40. package/src/core/functional/error-handler.ts +135 -0
  41. package/src/core/functional/error-types.ts +311 -0
  42. package/src/core/functional/index.ts +19 -0
  43. package/src/core/functional/option.ts +142 -0
  44. package/src/core/functional/pipe.ts +189 -0
  45. package/src/core/functional/result.ts +204 -0
  46. package/src/core/functional/validation.ts +138 -0
  47. package/src/core/headless-display.ts +96 -0
  48. package/src/core/index.ts +6 -0
  49. package/src/core/installers/file-installer.ts +303 -0
  50. package/src/core/installers/mcp-installer.ts +213 -0
  51. package/src/core/interfaces/index.ts +22 -0
  52. package/src/core/interfaces/repository.interface.ts +91 -0
  53. package/src/core/interfaces/service.interface.ts +133 -0
  54. package/src/core/interfaces.ts +129 -0
  55. package/src/core/loop-controller.ts +200 -0
  56. package/src/core/result.ts +351 -0
  57. package/src/core/rule-loader.ts +147 -0
  58. package/src/core/rule-manager.ts +240 -0
  59. package/src/core/service-config.ts +252 -0
  60. package/src/core/session-service.ts +121 -0
  61. package/src/core/state-detector.ts +389 -0
  62. package/src/core/storage-factory.ts +115 -0
  63. package/src/core/stream-handler.ts +288 -0
  64. package/src/core/target-manager.ts +161 -0
  65. package/src/core/type-utils.ts +427 -0
  66. package/src/core/unified-storage.ts +456 -0
  67. package/src/core/upgrade-manager.ts +300 -0
  68. package/src/core/validation/limit.test.ts +155 -0
  69. package/src/core/validation/limit.ts +46 -0
  70. package/src/core/validation/query.test.ts +44 -0
  71. package/src/core/validation/query.ts +20 -0
  72. package/src/db/auto-migrate.ts +322 -0
  73. package/src/db/base-database-client.ts +144 -0
  74. package/src/db/cache-db.ts +218 -0
  75. package/src/db/cache-schema.ts +75 -0
  76. package/src/db/database.ts +70 -0
  77. package/src/db/index.ts +252 -0
  78. package/src/db/memory-db.ts +153 -0
  79. package/src/db/memory-schema.ts +29 -0
  80. package/src/db/schema.ts +289 -0
  81. package/src/db/session-repository.ts +733 -0
  82. package/src/domains/codebase/index.ts +5 -0
  83. package/src/domains/codebase/tools.ts +139 -0
  84. package/src/domains/index.ts +8 -0
  85. package/src/domains/knowledge/index.ts +10 -0
  86. package/src/domains/knowledge/resources.ts +537 -0
  87. package/src/domains/knowledge/tools.ts +174 -0
  88. package/src/domains/utilities/index.ts +6 -0
  89. package/src/domains/utilities/time/index.ts +5 -0
  90. package/src/domains/utilities/time/tools.ts +291 -0
  91. package/src/index.ts +211 -0
  92. package/src/services/agent-service.ts +273 -0
  93. package/src/services/claude-config-service.ts +252 -0
  94. package/src/services/config-service.ts +258 -0
  95. package/src/services/evaluation-service.ts +271 -0
  96. package/src/services/functional/evaluation-logic.ts +296 -0
  97. package/src/services/functional/file-processor.ts +273 -0
  98. package/src/services/functional/index.ts +12 -0
  99. package/src/services/index.ts +13 -0
  100. package/src/services/mcp-service.ts +432 -0
  101. package/src/services/memory.service.ts +476 -0
  102. package/src/services/search/base-indexer.ts +156 -0
  103. package/src/services/search/codebase-indexer-types.ts +38 -0
  104. package/src/services/search/codebase-indexer.ts +647 -0
  105. package/src/services/search/embeddings-provider.ts +455 -0
  106. package/src/services/search/embeddings.ts +316 -0
  107. package/src/services/search/functional-indexer.ts +323 -0
  108. package/src/services/search/index.ts +27 -0
  109. package/src/services/search/indexer.ts +380 -0
  110. package/src/services/search/knowledge-indexer.ts +422 -0
  111. package/src/services/search/semantic-search.ts +244 -0
  112. package/src/services/search/tfidf.ts +559 -0
  113. package/src/services/search/unified-search-service.ts +888 -0
  114. package/src/services/smart-config-service.ts +385 -0
  115. package/src/services/storage/cache-storage.ts +487 -0
  116. package/src/services/storage/drizzle-storage.ts +581 -0
  117. package/src/services/storage/index.ts +15 -0
  118. package/src/services/storage/lancedb-vector-storage.ts +494 -0
  119. package/src/services/storage/memory-storage.ts +268 -0
  120. package/src/services/storage/separated-storage.ts +467 -0
  121. package/src/services/storage/vector-storage.ts +13 -0
  122. package/src/shared/agents/index.ts +63 -0
  123. package/src/shared/files/index.ts +99 -0
  124. package/src/shared/index.ts +32 -0
  125. package/src/shared/logging/index.ts +24 -0
  126. package/src/shared/processing/index.ts +153 -0
  127. package/src/shared/types/index.ts +25 -0
  128. package/src/targets/claude-code.ts +574 -0
  129. package/src/targets/functional/claude-code-logic.ts +185 -0
  130. package/src/targets/functional/index.ts +6 -0
  131. package/src/targets/opencode.ts +529 -0
  132. package/src/types/agent.types.ts +32 -0
  133. package/src/types/api/batch.ts +108 -0
  134. package/src/types/api/errors.ts +118 -0
  135. package/src/types/api/index.ts +55 -0
  136. package/src/types/api/requests.ts +76 -0
  137. package/src/types/api/responses.ts +180 -0
  138. package/src/types/api/websockets.ts +85 -0
  139. package/src/types/api.types.ts +9 -0
  140. package/src/types/benchmark.ts +49 -0
  141. package/src/types/cli.types.ts +87 -0
  142. package/src/types/common.types.ts +35 -0
  143. package/src/types/database.types.ts +510 -0
  144. package/src/types/mcp-config.types.ts +448 -0
  145. package/src/types/mcp.types.ts +69 -0
  146. package/src/types/memory-types.ts +63 -0
  147. package/src/types/provider.types.ts +28 -0
  148. package/src/types/rule.types.ts +24 -0
  149. package/src/types/session.types.ts +214 -0
  150. package/src/types/target-config.types.ts +295 -0
  151. package/src/types/target.types.ts +140 -0
  152. package/src/types/todo.types.ts +25 -0
  153. package/src/types.ts +40 -0
  154. package/src/utils/advanced-tokenizer.ts +191 -0
  155. package/src/utils/agent-enhancer.ts +114 -0
  156. package/src/utils/ai-model-fetcher.ts +19 -0
  157. package/src/utils/async-file-operations.ts +516 -0
  158. package/src/utils/audio-player.ts +345 -0
  159. package/src/utils/cli-output.ts +266 -0
  160. package/src/utils/codebase-helpers.ts +211 -0
  161. package/src/utils/console-ui.ts +79 -0
  162. package/src/utils/database-errors.ts +140 -0
  163. package/src/utils/debug-logger.ts +49 -0
  164. package/src/utils/error-handler.ts +53 -0
  165. package/src/utils/file-operations.ts +310 -0
  166. package/src/utils/file-scanner.ts +259 -0
  167. package/src/utils/functional/array.ts +355 -0
  168. package/src/utils/functional/index.ts +15 -0
  169. package/src/utils/functional/object.ts +279 -0
  170. package/src/utils/functional/string.ts +281 -0
  171. package/src/utils/functional.ts +543 -0
  172. package/src/utils/help.ts +20 -0
  173. package/src/utils/immutable-cache.ts +106 -0
  174. package/src/utils/index.ts +78 -0
  175. package/src/utils/jsonc.ts +158 -0
  176. package/src/utils/logger.ts +396 -0
  177. package/src/utils/mcp-config.ts +249 -0
  178. package/src/utils/memory-tui.ts +414 -0
  179. package/src/utils/models-dev.ts +91 -0
  180. package/src/utils/notifications.ts +169 -0
  181. package/src/utils/object-utils.ts +51 -0
  182. package/src/utils/parallel-operations.ts +487 -0
  183. package/src/utils/paths.ts +143 -0
  184. package/src/utils/process-manager.ts +155 -0
  185. package/src/utils/prompts.ts +120 -0
  186. package/src/utils/search-tool-builder.ts +214 -0
  187. package/src/utils/secret-utils.ts +179 -0
  188. package/src/utils/security.ts +537 -0
  189. package/src/utils/session-manager.ts +168 -0
  190. package/src/utils/session-title.ts +87 -0
  191. package/src/utils/settings.ts +182 -0
  192. package/src/utils/simplified-errors.ts +410 -0
  193. package/src/utils/sync-utils.ts +159 -0
  194. package/src/utils/target-config.ts +570 -0
  195. package/src/utils/target-utils.ts +394 -0
  196. package/src/utils/template-engine.ts +94 -0
  197. package/src/utils/test-audio.ts +71 -0
  198. package/src/utils/todo-context.ts +46 -0
  199. package/src/utils/token-counter.ts +288 -0
  200. package/dist/index.d.ts +0 -10
  201. package/dist/index.js +0 -59554
  202. package/dist/lancedb.linux-x64-gnu-b7f0jgsz.node +0 -0
  203. package/dist/lancedb.linux-x64-musl-tgcv22rx.node +0 -0
  204. package/dist/shared/chunk-25dwp0dp.js +0 -89
  205. package/dist/shared/chunk-3pjb6063.js +0 -208
  206. package/dist/shared/chunk-4d6ydpw7.js +0 -2854
  207. package/dist/shared/chunk-4wjcadjk.js +0 -225
  208. package/dist/shared/chunk-5j4w74t6.js +0 -30
  209. package/dist/shared/chunk-5j8m3dh3.js +0 -58
  210. package/dist/shared/chunk-5thh3qem.js +0 -91
  211. package/dist/shared/chunk-6g9xy73m.js +0 -252
  212. package/dist/shared/chunk-7eq34c42.js +0 -23
  213. package/dist/shared/chunk-c2gwgx3r.js +0 -115
  214. package/dist/shared/chunk-cjd3mk4c.js +0 -1320
  215. package/dist/shared/chunk-g5cv6703.js +0 -368
  216. package/dist/shared/chunk-hpkhykhq.js +0 -574
  217. package/dist/shared/chunk-m2322pdk.js +0 -122
  218. package/dist/shared/chunk-nd5fdvaq.js +0 -26
  219. package/dist/shared/chunk-pgd3m6zf.js +0 -108
  220. package/dist/shared/chunk-qk8n91hw.js +0 -494
  221. package/dist/shared/chunk-rkkn8szp.js +0 -16855
  222. package/dist/shared/chunk-t16rfxh0.js +0 -61
  223. package/dist/shared/chunk-t4fbfa5v.js +0 -19
  224. package/dist/shared/chunk-t77h86w6.js +0 -276
  225. package/dist/shared/chunk-v0ez4aef.js +0 -71
  226. package/dist/shared/chunk-v29j2r3s.js +0 -32051
  227. package/dist/shared/chunk-vfbc6ew5.js +0 -765
  228. package/dist/shared/chunk-vmeqwm1c.js +0 -204
  229. package/dist/shared/chunk-x66eh37x.js +0 -137
@@ -0,0 +1,311 @@
1
+ /**
2
+ * Standard error types for the application
3
+ * Typed errors enable better error handling and recovery
4
+ *
5
+ * DESIGN RATIONALE:
6
+ * - Discriminated union for all error types
7
+ * - Each error type has specific context
8
+ * - Enables type-safe error handling
9
+ * - Clear error categories for recovery strategies
10
+ */
11
+
12
+ /**
13
+ * Base error type with common fields
14
+ */
15
+ export interface BaseError {
16
+ readonly kind: string;
17
+ readonly message: string;
18
+ readonly context?: Record<string, unknown>;
19
+ readonly cause?: Error;
20
+ }
21
+
22
+ /**
23
+ * Configuration error - invalid configuration or missing required config
24
+ */
25
+ export interface ConfigError extends BaseError {
26
+ readonly kind: 'ConfigError';
27
+ readonly configKey?: string;
28
+ readonly configPath?: string;
29
+ }
30
+
31
+ /**
32
+ * File system error - file not found, permission denied, etc.
33
+ */
34
+ export interface FileSystemError extends BaseError {
35
+ readonly kind: 'FileSystemError';
36
+ readonly path: string;
37
+ readonly operation: 'read' | 'write' | 'delete' | 'create' | 'stat';
38
+ }
39
+
40
+ /**
41
+ * Database error - query failure, connection error, etc.
42
+ */
43
+ export interface DatabaseError extends BaseError {
44
+ readonly kind: 'DatabaseError';
45
+ readonly operation: string;
46
+ readonly table?: string;
47
+ }
48
+
49
+ /**
50
+ * Validation error - input validation failure
51
+ */
52
+ export interface ValidationError extends BaseError {
53
+ readonly kind: 'ValidationError';
54
+ readonly field?: string;
55
+ readonly errors: string[];
56
+ }
57
+
58
+ /**
59
+ * Network error - HTTP error, timeout, connection refused, etc.
60
+ */
61
+ export interface NetworkError extends BaseError {
62
+ readonly kind: 'NetworkError';
63
+ readonly url?: string;
64
+ readonly statusCode?: number;
65
+ }
66
+
67
+ /**
68
+ * CLI error - command line interface specific errors
69
+ */
70
+ export interface CLIError extends BaseError {
71
+ readonly kind: 'CLIError';
72
+ readonly command?: string;
73
+ readonly exitCode?: number;
74
+ }
75
+
76
+ /**
77
+ * Not found error - resource not found
78
+ */
79
+ export interface NotFoundError extends BaseError {
80
+ readonly kind: 'NotFoundError';
81
+ readonly resourceType: string;
82
+ readonly resourceId: string;
83
+ }
84
+
85
+ /**
86
+ * Permission error - insufficient permissions
87
+ */
88
+ export interface PermissionError extends BaseError {
89
+ readonly kind: 'PermissionError';
90
+ readonly resource: string;
91
+ readonly requiredPermission: string;
92
+ }
93
+
94
+ /**
95
+ * Unknown error - catch-all for unexpected errors
96
+ */
97
+ export interface UnknownError extends BaseError {
98
+ readonly kind: 'UnknownError';
99
+ }
100
+
101
+ /**
102
+ * Union of all error types
103
+ */
104
+ export type AppError =
105
+ | ConfigError
106
+ | FileSystemError
107
+ | DatabaseError
108
+ | ValidationError
109
+ | NetworkError
110
+ | CLIError
111
+ | NotFoundError
112
+ | PermissionError
113
+ | UnknownError;
114
+
115
+ /**
116
+ * Error constructors
117
+ */
118
+
119
+ export const configError = (
120
+ message: string,
121
+ options?: {
122
+ configKey?: string;
123
+ configPath?: string;
124
+ context?: Record<string, unknown>;
125
+ cause?: Error;
126
+ }
127
+ ): ConfigError => ({
128
+ kind: 'ConfigError',
129
+ message,
130
+ configKey: options?.configKey,
131
+ configPath: options?.configPath,
132
+ context: options?.context,
133
+ cause: options?.cause,
134
+ });
135
+
136
+ export const fileSystemError = (
137
+ message: string,
138
+ path: string,
139
+ operation: 'read' | 'write' | 'delete' | 'create' | 'stat',
140
+ options?: { context?: Record<string, unknown>; cause?: Error }
141
+ ): FileSystemError => ({
142
+ kind: 'FileSystemError',
143
+ message,
144
+ path,
145
+ operation,
146
+ context: options?.context,
147
+ cause: options?.cause,
148
+ });
149
+
150
+ export const databaseError = (
151
+ message: string,
152
+ operation: string,
153
+ options?: { table?: string; context?: Record<string, unknown>; cause?: Error }
154
+ ): DatabaseError => ({
155
+ kind: 'DatabaseError',
156
+ message,
157
+ operation,
158
+ table: options?.table,
159
+ context: options?.context,
160
+ cause: options?.cause,
161
+ });
162
+
163
+ export const validationError = (
164
+ message: string,
165
+ errors: string[],
166
+ options?: { field?: string; context?: Record<string, unknown> }
167
+ ): ValidationError => ({
168
+ kind: 'ValidationError',
169
+ message,
170
+ field: options?.field,
171
+ errors,
172
+ context: options?.context,
173
+ });
174
+
175
+ export const networkError = (
176
+ message: string,
177
+ options?: { url?: string; statusCode?: number; context?: Record<string, unknown>; cause?: Error }
178
+ ): NetworkError => ({
179
+ kind: 'NetworkError',
180
+ message,
181
+ url: options?.url,
182
+ statusCode: options?.statusCode,
183
+ context: options?.context,
184
+ cause: options?.cause,
185
+ });
186
+
187
+ export const cliError = (
188
+ message: string,
189
+ options?: {
190
+ command?: string;
191
+ exitCode?: number;
192
+ context?: Record<string, unknown>;
193
+ cause?: Error;
194
+ }
195
+ ): CLIError => ({
196
+ kind: 'CLIError',
197
+ message,
198
+ command: options?.command,
199
+ exitCode: options?.exitCode,
200
+ context: options?.context,
201
+ cause: options?.cause,
202
+ });
203
+
204
+ export const notFoundError = (
205
+ message: string,
206
+ resourceType: string,
207
+ resourceId: string,
208
+ options?: { context?: Record<string, unknown>; cause?: Error }
209
+ ): NotFoundError => ({
210
+ kind: 'NotFoundError',
211
+ message,
212
+ resourceType,
213
+ resourceId,
214
+ context: options?.context,
215
+ cause: options?.cause,
216
+ });
217
+
218
+ export const permissionError = (
219
+ message: string,
220
+ resource: string,
221
+ requiredPermission: string,
222
+ options?: { context?: Record<string, unknown>; cause?: Error }
223
+ ): PermissionError => ({
224
+ kind: 'PermissionError',
225
+ message,
226
+ resource,
227
+ requiredPermission,
228
+ context: options?.context,
229
+ cause: options?.cause,
230
+ });
231
+
232
+ export const unknownError = (
233
+ message: string,
234
+ options?: { context?: Record<string, unknown>; cause?: Error }
235
+ ): UnknownError => ({
236
+ kind: 'UnknownError',
237
+ message,
238
+ context: options?.context,
239
+ cause: options?.cause,
240
+ });
241
+
242
+ /**
243
+ * Convert unknown error to AppError
244
+ */
245
+ export const toAppError = (error: unknown): AppError => {
246
+ if (isAppError(error)) {
247
+ return error;
248
+ }
249
+
250
+ if (error instanceof Error) {
251
+ return unknownError(error.message, { cause: error });
252
+ }
253
+
254
+ return unknownError(String(error));
255
+ };
256
+
257
+ /**
258
+ * Type guard for AppError
259
+ */
260
+ export const isAppError = (error: unknown): error is AppError => {
261
+ return typeof error === 'object' && error !== null && 'kind' in error && 'message' in error;
262
+ };
263
+
264
+ /**
265
+ * Format error for display
266
+ */
267
+ export const formatError = (error: AppError): string => {
268
+ let formatted = `[${error.kind}] ${error.message}`;
269
+
270
+ if (error.kind === 'ConfigError' && error.configKey) {
271
+ formatted += `\n Config key: ${error.configKey}`;
272
+ }
273
+
274
+ if (error.kind === 'FileSystemError') {
275
+ formatted += `\n Path: ${error.path}`;
276
+ formatted += `\n Operation: ${error.operation}`;
277
+ }
278
+
279
+ if (error.kind === 'DatabaseError') {
280
+ formatted += `\n Operation: ${error.operation}`;
281
+ if (error.table) {
282
+ formatted += `\n Table: ${error.table}`;
283
+ }
284
+ }
285
+
286
+ if (error.kind === 'ValidationError') {
287
+ formatted += `\n Errors:`;
288
+ for (const err of error.errors) {
289
+ formatted += `\n - ${err}`;
290
+ }
291
+ }
292
+
293
+ if (error.kind === 'NetworkError') {
294
+ if (error.url) {
295
+ formatted += `\n URL: ${error.url}`;
296
+ }
297
+ if (error.statusCode) {
298
+ formatted += `\n Status: ${error.statusCode}`;
299
+ }
300
+ }
301
+
302
+ if (error.context) {
303
+ formatted += `\n Context: ${JSON.stringify(error.context, null, 2)}`;
304
+ }
305
+
306
+ if (error.cause) {
307
+ formatted += `\n Caused by: ${error.cause.message}`;
308
+ }
309
+
310
+ return formatted;
311
+ };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Functional programming utilities
3
+ * Core abstractions for composable, type-safe error handling
4
+ *
5
+ * PRINCIPLES:
6
+ * - Pure functions (no side effects)
7
+ * - Explicit error handling (no exceptions in business logic)
8
+ * - Composable through map/flatMap
9
+ * - Type-safe (leverages TypeScript's type system)
10
+ */
11
+
12
+ export * from './async.js';
13
+ export * from './either.js';
14
+ export * from './error-handler.js';
15
+ export * from './error-types.js';
16
+ export * from './option.js';
17
+ export * from './pipe.js';
18
+ export * from './result.js';
19
+ export * from './validation.js';
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Option type for representing optional values
3
+ * Eliminates null/undefined and makes optionality explicit
4
+ *
5
+ * DESIGN RATIONALE:
6
+ * - Makes absence of value explicit at type level
7
+ * - Eliminates null pointer errors
8
+ * - Composable through map/flatMap
9
+ * - Forces handling of missing values
10
+ */
11
+
12
+ export type Option<T> = Some<T> | None;
13
+
14
+ export interface Some<T> {
15
+ readonly _tag: 'Some';
16
+ readonly value: T;
17
+ }
18
+
19
+ export interface None {
20
+ readonly _tag: 'None';
21
+ }
22
+
23
+ /**
24
+ * Constructors
25
+ */
26
+
27
+ export const some = <T>(value: T): Some<T> => ({
28
+ _tag: 'Some',
29
+ value,
30
+ });
31
+
32
+ export const none: None = {
33
+ _tag: 'None',
34
+ };
35
+
36
+ /**
37
+ * Create Option from nullable value
38
+ */
39
+ export const fromNullable = <T>(value: T | null | undefined): Option<T> => {
40
+ if (value === null || value === undefined) {
41
+ return none;
42
+ }
43
+ return some(value);
44
+ };
45
+
46
+ /**
47
+ * Type guards
48
+ */
49
+
50
+ export const isSome = <T>(option: Option<T>): option is Some<T> => option._tag === 'Some';
51
+
52
+ export const isNone = <T>(option: Option<T>): option is None => option._tag === 'None';
53
+
54
+ /**
55
+ * Transformations
56
+ */
57
+
58
+ export const map =
59
+ <T, U>(fn: (value: T) => U) =>
60
+ (option: Option<T>): Option<U> => {
61
+ if (isSome(option)) {
62
+ return some(fn(option.value));
63
+ }
64
+ return none;
65
+ };
66
+
67
+ export const flatMap =
68
+ <T, U>(fn: (value: T) => Option<U>) =>
69
+ (option: Option<T>): Option<U> => {
70
+ if (isSome(option)) {
71
+ return fn(option.value);
72
+ }
73
+ return none;
74
+ };
75
+
76
+ /**
77
+ * Extract value or provide default
78
+ */
79
+ export const getOrElse =
80
+ <T>(defaultValue: T) =>
81
+ (option: Option<T>): T => {
82
+ if (isSome(option)) {
83
+ return option.value;
84
+ }
85
+ return defaultValue;
86
+ };
87
+
88
+ /**
89
+ * Extract value or compute default
90
+ */
91
+ export const getOrElseLazy =
92
+ <T>(fn: () => T) =>
93
+ (option: Option<T>): T => {
94
+ if (isSome(option)) {
95
+ return option.value;
96
+ }
97
+ return fn();
98
+ };
99
+
100
+ /**
101
+ * Pattern matching
102
+ */
103
+ export const match =
104
+ <T, U>(onSome: (value: T) => U, onNone: () => U) =>
105
+ (option: Option<T>): U => {
106
+ if (isSome(option)) {
107
+ return onSome(option.value);
108
+ }
109
+ return onNone();
110
+ };
111
+
112
+ /**
113
+ * Filter based on predicate
114
+ */
115
+ export const filter =
116
+ <T>(predicate: (value: T) => boolean) =>
117
+ (option: Option<T>): Option<T> => {
118
+ if (isSome(option) && predicate(option.value)) {
119
+ return option;
120
+ }
121
+ return none;
122
+ };
123
+
124
+ /**
125
+ * Convert to nullable
126
+ */
127
+ export const toNullable = <T>(option: Option<T>): T | null => {
128
+ if (isSome(option)) {
129
+ return option.value;
130
+ }
131
+ return null;
132
+ };
133
+
134
+ /**
135
+ * Convert to undefined
136
+ */
137
+ export const toUndefined = <T>(option: Option<T>): T | undefined => {
138
+ if (isSome(option)) {
139
+ return option.value;
140
+ }
141
+ return undefined;
142
+ };
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Function composition utilities
3
+ * Enable declarative data transformation pipelines
4
+ *
5
+ * DESIGN RATIONALE:
6
+ * - Left-to-right composition (more readable than f(g(h(x))))
7
+ * - Type-safe (TypeScript infers types through the pipeline)
8
+ * - Point-free style support
9
+ * - Declarative over imperative
10
+ */
11
+
12
+ /**
13
+ * Compose functions left-to-right
14
+ * pipe(value, fn1, fn2, fn3) === fn3(fn2(fn1(value)))
15
+ */
16
+ export function pipe<A>(value: A): A;
17
+ export function pipe<A, B>(value: A, fn1: (a: A) => B): B;
18
+ export function pipe<A, B, C>(value: A, fn1: (a: A) => B, fn2: (b: B) => C): C;
19
+ export function pipe<A, B, C, D>(value: A, fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D): D;
20
+ export function pipe<A, B, C, D, E>(
21
+ value: A,
22
+ fn1: (a: A) => B,
23
+ fn2: (b: B) => C,
24
+ fn3: (c: C) => D,
25
+ fn4: (d: D) => E
26
+ ): E;
27
+ export function pipe<A, B, C, D, E, F>(
28
+ value: A,
29
+ fn1: (a: A) => B,
30
+ fn2: (b: B) => C,
31
+ fn3: (c: C) => D,
32
+ fn4: (d: D) => E,
33
+ fn5: (e: E) => F
34
+ ): F;
35
+ export function pipe<A, B, C, D, E, F, G>(
36
+ value: A,
37
+ fn1: (a: A) => B,
38
+ fn2: (b: B) => C,
39
+ fn3: (c: C) => D,
40
+ fn4: (d: D) => E,
41
+ fn5: (e: E) => F,
42
+ fn6: (f: F) => G
43
+ ): G;
44
+ export function pipe<A, B, C, D, E, F, G, H>(
45
+ value: A,
46
+ fn1: (a: A) => B,
47
+ fn2: (b: B) => C,
48
+ fn3: (c: C) => D,
49
+ fn4: (d: D) => E,
50
+ fn5: (e: E) => F,
51
+ fn6: (f: F) => G,
52
+ fn7: (g: G) => H
53
+ ): H;
54
+ export function pipe<A, B, C, D, E, F, G, H, I>(
55
+ value: A,
56
+ fn1: (a: A) => B,
57
+ fn2: (b: B) => C,
58
+ fn3: (c: C) => D,
59
+ fn4: (d: D) => E,
60
+ fn5: (e: E) => F,
61
+ fn6: (f: F) => G,
62
+ fn7: (g: G) => H,
63
+ fn8: (h: H) => I
64
+ ): I;
65
+ export function pipe<A, B, C, D, E, F, G, H, I, J>(
66
+ value: A,
67
+ fn1: (a: A) => B,
68
+ fn2: (b: B) => C,
69
+ fn3: (c: C) => D,
70
+ fn4: (d: D) => E,
71
+ fn5: (e: E) => F,
72
+ fn6: (f: F) => G,
73
+ fn7: (g: G) => H,
74
+ fn8: (h: H) => I,
75
+ fn9: (i: I) => J
76
+ ): J;
77
+ export function pipe(value: any, ...fns: Array<(arg: any) => any>): any {
78
+ return fns.reduce((acc, fn) => fn(acc), value);
79
+ }
80
+
81
+ /**
82
+ * Create a composed function from multiple functions
83
+ * flow(fn1, fn2, fn3) creates a new function that applies fn1, then fn2, then fn3
84
+ */
85
+ export function flow<A, B>(fn1: (a: A) => B): (a: A) => B;
86
+ export function flow<A, B, C>(fn1: (a: A) => B, fn2: (b: B) => C): (a: A) => C;
87
+ export function flow<A, B, C, D>(fn1: (a: A) => B, fn2: (b: B) => C, fn3: (c: C) => D): (a: A) => D;
88
+ export function flow<A, B, C, D, E>(
89
+ fn1: (a: A) => B,
90
+ fn2: (b: B) => C,
91
+ fn3: (c: C) => D,
92
+ fn4: (d: D) => E
93
+ ): (a: A) => E;
94
+ export function flow<A, B, C, D, E, F>(
95
+ fn1: (a: A) => B,
96
+ fn2: (b: B) => C,
97
+ fn3: (c: C) => D,
98
+ fn4: (d: D) => E,
99
+ fn5: (e: E) => F
100
+ ): (a: A) => F;
101
+ export function flow<A, B, C, D, E, F, G>(
102
+ fn1: (a: A) => B,
103
+ fn2: (b: B) => C,
104
+ fn3: (c: C) => D,
105
+ fn4: (d: D) => E,
106
+ fn5: (e: E) => F,
107
+ fn6: (f: F) => G
108
+ ): (a: A) => G;
109
+ export function flow<A, B, C, D, E, F, G, H>(
110
+ fn1: (a: A) => B,
111
+ fn2: (b: B) => C,
112
+ fn3: (c: C) => D,
113
+ fn4: (d: D) => E,
114
+ fn5: (e: E) => F,
115
+ fn6: (f: F) => G,
116
+ fn7: (g: G) => H
117
+ ): (a: A) => H;
118
+ export function flow<A, B, C, D, E, F, G, H, I>(
119
+ fn1: (a: A) => B,
120
+ fn2: (b: B) => C,
121
+ fn3: (c: C) => D,
122
+ fn4: (d: D) => E,
123
+ fn5: (e: E) => F,
124
+ fn6: (f: F) => G,
125
+ fn7: (g: G) => H,
126
+ fn8: (h: H) => I
127
+ ): (a: A) => I;
128
+ export function flow<A, B, C, D, E, F, G, H, I, J>(
129
+ fn1: (a: A) => B,
130
+ fn2: (b: B) => C,
131
+ fn3: (c: C) => D,
132
+ fn4: (d: D) => E,
133
+ fn5: (e: E) => F,
134
+ fn6: (f: F) => G,
135
+ fn7: (g: G) => H,
136
+ fn8: (h: H) => I,
137
+ fn9: (i: I) => J
138
+ ): (a: A) => J;
139
+ export function flow(...fns: Array<(arg: any) => any>): (arg: any) => any {
140
+ return (value: any) => pipe(value, ...fns);
141
+ }
142
+
143
+ /**
144
+ * Identity function - returns input unchanged
145
+ * Useful as a no-op transformation or default
146
+ */
147
+ export const identity = <T>(value: T): T => value;
148
+
149
+ /**
150
+ * Constant function - returns a function that always returns the same value
151
+ * Useful for providing defaults
152
+ */
153
+ export const constant =
154
+ <T>(value: T) =>
155
+ (): T =>
156
+ value;
157
+
158
+ /**
159
+ * Tap - run a side effect and return the original value
160
+ * Useful for debugging or logging in a pipeline
161
+ */
162
+ export const tap =
163
+ <T>(fn: (value: T) => void) =>
164
+ (value: T): T => {
165
+ fn(value);
166
+ return value;
167
+ };
168
+
169
+ /**
170
+ * Memoize - cache function results
171
+ * Only for pure functions with string/number arguments
172
+ */
173
+ export const memoize = <Args extends Array<string | number>, R>(
174
+ fn: (...args: Args) => R
175
+ ): ((...args: Args) => R) => {
176
+ const cache = new Map<string, R>();
177
+
178
+ return (...args: Args): R => {
179
+ const key = JSON.stringify(args);
180
+
181
+ if (cache.has(key)) {
182
+ return cache.get(key)!;
183
+ }
184
+
185
+ const result = fn(...args);
186
+ cache.set(key, result);
187
+ return result;
188
+ };
189
+ };