@digitaldefiance/branded-enum 0.0.1 → 0.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 (79) hide show
  1. package/dist/cjs/index.cjs +149 -0
  2. package/dist/cjs/index.cjs.map +1 -0
  3. package/dist/cjs/lib/accessors.cjs +55 -0
  4. package/dist/cjs/lib/accessors.cjs.map +1 -0
  5. package/dist/cjs/lib/advanced.cjs +558 -0
  6. package/dist/cjs/lib/advanced.cjs.map +1 -0
  7. package/dist/cjs/lib/branded-enum.cjs +15 -0
  8. package/dist/cjs/lib/branded-enum.cjs.map +1 -0
  9. package/dist/cjs/lib/decorators.cjs +202 -0
  10. package/dist/cjs/lib/decorators.cjs.map +1 -0
  11. package/dist/cjs/lib/factory.cjs +45 -0
  12. package/dist/cjs/lib/factory.cjs.map +1 -0
  13. package/dist/cjs/lib/guards.cjs +119 -0
  14. package/dist/cjs/lib/guards.cjs.map +1 -0
  15. package/dist/cjs/lib/merge.cjs +47 -0
  16. package/dist/cjs/lib/merge.cjs.map +1 -0
  17. package/dist/cjs/lib/registry.cjs +85 -0
  18. package/dist/cjs/lib/registry.cjs.map +1 -0
  19. package/dist/cjs/lib/types.cjs +38 -0
  20. package/dist/cjs/lib/types.cjs.map +1 -0
  21. package/dist/cjs/lib/utils.cjs +80 -0
  22. package/dist/cjs/lib/utils.cjs.map +1 -0
  23. package/dist/esm/index.d.ts +21 -0
  24. package/dist/esm/index.d.ts.map +1 -0
  25. package/dist/esm/index.js.map +1 -0
  26. package/dist/esm/lib/accessors.d.ts +79 -0
  27. package/dist/esm/lib/accessors.d.ts.map +1 -0
  28. package/dist/esm/lib/accessors.js.map +1 -0
  29. package/dist/esm/lib/advanced.d.ts +1422 -0
  30. package/dist/esm/lib/advanced.d.ts.map +1 -0
  31. package/dist/esm/lib/advanced.js.map +1 -0
  32. package/dist/esm/lib/branded-enum.d.ts +2 -0
  33. package/dist/esm/lib/branded-enum.d.ts.map +1 -0
  34. package/dist/esm/lib/branded-enum.js.map +1 -0
  35. package/dist/esm/lib/decorators.d.ts +147 -0
  36. package/dist/esm/lib/decorators.d.ts.map +1 -0
  37. package/dist/esm/lib/decorators.js.map +1 -0
  38. package/dist/esm/lib/factory.d.ts +52 -0
  39. package/dist/esm/lib/factory.d.ts.map +1 -0
  40. package/dist/esm/lib/factory.js.map +1 -0
  41. package/dist/esm/lib/guards.d.ts +297 -0
  42. package/dist/esm/lib/guards.d.ts.map +1 -0
  43. package/dist/esm/lib/guards.js.map +1 -0
  44. package/dist/esm/lib/merge.d.ts +64 -0
  45. package/dist/esm/lib/merge.d.ts.map +1 -0
  46. package/dist/esm/lib/merge.js.map +1 -0
  47. package/dist/esm/lib/registry.d.ts +93 -0
  48. package/dist/esm/lib/registry.d.ts.map +1 -0
  49. package/dist/esm/lib/registry.js.map +1 -0
  50. package/dist/esm/lib/types.d.ts +258 -0
  51. package/dist/esm/lib/types.d.ts.map +1 -0
  52. package/dist/esm/lib/types.js.map +1 -0
  53. package/dist/esm/lib/utils.d.ts +121 -0
  54. package/dist/esm/lib/utils.d.ts.map +1 -0
  55. package/dist/esm/lib/utils.js.map +1 -0
  56. package/package.json +31 -18
  57. package/dist/index.js.map +0 -1
  58. package/dist/lib/accessors.js.map +0 -1
  59. package/dist/lib/advanced.js.map +0 -1
  60. package/dist/lib/branded-enum.js.map +0 -1
  61. package/dist/lib/decorators.js.map +0 -1
  62. package/dist/lib/factory.js.map +0 -1
  63. package/dist/lib/guards.js.map +0 -1
  64. package/dist/lib/merge.js.map +0 -1
  65. package/dist/lib/registry.js.map +0 -1
  66. package/dist/lib/types.js.map +0 -1
  67. package/dist/lib/utils.js.map +0 -1
  68. package/dist/package.json +0 -120
  69. /package/dist/{index.js → esm/index.js} +0 -0
  70. /package/dist/{lib → esm/lib}/accessors.js +0 -0
  71. /package/dist/{lib → esm/lib}/advanced.js +0 -0
  72. /package/dist/{lib → esm/lib}/branded-enum.js +0 -0
  73. /package/dist/{lib → esm/lib}/decorators.js +0 -0
  74. /package/dist/{lib → esm/lib}/factory.js +0 -0
  75. /package/dist/{lib → esm/lib}/guards.js +0 -0
  76. /package/dist/{lib → esm/lib}/merge.js +0 -0
  77. /package/dist/{lib → esm/lib}/registry.js +0 -0
  78. /package/dist/{lib → esm/lib}/types.js +0 -0
  79. /package/dist/{lib → esm/lib}/utils.js +0 -0
@@ -0,0 +1,258 @@
1
+ /**
2
+ * Core type definitions for branded-enum library
3
+ *
4
+ * These types enable runtime-identifiable enum-like objects in TypeScript
5
+ * with zero runtime overhead for value access.
6
+ */
7
+ /**
8
+ * Symbol key for storing the enum ID metadata.
9
+ * Using a Symbol prevents collision with user-defined keys.
10
+ */
11
+ export declare const ENUM_ID: unique symbol;
12
+ /**
13
+ * Symbol key for storing the enum values Set.
14
+ * Using a Symbol prevents collision with user-defined keys.
15
+ */
16
+ export declare const ENUM_VALUES: unique symbol;
17
+ /**
18
+ * Metadata attached to branded enums via Symbol properties.
19
+ * These properties are non-enumerable and won't appear in
20
+ * Object.keys(), Object.values(), or JSON serialization.
21
+ */
22
+ export interface BrandedEnumMetadata {
23
+ readonly [ENUM_ID]: string;
24
+ readonly [ENUM_VALUES]: Set<string>;
25
+ }
26
+ /**
27
+ * A branded enum object - combines the user's values object with metadata.
28
+ * The object is frozen (Readonly) to prevent modification after creation.
29
+ *
30
+ * @template T - The shape of the enum values object (Record<string, string>)
31
+ */
32
+ export type BrandedEnum<T extends Record<string, string>> = Readonly<T> & BrandedEnumMetadata;
33
+ /**
34
+ * Base constraint type for branded enums that works with both
35
+ * `as const` objects and regular Record<string, string> objects.
36
+ *
37
+ * This type is more permissive than `BrandedEnum<Record<string, string>>`
38
+ * and allows literal types from `as const` assertions.
39
+ */
40
+ export type AnyBrandedEnum = {
41
+ readonly [ENUM_ID]: string;
42
+ readonly [ENUM_VALUES]: Set<string>;
43
+ };
44
+ /**
45
+ * Utility type to extract the union of all value types from a branded enum.
46
+ * Useful for typing variables that can hold any value from the enum.
47
+ *
48
+ * @template E - A BrandedEnum type
49
+ *
50
+ * @example
51
+ * const Status = createBrandedEnum('status', { Active: 'active', Inactive: 'inactive' } as const);
52
+ * type StatusValue = BrandedEnumValue<typeof Status>; // 'active' | 'inactive'
53
+ */
54
+ export type BrandedEnumValue<E extends AnyBrandedEnum> = E extends BrandedEnum<infer T> ? T[keyof T] : never;
55
+ /**
56
+ * Registry entry for tracking a single branded enum in the global registry.
57
+ */
58
+ export interface RegistryEntry {
59
+ /** The unique identifier for this enum */
60
+ readonly enumId: string;
61
+ /** The branded enum object itself */
62
+ readonly enumObj: BrandedEnum<Record<string, string>>;
63
+ /** Set of all values in this enum for O(1) lookup */
64
+ readonly values: Set<string>;
65
+ }
66
+ /**
67
+ * Global registry structure stored on globalThis.
68
+ * Enables cross-bundle tracking of all branded enums.
69
+ */
70
+ export interface BrandedEnumRegistry {
71
+ /** Map from enumId to registry entry */
72
+ readonly enums: Map<string, RegistryEntry>;
73
+ /** Reverse index: value -> Set of enumIds containing that value */
74
+ readonly valueIndex: Map<string, Set<string>>;
75
+ }
76
+ /**
77
+ * The key used to store the registry on globalThis.
78
+ * Namespaced to avoid collisions with other libraries.
79
+ */
80
+ export declare const REGISTRY_KEY: "__brandedEnumRegistry__";
81
+ /**
82
+ * The key used to store the enum consumer registry on globalThis.
83
+ * Tracks which classes consume which branded enums.
84
+ */
85
+ export declare const CONSUMER_REGISTRY_KEY: "__brandedEnumConsumerRegistry__";
86
+ /**
87
+ * Entry tracking a class that consumes branded enums.
88
+ */
89
+ export interface EnumConsumerEntry {
90
+ /** The class constructor function */
91
+ readonly classRef: new (...args: any[]) => any;
92
+ /** The class name */
93
+ readonly className: string;
94
+ /** Set of enum IDs that this class consumes */
95
+ readonly enumIds: Set<string>;
96
+ }
97
+ /**
98
+ * Global registry for tracking enum consumers (classes decorated with @EnumClass).
99
+ * Enables debugging and introspection of enum usage across the codebase.
100
+ */
101
+ export interface EnumConsumerRegistry {
102
+ /** Map from class name to consumer entry */
103
+ readonly consumers: Map<string, EnumConsumerEntry>;
104
+ /** Reverse index: enumId -> Set of class names consuming that enum */
105
+ readonly enumToConsumers: Map<string, Set<string>>;
106
+ }
107
+ /**
108
+ * Extracts the union of all keys from a branded enum.
109
+ *
110
+ * This utility type provides compile-time access to all key names of a branded enum,
111
+ * excluding the Symbol metadata keys (ENUM_ID and ENUM_VALUES).
112
+ *
113
+ * @template E - A BrandedEnum type
114
+ *
115
+ * @example
116
+ * const Status = createBrandedEnum('status', {
117
+ * Active: 'active',
118
+ * Inactive: 'inactive',
119
+ * Pending: 'pending',
120
+ * } as const);
121
+ *
122
+ * type StatusKeys = EnumKeys<typeof Status>;
123
+ * // StatusKeys = 'Active' | 'Inactive' | 'Pending'
124
+ *
125
+ * @example
126
+ * // Use in function parameters
127
+ * function getStatusLabel<E extends AnyBrandedEnum>(
128
+ * enumObj: E,
129
+ * key: EnumKeys<E>
130
+ * ): string {
131
+ * return enumObj[key] as string;
132
+ * }
133
+ */
134
+ export type EnumKeys<E> = E extends BrandedEnum<infer T> ? keyof T & string : E extends AnyBrandedEnum ? Exclude<keyof E, typeof ENUM_ID | typeof ENUM_VALUES> & string : never;
135
+ /**
136
+ * Extracts the union of all values from a branded enum.
137
+ *
138
+ * This is an alias for BrandedEnumValue that provides a more intuitive name
139
+ * when working with compile-time type utilities.
140
+ *
141
+ * @template E - A BrandedEnum type
142
+ *
143
+ * @example
144
+ * const Status = createBrandedEnum('status', {
145
+ * Active: 'active',
146
+ * Inactive: 'inactive',
147
+ * Pending: 'pending',
148
+ * } as const);
149
+ *
150
+ * type StatusValues = EnumValues<typeof Status>;
151
+ * // StatusValues = 'active' | 'inactive' | 'pending'
152
+ *
153
+ * @example
154
+ * // Use for type-safe value handling
155
+ * function processStatus(value: EnumValues<typeof Status>) {
156
+ * // value is 'active' | 'inactive' | 'pending'
157
+ * }
158
+ */
159
+ export type EnumValues<E> = E extends BrandedEnum<infer T> ? T[keyof T] : E extends AnyBrandedEnum ? Exclude<E[Exclude<keyof E, typeof ENUM_ID | typeof ENUM_VALUES>], Set<string>> & string : never;
160
+ /**
161
+ * Validates that a value type V is a valid value of branded enum E at compile time.
162
+ *
163
+ * If V is a valid value of E, this type resolves to V.
164
+ * If V is NOT a valid value of E, this type resolves to `never`, causing a compile error
165
+ * when used in contexts that expect a non-never type.
166
+ *
167
+ * This enables compile-time validation of enum values without runtime overhead.
168
+ *
169
+ * @template E - A BrandedEnum type
170
+ * @template V - The value type to validate
171
+ *
172
+ * @example
173
+ * const Status = createBrandedEnum('status', {
174
+ * Active: 'active',
175
+ * Inactive: 'inactive',
176
+ * } as const);
177
+ *
178
+ * // Valid - 'active' is in Status
179
+ * type Valid = ValidEnumValue<typeof Status, 'active'>; // 'active'
180
+ *
181
+ * // Invalid - 'unknown' is not in Status
182
+ * type Invalid = ValidEnumValue<typeof Status, 'unknown'>; // never
183
+ *
184
+ * @example
185
+ * // Use in function to enforce valid values at compile time
186
+ * function setStatus<V extends string>(
187
+ * value: ValidEnumValue<typeof Status, V>
188
+ * ): void {
189
+ * // Only compiles if value is 'active' | 'inactive'
190
+ * }
191
+ *
192
+ * setStatus('active'); // OK
193
+ * setStatus('inactive'); // OK
194
+ * // setStatus('unknown'); // Compile error: Argument of type 'never' is not assignable
195
+ *
196
+ * @example
197
+ * // Type-level assertion
198
+ * type AssertActive = ValidEnumValue<typeof Status, 'active'>; // 'active' - OK
199
+ * type AssertBad = ValidEnumValue<typeof Status, 'bad'>; // never - indicates invalid
200
+ */
201
+ export type ValidEnumValue<E, V extends string> = V extends EnumValues<E> ? V : never;
202
+ /**
203
+ * Creates a strict parameter type that only accepts valid values from a branded enum.
204
+ *
205
+ * This utility type is designed for function parameters where you want to enforce
206
+ * that only values from a specific branded enum are accepted at compile time.
207
+ *
208
+ * Unlike using `BrandedEnumValue<E>` directly, `StrictEnumParam` provides better
209
+ * error messages and works well with generic functions.
210
+ *
211
+ * @template E - A BrandedEnum type
212
+ *
213
+ * @example
214
+ * const Status = createBrandedEnum('status', {
215
+ * Active: 'active',
216
+ * Inactive: 'inactive',
217
+ * Pending: 'pending',
218
+ * } as const);
219
+ *
220
+ * // Function that only accepts Status values
221
+ * function updateStatus(newStatus: StrictEnumParam<typeof Status>): void {
222
+ * console.log(`Status updated to: ${newStatus}`);
223
+ * }
224
+ *
225
+ * updateStatus(Status.Active); // OK
226
+ * updateStatus('active'); // OK (literal type matches)
227
+ * // updateStatus('unknown'); // Compile error
228
+ *
229
+ * @example
230
+ * // Use with multiple enum parameters
231
+ * const Priority = createBrandedEnum('priority', {
232
+ * High: 'high',
233
+ * Medium: 'medium',
234
+ * Low: 'low',
235
+ * } as const);
236
+ *
237
+ * function createTask(
238
+ * status: StrictEnumParam<typeof Status>,
239
+ * priority: StrictEnumParam<typeof Priority>
240
+ * ): void {
241
+ * // Both parameters are type-safe
242
+ * }
243
+ *
244
+ * createTask(Status.Active, Priority.High); // OK
245
+ * createTask('active', 'high'); // OK
246
+ * // createTask('active', 'invalid'); // Compile error on second param
247
+ *
248
+ * @example
249
+ * // Generic function with strict enum constraint
250
+ * function processValue<E extends AnyBrandedEnum>(
251
+ * enumObj: E,
252
+ * value: StrictEnumParam<E>
253
+ * ): void {
254
+ * // value is guaranteed to be a valid value of enumObj
255
+ * }
256
+ */
257
+ export type StrictEnumParam<E> = EnumValues<E>;
258
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/lib/types.ts"],"sourcesContent":["/**\n * Core type definitions for branded-enum library\n *\n * These types enable runtime-identifiable enum-like objects in TypeScript\n * with zero runtime overhead for value access.\n */\n\n/**\n * Symbol key for storing the enum ID metadata.\n * Using a Symbol prevents collision with user-defined keys.\n */\nexport const ENUM_ID: unique symbol = Symbol('ENUM_ID');\n\n/**\n * Symbol key for storing the enum values Set.\n * Using a Symbol prevents collision with user-defined keys.\n */\nexport const ENUM_VALUES: unique symbol = Symbol('ENUM_VALUES');\n\n/**\n * Metadata attached to branded enums via Symbol properties.\n * These properties are non-enumerable and won't appear in\n * Object.keys(), Object.values(), or JSON serialization.\n */\nexport interface BrandedEnumMetadata {\n readonly [ENUM_ID]: string;\n readonly [ENUM_VALUES]: Set<string>;\n}\n\n/**\n * A branded enum object - combines the user's values object with metadata.\n * The object is frozen (Readonly) to prevent modification after creation.\n *\n * @template T - The shape of the enum values object (Record<string, string>)\n */\nexport type BrandedEnum<T extends Record<string, string>> = Readonly<T> &\n BrandedEnumMetadata;\n\n/**\n * Base constraint type for branded enums that works with both\n * `as const` objects and regular Record<string, string> objects.\n *\n * This type is more permissive than `BrandedEnum<Record<string, string>>`\n * and allows literal types from `as const` assertions.\n */\nexport type AnyBrandedEnum = {\n readonly [ENUM_ID]: string;\n readonly [ENUM_VALUES]: Set<string>;\n};\n\n/**\n * Utility type to extract the union of all value types from a branded enum.\n * Useful for typing variables that can hold any value from the enum.\n *\n * @template E - A BrandedEnum type\n *\n * @example\n * const Status = createBrandedEnum('status', { Active: 'active', Inactive: 'inactive' } as const);\n * type StatusValue = BrandedEnumValue<typeof Status>; // 'active' | 'inactive'\n */\nexport type BrandedEnumValue<E extends AnyBrandedEnum> =\n E extends BrandedEnum<infer T> ? T[keyof T] : never;\n\n/**\n * Registry entry for tracking a single branded enum in the global registry.\n */\nexport interface RegistryEntry {\n /** The unique identifier for this enum */\n readonly enumId: string;\n /** The branded enum object itself */\n readonly enumObj: BrandedEnum<Record<string, string>>;\n /** Set of all values in this enum for O(1) lookup */\n readonly values: Set<string>;\n}\n\n/**\n * Global registry structure stored on globalThis.\n * Enables cross-bundle tracking of all branded enums.\n */\nexport interface BrandedEnumRegistry {\n /** Map from enumId to registry entry */\n readonly enums: Map<string, RegistryEntry>;\n /** Reverse index: value -> Set of enumIds containing that value */\n readonly valueIndex: Map<string, Set<string>>;\n}\n\n/**\n * The key used to store the registry on globalThis.\n * Namespaced to avoid collisions with other libraries.\n */\nexport const REGISTRY_KEY = '__brandedEnumRegistry__' as const;\n\n/**\n * The key used to store the enum consumer registry on globalThis.\n * Tracks which classes consume which branded enums.\n */\nexport const CONSUMER_REGISTRY_KEY = '__brandedEnumConsumerRegistry__' as const;\n\n/**\n * Entry tracking a class that consumes branded enums.\n */\nexport interface EnumConsumerEntry {\n /** The class constructor function */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n readonly classRef: new (...args: any[]) => any;\n /** The class name */\n readonly className: string;\n /** Set of enum IDs that this class consumes */\n readonly enumIds: Set<string>;\n}\n\n/**\n * Global registry for tracking enum consumers (classes decorated with @EnumClass).\n * Enables debugging and introspection of enum usage across the codebase.\n */\nexport interface EnumConsumerRegistry {\n /** Map from class name to consumer entry */\n readonly consumers: Map<string, EnumConsumerEntry>;\n /** Reverse index: enumId -> Set of class names consuming that enum */\n readonly enumToConsumers: Map<string, Set<string>>;\n}\n\n// =============================================================================\n// Compile-Time Validation Types\n// =============================================================================\n\n/**\n * Extracts the union of all keys from a branded enum.\n *\n * This utility type provides compile-time access to all key names of a branded enum,\n * excluding the Symbol metadata keys (ENUM_ID and ENUM_VALUES).\n *\n * @template E - A BrandedEnum type\n *\n * @example\n * const Status = createBrandedEnum('status', {\n * Active: 'active',\n * Inactive: 'inactive',\n * Pending: 'pending',\n * } as const);\n *\n * type StatusKeys = EnumKeys<typeof Status>;\n * // StatusKeys = 'Active' | 'Inactive' | 'Pending'\n *\n * @example\n * // Use in function parameters\n * function getStatusLabel<E extends AnyBrandedEnum>(\n * enumObj: E,\n * key: EnumKeys<E>\n * ): string {\n * return enumObj[key] as string;\n * }\n */\nexport type EnumKeys<E> = E extends BrandedEnum<infer T>\n ? keyof T & string\n : E extends AnyBrandedEnum\n ? Exclude<keyof E, typeof ENUM_ID | typeof ENUM_VALUES> & string\n : never;\n\n/**\n * Extracts the union of all values from a branded enum.\n *\n * This is an alias for BrandedEnumValue that provides a more intuitive name\n * when working with compile-time type utilities.\n *\n * @template E - A BrandedEnum type\n *\n * @example\n * const Status = createBrandedEnum('status', {\n * Active: 'active',\n * Inactive: 'inactive',\n * Pending: 'pending',\n * } as const);\n *\n * type StatusValues = EnumValues<typeof Status>;\n * // StatusValues = 'active' | 'inactive' | 'pending'\n *\n * @example\n * // Use for type-safe value handling\n * function processStatus(value: EnumValues<typeof Status>) {\n * // value is 'active' | 'inactive' | 'pending'\n * }\n */\nexport type EnumValues<E> = E extends BrandedEnum<infer T>\n ? T[keyof T]\n : E extends AnyBrandedEnum\n ? Exclude<E[Exclude<keyof E, typeof ENUM_ID | typeof ENUM_VALUES>], Set<string>> & string\n : never;\n\n/**\n * Validates that a value type V is a valid value of branded enum E at compile time.\n *\n * If V is a valid value of E, this type resolves to V.\n * If V is NOT a valid value of E, this type resolves to `never`, causing a compile error\n * when used in contexts that expect a non-never type.\n *\n * This enables compile-time validation of enum values without runtime overhead.\n *\n * @template E - A BrandedEnum type\n * @template V - The value type to validate\n *\n * @example\n * const Status = createBrandedEnum('status', {\n * Active: 'active',\n * Inactive: 'inactive',\n * } as const);\n *\n * // Valid - 'active' is in Status\n * type Valid = ValidEnumValue<typeof Status, 'active'>; // 'active'\n *\n * // Invalid - 'unknown' is not in Status\n * type Invalid = ValidEnumValue<typeof Status, 'unknown'>; // never\n *\n * @example\n * // Use in function to enforce valid values at compile time\n * function setStatus<V extends string>(\n * value: ValidEnumValue<typeof Status, V>\n * ): void {\n * // Only compiles if value is 'active' | 'inactive'\n * }\n *\n * setStatus('active'); // OK\n * setStatus('inactive'); // OK\n * // setStatus('unknown'); // Compile error: Argument of type 'never' is not assignable\n *\n * @example\n * // Type-level assertion\n * type AssertActive = ValidEnumValue<typeof Status, 'active'>; // 'active' - OK\n * type AssertBad = ValidEnumValue<typeof Status, 'bad'>; // never - indicates invalid\n */\nexport type ValidEnumValue<E, V extends string> = V extends EnumValues<E>\n ? V\n : never;\n\n/**\n * Creates a strict parameter type that only accepts valid values from a branded enum.\n *\n * This utility type is designed for function parameters where you want to enforce\n * that only values from a specific branded enum are accepted at compile time.\n *\n * Unlike using `BrandedEnumValue<E>` directly, `StrictEnumParam` provides better\n * error messages and works well with generic functions.\n *\n * @template E - A BrandedEnum type\n *\n * @example\n * const Status = createBrandedEnum('status', {\n * Active: 'active',\n * Inactive: 'inactive',\n * Pending: 'pending',\n * } as const);\n *\n * // Function that only accepts Status values\n * function updateStatus(newStatus: StrictEnumParam<typeof Status>): void {\n * console.log(`Status updated to: ${newStatus}`);\n * }\n *\n * updateStatus(Status.Active); // OK\n * updateStatus('active'); // OK (literal type matches)\n * // updateStatus('unknown'); // Compile error\n *\n * @example\n * // Use with multiple enum parameters\n * const Priority = createBrandedEnum('priority', {\n * High: 'high',\n * Medium: 'medium',\n * Low: 'low',\n * } as const);\n *\n * function createTask(\n * status: StrictEnumParam<typeof Status>,\n * priority: StrictEnumParam<typeof Priority>\n * ): void {\n * // Both parameters are type-safe\n * }\n *\n * createTask(Status.Active, Priority.High); // OK\n * createTask('active', 'high'); // OK\n * // createTask('active', 'invalid'); // Compile error on second param\n *\n * @example\n * // Generic function with strict enum constraint\n * function processValue<E extends AnyBrandedEnum>(\n * enumObj: E,\n * value: StrictEnumParam<E>\n * ): void {\n * // value is guaranteed to be a valid value of enumObj\n * }\n */\nexport type StrictEnumParam<E> = EnumValues<E>;\n"],"names":["ENUM_ID","Symbol","ENUM_VALUES","REGISTRY_KEY","CONSUMER_REGISTRY_KEY"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;","mappings":"AAAA;;;;;CAKC,GAED;;;CAGC,GACD,OAAO,MAAMA,UAAyBC,OAAO,WAAW;AAExD;;;CAGC,GACD,OAAO,MAAMC,cAA6BD,OAAO,eAAe;AAqEhE;;;CAGC,GACD,OAAO,MAAME,eAAe,0BAAmC;AAE/D;;;CAGC,GACD,OAAO,MAAMC,wBAAwB,kCAA2C"}
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Utility functions for branded enums.
3
+ *
4
+ * Provides additional functionality beyond standard enum operations,
5
+ * including reverse lookup, key validation, and iteration.
6
+ */
7
+ import { AnyBrandedEnum, EnumKeys, EnumValues } from './types.js';
8
+ /**
9
+ * Checks if a value exists in a branded enum (reverse lookup).
10
+ *
11
+ * Similar to `isFromEnum`, but with arguments in a different order that
12
+ * may be more natural for some use cases. Also provides type narrowing.
13
+ *
14
+ * @template E - The branded enum type
15
+ * @param enumObj - The branded enum to search in
16
+ * @param value - The value to check. Can be any type; non-strings return false.
17
+ * @returns `true` if the value exists in the enum (with type narrowing),
18
+ * `false` otherwise. Returns `false` for non-string values or if
19
+ * enumObj is not a branded enum.
20
+ *
21
+ * @example
22
+ * // Check if value exists
23
+ * const Status = createBrandedEnum('status', { Active: 'active', Inactive: 'inactive' } as const);
24
+ * hasValue(Status, 'active'); // true
25
+ * hasValue(Status, 'unknown'); // false
26
+ *
27
+ * @example
28
+ * // Returns false for non-string values
29
+ * hasValue(Status, 123); // false
30
+ * hasValue(Status, null); // false
31
+ */
32
+ export declare function hasValue<E extends AnyBrandedEnum>(enumObj: E, value: unknown): value is EnumValues<E>;
33
+ /**
34
+ * Gets the key name for a value in a branded enum.
35
+ *
36
+ * Performs a reverse lookup to find which key maps to a given value.
37
+ * If multiple keys have the same value, returns the first one found
38
+ * (order is not guaranteed).
39
+ *
40
+ * @template E - The branded enum type
41
+ * @param enumObj - The branded enum to search in
42
+ * @param value - The string value to look up
43
+ * @returns The key name that maps to the value, or `undefined` if the
44
+ * value is not found or enumObj is not a branded enum.
45
+ *
46
+ * @example
47
+ * // Find key for value
48
+ * const Status = createBrandedEnum('status', { Active: 'active', Inactive: 'inactive' } as const);
49
+ * getKeyForValue(Status, 'active'); // 'Active'
50
+ * getKeyForValue(Status, 'inactive'); // 'Inactive'
51
+ *
52
+ * @example
53
+ * // Returns undefined for unknown values
54
+ * getKeyForValue(Status, 'unknown'); // undefined
55
+ *
56
+ * @example
57
+ * // Roundtrip: value -> key -> value
58
+ * const key = getKeyForValue(Status, 'active'); // 'Active'
59
+ * Status[key]; // 'active'
60
+ */
61
+ export declare function getKeyForValue<E extends AnyBrandedEnum>(enumObj: E, value: string): EnumKeys<E> | undefined;
62
+ /**
63
+ * Checks if a key exists in a branded enum.
64
+ *
65
+ * Validates whether a given key is a valid member of the enum.
66
+ * Returns false for Symbol keys (metadata) and non-string keys.
67
+ *
68
+ * @template E - The branded enum type
69
+ * @param enumObj - The branded enum to check
70
+ * @param key - The key to validate. Can be any type; non-strings return false.
71
+ * @returns `true` if the key exists in the enum (with type narrowing),
72
+ * `false` otherwise. Returns `false` for metadata Symbol keys or if
73
+ * enumObj is not a branded enum.
74
+ *
75
+ * @example
76
+ * // Check if key exists
77
+ * const Status = createBrandedEnum('status', { Active: 'active', Inactive: 'inactive' } as const);
78
+ * isValidKey(Status, 'Active'); // true
79
+ * isValidKey(Status, 'Inactive'); // true
80
+ * isValidKey(Status, 'Unknown'); // false
81
+ *
82
+ * @example
83
+ * // Returns false for non-string keys
84
+ * isValidKey(Status, 123); // false
85
+ * isValidKey(Status, Symbol('test')); // false
86
+ */
87
+ export declare function isValidKey<E extends AnyBrandedEnum>(enumObj: E, key: unknown): key is EnumKeys<E>;
88
+ /**
89
+ * Returns an iterator of [key, value] pairs for a branded enum.
90
+ *
91
+ * Provides a way to iterate over all key-value pairs in the enum using
92
+ * a for...of loop. Only yields user-defined entries, not metadata.
93
+ * Equivalent to `Object.entries(enumObj)` but with proper typing.
94
+ *
95
+ * @template E - The branded enum type
96
+ * @param enumObj - The branded enum to iterate over
97
+ * @returns An iterator yielding [key, value] tuples. Returns an empty
98
+ * iterator if enumObj is not a branded enum.
99
+ *
100
+ * @example
101
+ * // Iterate over entries
102
+ * const Status = createBrandedEnum('status', { Active: 'active', Inactive: 'inactive' } as const);
103
+ *
104
+ * for (const [key, value] of enumEntries(Status)) {
105
+ * console.log(`${key}: ${value}`);
106
+ * }
107
+ * // Output:
108
+ * // Active: active
109
+ * // Inactive: inactive
110
+ *
111
+ * @example
112
+ * // Convert to array
113
+ * const entries = [...enumEntries(Status)];
114
+ * // [['Active', 'active'], ['Inactive', 'inactive']]
115
+ *
116
+ * @example
117
+ * // Use with Array.from
118
+ * const entriesArray = Array.from(enumEntries(Status));
119
+ */
120
+ export declare function enumEntries<E extends AnyBrandedEnum>(enumObj: E): IterableIterator<[EnumKeys<E>, EnumValues<E>]>;
121
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,cAAc,EAKd,QAAQ,EACR,UAAU,EACX,MAAM,YAAY,CAAC;AAmBpB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,cAAc,EAC/C,OAAO,EAAE,CAAC,EACV,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,UAAU,CAAC,CAAC,CAAC,CAQxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,cAAc,EACrD,OAAO,EAAE,CAAC,EACV,KAAK,EAAE,MAAM,GACZ,QAAQ,CAAC,CAAC,CAAC,GAAG,SAAS,CAUzB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,cAAc,EACjD,OAAO,EAAE,CAAC,EACV,GAAG,EAAE,OAAO,GACX,GAAG,IAAI,QAAQ,CAAC,CAAC,CAAC,CAQpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAiB,WAAW,CAAC,CAAC,SAAS,cAAc,EACnD,OAAO,EAAE,CAAC,GACT,gBAAgB,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAOhD"}
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/lib/utils.ts"],"sourcesContent":["/**\n * Utility functions for branded enums.\n *\n * Provides additional functionality beyond standard enum operations,\n * including reverse lookup, key validation, and iteration.\n */\n\nimport {\n AnyBrandedEnum,\n BrandedEnum,\n BrandedEnumValue,\n ENUM_ID,\n ENUM_VALUES,\n EnumKeys,\n EnumValues,\n} from './types.js';\n\n/**\n * Checks if an object is a branded enum (has Symbol metadata).\n *\n * @param obj - The object to check\n * @returns true if obj is a branded enum\n */\nfunction isBrandedEnum(obj: unknown): obj is AnyBrandedEnum {\n return (\n obj !== null &&\n typeof obj === 'object' &&\n ENUM_ID in obj &&\n ENUM_VALUES in obj &&\n typeof (obj as AnyBrandedEnum)[ENUM_ID] === 'string' &&\n (obj as AnyBrandedEnum)[ENUM_VALUES] instanceof Set\n );\n}\n\n/**\n * Checks if a value exists in a branded enum (reverse lookup).\n *\n * Similar to `isFromEnum`, but with arguments in a different order that\n * may be more natural for some use cases. Also provides type narrowing.\n *\n * @template E - The branded enum type\n * @param enumObj - The branded enum to search in\n * @param value - The value to check. Can be any type; non-strings return false.\n * @returns `true` if the value exists in the enum (with type narrowing),\n * `false` otherwise. Returns `false` for non-string values or if\n * enumObj is not a branded enum.\n *\n * @example\n * // Check if value exists\n * const Status = createBrandedEnum('status', { Active: 'active', Inactive: 'inactive' } as const);\n * hasValue(Status, 'active'); // true\n * hasValue(Status, 'unknown'); // false\n *\n * @example\n * // Returns false for non-string values\n * hasValue(Status, 123); // false\n * hasValue(Status, null); // false\n */\nexport function hasValue<E extends AnyBrandedEnum>(\n enumObj: E,\n value: unknown\n): value is EnumValues<E> {\n if (!isBrandedEnum(enumObj)) {\n return false;\n }\n if (typeof value !== 'string') {\n return false;\n }\n return enumObj[ENUM_VALUES].has(value);\n}\n\n/**\n * Gets the key name for a value in a branded enum.\n *\n * Performs a reverse lookup to find which key maps to a given value.\n * If multiple keys have the same value, returns the first one found\n * (order is not guaranteed).\n *\n * @template E - The branded enum type\n * @param enumObj - The branded enum to search in\n * @param value - The string value to look up\n * @returns The key name that maps to the value, or `undefined` if the\n * value is not found or enumObj is not a branded enum.\n *\n * @example\n * // Find key for value\n * const Status = createBrandedEnum('status', { Active: 'active', Inactive: 'inactive' } as const);\n * getKeyForValue(Status, 'active'); // 'Active'\n * getKeyForValue(Status, 'inactive'); // 'Inactive'\n *\n * @example\n * // Returns undefined for unknown values\n * getKeyForValue(Status, 'unknown'); // undefined\n *\n * @example\n * // Roundtrip: value -> key -> value\n * const key = getKeyForValue(Status, 'active'); // 'Active'\n * Status[key]; // 'active'\n */\nexport function getKeyForValue<E extends AnyBrandedEnum>(\n enumObj: E,\n value: string\n): EnumKeys<E> | undefined {\n if (!isBrandedEnum(enumObj)) {\n return undefined;\n }\n for (const key of Object.keys(enumObj)) {\n if ((enumObj as Record<string, unknown>)[key] === value) {\n return key as EnumKeys<E>;\n }\n }\n return undefined;\n}\n\n/**\n * Checks if a key exists in a branded enum.\n *\n * Validates whether a given key is a valid member of the enum.\n * Returns false for Symbol keys (metadata) and non-string keys.\n *\n * @template E - The branded enum type\n * @param enumObj - The branded enum to check\n * @param key - The key to validate. Can be any type; non-strings return false.\n * @returns `true` if the key exists in the enum (with type narrowing),\n * `false` otherwise. Returns `false` for metadata Symbol keys or if\n * enumObj is not a branded enum.\n *\n * @example\n * // Check if key exists\n * const Status = createBrandedEnum('status', { Active: 'active', Inactive: 'inactive' } as const);\n * isValidKey(Status, 'Active'); // true\n * isValidKey(Status, 'Inactive'); // true\n * isValidKey(Status, 'Unknown'); // false\n *\n * @example\n * // Returns false for non-string keys\n * isValidKey(Status, 123); // false\n * isValidKey(Status, Symbol('test')); // false\n */\nexport function isValidKey<E extends AnyBrandedEnum>(\n enumObj: E,\n key: unknown\n): key is EnumKeys<E> {\n if (!isBrandedEnum(enumObj)) {\n return false;\n }\n if (typeof key !== 'string') {\n return false;\n }\n return Object.prototype.hasOwnProperty.call(enumObj, key);\n}\n\n/**\n * Returns an iterator of [key, value] pairs for a branded enum.\n *\n * Provides a way to iterate over all key-value pairs in the enum using\n * a for...of loop. Only yields user-defined entries, not metadata.\n * Equivalent to `Object.entries(enumObj)` but with proper typing.\n *\n * @template E - The branded enum type\n * @param enumObj - The branded enum to iterate over\n * @returns An iterator yielding [key, value] tuples. Returns an empty\n * iterator if enumObj is not a branded enum.\n *\n * @example\n * // Iterate over entries\n * const Status = createBrandedEnum('status', { Active: 'active', Inactive: 'inactive' } as const);\n *\n * for (const [key, value] of enumEntries(Status)) {\n * console.log(`${key}: ${value}`);\n * }\n * // Output:\n * // Active: active\n * // Inactive: inactive\n *\n * @example\n * // Convert to array\n * const entries = [...enumEntries(Status)];\n * // [['Active', 'active'], ['Inactive', 'inactive']]\n *\n * @example\n * // Use with Array.from\n * const entriesArray = Array.from(enumEntries(Status));\n */\nexport function* enumEntries<E extends AnyBrandedEnum>(\n enumObj: E\n): IterableIterator<[EnumKeys<E>, EnumValues<E>]> {\n if (!isBrandedEnum(enumObj)) {\n return;\n }\n for (const [key, value] of Object.entries(enumObj)) {\n yield [key as EnumKeys<E>, value as EnumValues<E>];\n }\n}\n"],"names":["ENUM_ID","ENUM_VALUES","isBrandedEnum","obj","Set","hasValue","enumObj","value","has","getKeyForValue","undefined","key","Object","keys","isValidKey","prototype","hasOwnProperty","call","enumEntries","entries"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA;;;;;CAKC,GAED,SAIEA,OAAO,EACPC,WAAW,QAGN,aAAa;AAEpB;;;;;CAKC,GACD,SAASC,cAAcC,GAAY;IACjC,OACEA,QAAQ,QACR,OAAOA,QAAQ,YACfH,WAAWG,OACXF,eAAeE,OACf,OAAO,AAACA,GAAsB,CAACH,QAAQ,KAAK,YAC5C,AAACG,GAAsB,CAACF,YAAY,YAAYG;AAEpD;AAEA;;;;;;;;;;;;;;;;;;;;;;;CAuBC,GACD,OAAO,SAASC,SACdC,OAAU,EACVC,KAAc;IAEd,IAAI,CAACL,cAAcI,UAAU;QAC3B,OAAO;IACT;IACA,IAAI,OAAOC,UAAU,UAAU;QAC7B,OAAO;IACT;IACA,OAAOD,OAAO,CAACL,YAAY,CAACO,GAAG,CAACD;AAClC;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BC,GACD,OAAO,SAASE,eACdH,OAAU,EACVC,KAAa;IAEb,IAAI,CAACL,cAAcI,UAAU;QAC3B,OAAOI;IACT;IACA,KAAK,MAAMC,OAAOC,OAAOC,IAAI,CAACP,SAAU;QACtC,IAAI,AAACA,OAAmC,CAACK,IAAI,KAAKJ,OAAO;YACvD,OAAOI;QACT;IACF;IACA,OAAOD;AACT;AAEA;;;;;;;;;;;;;;;;;;;;;;;;CAwBC,GACD,OAAO,SAASI,WACdR,OAAU,EACVK,GAAY;IAEZ,IAAI,CAACT,cAAcI,UAAU;QAC3B,OAAO;IACT;IACA,IAAI,OAAOK,QAAQ,UAAU;QAC3B,OAAO;IACT;IACA,OAAOC,OAAOG,SAAS,CAACC,cAAc,CAACC,IAAI,CAACX,SAASK;AACvD;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+BC,GACD,OAAO,UAAUO,YACfZ,OAAU;IAEV,IAAI,CAACJ,cAAcI,UAAU;QAC3B;IACF;IACA,KAAK,MAAM,CAACK,KAAKJ,MAAM,IAAIK,OAAOO,OAAO,CAACb,SAAU;QAClD,MAAM;YAACK;YAAoBJ;SAAuB;IACpD;AACF"}
package/package.json CHANGED
@@ -1,18 +1,19 @@
1
1
  {
2
2
  "name": "@digitaldefiance/branded-enum",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "Runtime-identifiable enum-like types for TypeScript with zero runtime overhead",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
- "main": "./dist/index.js",
8
- "module": "./dist/index.js",
9
- "types": "./dist/index.d.ts",
7
+ "main": "./dist/cjs/index.cjs",
8
+ "module": "./dist/esm/index.js",
9
+ "types": "./dist/esm/index.d.ts",
10
10
  "exports": {
11
11
  "./package.json": "./package.json",
12
12
  ".": {
13
- "types": "./dist/index.d.ts",
14
- "import": "./dist/index.js",
15
- "default": "./dist/index.js"
13
+ "types": "./dist/esm/index.d.ts",
14
+ "import": "./dist/esm/index.js",
15
+ "require": "./dist/cjs/index.cjs",
16
+ "default": "./dist/esm/index.js"
16
17
  }
17
18
  },
18
19
  "files": [
@@ -69,19 +70,25 @@
69
70
  "sourceRoot": "src",
70
71
  "targets": {
71
72
  "build": {
72
- "executor": "@nx/js:swc",
73
- "outputs": ["{options.outputPath}"],
73
+ "executor": "nx:run-commands",
74
+ "outputs": [
75
+ "{projectRoot}/dist"
76
+ ],
74
77
  "options": {
75
- "outputPath": "dist",
76
- "main": "src/index.ts",
77
- "tsConfig": "tsconfig.lib.json",
78
- "skipTypeCheck": true,
79
- "stripLeadingPaths": true
78
+ "commands": [
79
+ "swc src -d dist/esm --config-file .swcrc --strip-leading-paths",
80
+ "swc src -d dist/cjs --config-file .swcrc.cjs --strip-leading-paths -C module.type=commonjs --out-file-extension cjs",
81
+ "tsc -p tsconfig.lib.json"
82
+ ],
83
+ "cwd": "{projectRoot}",
84
+ "parallel": false
80
85
  }
81
86
  },
82
87
  "test": {
83
88
  "executor": "@nx/jest:jest",
84
- "outputs": ["{projectRoot}/test-output/jest/coverage"],
89
+ "outputs": [
90
+ "{projectRoot}/test-output/jest/coverage"
91
+ ],
85
92
  "options": {
86
93
  "jestConfig": "jest.config.cts",
87
94
  "passWithNoTests": true
@@ -89,18 +96,24 @@
89
96
  },
90
97
  "build-examples": {
91
98
  "executor": "nx:run-commands",
92
- "outputs": ["{projectRoot}/examples/dist"],
99
+ "outputs": [
100
+ "{projectRoot}/examples/dist"
101
+ ],
93
102
  "options": {
94
103
  "command": "tsc -p examples/tsconfig.json"
95
104
  },
96
- "dependsOn": ["build"]
105
+ "dependsOn": [
106
+ "build"
107
+ ]
97
108
  },
98
109
  "publish-public": {
99
110
  "executor": "nx:run-commands",
100
111
  "options": {
101
112
  "command": "npm publish --access public"
102
113
  },
103
- "dependsOn": ["build"]
114
+ "dependsOn": [
115
+ "build"
116
+ ]
104
117
  }
105
118
  }
106
119
  },
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * branded-enum - Runtime-identifiable enum-like types for TypeScript\n *\n * This library provides enum-like objects with embedded metadata for runtime\n * identification, enabling you to determine which enum a string value belongs to.\n *\n * @packageDocumentation\n */\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type {\n BrandedEnumMetadata,\n BrandedEnum,\n BrandedEnumValue,\n RegistryEntry,\n BrandedEnumRegistry,\n EnumConsumerEntry,\n EnumConsumerRegistry,\n AnyBrandedEnum,\n EnumKeys,\n EnumValues,\n ValidEnumValue,\n StrictEnumParam,\n} from './lib/types.js';\n\n// =============================================================================\n// Factory\n// =============================================================================\n\nexport { createBrandedEnum } from './lib/factory.js';\n\n// =============================================================================\n// Registry\n// =============================================================================\n\nexport {\n getRegistry,\n getAllEnumIds,\n getEnumById,\n findEnumSources,\n} from './lib/registry.js';\n\n// =============================================================================\n// Type Guards\n// =============================================================================\n\nexport { isFromEnum, assertFromEnum, parseEnum, safeParseEnum } from './lib/guards.js';\nexport type { SafeParseSuccess, SafeParseFailure, SafeParseError, SafeParseErrorCode, SafeParseResult } from './lib/guards.js';\n\n// =============================================================================\n// Metadata Accessors\n// =============================================================================\n\nexport { getEnumId, getEnumValues, enumSize } from './lib/accessors.js';\n\n// =============================================================================\n// Utility Functions\n// =============================================================================\n\nexport {\n hasValue,\n getKeyForValue,\n isValidKey,\n enumEntries,\n} from './lib/utils.js';\n\n// =============================================================================\n// Composition\n// =============================================================================\n\nexport { mergeEnums } from './lib/merge.js';\n\n// =============================================================================\n// Advanced Operations\n// =============================================================================\n\nexport { enumSubset, enumExclude, enumMap, enumFromKeys, enumDiff, enumIntersect, enumToRecord, watchEnum, watchAllEnums, clearAllEnumWatchers, getEnumWatcherCount, getGlobalWatcherCount, exhaustive, exhaustiveGuard, toJsonSchema, toZodSchema, enumSerializer } from './lib/advanced.js';\nexport type { EnumDiffResult, EnumIntersectEntry, EnumAccessType, EnumAccessEvent, EnumWatchCallback, WatchEnumResult, ToJsonSchemaOptions, EnumJsonSchema, ToZodSchemaOptions, ZodEnumSchemaDefinition, EnumSerializerOptions, DeserializeSuccess, DeserializeFailure, DeserializeResult, EnumSerializer } from './lib/advanced.js';\n\n// =============================================================================\n// Decorators\n// =============================================================================\n\nexport {\n EnumValue,\n EnumClass,\n getEnumConsumers,\n getConsumedEnums,\n getAllEnumConsumers,\n} from './lib/decorators.js';\nexport type { EnumValueOptions } from './lib/decorators.js';\n"],"names":["createBrandedEnum","getRegistry","getAllEnumIds","getEnumById","findEnumSources","isFromEnum","assertFromEnum","parseEnum","safeParseEnum","getEnumId","getEnumValues","enumSize","hasValue","getKeyForValue","isValidKey","enumEntries","mergeEnums","enumSubset","enumExclude","enumMap","enumFromKeys","enumDiff","enumIntersect","enumToRecord","watchEnum","watchAllEnums","clearAllEnumWatchers","getEnumWatcherCount","getGlobalWatcherCount","exhaustive","exhaustiveGuard","toJsonSchema","toZodSchema","enumSerializer","EnumValue","EnumClass","getEnumConsumers","getConsumedEnums","getAllEnumConsumers"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA;;;;;;;CAOC,GAED,gFAAgF;AAChF,QAAQ;AACR,gFAAgF;AAiBhF,gFAAgF;AAChF,UAAU;AACV,gFAAgF;AAEhF,SAASA,iBAAiB,QAAQ,mBAAmB;AAErD,gFAAgF;AAChF,WAAW;AACX,gFAAgF;AAEhF,SACEC,WAAW,EACXC,aAAa,EACbC,WAAW,EACXC,eAAe,QACV,oBAAoB;AAE3B,gFAAgF;AAChF,cAAc;AACd,gFAAgF;AAEhF,SAASC,UAAU,EAAEC,cAAc,EAAEC,SAAS,EAAEC,aAAa,QAAQ,kBAAkB;AAGvF,gFAAgF;AAChF,qBAAqB;AACrB,gFAAgF;AAEhF,SAASC,SAAS,EAAEC,aAAa,EAAEC,QAAQ,QAAQ,qBAAqB;AAExE,gFAAgF;AAChF,oBAAoB;AACpB,gFAAgF;AAEhF,SACEC,QAAQ,EACRC,cAAc,EACdC,UAAU,EACVC,WAAW,QACN,iBAAiB;AAExB,gFAAgF;AAChF,cAAc;AACd,gFAAgF;AAEhF,SAASC,UAAU,QAAQ,iBAAiB;AAE5C,gFAAgF;AAChF,sBAAsB;AACtB,gFAAgF;AAEhF,SAASC,UAAU,EAAEC,WAAW,EAAEC,OAAO,EAAEC,YAAY,EAAEC,QAAQ,EAAEC,aAAa,EAAEC,YAAY,EAAEC,SAAS,EAAEC,aAAa,EAAEC,oBAAoB,EAAEC,mBAAmB,EAAEC,qBAAqB,EAAEC,UAAU,EAAEC,eAAe,EAAEC,YAAY,EAAEC,WAAW,EAAEC,cAAc,QAAQ,oBAAoB;AAG9R,gFAAgF;AAChF,aAAa;AACb,gFAAgF;AAEhF,SACEC,SAAS,EACTC,SAAS,EACTC,gBAAgB,EAChBC,gBAAgB,EAChBC,mBAAmB,QACd,sBAAsB"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/lib/accessors.ts"],"sourcesContent":["/**\n * Metadata accessors for branded enums.\n *\n * Provides functions to retrieve metadata from branded enum objects,\n * including enum ID, values array, and size.\n */\n\nimport {\n AnyBrandedEnum,\n BrandedEnum,\n BrandedEnumValue,\n ENUM_ID,\n ENUM_VALUES,\n EnumValues,\n} from './types.js';\n\n/**\n * Checks if an object is a branded enum (has Symbol metadata).\n *\n * @param obj - The object to check\n * @returns true if obj is a branded enum\n */\nfunction isBrandedEnum(obj: unknown): obj is AnyBrandedEnum {\n return (\n obj !== null &&\n typeof obj === 'object' &&\n ENUM_ID in obj &&\n ENUM_VALUES in obj &&\n typeof (obj as AnyBrandedEnum)[ENUM_ID] === 'string' &&\n (obj as AnyBrandedEnum)[ENUM_VALUES] instanceof Set\n );\n}\n\n/**\n * Gets the enum ID from a branded enum.\n *\n * Retrieves the unique identifier that was assigned when the enum was created.\n * Returns undefined for objects that are not branded enums.\n *\n * @param enumObj - The object to get the enum ID from. Can be any type.\n * @returns The enum ID string if enumObj is a branded enum, `undefined` otherwise.\n *\n * @example\n * // Get ID from branded enum\n * const Status = createBrandedEnum('status', { Active: 'active' } as const);\n * getEnumId(Status); // 'status'\n *\n * @example\n * // Returns undefined for non-branded objects\n * getEnumId({}); // undefined\n * getEnumId({ Active: 'active' }); // undefined\n * getEnumId(null); // undefined\n */\nexport function getEnumId(enumObj: unknown): string | undefined {\n if (!isBrandedEnum(enumObj)) {\n return undefined;\n }\n return enumObj[ENUM_ID];\n}\n\n/**\n * Gets all values from a branded enum as an array.\n *\n * Returns an array containing all the string values in the enum.\n * The order of values is not guaranteed.\n *\n * @template E - The branded enum type\n * @param enumObj - The object to get values from. Can be any type.\n * @returns Array of all enum values if enumObj is a branded enum,\n * `undefined` otherwise.\n *\n * @example\n * // Get values from branded enum\n * const Status = createBrandedEnum('status', {\n * Active: 'active',\n * Inactive: 'inactive'\n * } as const);\n * getEnumValues(Status); // ['active', 'inactive']\n *\n * @example\n * // Returns undefined for non-branded objects\n * getEnumValues({}); // undefined\n * getEnumValues({ Active: 'active' }); // undefined\n */\nexport function getEnumValues<E extends AnyBrandedEnum>(\n enumObj: E\n): EnumValues<E>[] | undefined;\nexport function getEnumValues(enumObj: unknown): string[] | undefined;\nexport function getEnumValues(enumObj: unknown): string[] | undefined {\n if (!isBrandedEnum(enumObj)) {\n return undefined;\n }\n return Array.from(enumObj[ENUM_VALUES]);\n}\n\n/**\n * Gets the number of values in a branded enum.\n *\n * Returns the count of unique values in the enum. This is equivalent to\n * the number of key-value pairs defined when the enum was created.\n *\n * @param enumObj - The object to get the size of. Can be any type.\n * @returns The number of values in the enum if enumObj is a branded enum,\n * `undefined` otherwise.\n *\n * @example\n * // Get size of branded enum\n * const Status = createBrandedEnum('status', {\n * Active: 'active',\n * Inactive: 'inactive'\n * } as const);\n * enumSize(Status); // 2\n *\n * @example\n * // Returns undefined for non-branded objects\n * enumSize({}); // undefined\n * enumSize({ Active: 'active' }); // undefined\n */\nexport function enumSize(enumObj: unknown): number | undefined {\n if (!isBrandedEnum(enumObj)) {\n return undefined;\n }\n return enumObj[ENUM_VALUES].size;\n}\n"],"names":["ENUM_ID","ENUM_VALUES","isBrandedEnum","obj","Set","getEnumId","enumObj","undefined","getEnumValues","Array","from","enumSize","size"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA;;;;;CAKC,GAED,SAIEA,OAAO,EACPC,WAAW,QAEN,aAAa;AAEpB;;;;;CAKC,GACD,SAASC,cAAcC,GAAY;IACjC,OACEA,QAAQ,QACR,OAAOA,QAAQ,YACfH,WAAWG,OACXF,eAAeE,OACf,OAAO,AAACA,GAAsB,CAACH,QAAQ,KAAK,YAC5C,AAACG,GAAsB,CAACF,YAAY,YAAYG;AAEpD;AAEA;;;;;;;;;;;;;;;;;;;CAmBC,GACD,OAAO,SAASC,UAAUC,OAAgB;IACxC,IAAI,CAACJ,cAAcI,UAAU;QAC3B,OAAOC;IACT;IACA,OAAOD,OAAO,CAACN,QAAQ;AACzB;AA8BA,OAAO,SAASQ,cAAcF,OAAgB;IAC5C,IAAI,CAACJ,cAAcI,UAAU;QAC3B,OAAOC;IACT;IACA,OAAOE,MAAMC,IAAI,CAACJ,OAAO,CAACL,YAAY;AACxC;AAEA;;;;;;;;;;;;;;;;;;;;;;CAsBC,GACD,OAAO,SAASU,SAASL,OAAgB;IACvC,IAAI,CAACJ,cAAcI,UAAU;QAC3B,OAAOC;IACT;IACA,OAAOD,OAAO,CAACL,YAAY,CAACW,IAAI;AAClC"}