@digitaldefiance/branded-enum 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"advanced.d.ts","sourceRoot":"","sources":["../../src/lib/advanced.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function brandedEnum(): string;
2
+ //# sourceMappingURL=branded-enum.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branded-enum.d.ts","sourceRoot":"","sources":["../../src/lib/branded-enum.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,IAAI,MAAM,CAEpC"}
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Decorators for branded enums.
3
+ *
4
+ * Provides runtime validation decorators for class properties
5
+ * that should only accept values from branded enums.
6
+ */
7
+ import { AnyBrandedEnum, BrandedEnum, EnumConsumerEntry } from './types.js';
8
+ /**
9
+ * Options for the EnumValue decorator.
10
+ */
11
+ export interface EnumValueOptions {
12
+ /**
13
+ * Whether the property is optional (can be undefined).
14
+ * @default false
15
+ */
16
+ optional?: boolean;
17
+ /**
18
+ * Whether the property is nullable (can be null).
19
+ * @default false
20
+ */
21
+ nullable?: boolean;
22
+ }
23
+ /**
24
+ * Property decorator that validates values against a branded enum at runtime.
25
+ *
26
+ * When a value is assigned to the decorated property, it validates that the value
27
+ * is a member of the specified branded enum. If validation fails, a descriptive
28
+ * error is thrown.
29
+ *
30
+ * Supports optional and nullable properties through the options parameter.
31
+ *
32
+ * @template E - The branded enum type
33
+ * @param enumObj - The branded enum to validate against
34
+ * @param options - Optional configuration for nullable/optional support
35
+ * @returns A property decorator function
36
+ * @throws {Error} Throws `Error` if enumObj is not a valid branded enum
37
+ * @throws {Error} Throws `Error` at runtime if assigned value is not in the enum
38
+ *
39
+ * @example
40
+ * // Basic usage
41
+ * const Status = createBrandedEnum('status', { Active: 'active', Inactive: 'inactive' } as const);
42
+ *
43
+ * class User {
44
+ * \@EnumValue(Status)
45
+ * accessor status: string = Status.Active;
46
+ * }
47
+ *
48
+ * const user = new User();
49
+ * user.status = Status.Active; // OK
50
+ * user.status = 'invalid'; // Throws Error
51
+ *
52
+ * @example
53
+ * // Optional property
54
+ * class Config {
55
+ * \@EnumValue(Status, { optional: true })
56
+ * accessor status: string | undefined;
57
+ * }
58
+ *
59
+ * const config = new Config();
60
+ * config.status = undefined; // OK
61
+ * config.status = Status.Active; // OK
62
+ *
63
+ * @example
64
+ * // Nullable property
65
+ * class Settings {
66
+ * \@EnumValue(Status, { nullable: true })
67
+ * accessor status: string | null = null;
68
+ * }
69
+ *
70
+ * const settings = new Settings();
71
+ * settings.status = null; // OK
72
+ * settings.status = Status.Active; // OK
73
+ */
74
+ export declare function EnumValue<E extends BrandedEnum<any>>(enumObj: E, options?: EnumValueOptions): <V extends string | null | undefined>(target: ClassAccessorDecoratorTarget<unknown, V>, context: ClassAccessorDecoratorContext<unknown, V>) => ClassAccessorDecoratorResult<unknown, V>;
75
+ /**
76
+ * Gets all class names that consume a specific branded enum.
77
+ *
78
+ * @param enumId - The enum ID to look up
79
+ * @returns Array of class names that consume the enum
80
+ *
81
+ * @example
82
+ * const Status = createBrandedEnum('status', { Active: 'active' } as const);
83
+ *
84
+ * \@EnumClass(Status)
85
+ * class User { }
86
+ *
87
+ * getEnumConsumers('status'); // ['User']
88
+ */
89
+ export declare function getEnumConsumers(enumId: string): string[];
90
+ /**
91
+ * Gets all enum IDs consumed by a specific class.
92
+ *
93
+ * @param className - The class name to look up
94
+ * @returns Array of enum IDs consumed by the class
95
+ *
96
+ * @example
97
+ * const Status = createBrandedEnum('status', { Active: 'active' } as const);
98
+ * const Priority = createBrandedEnum('priority', { High: 'high' } as const);
99
+ *
100
+ * \@EnumClass(Status, Priority)
101
+ * class Task { }
102
+ *
103
+ * getConsumedEnums('Task'); // ['status', 'priority']
104
+ */
105
+ export declare function getConsumedEnums(className: string): string[];
106
+ /**
107
+ * Gets all registered enum consumer entries.
108
+ *
109
+ * @returns Array of all consumer entries
110
+ *
111
+ * @example
112
+ * getAllEnumConsumers(); // [{ className: 'User', enumIds: Set(['status']) }, ...]
113
+ */
114
+ export declare function getAllEnumConsumers(): EnumConsumerEntry[];
115
+ /**
116
+ * Clears the consumer registry. Useful for testing.
117
+ * @internal
118
+ */
119
+ export declare function clearConsumerRegistry(): void;
120
+ /**
121
+ * Class decorator that registers a class as a consumer of branded enums.
122
+ *
123
+ * This decorator tracks which classes use which branded enums, enabling
124
+ * debugging and introspection of enum usage across the codebase.
125
+ *
126
+ * @param enums - One or more branded enums that the class consumes
127
+ * @returns A class decorator function
128
+ * @throws {Error} Throws `Error` if any argument is not a valid branded enum
129
+ *
130
+ * @example
131
+ * const Status = createBrandedEnum('status', { Active: 'active', Inactive: 'inactive' } as const);
132
+ * const Priority = createBrandedEnum('priority', { High: 'high', Low: 'low' } as const);
133
+ *
134
+ * \@EnumClass(Status, Priority)
135
+ * class Task {
136
+ * status = Status.Active;
137
+ * priority = Priority.High;
138
+ * }
139
+ *
140
+ * // Query which classes consume an enum
141
+ * getEnumConsumers('status'); // ['Task']
142
+ *
143
+ * // Query which enums a class consumes
144
+ * getConsumedEnums('Task'); // ['status', 'priority']
145
+ */
146
+ export declare function EnumClass(...enums: AnyBrandedEnum[]): <T extends new (...args: any[]) => any>(target: T, context: ClassDecoratorContext<T>) => T;
147
+ //# sourceMappingURL=decorators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../../src/lib/decorators.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,cAAc,EACd,WAAW,EAKX,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAsBpB;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,wBAAgB,SAAS,CAEvB,CAAC,SAAS,WAAW,CAAC,GAAG,CAAC,EAE1B,OAAO,EAAE,CAAC,EACV,OAAO,GAAE,gBAAqB,GAC7B,CAAC,CAAC,SAAS,MAAM,GAAG,IAAI,GAAG,SAAS,EACrC,MAAM,EAAE,4BAA4B,CAAC,OAAO,EAAE,CAAC,CAAC,EAChD,OAAO,EAAE,6BAA6B,CAAC,OAAO,EAAE,CAAC,CAAC,KAC/C,4BAA4B,CAAC,OAAO,EAAE,CAAC,CAAC,CAwG5C;AA8DD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAIzD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAI5D;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,IAAI,iBAAiB,EAAE,CAGzD;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAK5C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,SAAS,CACvB,GAAG,KAAK,EAAE,cAAc,EAAE,GAEzB,CAAC,CAAC,SAAS,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EACvC,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,qBAAqB,CAAC,CAAC,CAAC,KAC9B,CAAC,CA0BL"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Factory function for creating branded enums.
3
+ *
4
+ * Creates enum-like objects with runtime metadata for identification,
5
+ * while keeping values as raw strings for serialization compatibility.
6
+ */
7
+ import { BrandedEnum } from './types.js';
8
+ /**
9
+ * Creates a branded enum with runtime metadata.
10
+ *
11
+ * The returned object:
12
+ * - Contains all provided key-value pairs as enumerable properties
13
+ * - Has non-enumerable Symbol properties for metadata (ENUM_ID, ENUM_VALUES)
14
+ * - Is frozen to prevent modification
15
+ * - Is registered in the global registry
16
+ *
17
+ * @template T - The shape of the values object (use `as const` for literal types)
18
+ * @param enumId - Unique identifier for this enum. Must be unique across all
19
+ * branded enums in the application.
20
+ * @param values - Object containing key-value pairs where keys are enum member
21
+ * names and values are the string values. Use `as const` for literal type inference.
22
+ * @returns A frozen branded enum object with attached metadata
23
+ * @throws {Error} Throws `Error` with message `Branded enum with ID "${enumId}" already exists`
24
+ * if an enum with the same ID has already been registered.
25
+ *
26
+ * @example
27
+ * // Basic usage
28
+ * const Status = createBrandedEnum('status', {
29
+ * Active: 'active',
30
+ * Inactive: 'inactive',
31
+ * } as const);
32
+ *
33
+ * Status.Active // 'active' (raw string)
34
+ * getEnumId(Status) // 'status'
35
+ *
36
+ * @example
37
+ * // Type inference with as const
38
+ * const Colors = createBrandedEnum('colors', {
39
+ * Red: 'red',
40
+ * Green: 'green',
41
+ * Blue: 'blue',
42
+ * } as const);
43
+ *
44
+ * type ColorValue = typeof Colors[keyof typeof Colors]; // 'red' | 'green' | 'blue'
45
+ *
46
+ * @example
47
+ * // Error handling for duplicate IDs
48
+ * createBrandedEnum('myEnum', { A: 'a' } as const);
49
+ * createBrandedEnum('myEnum', { B: 'b' } as const); // Throws Error
50
+ */
51
+ export declare function createBrandedEnum<T extends Record<string, string>>(enumId: string, values: T): BrandedEnum<T>;
52
+ //# sourceMappingURL=factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/lib/factory.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,WAAW,EAIZ,MAAM,YAAY,CAAC;AAGpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAChE,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,CAAC,GACR,WAAW,CAAC,CAAC,CAAC,CA6BhB"}
@@ -0,0 +1,297 @@
1
+ /**
2
+ * Type guards for branded enums.
3
+ *
4
+ * Provides runtime type checking and assertion functions
5
+ * for validating values against branded enums.
6
+ */
7
+ import { AnyBrandedEnum, EnumValues } from './types.js';
8
+ /**
9
+ * Checks if a value belongs to a specific branded enum.
10
+ *
11
+ * Returns true if and only if:
12
+ * - enumObj is a valid branded enum (has Symbol metadata)
13
+ * - value is a string
14
+ * - value exists in the enum's value Set
15
+ *
16
+ * This function provides TypeScript type narrowing - when it returns true,
17
+ * the value's type is narrowed to the enum's value type.
18
+ *
19
+ * @template E - The branded enum type
20
+ * @param value - The value to check. Can be any type; non-strings return false.
21
+ * @param enumObj - The branded enum to check against
22
+ * @returns `true` if value is in the enum (with type narrowing), `false` otherwise.
23
+ * Returns `false` for non-string values, null, undefined, or if enumObj
24
+ * is not a branded enum.
25
+ *
26
+ * @example
27
+ * // Basic type guard usage
28
+ * const Status = createBrandedEnum('status', { Active: 'active', Inactive: 'inactive' } as const);
29
+ *
30
+ * function handleStatus(value: unknown) {
31
+ * if (isFromEnum(value, Status)) {
32
+ * // value is narrowed to 'active' | 'inactive'
33
+ * console.log('Valid status:', value);
34
+ * } else {
35
+ * console.log('Invalid status');
36
+ * }
37
+ * }
38
+ *
39
+ * @example
40
+ * // Returns false for non-string values
41
+ * isFromEnum(123, Status); // false
42
+ * isFromEnum(null, Status); // false
43
+ * isFromEnum(undefined, Status); // false
44
+ *
45
+ * @example
46
+ * // Returns false for non-branded enum objects
47
+ * isFromEnum('active', { Active: 'active' }); // false (not a branded enum)
48
+ */
49
+ export declare function isFromEnum<E extends AnyBrandedEnum>(value: unknown, enumObj: E): value is EnumValues<E>;
50
+ /**
51
+ * Asserts that a value belongs to a branded enum, throwing if not.
52
+ *
53
+ * Use this function when you want to validate a value and throw an error
54
+ * if it's invalid, rather than handling the false case manually.
55
+ *
56
+ * @template E - The branded enum type
57
+ * @param value - The value to check. Can be any type.
58
+ * @param enumObj - The branded enum to check against
59
+ * @returns The value with narrowed type if valid
60
+ * @throws {Error} Throws `Error` with message `Second argument is not a branded enum`
61
+ * if enumObj is not a valid branded enum.
62
+ * @throws {Error} Throws `Error` with message `Value "${value}" is not a member of enum "${enumId}"`
63
+ * if the value is not found in the enum.
64
+ *
65
+ * @example
66
+ * // Successful assertion
67
+ * const Status = createBrandedEnum('status', { Active: 'active', Inactive: 'inactive' } as const);
68
+ * const validated = assertFromEnum('active', Status);
69
+ * // validated is typed as 'active' | 'inactive'
70
+ *
71
+ * @example
72
+ * // Throws for invalid value
73
+ * try {
74
+ * assertFromEnum('unknown', Status);
75
+ * } catch (e) {
76
+ * console.log(e.message); // 'Value "unknown" is not a member of enum "status"'
77
+ * }
78
+ *
79
+ * @example
80
+ * // Throws for non-branded enum
81
+ * try {
82
+ * assertFromEnum('active', { Active: 'active' });
83
+ * } catch (e) {
84
+ * console.log(e.message); // 'Second argument is not a branded enum'
85
+ * }
86
+ */
87
+ export declare function assertFromEnum<E extends AnyBrandedEnum>(value: unknown, enumObj: E): EnumValues<E>;
88
+ /**
89
+ * Safely parses a value against a branded enum, returning a default if invalid.
90
+ *
91
+ * This is a non-throwing alternative to `assertFromEnum`. Instead of throwing
92
+ * an error when the value is not in the enum, it returns the provided default value.
93
+ *
94
+ * Use this function when you want to handle invalid values gracefully without
95
+ * try/catch blocks, such as when parsing user input or external data.
96
+ *
97
+ * @template E - The branded enum type
98
+ * @param value - The value to parse. Can be any type; non-strings will return the default.
99
+ * @param enumObj - The branded enum to validate against
100
+ * @param defaultValue - The value to return if parsing fails. Must be a valid enum value.
101
+ * @returns The original value if it exists in the enum, otherwise the default value.
102
+ * The return type is narrowed to the enum's value type.
103
+ *
104
+ * @example
105
+ * // Basic usage with default fallback
106
+ * const Status = createBrandedEnum('status', {
107
+ * Active: 'active',
108
+ * Inactive: 'inactive',
109
+ * Pending: 'pending',
110
+ * } as const);
111
+ *
112
+ * // Valid value returns as-is
113
+ * parseEnum('active', Status, Status.Pending); // 'active'
114
+ *
115
+ * // Invalid value returns default
116
+ * parseEnum('unknown', Status, Status.Pending); // 'pending'
117
+ *
118
+ * // Non-string value returns default
119
+ * parseEnum(null, Status, Status.Inactive); // 'inactive'
120
+ * parseEnum(123, Status, Status.Inactive); // 'inactive'
121
+ *
122
+ * @example
123
+ * // Parsing user input safely
124
+ * function handleUserStatus(input: unknown): void {
125
+ * const status = parseEnum(input, Status, Status.Pending);
126
+ * // status is guaranteed to be 'active' | 'inactive' | 'pending'
127
+ * console.log('Processing status:', status);
128
+ * }
129
+ *
130
+ * @example
131
+ * // Parsing API response with fallback
132
+ * interface ApiResponse {
133
+ * status?: string;
134
+ * }
135
+ *
136
+ * function processResponse(response: ApiResponse) {
137
+ * const status = parseEnum(response.status, Status, Status.Inactive);
138
+ * // Handles undefined, null, or invalid status values gracefully
139
+ * return { status };
140
+ * }
141
+ *
142
+ * @example
143
+ * // Chaining with optional values
144
+ * const userStatus = parseEnum(
145
+ * localStorage.getItem('userStatus'),
146
+ * Status,
147
+ * Status.Active
148
+ * );
149
+ */
150
+ export declare function parseEnum<E extends AnyBrandedEnum>(value: unknown, enumObj: E, defaultValue: EnumValues<E>): EnumValues<E>;
151
+ /**
152
+ * Represents a successful parse result from safeParseEnum.
153
+ *
154
+ * @template T - The type of the successfully parsed value
155
+ */
156
+ export interface SafeParseSuccess<T> {
157
+ /** Indicates the parse was successful */
158
+ readonly success: true;
159
+ /** The validated enum value */
160
+ readonly value: T;
161
+ }
162
+ /**
163
+ * Represents a failed parse result from safeParseEnum.
164
+ *
165
+ * Contains detailed error information for debugging and user feedback.
166
+ */
167
+ export interface SafeParseFailure {
168
+ /** Indicates the parse failed */
169
+ readonly success: false;
170
+ /** Detailed error information */
171
+ readonly error: SafeParseError;
172
+ }
173
+ /**
174
+ * Detailed error information for a failed parse.
175
+ */
176
+ export interface SafeParseError {
177
+ /** Human-readable error message */
178
+ readonly message: string;
179
+ /** The code identifying the type of error */
180
+ readonly code: SafeParseErrorCode;
181
+ /** The input value that failed validation */
182
+ readonly input: unknown;
183
+ /** The enum ID (if available) */
184
+ readonly enumId?: string;
185
+ /** The valid values for the enum (if available) */
186
+ readonly validValues?: readonly string[];
187
+ }
188
+ /**
189
+ * Error codes for safe parse failures.
190
+ */
191
+ export type SafeParseErrorCode = 'INVALID_ENUM_OBJECT' | 'INVALID_VALUE_TYPE' | 'VALUE_NOT_IN_ENUM';
192
+ /**
193
+ * Union type representing the result of safeParseEnum.
194
+ *
195
+ * @template T - The type of the successfully parsed value
196
+ */
197
+ export type SafeParseResult<T> = SafeParseSuccess<T> | SafeParseFailure;
198
+ /**
199
+ * Safely parses a value against a branded enum, returning a result object.
200
+ *
201
+ * This function provides validated deserialization with detailed error information.
202
+ * Unlike `parseEnum` which returns a default value on failure, or `assertFromEnum`
203
+ * which throws an error, `safeParseEnum` returns a discriminated union result
204
+ * that allows for explicit success/failure handling.
205
+ *
206
+ * The result is either:
207
+ * - `{ success: true, value: T }` - The value is valid and typed correctly
208
+ * - `{ success: false, error: SafeParseError }` - The value is invalid with details
209
+ *
210
+ * Error codes:
211
+ * - `INVALID_ENUM_OBJECT` - The enumObj is not a valid branded enum
212
+ * - `INVALID_VALUE_TYPE` - The value is not a string
213
+ * - `VALUE_NOT_IN_ENUM` - The value is a string but not in the enum
214
+ *
215
+ * @template E - The branded enum type
216
+ * @param value - The value to parse. Can be any type.
217
+ * @param enumObj - The branded enum to validate against
218
+ * @returns A SafeParseResult containing either the validated value or error details
219
+ *
220
+ * @example
221
+ * // Basic usage with success
222
+ * const Status = createBrandedEnum('status', {
223
+ * Active: 'active',
224
+ * Inactive: 'inactive',
225
+ * } as const);
226
+ *
227
+ * const result = safeParseEnum('active', Status);
228
+ * if (result.success) {
229
+ * console.log('Valid status:', result.value); // 'active'
230
+ * } else {
231
+ * console.log('Error:', result.error.message);
232
+ * }
233
+ *
234
+ * @example
235
+ * // Handling invalid value
236
+ * const result = safeParseEnum('unknown', Status);
237
+ * if (!result.success) {
238
+ * console.log(result.error.code); // 'VALUE_NOT_IN_ENUM'
239
+ * console.log(result.error.message); // 'Value "unknown" is not a member of enum "status"'
240
+ * console.log(result.error.validValues); // ['active', 'inactive']
241
+ * }
242
+ *
243
+ * @example
244
+ * // Handling non-string input
245
+ * const result = safeParseEnum(123, Status);
246
+ * if (!result.success) {
247
+ * console.log(result.error.code); // 'INVALID_VALUE_TYPE'
248
+ * console.log(result.error.message); // 'Expected a string value, received number'
249
+ * }
250
+ *
251
+ * @example
252
+ * // Parsing API response
253
+ * interface ApiResponse {
254
+ * status?: string;
255
+ * }
256
+ *
257
+ * function processResponse(response: ApiResponse) {
258
+ * const result = safeParseEnum(response.status, Status);
259
+ * if (result.success) {
260
+ * return { status: result.value };
261
+ * } else {
262
+ * // Log detailed error for debugging
263
+ * console.error('Invalid status:', result.error);
264
+ * return { status: Status.Inactive }; // fallback
265
+ * }
266
+ * }
267
+ *
268
+ * @example
269
+ * // Form validation with detailed errors
270
+ * function validateForm(data: Record<string, unknown>) {
271
+ * const statusResult = safeParseEnum(data.status, Status);
272
+ * const errors: string[] = [];
273
+ *
274
+ * if (!statusResult.success) {
275
+ * errors.push(`Status: ${statusResult.error.message}`);
276
+ * }
277
+ *
278
+ * return {
279
+ * isValid: errors.length === 0,
280
+ * errors,
281
+ * data: statusResult.success ? { status: statusResult.value } : null,
282
+ * };
283
+ * }
284
+ *
285
+ * @example
286
+ * // Type narrowing with result
287
+ * const result = safeParseEnum(userInput, Status);
288
+ * if (result.success) {
289
+ * // result.value is typed as 'active' | 'inactive'
290
+ * handleStatus(result.value);
291
+ * } else {
292
+ * // result.error is typed as SafeParseError
293
+ * showError(result.error.message);
294
+ * }
295
+ */
296
+ export declare function safeParseEnum<E extends AnyBrandedEnum>(value: unknown, enumObj: E): SafeParseResult<EnumValues<E>>;
297
+ //# sourceMappingURL=guards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guards.d.ts","sourceRoot":"","sources":["../../src/lib/guards.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,cAAc,EAKd,UAAU,EACX,MAAM,YAAY,CAAC;AAmBpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,cAAc,EACjD,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,CAAC,GACT,KAAK,IAAI,UAAU,CAAC,CAAC,CAAC,CAaxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,cAAc,EACrD,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,CAAC,GACT,UAAU,CAAC,CAAC,CAAC,CAaf;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,cAAc,EAChD,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,CAAC,EACV,YAAY,EAAE,UAAU,CAAC,CAAC,CAAC,GAC1B,UAAU,CAAC,CAAC,CAAC,CAQf;AAMD;;;;GAIG;AACH,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,yCAAyC;IACzC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;IACvB,+BAA+B;IAC/B,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,iCAAiC;IACjC,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;IACxB,iCAAiC;IACjC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,mCAAmC;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,6CAA6C;IAC7C,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,6CAA6C;IAC7C,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,iCAAiC;IACjC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,mDAAmD;IACnD,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1C;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAC1B,qBAAqB,GACrB,oBAAoB,GACpB,mBAAmB,CAAC;AAExB;;;;GAIG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI,gBAAgB,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC;AAExE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiGG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,cAAc,EACpD,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,CAAC,GACT,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAkDhC"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Enum composition functions for branded enums.
3
+ *
4
+ * Enables merging multiple branded enums into a new combined enum
5
+ * while maintaining type safety and registry tracking.
6
+ */
7
+ import { AnyBrandedEnum, BrandedEnum } from './types.js';
8
+ /**
9
+ * Merges multiple branded enums into a new branded enum.
10
+ *
11
+ * Creates a new branded enum that contains all key-value pairs from all
12
+ * source enums. The merged enum is registered in the global registry
13
+ * as a new independent enum.
14
+ *
15
+ * Key collision handling:
16
+ * - Duplicate keys (same key in multiple enums) throw an error
17
+ * - Duplicate values (same value in multiple enums) are allowed
18
+ *
19
+ * @template T - Tuple of branded enum types being merged
20
+ * @param newId - Unique identifier for the merged enum. Must not already
21
+ * be registered.
22
+ * @param enums - One or more branded enums to merge
23
+ * @returns A new branded enum containing all values from source enums
24
+ * @throws {Error} Throws `Error` with message
25
+ * `Cannot merge enums: duplicate key "${key}" found in enums "${enumId1}" and "${enumId2}"`
26
+ * if the same key exists in multiple source enums.
27
+ * @throws {Error} Throws `Error` with message
28
+ * `Branded enum with ID "${newId}" already exists` if newId is already registered.
29
+ * @throws {Error} Throws `Error` with message `All arguments must be branded enums`
30
+ * if any argument is not a valid branded enum.
31
+ *
32
+ * @example
33
+ * // Basic merge
34
+ * const Colors = createBrandedEnum('colors', { Red: 'red', Blue: 'blue' } as const);
35
+ * const Sizes = createBrandedEnum('sizes', { Small: 'small', Large: 'large' } as const);
36
+ *
37
+ * const Combined = mergeEnums('combined', Colors, Sizes);
38
+ * // Combined has: Red, Blue, Small, Large
39
+ *
40
+ * Combined.Red; // 'red'
41
+ * Combined.Small; // 'small'
42
+ *
43
+ * @example
44
+ * // Duplicate values are allowed
45
+ * const Status1 = createBrandedEnum('status1', { Active: 'active' } as const);
46
+ * const Status2 = createBrandedEnum('status2', { Enabled: 'active' } as const);
47
+ *
48
+ * const Merged = mergeEnums('merged', Status1, Status2);
49
+ * // Both Active and Enabled have value 'active' - this is allowed
50
+ *
51
+ * @example
52
+ * // Duplicate keys throw an error
53
+ * const Enum1 = createBrandedEnum('enum1', { Key: 'value1' } as const);
54
+ * const Enum2 = createBrandedEnum('enum2', { Key: 'value2' } as const);
55
+ *
56
+ * try {
57
+ * mergeEnums('merged', Enum1, Enum2);
58
+ * } catch (e) {
59
+ * console.log(e.message);
60
+ * // 'Cannot merge enums: duplicate key "Key" found in enums "enum1" and "enum2"'
61
+ * }
62
+ */
63
+ export declare function mergeEnums<T extends readonly AnyBrandedEnum[]>(newId: string, ...enums: T): BrandedEnum<Record<string, string>>;
64
+ //# sourceMappingURL=merge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../src/lib/merge.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,WAAW,EAAwB,MAAM,YAAY,CAAC;AA2B/E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,SAAS,cAAc,EAAE,EAC5D,KAAK,EAAE,MAAM,EACb,GAAG,KAAK,EAAE,CAAC,GACV,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CA6BrC"}