wellcrafted 0.26.0 → 0.27.0

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.
@@ -158,136 +158,6 @@ declare function extractErrorMessage(error: unknown): string;
158
158
  * ```
159
159
  */
160
160
  type ReplaceErrorWithErr<T extends `${string}Error`> = T extends `${infer TBase}Error` ? `${TBase}Err` : never;
161
- /**
162
- * Return type when neither context nor cause are constrained (flexible mode).
163
- * Context and cause are optional with loose typing.
164
- */
165
- type FlexibleFactories<TName extends `${string}Error`> = { [K in TName]: FlexibleErrorConstructor<K> } & { [K in ReplaceErrorWithErr<TName>]: FlexibleErrConstructor<TName> };
166
- /**
167
- * Return type when context is fixed.
168
- * Context is required with exact type; cause is optional.
169
- */
170
- type ContextFixedFactories<TName extends `${string}Error`, TContext extends Record<string, unknown>> = { [K in TName]: ContextFixedErrorConstructor<K, TContext> } & { [K in ReplaceErrorWithErr<TName>]: ContextFixedErrConstructor<TName, TContext> };
171
- /**
172
- * Return type when both context and cause are fixed.
173
- * Context is required; cause is optional but constrained to specific type.
174
- */
175
- type BothFixedFactories<TName extends `${string}Error`, TContext extends Record<string, unknown>, TCause extends AnyTaggedError> = { [K in TName]: BothFixedErrorConstructor<K, TContext, TCause> } & { [K in ReplaceErrorWithErr<TName>]: BothFixedErrConstructor<TName, TContext, TCause> };
176
- /**
177
- * Creates plain TaggedError objects with flexible context and cause.
178
- * Single signature: context and cause are optional with loose typing.
179
- */
180
- type FlexibleErrorConstructor<TName extends string> = (input: {
181
- message: string;
182
- context?: Record<string, unknown>;
183
- cause?: AnyTaggedError;
184
- }) => TaggedError<TName>;
185
- /**
186
- * Creates Err-wrapped TaggedError objects with flexible context and cause.
187
- * Single signature: context and cause are optional with loose typing.
188
- */
189
- type FlexibleErrConstructor<TName extends string> = (input: {
190
- message: string;
191
- context?: Record<string, unknown>;
192
- cause?: AnyTaggedError;
193
- }) => Err<TaggedError<TName>>;
194
- /**
195
- * Creates plain TaggedError objects with fixed context.
196
- * Single signature: context is required, cause is optional.
197
- */
198
- type ContextFixedErrorConstructor<TName extends string, TContext extends Record<string, unknown>> = (input: {
199
- message: string;
200
- context: TContext;
201
- cause?: AnyTaggedError;
202
- }) => TaggedError<TName, TContext>;
203
- /**
204
- * Creates Err-wrapped TaggedError objects with fixed context.
205
- * Single signature: context is required, cause is optional.
206
- */
207
- type ContextFixedErrConstructor<TName extends string, TContext extends Record<string, unknown>> = (input: {
208
- message: string;
209
- context: TContext;
210
- cause?: AnyTaggedError;
211
- }) => Err<TaggedError<TName, TContext>>;
212
- /**
213
- * Creates plain TaggedError objects with both context and cause fixed.
214
- * Single signature: context is required, cause is optional but constrained.
215
- */
216
- type BothFixedErrorConstructor<TName extends string, TContext extends Record<string, unknown>, TCause extends AnyTaggedError> = (input: {
217
- message: string;
218
- context: TContext;
219
- cause?: TCause;
220
- }) => TaggedError<TName, TContext, TCause>;
221
- /**
222
- * Creates Err-wrapped TaggedError objects with both context and cause fixed.
223
- * Single signature: context is required, cause is optional but constrained.
224
- */
225
- type BothFixedErrConstructor<TName extends string, TContext extends Record<string, unknown>, TCause extends AnyTaggedError> = (input: {
226
- message: string;
227
- context: TContext;
228
- cause?: TCause;
229
- }) => Err<TaggedError<TName, TContext, TCause>>;
230
- /**
231
- * Creates two factory functions for building tagged errors with type-safe error chaining.
232
- *
233
- * @deprecated Use `defineError()` instead for a cleaner fluent API:
234
- * ```ts
235
- * // Before
236
- * const { FileError } = createTaggedError<'FileError', { path: string }>('FileError')
237
- *
238
- * // After
239
- * const { FileError } = defineError('FileError')
240
- * .withContext<{ path: string }>()
241
- * ```
242
- *
243
- * Given an error name like "NetworkError", this returns:
244
- * - `NetworkError`: Creates a plain TaggedError object
245
- * - `NetworkErr`: Creates a TaggedError object wrapped in an Err result
246
- *
247
- * **Three usage modes:**
248
- *
249
- * 1. **Flexible mode** (no type params): Context and cause are optional, loosely typed
250
- * 2. **Fixed context mode** (TContext specified): Context is required with exact shape
251
- * 3. **Both fixed mode** (TContext + TCause): Context required, cause constrained
252
- *
253
- * **ReturnType works correctly in all modes:**
254
- * ```ts
255
- * const { NetworkError } = createTaggedError('NetworkError');
256
- * type NetworkError = ReturnType<typeof NetworkError>;
257
- * // = TaggedError<'NetworkError'> with optional context/cause
258
- * ```
259
- *
260
- * @template TName - The name of the error type (must end with "Error")
261
- * @template TContext - Optional fixed context shape (makes context required)
262
- * @template TCause - Optional fixed cause type (constrains cause type if provided)
263
- * @param name - The name of the error type (must end with "Error")
264
- *
265
- * @example
266
- * ```ts
267
- * // Mode 1: Flexible - context and cause optional, loosely typed
268
- * const { NetworkError, NetworkErr } = createTaggedError('NetworkError');
269
- * NetworkError({ message: 'Connection failed' });
270
- * NetworkError({ message: 'Timeout', context: { url: 'https://...' } });
271
- * NetworkError({ message: 'Failed', cause: otherError });
272
- *
273
- * // Type annotation works with ReturnType:
274
- * type NetworkError = ReturnType<typeof NetworkError>;
275
- *
276
- * // Mode 2: Fixed context - context REQUIRED with exact shape
277
- * type BlobContext = { filename: string; code: 'INVALID' | 'TOO_LARGE' };
278
- * const { BlobError, BlobErr } = createTaggedError<'BlobError', BlobContext>('BlobError');
279
- * BlobError({ message: 'Invalid', context: { filename: 'x', code: 'INVALID' } });
280
- * // BlobError({ message: 'Error' }); // Type error - context required
281
- *
282
- * // Mode 3: Fixed context + cause - context required, cause constrained
283
- * const { ApiError, ApiErr } = createTaggedError<'ApiError', { endpoint: string }, NetworkError>('ApiError');
284
- * ApiError({ message: 'Failed', context: { endpoint: '/users' } });
285
- * ApiError({ message: 'Failed', context: { endpoint: '/users' }, cause: networkError });
286
- * ```
287
- */
288
- declare function createTaggedError<TName extends `${string}Error`>(name: TName): FlexibleFactories<TName>;
289
- declare function createTaggedError<TName extends `${string}Error`, TContext extends Record<string, unknown>>(name: TName): ContextFixedFactories<TName, TContext>;
290
- declare function createTaggedError<TName extends `${string}Error`, TContext extends Record<string, unknown>, TCause extends AnyTaggedError>(name: TName): BothFixedFactories<TName, TContext, TCause>;
291
161
  /**
292
162
  * Helper type that determines optionality based on whether T includes undefined.
293
163
  * - If T includes undefined → property is optional
@@ -305,11 +175,11 @@ type ErrorInput<TContext extends Record<string, unknown> | undefined, TCause ext
305
175
  cause?: AnyTaggedError;
306
176
  } : OptionalIfUndefined<TCause, "cause">);
307
177
  /**
308
- * The factories object returned by defineError and its builder methods.
178
+ * The factories object returned by createTaggedError and its builder methods.
309
179
  */
310
180
  type ErrorFactories<TName extends `${string}Error`, TContext extends Record<string, unknown> | undefined, TCause extends AnyTaggedError | undefined> = { [K in TName]: (input: ErrorInput<TContext, TCause>) => TaggedError<TName, TContext, TCause> } & { [K in ReplaceErrorWithErr<TName>]: (input: ErrorInput<TContext, TCause>) => Err<TaggedError<TName, TContext, TCause>> };
311
181
  /**
312
- * Builder interface for the fluent defineError API.
182
+ * Builder interface for the fluent createTaggedError API.
313
183
  * Provides chaining methods and the error factories.
314
184
  */
315
185
  type ErrorBuilder<TName extends `${string}Error`, TContext extends Record<string, unknown> | undefined = undefined, TCause extends AnyTaggedError | undefined = undefined> = ErrorFactories<TName, TContext, TCause> & {
@@ -324,7 +194,7 @@ type ErrorBuilder<TName extends `${string}Error`, TContext extends Record<string
324
194
  *
325
195
  * @example Required context
326
196
  * ```ts
327
- * const { FileError } = defineError('FileError')
197
+ * const { FileError } = createTaggedError('FileError')
328
198
  * .withContext<{ path: string }>()
329
199
  *
330
200
  * FileError({ message: 'Not found', context: { path: '/etc/config' } }) // OK
@@ -333,7 +203,7 @@ type ErrorBuilder<TName extends `${string}Error`, TContext extends Record<string
333
203
  *
334
204
  * @example Optional but typed context
335
205
  * ```ts
336
- * const { LogError } = defineError('LogError')
206
+ * const { LogError } = createTaggedError('LogError')
337
207
  * .withContext<{ file: string; line: number } | undefined>()
338
208
  *
339
209
  * LogError({ message: 'Parse error' }) // OK
@@ -354,7 +224,7 @@ type ErrorBuilder<TName extends `${string}Error`, TContext extends Record<string
354
224
  *
355
225
  * @example Optional typed cause (common)
356
226
  * ```ts
357
- * const { ServiceError } = defineError('ServiceError')
227
+ * const { ServiceError } = createTaggedError('ServiceError')
358
228
  * .withCause<DbError | CacheError | undefined>()
359
229
  *
360
230
  * ServiceError({ message: 'Failed' }) // OK
@@ -363,7 +233,7 @@ type ErrorBuilder<TName extends `${string}Error`, TContext extends Record<string
363
233
  *
364
234
  * @example Required cause (for wrapper errors)
365
235
  * ```ts
366
- * const { UnhandledError } = defineError('UnhandledError')
236
+ * const { UnhandledError } = createTaggedError('UnhandledError')
367
237
  * .withCause<AnyTaggedError>()
368
238
  *
369
239
  * UnhandledError({ message: 'Unexpected', cause: originalError }) // OK
@@ -373,7 +243,7 @@ type ErrorBuilder<TName extends `${string}Error`, TContext extends Record<string
373
243
  withCause<T extends AnyTaggedError | undefined>(): ErrorBuilder<TName, TContext, T>;
374
244
  };
375
245
  /**
376
- * Defines a new tagged error type with a fluent builder API.
246
+ * Creates a new tagged error type with a fluent builder API.
377
247
  *
378
248
  * Returns an object containing:
379
249
  * - `{Name}Error`: Factory function that creates plain TaggedError objects
@@ -396,7 +266,7 @@ type ErrorBuilder<TName extends `${string}Error`, TContext extends Record<string
396
266
  *
397
267
  * @example Simple error (flexible mode)
398
268
  * ```ts
399
- * const { NetworkError, NetworkErr } = defineError('NetworkError')
269
+ * const { NetworkError, NetworkErr } = createTaggedError('NetworkError')
400
270
  *
401
271
  * NetworkError({ message: 'Connection failed' })
402
272
  * NetworkError({ message: 'Timeout', context: { url: 'https://...' } })
@@ -404,7 +274,7 @@ type ErrorBuilder<TName extends `${string}Error`, TContext extends Record<string
404
274
  *
405
275
  * @example Required context
406
276
  * ```ts
407
- * const { ApiError, ApiErr } = defineError('ApiError')
277
+ * const { ApiError, ApiErr } = createTaggedError('ApiError')
408
278
  * .withContext<{ endpoint: string; status: number }>()
409
279
  *
410
280
  * ApiError({ message: 'Failed', context: { endpoint: '/users', status: 500 } })
@@ -413,7 +283,7 @@ type ErrorBuilder<TName extends `${string}Error`, TContext extends Record<string
413
283
  *
414
284
  * @example Optional typed cause
415
285
  * ```ts
416
- * const { ServiceError } = defineError('ServiceError')
286
+ * const { ServiceError } = createTaggedError('ServiceError')
417
287
  * .withCause<DbError | CacheError | undefined>()
418
288
  *
419
289
  * ServiceError({ message: 'Failed' }) // OK
@@ -422,7 +292,7 @@ type ErrorBuilder<TName extends `${string}Error`, TContext extends Record<string
422
292
  *
423
293
  * @example Full example with both
424
294
  * ```ts
425
- * const { UserServiceError } = defineError('UserServiceError')
295
+ * const { UserServiceError } = createTaggedError('UserServiceError')
426
296
  * .withContext<{ userId: string }>()
427
297
  * .withCause<RepoError | undefined>()
428
298
  *
@@ -430,7 +300,7 @@ type ErrorBuilder<TName extends `${string}Error`, TContext extends Record<string
430
300
  * type UserServiceError = ReturnType<typeof UserServiceError>
431
301
  * ```
432
302
  */
433
- declare function defineError<TName extends `${string}Error`>(name: TName): ErrorBuilder<TName>;
303
+ declare function createTaggedError<TName extends `${string}Error`>(name: TName): ErrorBuilder<TName>;
434
304
  //#endregion
435
- export { AnyTaggedError, TaggedError, createTaggedError, defineError, extractErrorMessage };
305
+ export { AnyTaggedError, TaggedError, createTaggedError, extractErrorMessage };
436
306
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/error/types.ts","../../src/error/utils.ts"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/error/types.ts","../../src/error/utils.ts"],"sourcesContent":[],"mappings":"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"}
@@ -63,20 +63,8 @@ function extractErrorMessage(error) {
63
63
  }
64
64
  return String(error);
65
65
  }
66
- function createTaggedError(name) {
67
- const errorConstructor = (input) => ({
68
- name,
69
- ...input
70
- });
71
- const errName = name.replace(/Error$/, "Err");
72
- const errConstructor = (input) => Err(errorConstructor(input));
73
- return {
74
- [name]: errorConstructor,
75
- [errName]: errConstructor
76
- };
77
- }
78
66
  /**
79
- * Defines a new tagged error type with a fluent builder API.
67
+ * Creates a new tagged error type with a fluent builder API.
80
68
  *
81
69
  * Returns an object containing:
82
70
  * - `{Name}Error`: Factory function that creates plain TaggedError objects
@@ -99,7 +87,7 @@ function createTaggedError(name) {
99
87
  *
100
88
  * @example Simple error (flexible mode)
101
89
  * ```ts
102
- * const { NetworkError, NetworkErr } = defineError('NetworkError')
90
+ * const { NetworkError, NetworkErr } = createTaggedError('NetworkError')
103
91
  *
104
92
  * NetworkError({ message: 'Connection failed' })
105
93
  * NetworkError({ message: 'Timeout', context: { url: 'https://...' } })
@@ -107,7 +95,7 @@ function createTaggedError(name) {
107
95
  *
108
96
  * @example Required context
109
97
  * ```ts
110
- * const { ApiError, ApiErr } = defineError('ApiError')
98
+ * const { ApiError, ApiErr } = createTaggedError('ApiError')
111
99
  * .withContext<{ endpoint: string; status: number }>()
112
100
  *
113
101
  * ApiError({ message: 'Failed', context: { endpoint: '/users', status: 500 } })
@@ -116,7 +104,7 @@ function createTaggedError(name) {
116
104
  *
117
105
  * @example Optional typed cause
118
106
  * ```ts
119
- * const { ServiceError } = defineError('ServiceError')
107
+ * const { ServiceError } = createTaggedError('ServiceError')
120
108
  * .withCause<DbError | CacheError | undefined>()
121
109
  *
122
110
  * ServiceError({ message: 'Failed' }) // OK
@@ -125,7 +113,7 @@ function createTaggedError(name) {
125
113
  *
126
114
  * @example Full example with both
127
115
  * ```ts
128
- * const { UserServiceError } = defineError('UserServiceError')
116
+ * const { UserServiceError } = createTaggedError('UserServiceError')
129
117
  * .withContext<{ userId: string }>()
130
118
  * .withCause<RepoError | undefined>()
131
119
  *
@@ -133,7 +121,7 @@ function createTaggedError(name) {
133
121
  * type UserServiceError = ReturnType<typeof UserServiceError>
134
122
  * ```
135
123
  */
136
- function defineError(name) {
124
+ function createTaggedError(name) {
137
125
  const createBuilder = () => {
138
126
  const errorConstructor = (input) => ({
139
127
  name,
@@ -156,5 +144,5 @@ function defineError(name) {
156
144
  }
157
145
 
158
146
  //#endregion
159
- export { createTaggedError, defineError, extractErrorMessage };
147
+ export { createTaggedError, extractErrorMessage };
160
148
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["error: unknown","name: TName","input: {\n\t\tmessage: string;\n\t\tcontext?: TContext;\n\t\tcause?: TCause;\n\t}","input: ErrorInput<TContext, TCause>"],"sources":["../../src/error/utils.ts"],"sourcesContent":["import type { TaggedError, AnyTaggedError } from \"./types.js\";\nimport { Err } from \"../result/result.js\";\n\n/**\n * Extracts a readable error message from an unknown error value\n *\n * This utility is commonly used in mapErr functions when converting\n * unknown errors to typed error objects in the Result system.\n *\n * @param error - The unknown error to extract a message from\n * @returns A string representation of the error\n *\n * @example\n * ```ts\n * // With native Error\n * const error = new Error(\"Something went wrong\");\n * const message = extractErrorMessage(error); // \"Something went wrong\"\n *\n * // With string error\n * const stringError = \"String error\";\n * const message2 = extractErrorMessage(stringError); // \"String error\"\n *\n * // With object error\n * const unknownError = { code: 500, details: \"Server error\" };\n * const message3 = extractErrorMessage(unknownError); // '{\"code\":500,\"details\":\"Server error\"}'\n *\n * // Used in mapErr function\n * const result = await tryAsync({\n * try: () => riskyOperation(),\n * mapErr: (error) => Err({\n * name: \"NetworkError\",\n * message: extractErrorMessage(error),\n * context: { operation: \"riskyOperation\" },\n * cause: error,\n * }),\n * });\n * ```\n */\nexport function extractErrorMessage(error: unknown): string {\n\t// Handle Error instances\n\tif (error instanceof Error) {\n\t\treturn error.message;\n\t}\n\n\t// Handle primitives\n\tif (typeof error === \"string\") return error;\n\tif (\n\t\ttypeof error === \"number\" ||\n\t\ttypeof error === \"boolean\" ||\n\t\ttypeof error === \"bigint\"\n\t)\n\t\treturn String(error);\n\tif (typeof error === \"symbol\") return error.toString();\n\tif (error === null) return \"null\";\n\tif (error === undefined) return \"undefined\";\n\n\t// Handle arrays\n\tif (Array.isArray(error)) return JSON.stringify(error);\n\n\t// Handle plain objects\n\tif (typeof error === \"object\") {\n\t\tconst errorObj = error as Record<string, unknown>;\n\n\t\t// Check common error properties\n\t\tconst messageProps = [\n\t\t\t\"message\",\n\t\t\t\"error\",\n\t\t\t\"description\",\n\t\t\t\"title\",\n\t\t\t\"reason\",\n\t\t\t\"details\",\n\t\t] as const;\n\t\tfor (const prop of messageProps) {\n\t\t\tif (prop in errorObj && typeof errorObj[prop] === \"string\") {\n\t\t\t\treturn errorObj[prop];\n\t\t\t}\n\t\t}\n\n\t\t// Fallback to JSON stringification\n\t\ttry {\n\t\t\treturn JSON.stringify(error);\n\t\t} catch {\n\t\t\treturn String(error);\n\t\t}\n\t}\n\n\t// Final fallback\n\treturn String(error);\n}\n\n/**\n * Replaces the \"Error\" suffix with \"Err\" suffix in error type names.\n *\n * @template T - An error type name that must end with \"Error\"\n * @returns The type name with \"Error\" replaced by \"Err\"\n *\n * @example\n * ```ts\n * type NetworkErr = ReplaceErrorWithErr<\"NetworkError\">; // \"NetworkErr\"\n * type ValidationErr = ReplaceErrorWithErr<\"ValidationError\">; // \"ValidationErr\"\n * ```\n */\ntype ReplaceErrorWithErr<T extends `${string}Error`> =\n\tT extends `${infer TBase}Error` ? `${TBase}Err` : never;\n\n// =============================================================================\n// Factory Return Types\n// =============================================================================\n\n/**\n * Return type when neither context nor cause are constrained (flexible mode).\n * Context and cause are optional with loose typing.\n */\ntype FlexibleFactories<TName extends `${string}Error`> = {\n\t[K in TName]: FlexibleErrorConstructor<K>;\n} & {\n\t[K in ReplaceErrorWithErr<TName>]: FlexibleErrConstructor<TName>;\n};\n\n/**\n * Return type when context is fixed.\n * Context is required with exact type; cause is optional.\n */\ntype ContextFixedFactories<\n\tTName extends `${string}Error`,\n\tTContext extends Record<string, unknown>,\n> = {\n\t[K in TName]: ContextFixedErrorConstructor<K, TContext>;\n} & {\n\t[K in ReplaceErrorWithErr<TName>]: ContextFixedErrConstructor<TName, TContext>;\n};\n\n/**\n * Return type when both context and cause are fixed.\n * Context is required; cause is optional but constrained to specific type.\n */\ntype BothFixedFactories<\n\tTName extends `${string}Error`,\n\tTContext extends Record<string, unknown>,\n\tTCause extends AnyTaggedError,\n> = {\n\t[K in TName]: BothFixedErrorConstructor<K, TContext, TCause>;\n} & {\n\t[K in ReplaceErrorWithErr<TName>]: BothFixedErrConstructor<\n\t\tTName,\n\t\tTContext,\n\t\tTCause\n\t>;\n};\n\n// =============================================================================\n// Flexible Mode Constructor Types (SIMPLIFIED - no overloads)\n// =============================================================================\n\n/**\n * Creates plain TaggedError objects with flexible context and cause.\n * Single signature: context and cause are optional with loose typing.\n */\ntype FlexibleErrorConstructor<TName extends string> = (input: {\n\tmessage: string;\n\tcontext?: Record<string, unknown>;\n\tcause?: AnyTaggedError;\n}) => TaggedError<TName>;\n\n/**\n * Creates Err-wrapped TaggedError objects with flexible context and cause.\n * Single signature: context and cause are optional with loose typing.\n */\ntype FlexibleErrConstructor<TName extends string> = (input: {\n\tmessage: string;\n\tcontext?: Record<string, unknown>;\n\tcause?: AnyTaggedError;\n}) => Err<TaggedError<TName>>;\n\n// =============================================================================\n// Context-Fixed Mode Constructor Types (SIMPLIFIED - no overloads)\n// =============================================================================\n\n/**\n * Creates plain TaggedError objects with fixed context.\n * Single signature: context is required, cause is optional.\n */\ntype ContextFixedErrorConstructor<\n\tTName extends string,\n\tTContext extends Record<string, unknown>,\n> = (input: {\n\tmessage: string;\n\tcontext: TContext;\n\tcause?: AnyTaggedError;\n}) => TaggedError<TName, TContext>;\n\n/**\n * Creates Err-wrapped TaggedError objects with fixed context.\n * Single signature: context is required, cause is optional.\n */\ntype ContextFixedErrConstructor<\n\tTName extends string,\n\tTContext extends Record<string, unknown>,\n> = (input: {\n\tmessage: string;\n\tcontext: TContext;\n\tcause?: AnyTaggedError;\n}) => Err<TaggedError<TName, TContext>>;\n\n// =============================================================================\n// Both-Fixed Mode Constructor Types (SIMPLIFIED - no overloads)\n// =============================================================================\n\n/**\n * Creates plain TaggedError objects with both context and cause fixed.\n * Single signature: context is required, cause is optional but constrained.\n */\ntype BothFixedErrorConstructor<\n\tTName extends string,\n\tTContext extends Record<string, unknown>,\n\tTCause extends AnyTaggedError,\n> = (input: {\n\tmessage: string;\n\tcontext: TContext;\n\tcause?: TCause;\n}) => TaggedError<TName, TContext, TCause>;\n\n/**\n * Creates Err-wrapped TaggedError objects with both context and cause fixed.\n * Single signature: context is required, cause is optional but constrained.\n */\ntype BothFixedErrConstructor<\n\tTName extends string,\n\tTContext extends Record<string, unknown>,\n\tTCause extends AnyTaggedError,\n> = (input: {\n\tmessage: string;\n\tcontext: TContext;\n\tcause?: TCause;\n}) => Err<TaggedError<TName, TContext, TCause>>;\n\n// =============================================================================\n// Main Factory Function\n// =============================================================================\n\n/**\n * Creates two factory functions for building tagged errors with type-safe error chaining.\n *\n * @deprecated Use `defineError()` instead for a cleaner fluent API:\n * ```ts\n * // Before\n * const { FileError } = createTaggedError<'FileError', { path: string }>('FileError')\n *\n * // After\n * const { FileError } = defineError('FileError')\n * .withContext<{ path: string }>()\n * ```\n *\n * Given an error name like \"NetworkError\", this returns:\n * - `NetworkError`: Creates a plain TaggedError object\n * - `NetworkErr`: Creates a TaggedError object wrapped in an Err result\n *\n * **Three usage modes:**\n *\n * 1. **Flexible mode** (no type params): Context and cause are optional, loosely typed\n * 2. **Fixed context mode** (TContext specified): Context is required with exact shape\n * 3. **Both fixed mode** (TContext + TCause): Context required, cause constrained\n *\n * **ReturnType works correctly in all modes:**\n * ```ts\n * const { NetworkError } = createTaggedError('NetworkError');\n * type NetworkError = ReturnType<typeof NetworkError>;\n * // = TaggedError<'NetworkError'> with optional context/cause\n * ```\n *\n * @template TName - The name of the error type (must end with \"Error\")\n * @template TContext - Optional fixed context shape (makes context required)\n * @template TCause - Optional fixed cause type (constrains cause type if provided)\n * @param name - The name of the error type (must end with \"Error\")\n *\n * @example\n * ```ts\n * // Mode 1: Flexible - context and cause optional, loosely typed\n * const { NetworkError, NetworkErr } = createTaggedError('NetworkError');\n * NetworkError({ message: 'Connection failed' });\n * NetworkError({ message: 'Timeout', context: { url: 'https://...' } });\n * NetworkError({ message: 'Failed', cause: otherError });\n *\n * // Type annotation works with ReturnType:\n * type NetworkError = ReturnType<typeof NetworkError>;\n *\n * // Mode 2: Fixed context - context REQUIRED with exact shape\n * type BlobContext = { filename: string; code: 'INVALID' | 'TOO_LARGE' };\n * const { BlobError, BlobErr } = createTaggedError<'BlobError', BlobContext>('BlobError');\n * BlobError({ message: 'Invalid', context: { filename: 'x', code: 'INVALID' } });\n * // BlobError({ message: 'Error' }); // Type error - context required\n *\n * // Mode 3: Fixed context + cause - context required, cause constrained\n * const { ApiError, ApiErr } = createTaggedError<'ApiError', { endpoint: string }, NetworkError>('ApiError');\n * ApiError({ message: 'Failed', context: { endpoint: '/users' } });\n * ApiError({ message: 'Failed', context: { endpoint: '/users' }, cause: networkError });\n * ```\n */\n// Overload 1: Flexible (no type constraints)\nexport function createTaggedError<TName extends `${string}Error`>(\n\tname: TName,\n): FlexibleFactories<TName>;\n\n// Overload 2: Context fixed, cause flexible\nexport function createTaggedError<\n\tTName extends `${string}Error`,\n\tTContext extends Record<string, unknown>,\n>(name: TName): ContextFixedFactories<TName, TContext>;\n\n// Overload 3: Both context and cause fixed\nexport function createTaggedError<\n\tTName extends `${string}Error`,\n\tTContext extends Record<string, unknown>,\n\tTCause extends AnyTaggedError,\n>(name: TName): BothFixedFactories<TName, TContext, TCause>;\n\n// Implementation\nexport function createTaggedError<\n\tTName extends `${string}Error`,\n\tTContext extends Record<string, unknown> = Record<string, unknown>,\n\tTCause extends AnyTaggedError = AnyTaggedError,\n>(name: TName): unknown {\n\tconst errorConstructor = (input: {\n\t\tmessage: string;\n\t\tcontext?: TContext;\n\t\tcause?: TCause;\n\t}) => ({ name, ...input });\n\n\tconst errName = name.replace(/Error$/, \"Err\") as ReplaceErrorWithErr<TName>;\n\tconst errConstructor = (input: {\n\t\tmessage: string;\n\t\tcontext?: TContext;\n\t\tcause?: TCause;\n\t}) => Err(errorConstructor(input));\n\n\treturn {\n\t\t[name]: errorConstructor,\n\t\t[errName]: errConstructor,\n\t};\n}\n\n// =============================================================================\n// Fluent API Types\n// =============================================================================\n\n/**\n * Helper type that determines optionality based on whether T includes undefined.\n * - If T includes undefined → property is optional\n * - If T does not include undefined → property is required\n */\ntype OptionalIfUndefined<T, TKey extends string> = undefined extends T\n\t? { [K in TKey]?: Exclude<T, undefined> }\n\t: { [K in TKey]: T };\n\n/**\n * Input type for error constructors with fluent API context/cause handling.\n */\ntype ErrorInput<\n\tTContext extends Record<string, unknown> | undefined,\n\tTCause extends AnyTaggedError | undefined,\n> = { message: string } & (TContext extends undefined\n\t? { context?: Record<string, unknown> }\n\t: OptionalIfUndefined<TContext, \"context\">) &\n\t(TCause extends undefined\n\t\t? { cause?: AnyTaggedError }\n\t\t: OptionalIfUndefined<TCause, \"cause\">);\n\n/**\n * The factories object returned by defineError and its builder methods.\n */\ntype ErrorFactories<\n\tTName extends `${string}Error`,\n\tTContext extends Record<string, unknown> | undefined,\n\tTCause extends AnyTaggedError | undefined,\n> = {\n\t[K in TName]: (\n\t\tinput: ErrorInput<TContext, TCause>,\n\t) => TaggedError<TName, TContext, TCause>;\n} & {\n\t[K in ReplaceErrorWithErr<TName>]: (\n\t\tinput: ErrorInput<TContext, TCause>,\n\t) => Err<TaggedError<TName, TContext, TCause>>;\n};\n\n/**\n * Builder interface for the fluent defineError API.\n * Provides chaining methods and the error factories.\n */\ntype ErrorBuilder<\n\tTName extends `${string}Error`,\n\tTContext extends Record<string, unknown> | undefined = undefined,\n\tTCause extends AnyTaggedError | undefined = undefined,\n> = ErrorFactories<TName, TContext, TCause> & {\n\t/**\n\t * Constrains the context type for this error.\n\t *\n\t * Optionality is determined by whether the type includes `undefined`:\n\t * - `withContext<T>()` where T doesn't include undefined → context is **required**\n\t * - `withContext<T | undefined>()` → context is **optional** but typed when provided\n\t *\n\t * @typeParam T - The shape of the context object. Include `| undefined` to make optional.\n\t *\n\t * @example Required context\n\t * ```ts\n\t * const { FileError } = defineError('FileError')\n\t * .withContext<{ path: string }>()\n\t *\n\t * FileError({ message: 'Not found', context: { path: '/etc/config' } }) // OK\n\t * FileError({ message: 'Not found' }) // Type error: context required\n\t * ```\n\t *\n\t * @example Optional but typed context\n\t * ```ts\n\t * const { LogError } = defineError('LogError')\n\t * .withContext<{ file: string; line: number } | undefined>()\n\t *\n\t * LogError({ message: 'Parse error' }) // OK\n\t * LogError({ message: 'Parse error', context: { file: 'app.ts', line: 42 } }) // OK\n\t * ```\n\t */\n\twithContext<T extends Record<string, unknown> | undefined>(): ErrorBuilder<\n\t\tTName,\n\t\tT,\n\t\tTCause\n\t>;\n\n\t/**\n\t * Constrains the cause type for this error.\n\t *\n\t * Optionality is determined by whether the type includes `undefined`:\n\t * - `withCause<T>()` where T doesn't include undefined → cause is **required**\n\t * - `withCause<T | undefined>()` → cause is **optional** but typed when provided\n\t *\n\t * Since cause is typically optional, include `| undefined` in most cases.\n\t *\n\t * @typeParam T - The allowed cause type(s). Include `| undefined` to make optional.\n\t *\n\t * @example Optional typed cause (common)\n\t * ```ts\n\t * const { ServiceError } = defineError('ServiceError')\n\t * .withCause<DbError | CacheError | undefined>()\n\t *\n\t * ServiceError({ message: 'Failed' }) // OK\n\t * ServiceError({ message: 'Failed', cause: dbError }) // OK\n\t * ```\n\t *\n\t * @example Required cause (for wrapper errors)\n\t * ```ts\n\t * const { UnhandledError } = defineError('UnhandledError')\n\t * .withCause<AnyTaggedError>()\n\t *\n\t * UnhandledError({ message: 'Unexpected', cause: originalError }) // OK\n\t * UnhandledError({ message: 'Unexpected' }) // Type error: cause required\n\t * ```\n\t */\n\twithCause<T extends AnyTaggedError | undefined>(): ErrorBuilder<\n\t\tTName,\n\t\tTContext,\n\t\tT\n\t>;\n};\n\n// =============================================================================\n// Fluent API Implementation\n// =============================================================================\n\n/**\n * Defines a new tagged error type with a fluent builder API.\n *\n * Returns an object containing:\n * - `{Name}Error`: Factory function that creates plain TaggedError objects\n * - `{Name}Err`: Factory function that creates Err-wrapped TaggedError objects\n * - `withContext<T>()`: Chain method to constrain context type\n * - `withCause<T>()`: Chain method to constrain cause type\n *\n * **Default behavior (no chaining):**\n * - `context` is optional and accepts any `Record<string, unknown>`\n * - `cause` is optional and accepts any `AnyTaggedError`\n *\n * **Optionality via type unions:**\n * Both `withContext` and `withCause` determine optionality based on whether\n * the type includes `undefined`:\n * - `T` without undefined → property is required\n * - `T | undefined` → property is optional but typed when provided\n *\n * @template TName - The name of the error type (must end with \"Error\")\n * @param name - The name of the error type\n *\n * @example Simple error (flexible mode)\n * ```ts\n * const { NetworkError, NetworkErr } = defineError('NetworkError')\n *\n * NetworkError({ message: 'Connection failed' })\n * NetworkError({ message: 'Timeout', context: { url: 'https://...' } })\n * ```\n *\n * @example Required context\n * ```ts\n * const { ApiError, ApiErr } = defineError('ApiError')\n * .withContext<{ endpoint: string; status: number }>()\n *\n * ApiError({ message: 'Failed', context: { endpoint: '/users', status: 500 } })\n * // ApiError({ message: 'Failed' }) // Type error: context required\n * ```\n *\n * @example Optional typed cause\n * ```ts\n * const { ServiceError } = defineError('ServiceError')\n * .withCause<DbError | CacheError | undefined>()\n *\n * ServiceError({ message: 'Failed' }) // OK\n * ServiceError({ message: 'Failed', cause: dbError }) // OK, typed\n * ```\n *\n * @example Full example with both\n * ```ts\n * const { UserServiceError } = defineError('UserServiceError')\n * .withContext<{ userId: string }>()\n * .withCause<RepoError | undefined>()\n *\n * // Type extraction works\n * type UserServiceError = ReturnType<typeof UserServiceError>\n * ```\n */\nexport function defineError<TName extends `${string}Error`>(\n\tname: TName,\n): ErrorBuilder<TName> {\n\tconst createBuilder = <\n\t\tTContext extends Record<string, unknown> | undefined = undefined,\n\t\tTCause extends AnyTaggedError | undefined = undefined,\n\t>(): ErrorBuilder<TName, TContext, TCause> => {\n\t\tconst errorConstructor = (input: ErrorInput<TContext, TCause>) =>\n\t\t\t({ name, ...input }) as unknown as TaggedError<TName, TContext, TCause>;\n\n\t\tconst errName = name.replace(\n\t\t\t/Error$/,\n\t\t\t\"Err\",\n\t\t) as ReplaceErrorWithErr<TName>;\n\t\tconst errConstructor = (input: ErrorInput<TContext, TCause>) =>\n\t\t\tErr(errorConstructor(input));\n\n\t\treturn {\n\t\t\t[name]: errorConstructor,\n\t\t\t[errName]: errConstructor,\n\t\t\twithContext<T extends Record<string, unknown> | undefined>() {\n\t\t\t\treturn createBuilder<T, TCause>();\n\t\t\t},\n\t\t\twithCause<T extends AnyTaggedError | undefined>() {\n\t\t\t\treturn createBuilder<TContext, T>();\n\t\t\t},\n\t\t} as ErrorBuilder<TName, TContext, TCause>;\n\t};\n\n\treturn createBuilder();\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCA,SAAgB,oBAAoBA,OAAwB;AAE3D,KAAI,iBAAiB,MACpB,QAAO,MAAM;AAId,YAAW,UAAU,SAAU,QAAO;AACtC,YACQ,UAAU,mBACV,UAAU,oBACV,UAAU,SAEjB,QAAO,OAAO,MAAM;AACrB,YAAW,UAAU,SAAU,QAAO,MAAM,UAAU;AACtD,KAAI,UAAU,KAAM,QAAO;AAC3B,KAAI,iBAAqB,QAAO;AAGhC,KAAI,MAAM,QAAQ,MAAM,CAAE,QAAO,KAAK,UAAU,MAAM;AAGtD,YAAW,UAAU,UAAU;EAC9B,MAAM,WAAW;EAGjB,MAAM,eAAe;GACpB;GACA;GACA;GACA;GACA;GACA;EACA;AACD,OAAK,MAAM,QAAQ,aAClB,KAAI,QAAQ,mBAAmB,SAAS,UAAU,SACjD,QAAO,SAAS;AAKlB,MAAI;AACH,UAAO,KAAK,UAAU,MAAM;EAC5B,QAAO;AACP,UAAO,OAAO,MAAM;EACpB;CACD;AAGD,QAAO,OAAO,MAAM;AACpB;AAqOD,SAAgB,kBAIdC,MAAsB;CACvB,MAAM,mBAAmB,CAACC,WAInB;EAAE;EAAM,GAAG;CAAO;CAEzB,MAAM,UAAU,KAAK,QAAQ,UAAU,MAAM;CAC7C,MAAM,iBAAiB,CAACA,UAIlB,IAAI,iBAAiB,MAAM,CAAC;AAElC,QAAO;GACL,OAAO;GACP,UAAU;CACX;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyLD,SAAgB,YACfD,MACsB;CACtB,MAAM,gBAAgB,MAGwB;EAC7C,MAAM,mBAAmB,CAACE,WACxB;GAAE;GAAM,GAAG;EAAO;EAEpB,MAAM,UAAU,KAAK,QACpB,UACA,MACA;EACD,MAAM,iBAAiB,CAACA,UACvB,IAAI,iBAAiB,MAAM,CAAC;AAE7B,SAAO;IACL,OAAO;IACP,UAAU;GACX,cAA6D;AAC5D,WAAO,eAA0B;GACjC;GACD,YAAkD;AACjD,WAAO,eAA4B;GACnC;EACD;CACD;AAED,QAAO,eAAe;AACtB"}
1
+ {"version":3,"file":"index.js","names":["error: unknown","name: TName","input: ErrorInput<TContext, TCause>"],"sources":["../../src/error/utils.ts"],"sourcesContent":["import type { TaggedError, AnyTaggedError } from \"./types.js\";\nimport { Err } from \"../result/result.js\";\n\n/**\n * Extracts a readable error message from an unknown error value\n *\n * This utility is commonly used in mapErr functions when converting\n * unknown errors to typed error objects in the Result system.\n *\n * @param error - The unknown error to extract a message from\n * @returns A string representation of the error\n *\n * @example\n * ```ts\n * // With native Error\n * const error = new Error(\"Something went wrong\");\n * const message = extractErrorMessage(error); // \"Something went wrong\"\n *\n * // With string error\n * const stringError = \"String error\";\n * const message2 = extractErrorMessage(stringError); // \"String error\"\n *\n * // With object error\n * const unknownError = { code: 500, details: \"Server error\" };\n * const message3 = extractErrorMessage(unknownError); // '{\"code\":500,\"details\":\"Server error\"}'\n *\n * // Used in mapErr function\n * const result = await tryAsync({\n * try: () => riskyOperation(),\n * mapErr: (error) => Err({\n * name: \"NetworkError\",\n * message: extractErrorMessage(error),\n * context: { operation: \"riskyOperation\" },\n * cause: error,\n * }),\n * });\n * ```\n */\nexport function extractErrorMessage(error: unknown): string {\n\t// Handle Error instances\n\tif (error instanceof Error) {\n\t\treturn error.message;\n\t}\n\n\t// Handle primitives\n\tif (typeof error === \"string\") return error;\n\tif (\n\t\ttypeof error === \"number\" ||\n\t\ttypeof error === \"boolean\" ||\n\t\ttypeof error === \"bigint\"\n\t)\n\t\treturn String(error);\n\tif (typeof error === \"symbol\") return error.toString();\n\tif (error === null) return \"null\";\n\tif (error === undefined) return \"undefined\";\n\n\t// Handle arrays\n\tif (Array.isArray(error)) return JSON.stringify(error);\n\n\t// Handle plain objects\n\tif (typeof error === \"object\") {\n\t\tconst errorObj = error as Record<string, unknown>;\n\n\t\t// Check common error properties\n\t\tconst messageProps = [\n\t\t\t\"message\",\n\t\t\t\"error\",\n\t\t\t\"description\",\n\t\t\t\"title\",\n\t\t\t\"reason\",\n\t\t\t\"details\",\n\t\t] as const;\n\t\tfor (const prop of messageProps) {\n\t\t\tif (prop in errorObj && typeof errorObj[prop] === \"string\") {\n\t\t\t\treturn errorObj[prop];\n\t\t\t}\n\t\t}\n\n\t\t// Fallback to JSON stringification\n\t\ttry {\n\t\t\treturn JSON.stringify(error);\n\t\t} catch {\n\t\t\treturn String(error);\n\t\t}\n\t}\n\n\t// Final fallback\n\treturn String(error);\n}\n\n/**\n * Replaces the \"Error\" suffix with \"Err\" suffix in error type names.\n *\n * @template T - An error type name that must end with \"Error\"\n * @returns The type name with \"Error\" replaced by \"Err\"\n *\n * @example\n * ```ts\n * type NetworkErr = ReplaceErrorWithErr<\"NetworkError\">; // \"NetworkErr\"\n * type ValidationErr = ReplaceErrorWithErr<\"ValidationError\">; // \"ValidationErr\"\n * ```\n */\ntype ReplaceErrorWithErr<T extends `${string}Error`> =\n\tT extends `${infer TBase}Error` ? `${TBase}Err` : never;\n\n// =============================================================================\n// Fluent API Types\n// =============================================================================\n\n/**\n * Helper type that determines optionality based on whether T includes undefined.\n * - If T includes undefined → property is optional\n * - If T does not include undefined → property is required\n */\ntype OptionalIfUndefined<T, TKey extends string> = undefined extends T\n\t? { [K in TKey]?: Exclude<T, undefined> }\n\t: { [K in TKey]: T };\n\n/**\n * Input type for error constructors with fluent API context/cause handling.\n */\ntype ErrorInput<\n\tTContext extends Record<string, unknown> | undefined,\n\tTCause extends AnyTaggedError | undefined,\n> = { message: string } & (TContext extends undefined\n\t? { context?: Record<string, unknown> }\n\t: OptionalIfUndefined<TContext, \"context\">) &\n\t(TCause extends undefined\n\t\t? { cause?: AnyTaggedError }\n\t\t: OptionalIfUndefined<TCause, \"cause\">);\n\n/**\n * The factories object returned by createTaggedError and its builder methods.\n */\ntype ErrorFactories<\n\tTName extends `${string}Error`,\n\tTContext extends Record<string, unknown> | undefined,\n\tTCause extends AnyTaggedError | undefined,\n> = {\n\t[K in TName]: (\n\t\tinput: ErrorInput<TContext, TCause>,\n\t) => TaggedError<TName, TContext, TCause>;\n} & {\n\t[K in ReplaceErrorWithErr<TName>]: (\n\t\tinput: ErrorInput<TContext, TCause>,\n\t) => Err<TaggedError<TName, TContext, TCause>>;\n};\n\n/**\n * Builder interface for the fluent createTaggedError API.\n * Provides chaining methods and the error factories.\n */\ntype ErrorBuilder<\n\tTName extends `${string}Error`,\n\tTContext extends Record<string, unknown> | undefined = undefined,\n\tTCause extends AnyTaggedError | undefined = undefined,\n> = ErrorFactories<TName, TContext, TCause> & {\n\t/**\n\t * Constrains the context type for this error.\n\t *\n\t * Optionality is determined by whether the type includes `undefined`:\n\t * - `withContext<T>()` where T doesn't include undefined → context is **required**\n\t * - `withContext<T | undefined>()` → context is **optional** but typed when provided\n\t *\n\t * @typeParam T - The shape of the context object. Include `| undefined` to make optional.\n\t *\n\t * @example Required context\n\t * ```ts\n\t * const { FileError } = createTaggedError('FileError')\n\t * .withContext<{ path: string }>()\n\t *\n\t * FileError({ message: 'Not found', context: { path: '/etc/config' } }) // OK\n\t * FileError({ message: 'Not found' }) // Type error: context required\n\t * ```\n\t *\n\t * @example Optional but typed context\n\t * ```ts\n\t * const { LogError } = createTaggedError('LogError')\n\t * .withContext<{ file: string; line: number } | undefined>()\n\t *\n\t * LogError({ message: 'Parse error' }) // OK\n\t * LogError({ message: 'Parse error', context: { file: 'app.ts', line: 42 } }) // OK\n\t * ```\n\t */\n\twithContext<T extends Record<string, unknown> | undefined>(): ErrorBuilder<\n\t\tTName,\n\t\tT,\n\t\tTCause\n\t>;\n\n\t/**\n\t * Constrains the cause type for this error.\n\t *\n\t * Optionality is determined by whether the type includes `undefined`:\n\t * - `withCause<T>()` where T doesn't include undefined → cause is **required**\n\t * - `withCause<T | undefined>()` → cause is **optional** but typed when provided\n\t *\n\t * Since cause is typically optional, include `| undefined` in most cases.\n\t *\n\t * @typeParam T - The allowed cause type(s). Include `| undefined` to make optional.\n\t *\n\t * @example Optional typed cause (common)\n\t * ```ts\n\t * const { ServiceError } = createTaggedError('ServiceError')\n\t * .withCause<DbError | CacheError | undefined>()\n\t *\n\t * ServiceError({ message: 'Failed' }) // OK\n\t * ServiceError({ message: 'Failed', cause: dbError }) // OK\n\t * ```\n\t *\n\t * @example Required cause (for wrapper errors)\n\t * ```ts\n\t * const { UnhandledError } = createTaggedError('UnhandledError')\n\t * .withCause<AnyTaggedError>()\n\t *\n\t * UnhandledError({ message: 'Unexpected', cause: originalError }) // OK\n\t * UnhandledError({ message: 'Unexpected' }) // Type error: cause required\n\t * ```\n\t */\n\twithCause<T extends AnyTaggedError | undefined>(): ErrorBuilder<\n\t\tTName,\n\t\tTContext,\n\t\tT\n\t>;\n};\n\n// =============================================================================\n// Fluent API Implementation\n// =============================================================================\n\n/**\n * Creates a new tagged error type with a fluent builder API.\n *\n * Returns an object containing:\n * - `{Name}Error`: Factory function that creates plain TaggedError objects\n * - `{Name}Err`: Factory function that creates Err-wrapped TaggedError objects\n * - `withContext<T>()`: Chain method to constrain context type\n * - `withCause<T>()`: Chain method to constrain cause type\n *\n * **Default behavior (no chaining):**\n * - `context` is optional and accepts any `Record<string, unknown>`\n * - `cause` is optional and accepts any `AnyTaggedError`\n *\n * **Optionality via type unions:**\n * Both `withContext` and `withCause` determine optionality based on whether\n * the type includes `undefined`:\n * - `T` without undefined → property is required\n * - `T | undefined` → property is optional but typed when provided\n *\n * @template TName - The name of the error type (must end with \"Error\")\n * @param name - The name of the error type\n *\n * @example Simple error (flexible mode)\n * ```ts\n * const { NetworkError, NetworkErr } = createTaggedError('NetworkError')\n *\n * NetworkError({ message: 'Connection failed' })\n * NetworkError({ message: 'Timeout', context: { url: 'https://...' } })\n * ```\n *\n * @example Required context\n * ```ts\n * const { ApiError, ApiErr } = createTaggedError('ApiError')\n * .withContext<{ endpoint: string; status: number }>()\n *\n * ApiError({ message: 'Failed', context: { endpoint: '/users', status: 500 } })\n * // ApiError({ message: 'Failed' }) // Type error: context required\n * ```\n *\n * @example Optional typed cause\n * ```ts\n * const { ServiceError } = createTaggedError('ServiceError')\n * .withCause<DbError | CacheError | undefined>()\n *\n * ServiceError({ message: 'Failed' }) // OK\n * ServiceError({ message: 'Failed', cause: dbError }) // OK, typed\n * ```\n *\n * @example Full example with both\n * ```ts\n * const { UserServiceError } = createTaggedError('UserServiceError')\n * .withContext<{ userId: string }>()\n * .withCause<RepoError | undefined>()\n *\n * // Type extraction works\n * type UserServiceError = ReturnType<typeof UserServiceError>\n * ```\n */\nexport function createTaggedError<TName extends `${string}Error`>(\n\tname: TName,\n): ErrorBuilder<TName> {\n\tconst createBuilder = <\n\t\tTContext extends Record<string, unknown> | undefined = undefined,\n\t\tTCause extends AnyTaggedError | undefined = undefined,\n\t>(): ErrorBuilder<TName, TContext, TCause> => {\n\t\tconst errorConstructor = (input: ErrorInput<TContext, TCause>) =>\n\t\t\t({ name, ...input }) as unknown as TaggedError<TName, TContext, TCause>;\n\n\t\tconst errName = name.replace(\n\t\t\t/Error$/,\n\t\t\t\"Err\",\n\t\t) as ReplaceErrorWithErr<TName>;\n\t\tconst errConstructor = (input: ErrorInput<TContext, TCause>) =>\n\t\t\tErr(errorConstructor(input));\n\n\t\treturn {\n\t\t\t[name]: errorConstructor,\n\t\t\t[errName]: errConstructor,\n\t\t\twithContext<T extends Record<string, unknown> | undefined>() {\n\t\t\t\treturn createBuilder<T, TCause>();\n\t\t\t},\n\t\t\twithCause<T extends AnyTaggedError | undefined>() {\n\t\t\t\treturn createBuilder<TContext, T>();\n\t\t\t},\n\t\t} as ErrorBuilder<TName, TContext, TCause>;\n\t};\n\n\treturn createBuilder();\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCA,SAAgB,oBAAoBA,OAAwB;AAE3D,KAAI,iBAAiB,MACpB,QAAO,MAAM;AAId,YAAW,UAAU,SAAU,QAAO;AACtC,YACQ,UAAU,mBACV,UAAU,oBACV,UAAU,SAEjB,QAAO,OAAO,MAAM;AACrB,YAAW,UAAU,SAAU,QAAO,MAAM,UAAU;AACtD,KAAI,UAAU,KAAM,QAAO;AAC3B,KAAI,iBAAqB,QAAO;AAGhC,KAAI,MAAM,QAAQ,MAAM,CAAE,QAAO,KAAK,UAAU,MAAM;AAGtD,YAAW,UAAU,UAAU;EAC9B,MAAM,WAAW;EAGjB,MAAM,eAAe;GACpB;GACA;GACA;GACA;GACA;GACA;EACA;AACD,OAAK,MAAM,QAAQ,aAClB,KAAI,QAAQ,mBAAmB,SAAS,UAAU,SACjD,QAAO,SAAS;AAKlB,MAAI;AACH,UAAO,KAAK,UAAU,MAAM;EAC5B,QAAO;AACP,UAAO,OAAO,MAAM;EACpB;CACD;AAGD,QAAO,OAAO,MAAM;AACpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwMD,SAAgB,kBACfC,MACsB;CACtB,MAAM,gBAAgB,MAGwB;EAC7C,MAAM,mBAAmB,CAACC,WACxB;GAAE;GAAM,GAAG;EAAO;EAEpB,MAAM,UAAU,KAAK,QACpB,UACA,MACA;EACD,MAAM,iBAAiB,CAACA,UACvB,IAAI,iBAAiB,MAAM,CAAC;AAE7B,SAAO;IACL,OAAO;IACP,UAAU;GACX,cAA6D;AAC5D,WAAO,eAA0B;GACjC;GACD,YAAkD;AACjD,WAAO,eAA4B;GACnC;EACD;CACD;AAED,QAAO,eAAe;AACtB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wellcrafted",
3
- "version": "0.26.0",
3
+ "version": "0.27.0",
4
4
  "description": "Delightful TypeScript patterns for elegant, type-safe applications",
5
5
  "type": "module",
6
6
  "files": [