@reharik/smart-enum 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,3 +1,4 @@
1
- export { A as AnyEnumLike, D as DatabaseFormat, h as EnumLikeBase, E as Enumeration, F as FieldEnumMapping, c as LogLevel, L as Logger, P as PathEnumMapping, l as RevivePayloadOptions, k as ReviveRowOptions, R as RevivedSmartEnums, f as SerializedSmartEnums, S as SmartApiHelperConfig, g as SmartEnumItemSerialized, j as SmartEnumLike, d as SmartEnumMappingsConfig, n as StandardEnumItem, m as StandardEnumItemBase, e as enumeration, a as isSmartEnum, i as isSmartEnumItem, b as reviveEnumField, r as reviveSmartEnums, s as serializeSmartEnums } from './core-DU5cpej6.cjs';
1
+ export { A as AnyEnumLike, D as DatabaseFormat, h as EnumLikeBase, E as Enumeration, F as FieldEnumMapping, c as LogLevel, L as Logger, P as PathEnumMapping, l as RevivePayloadOptions, k as ReviveRowOptions, R as RevivedSmartEnums, f as SerializedSmartEnums, S as SmartApiHelperConfig, g as SmartEnumItemSerialized, j as SmartEnumLike, d as SmartEnumMappingsConfig, n as StandardEnumItem, m as StandardEnumItemBase, e as enumeration, a as isSmartEnum, i as isSmartEnumItem, b as reviveEnumField, r as reviveSmartEnums, s as serializeSmartEnums } from './transformation-BPyoxZyV.cjs';
2
+ export { getSubsetByProp, subsetByProp } from './core.cjs';
2
3
  export { getGlobalEnumRegistry, initializeSmartEnumMappings, reviveAfterTransport, serializeForTransport } from './transport.cjs';
3
4
  export { EnumRevivalError, prepareForDatabase, revivePayloadFromDatabase, reviveRowFromDatabase } from './database.cjs';
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
- export { A as AnyEnumLike, D as DatabaseFormat, h as EnumLikeBase, E as Enumeration, F as FieldEnumMapping, c as LogLevel, L as Logger, P as PathEnumMapping, l as RevivePayloadOptions, k as ReviveRowOptions, R as RevivedSmartEnums, f as SerializedSmartEnums, S as SmartApiHelperConfig, g as SmartEnumItemSerialized, j as SmartEnumLike, d as SmartEnumMappingsConfig, n as StandardEnumItem, m as StandardEnumItemBase, e as enumeration, a as isSmartEnum, i as isSmartEnumItem, b as reviveEnumField, r as reviveSmartEnums, s as serializeSmartEnums } from './core-DU5cpej6.js';
1
+ export { A as AnyEnumLike, D as DatabaseFormat, h as EnumLikeBase, E as Enumeration, F as FieldEnumMapping, c as LogLevel, L as Logger, P as PathEnumMapping, l as RevivePayloadOptions, k as ReviveRowOptions, R as RevivedSmartEnums, f as SerializedSmartEnums, S as SmartApiHelperConfig, g as SmartEnumItemSerialized, j as SmartEnumLike, d as SmartEnumMappingsConfig, n as StandardEnumItem, m as StandardEnumItemBase, e as enumeration, a as isSmartEnum, i as isSmartEnumItem, b as reviveEnumField, r as reviveSmartEnums, s as serializeSmartEnums } from './transformation-BPyoxZyV.js';
2
+ export { getSubsetByProp, subsetByProp } from './core.js';
2
3
  export { getGlobalEnumRegistry, initializeSmartEnumMappings, reviveAfterTransport, serializeForTransport } from './transport.js';
3
4
  export { EnumRevivalError, prepareForDatabase, revivePayloadFromDatabase, reviveRowFromDatabase } from './database.js';
package/dist/index.js CHANGED
@@ -1,15 +1,19 @@
1
+ import {
2
+ getSubsetByProp,
3
+ subsetByProp
4
+ } from "./chunk-YEU2HCVA.js";
1
5
  import {
2
6
  EnumRevivalError,
3
7
  prepareForDatabase,
4
8
  revivePayloadFromDatabase,
5
9
  reviveRowFromDatabase
6
- } from "./chunk-XG7XL4T7.js";
10
+ } from "./chunk-3N6NMQCD.js";
7
11
  import {
8
12
  getGlobalEnumRegistry,
9
13
  initializeSmartEnumMappings,
10
14
  reviveAfterTransport,
11
15
  serializeForTransport
12
- } from "./chunk-YWKBI354.js";
16
+ } from "./chunk-RO2L7N2F.js";
13
17
  import {
14
18
  enumeration,
15
19
  isSmartEnum,
@@ -17,11 +21,12 @@ import {
17
21
  reviveEnumField,
18
22
  reviveSmartEnums,
19
23
  serializeSmartEnums
20
- } from "./chunk-PKREHKGD.js";
24
+ } from "./chunk-PUK5FOIE.js";
21
25
  export {
22
26
  EnumRevivalError,
23
27
  enumeration,
24
28
  getGlobalEnumRegistry,
29
+ getSubsetByProp,
25
30
  initializeSmartEnumMappings,
26
31
  isSmartEnum,
27
32
  isSmartEnumItem,
@@ -32,6 +37,7 @@ export {
32
37
  reviveRowFromDatabase,
33
38
  reviveSmartEnums,
34
39
  serializeForTransport,
35
- serializeSmartEnums
40
+ serializeSmartEnums,
41
+ subsetByProp
36
42
  };
37
43
  //# sourceMappingURL=index.js.map
@@ -63,6 +63,7 @@ type SmartEnumMappingsConfig = {
63
63
  logLevel?: LogLevel;
64
64
  logger?: Logger;
65
65
  };
66
+ type BuiltInOverrideKeys = 'key' | 'value' | 'display' | 'deprecated' | 'index' | '__smart_enum_brand' | '__smart_enum_type';
66
67
  /**
67
68
  * Structural fields shared by every enum member (key, value, display, index, optional deprecated).
68
69
  * Does not include smart-enum branding or database helpers; see {@link StandardEnumItem}.
@@ -83,45 +84,12 @@ type StandardEnumItem = StandardEnumItemBase & {
83
84
  readonly __smart_enum_type: string;
84
85
  readonly toPostgres: () => string;
85
86
  };
86
- /**
87
- * Structural shape of a smart-style enum object: lookup by value/key, list items/values/keys,
88
- * plus an index signature so registry and mapping types can treat instances as records.
89
- * Use {@link SmartEnumLike} when items are full {@link StandardEnumItem}s (the usual case).
90
- */
91
- type EnumLikeBase<TItem extends StandardEnumItemBase = StandardEnumItemBase> = {
92
- fromValue(value: string): TItem;
93
- tryFromValue(value?: string | null): TItem | undefined;
94
- fromKey(key: string): TItem;
95
- tryFromKey(key?: string | null): TItem | undefined;
96
- items(): readonly TItem[];
97
- values(): readonly TItem['value'][];
98
- keys(): readonly TItem['key'][];
99
- } & Record<string, unknown>;
100
- /**
101
- * A {@link EnumLikeBase} whose items are branded {@link StandardEnumItem}s (typical `enumeration()` result).
102
- */
103
- type SmartEnumLike<TItem extends StandardEnumItem = StandardEnumItem> = EnumLikeBase<TItem>;
104
- type FieldEnumMapping = Record<string, SmartEnumLike>;
105
- type ReviveRowOptions = {
106
- fieldEnumMapping: FieldEnumMapping;
107
- strict?: boolean;
108
- };
109
- type PathEnumMapping = Record<string, SmartEnumLike>;
110
- type RevivePayloadOptions = {
111
- pathEnumMapping: PathEnumMapping;
112
- strict?: boolean;
113
- };
114
- type Enumeration<TEnum> = TEnum extends Record<string, infer V> ? V extends {
115
- __smart_enum_brand: true;
116
- } ? V : never : never;
117
-
118
- type BuiltInOverrideKeys = 'key' | 'value' | 'display' | 'deprecated' | 'index' | '__smart_enum_brand' | '__smart_enum_type';
119
87
  type EnumInputItem = Partial<{
120
88
  key: string;
121
89
  value: string;
122
90
  display: string;
123
91
  deprecated: boolean;
124
- }> & object;
92
+ }> & Record<string, unknown>;
125
93
  type ObjectEnumInput = Record<string, EnumInputItem>;
126
94
  type EmptyEnumInputItem = Record<never, never>;
127
95
  type Separator = '-' | '_' | ' ' | '.';
@@ -132,49 +100,107 @@ type TrimUnderscore<S extends string> = S extends `_${infer R}` ? TrimUnderscore
132
100
  type CollapseUnderscores<S extends string> = S extends `${infer A}__${infer B}` ? CollapseUnderscores<`${A}_${B}`> : S;
133
101
  type ConstantCaseInternal<S extends string, Prev extends string = '', Out extends string = ''> = S extends `${infer C}${infer Rest}` ? C extends Separator ? ConstantCaseInternal<Rest, C, PushUnderscore<Out>> : IsUpperChar<C> extends true ? IsLowerChar<Prev> extends true ? ConstantCaseInternal<Rest, C, `${PushUnderscore<Out>}${Uppercase<C>}`> : ConstantCaseInternal<Rest, C, `${Out}${Uppercase<C>}`> : ConstantCaseInternal<Rest, C, `${Out}${Uppercase<C>}`> : CollapseUnderscores<TrimUnderscore<Out>>;
134
102
  type ConstantCase<S extends string> = string extends S ? string : ConstantCaseInternal<S>;
103
+ /** Segments of a `ConstantCase` string (underscore-separated ALL CAPS words). */
104
+ type SplitConstantCaseSegments<S extends string> = S extends `${infer A}_${infer B}` ? [A, ...SplitConstantCaseSegments<B>] : [S];
105
+ /** First character upper, remainder lower (for ALL-CAPS words from `ConstantCase`). */
106
+ type TitleCaseAllCapsWord<W extends string> = W extends '' ? '' : W extends `${infer F}${infer R}` ? `${Uppercase<F>}${Lowercase<R>}` : W;
107
+ type JoinDisplaySegments<T extends readonly string[]> = T extends readonly [
108
+ infer A extends string,
109
+ ...infer Rest extends readonly string[]
110
+ ] ? Rest extends readonly [] ? TitleCaseAllCapsWord<A> : `${TitleCaseAllCapsWord<A>} ${JoinDisplaySegments<Rest>}` : '';
111
+ /**
112
+ * Display string derived from the enum member key: `ConstantCase` → split → title-case words → join with spaces.
113
+ * Matches default runtime `capitalCase(key)` for typical PascalCase / camelCase keys. Member keys that already
114
+ * contain separators may differ from `capitalCase` at runtime; custom `propertyAutoFormatters` for `display`
115
+ * are not reflected in this type.
116
+ */
117
+ type DisplayCaseFromEnumKey<K extends string> = string extends K ? string : JoinDisplaySegments<SplitConstantCaseSegments<ConstantCase<K>>>;
135
118
  type ArrayToObjectType<T extends readonly string[]> = {
136
119
  [K in T[number]]: EmptyEnumInputItem & {
137
120
  readonly value?: ConstantCase<K>;
138
121
  };
139
122
  };
140
123
  type NormalizedInputType<TInput> = TInput extends readonly string[] ? ArrayToObjectType<TInput> : TInput extends ObjectEnumInput ? TInput : never;
141
- type UnionKeys<T> = T extends T ? keyof T : never;
142
- type MergeUnionToObject<T> = {
143
- [K in UnionKeys<T>]: T extends Record<K, infer V> ? V : undefined;
144
- };
145
- type ExtraShapeUnion<TObj extends ObjectEnumInput> = {
146
- [K in keyof TObj]: Omit<TObj[K], BuiltInOverrideKeys>;
147
- }[keyof TObj];
148
- type InferredExtraFields<TObj extends ObjectEnumInput> = MergeUnionToObject<ExtraShapeUnion<TObj>>;
149
- type EnumItemFromNormalizedObject<TObj extends ObjectEnumInput, K extends keyof TObj = keyof TObj> = Omit<StandardEnumItem, 'key' | 'value'> & InferredExtraFields<TObj> & {
124
+ /** Input-derived fields for one member key (excludes built-ins filled by `enumeration()`). */
125
+ type EnumMemberExtra<TObj extends ObjectEnumInput, K extends keyof TObj> = Omit<TObj[K], BuiltInOverrideKeys>;
126
+ type EnumItemFromNormalizedObject<TObj extends ObjectEnumInput, K extends keyof TObj = keyof TObj> = Omit<StandardEnumItem, 'key' | 'value' | 'display'> & EnumMemberExtra<TObj, K> & {
150
127
  readonly key: Extract<K, string>;
151
128
  readonly value: TObj[K] extends {
152
129
  value?: infer V;
153
- } ? Extract<V, string> extends never ? string : Extract<V, string> : string;
130
+ } ? [Extract<V, string>] extends [never] ? ConstantCase<Extract<K, string>> : Extract<V, string> : ConstantCase<Extract<K, string>>;
131
+ readonly display: TObj[K] extends {
132
+ display?: infer D;
133
+ } ? [Extract<D, string>] extends [never] ? DisplayCaseFromEnumKey<Extract<K, string>> : Extract<D, string> : DisplayCaseFromEnumKey<Extract<K, string>>;
154
134
  };
155
135
  type EnumMemberUnionFromNormalizedObject<TObj extends ObjectEnumInput> = {
156
136
  [K in keyof TObj]: EnumItemFromNormalizedObject<TObj, K>;
157
137
  }[keyof TObj];
138
+ type EnumFromNormalizedObject<TObj extends ObjectEnumInput> = {
139
+ [K in keyof TObj]: EnumItemFromNormalizedObject<TObj, K>;
140
+ } & CoreEnumMethods<EnumMemberUnionFromNormalizedObject<TObj>>;
141
+ type PropertyAutoFormatter = {
142
+ /** The property name to generate */
143
+ key: string;
144
+ /** Function to transform the key into the property value */
145
+ format: (k: string) => string;
146
+ };
158
147
  type CoreEnumMethods<TItem extends StandardEnumItem> = {
159
148
  fromValue(value: string): TItem;
160
149
  tryFromValue(value?: string | null): TItem | undefined;
161
150
  fromKey(key: string): TItem;
162
151
  tryFromKey(key?: string | null): TItem | undefined;
163
152
  items(): readonly TItem[];
164
- values(): readonly string[];
165
- keys(): readonly string[];
153
+ /** Matches runtime: `items.map(i => i.value)` (see {@link EnumLikeBase}). */
154
+ values(): readonly TItem['value'][];
155
+ /** Matches runtime: `items.map(i => i.key)` (see {@link EnumLikeBase}). */
156
+ keys(): readonly TItem['key'][];
157
+ };
158
+ /**
159
+ * Structural shape of a smart-style enum object: lookup by value/key, list items/values/keys,
160
+ * plus an index signature so registry and mapping types can treat instances as records.
161
+ * Use {@link SmartEnumLike} when items are full {@link StandardEnumItem}s (the usual case).
162
+ */
163
+ type EnumLikeBase<TItem extends StandardEnumItemBase = StandardEnumItemBase> = {
164
+ fromValue(value: string): TItem;
165
+ tryFromValue(value?: string | null): TItem | undefined;
166
+ fromKey(key: string): TItem;
167
+ tryFromKey(key?: string | null): TItem | undefined;
168
+ items(): readonly TItem[];
169
+ values(): readonly TItem['value'][];
170
+ keys(): readonly TItem['key'][];
171
+ } & Record<string, unknown>;
172
+ /**
173
+ * A {@link EnumLikeBase} whose items are branded {@link StandardEnumItem}s (typical `enumeration()` result).
174
+ */
175
+ type SmartEnumLike<TItem extends StandardEnumItem = StandardEnumItem> = EnumLikeBase<TItem>;
176
+ /** Union of branded enum member values on an enum object `T`. */
177
+ type SmartEnumMemberUnion<T extends Record<string, unknown>> = {
178
+ [K in keyof T]: T[K] extends StandardEnumItem ? T[K] : never;
179
+ }[keyof T];
180
+ /** Keys on `TEnum` whose member matches `Record<P, V>` within `ItemUnion`. */
181
+ type SmartEnumSubsetKeys<TEnum extends Record<string, unknown>, ItemUnion extends StandardEnumItem, P extends keyof ItemUnion & string, V extends ItemUnion[P]> = {
182
+ [K in keyof TEnum]: TEnum[K] extends Extract<ItemUnion, Record<P, V>> ? K : never;
183
+ }[keyof TEnum];
184
+ type SmartEnumSubsetItemUnion<ItemUnion extends StandardEnumItem, P extends keyof ItemUnion & string, V extends ItemUnion[P]> = Extract<ItemUnion, Record<P, V>>;
185
+ type SmartEnumSubsetView<TEnum extends Record<string, unknown>, ItemUnion extends StandardEnumItem, P extends keyof ItemUnion & string, V extends ItemUnion[P]> = Pick<TEnum, SmartEnumSubsetKeys<TEnum, ItemUnion, P, V>> & CoreEnumMethods<SmartEnumSubsetItemUnion<ItemUnion, P, V>>;
186
+ type FieldEnumMapping = Record<string, SmartEnumLike>;
187
+ type ReviveRowOptions = {
188
+ fieldEnumMapping: FieldEnumMapping;
189
+ strict?: boolean;
190
+ };
191
+ type PathEnumMapping = Record<string, SmartEnumLike>;
192
+ type RevivePayloadOptions = {
193
+ pathEnumMapping: PathEnumMapping;
194
+ strict?: boolean;
166
195
  };
167
- type EnumFromNormalizedObject<TObj extends ObjectEnumInput> = {
168
- [K in keyof TObj]: EnumItemFromNormalizedObject<TObj, K>;
169
- } & CoreEnumMethods<EnumMemberUnionFromNormalizedObject<TObj>>;
170
196
  type EnumerationProps<TInput> = {
171
197
  input: TInput;
172
198
  propertyAutoFormatters?: PropertyAutoFormatter[];
173
199
  };
174
- type PropertyAutoFormatter = {
175
- key: string;
176
- format: (k: string) => string;
177
- };
200
+ type Enumeration<TEnum> = TEnum extends Record<string, infer V> ? V extends {
201
+ __smart_enum_brand: true;
202
+ } ? V : never : never;
203
+
178
204
  declare function enumeration<const TArr extends readonly string[]>(enumType: string, props: EnumerationProps<TArr>): EnumFromNormalizedObject<NormalizedInputType<TArr>>;
179
205
  declare function enumeration<const TObj extends ObjectEnumInput>(enumType: string, props: EnumerationProps<TObj>): EnumFromNormalizedObject<NormalizedInputType<TObj>>;
180
206
 
@@ -266,4 +292,4 @@ declare function reviveSmartEnums<R>(input: unknown, registry: Record<string, An
266
292
  */
267
293
  declare const reviveEnumField: <TItem>(value: unknown, smartEnum: AnyEnumLike<TItem>, strict?: boolean) => TItem | undefined;
268
294
 
269
- export { type AnyEnumLike as A, type DatabaseFormat as D, type Enumeration as E, type FieldEnumMapping as F, type Logger as L, type PathEnumMapping as P, type RevivedSmartEnums as R, type SmartApiHelperConfig as S, isSmartEnum as a, reviveEnumField as b, type LogLevel as c, type SmartEnumMappingsConfig as d, enumeration as e, type SerializedSmartEnums as f, type SmartEnumItemSerialized as g, type EnumLikeBase as h, isSmartEnumItem as i, type SmartEnumLike as j, type ReviveRowOptions as k, type RevivePayloadOptions as l, type StandardEnumItemBase as m, type StandardEnumItem as n, reviveSmartEnums as r, serializeSmartEnums as s };
295
+ export { type AnyEnumLike as A, type DatabaseFormat as D, type Enumeration as E, type FieldEnumMapping as F, type Logger as L, type PathEnumMapping as P, type RevivedSmartEnums as R, type SmartApiHelperConfig as S, isSmartEnum as a, reviveEnumField as b, type LogLevel as c, type SmartEnumMappingsConfig as d, enumeration as e, type SerializedSmartEnums as f, type SmartEnumItemSerialized as g, type EnumLikeBase as h, isSmartEnumItem as i, type SmartEnumLike as j, type ReviveRowOptions as k, type RevivePayloadOptions as l, type StandardEnumItemBase as m, type StandardEnumItem as n, type SmartEnumMemberUnion as o, type SmartEnumSubsetView as p, reviveSmartEnums as r, serializeSmartEnums as s };
@@ -63,6 +63,7 @@ type SmartEnumMappingsConfig = {
63
63
  logLevel?: LogLevel;
64
64
  logger?: Logger;
65
65
  };
66
+ type BuiltInOverrideKeys = 'key' | 'value' | 'display' | 'deprecated' | 'index' | '__smart_enum_brand' | '__smart_enum_type';
66
67
  /**
67
68
  * Structural fields shared by every enum member (key, value, display, index, optional deprecated).
68
69
  * Does not include smart-enum branding or database helpers; see {@link StandardEnumItem}.
@@ -83,45 +84,12 @@ type StandardEnumItem = StandardEnumItemBase & {
83
84
  readonly __smart_enum_type: string;
84
85
  readonly toPostgres: () => string;
85
86
  };
86
- /**
87
- * Structural shape of a smart-style enum object: lookup by value/key, list items/values/keys,
88
- * plus an index signature so registry and mapping types can treat instances as records.
89
- * Use {@link SmartEnumLike} when items are full {@link StandardEnumItem}s (the usual case).
90
- */
91
- type EnumLikeBase<TItem extends StandardEnumItemBase = StandardEnumItemBase> = {
92
- fromValue(value: string): TItem;
93
- tryFromValue(value?: string | null): TItem | undefined;
94
- fromKey(key: string): TItem;
95
- tryFromKey(key?: string | null): TItem | undefined;
96
- items(): readonly TItem[];
97
- values(): readonly TItem['value'][];
98
- keys(): readonly TItem['key'][];
99
- } & Record<string, unknown>;
100
- /**
101
- * A {@link EnumLikeBase} whose items are branded {@link StandardEnumItem}s (typical `enumeration()` result).
102
- */
103
- type SmartEnumLike<TItem extends StandardEnumItem = StandardEnumItem> = EnumLikeBase<TItem>;
104
- type FieldEnumMapping = Record<string, SmartEnumLike>;
105
- type ReviveRowOptions = {
106
- fieldEnumMapping: FieldEnumMapping;
107
- strict?: boolean;
108
- };
109
- type PathEnumMapping = Record<string, SmartEnumLike>;
110
- type RevivePayloadOptions = {
111
- pathEnumMapping: PathEnumMapping;
112
- strict?: boolean;
113
- };
114
- type Enumeration<TEnum> = TEnum extends Record<string, infer V> ? V extends {
115
- __smart_enum_brand: true;
116
- } ? V : never : never;
117
-
118
- type BuiltInOverrideKeys = 'key' | 'value' | 'display' | 'deprecated' | 'index' | '__smart_enum_brand' | '__smart_enum_type';
119
87
  type EnumInputItem = Partial<{
120
88
  key: string;
121
89
  value: string;
122
90
  display: string;
123
91
  deprecated: boolean;
124
- }> & object;
92
+ }> & Record<string, unknown>;
125
93
  type ObjectEnumInput = Record<string, EnumInputItem>;
126
94
  type EmptyEnumInputItem = Record<never, never>;
127
95
  type Separator = '-' | '_' | ' ' | '.';
@@ -132,49 +100,107 @@ type TrimUnderscore<S extends string> = S extends `_${infer R}` ? TrimUnderscore
132
100
  type CollapseUnderscores<S extends string> = S extends `${infer A}__${infer B}` ? CollapseUnderscores<`${A}_${B}`> : S;
133
101
  type ConstantCaseInternal<S extends string, Prev extends string = '', Out extends string = ''> = S extends `${infer C}${infer Rest}` ? C extends Separator ? ConstantCaseInternal<Rest, C, PushUnderscore<Out>> : IsUpperChar<C> extends true ? IsLowerChar<Prev> extends true ? ConstantCaseInternal<Rest, C, `${PushUnderscore<Out>}${Uppercase<C>}`> : ConstantCaseInternal<Rest, C, `${Out}${Uppercase<C>}`> : ConstantCaseInternal<Rest, C, `${Out}${Uppercase<C>}`> : CollapseUnderscores<TrimUnderscore<Out>>;
134
102
  type ConstantCase<S extends string> = string extends S ? string : ConstantCaseInternal<S>;
103
+ /** Segments of a `ConstantCase` string (underscore-separated ALL CAPS words). */
104
+ type SplitConstantCaseSegments<S extends string> = S extends `${infer A}_${infer B}` ? [A, ...SplitConstantCaseSegments<B>] : [S];
105
+ /** First character upper, remainder lower (for ALL-CAPS words from `ConstantCase`). */
106
+ type TitleCaseAllCapsWord<W extends string> = W extends '' ? '' : W extends `${infer F}${infer R}` ? `${Uppercase<F>}${Lowercase<R>}` : W;
107
+ type JoinDisplaySegments<T extends readonly string[]> = T extends readonly [
108
+ infer A extends string,
109
+ ...infer Rest extends readonly string[]
110
+ ] ? Rest extends readonly [] ? TitleCaseAllCapsWord<A> : `${TitleCaseAllCapsWord<A>} ${JoinDisplaySegments<Rest>}` : '';
111
+ /**
112
+ * Display string derived from the enum member key: `ConstantCase` → split → title-case words → join with spaces.
113
+ * Matches default runtime `capitalCase(key)` for typical PascalCase / camelCase keys. Member keys that already
114
+ * contain separators may differ from `capitalCase` at runtime; custom `propertyAutoFormatters` for `display`
115
+ * are not reflected in this type.
116
+ */
117
+ type DisplayCaseFromEnumKey<K extends string> = string extends K ? string : JoinDisplaySegments<SplitConstantCaseSegments<ConstantCase<K>>>;
135
118
  type ArrayToObjectType<T extends readonly string[]> = {
136
119
  [K in T[number]]: EmptyEnumInputItem & {
137
120
  readonly value?: ConstantCase<K>;
138
121
  };
139
122
  };
140
123
  type NormalizedInputType<TInput> = TInput extends readonly string[] ? ArrayToObjectType<TInput> : TInput extends ObjectEnumInput ? TInput : never;
141
- type UnionKeys<T> = T extends T ? keyof T : never;
142
- type MergeUnionToObject<T> = {
143
- [K in UnionKeys<T>]: T extends Record<K, infer V> ? V : undefined;
144
- };
145
- type ExtraShapeUnion<TObj extends ObjectEnumInput> = {
146
- [K in keyof TObj]: Omit<TObj[K], BuiltInOverrideKeys>;
147
- }[keyof TObj];
148
- type InferredExtraFields<TObj extends ObjectEnumInput> = MergeUnionToObject<ExtraShapeUnion<TObj>>;
149
- type EnumItemFromNormalizedObject<TObj extends ObjectEnumInput, K extends keyof TObj = keyof TObj> = Omit<StandardEnumItem, 'key' | 'value'> & InferredExtraFields<TObj> & {
124
+ /** Input-derived fields for one member key (excludes built-ins filled by `enumeration()`). */
125
+ type EnumMemberExtra<TObj extends ObjectEnumInput, K extends keyof TObj> = Omit<TObj[K], BuiltInOverrideKeys>;
126
+ type EnumItemFromNormalizedObject<TObj extends ObjectEnumInput, K extends keyof TObj = keyof TObj> = Omit<StandardEnumItem, 'key' | 'value' | 'display'> & EnumMemberExtra<TObj, K> & {
150
127
  readonly key: Extract<K, string>;
151
128
  readonly value: TObj[K] extends {
152
129
  value?: infer V;
153
- } ? Extract<V, string> extends never ? string : Extract<V, string> : string;
130
+ } ? [Extract<V, string>] extends [never] ? ConstantCase<Extract<K, string>> : Extract<V, string> : ConstantCase<Extract<K, string>>;
131
+ readonly display: TObj[K] extends {
132
+ display?: infer D;
133
+ } ? [Extract<D, string>] extends [never] ? DisplayCaseFromEnumKey<Extract<K, string>> : Extract<D, string> : DisplayCaseFromEnumKey<Extract<K, string>>;
154
134
  };
155
135
  type EnumMemberUnionFromNormalizedObject<TObj extends ObjectEnumInput> = {
156
136
  [K in keyof TObj]: EnumItemFromNormalizedObject<TObj, K>;
157
137
  }[keyof TObj];
138
+ type EnumFromNormalizedObject<TObj extends ObjectEnumInput> = {
139
+ [K in keyof TObj]: EnumItemFromNormalizedObject<TObj, K>;
140
+ } & CoreEnumMethods<EnumMemberUnionFromNormalizedObject<TObj>>;
141
+ type PropertyAutoFormatter = {
142
+ /** The property name to generate */
143
+ key: string;
144
+ /** Function to transform the key into the property value */
145
+ format: (k: string) => string;
146
+ };
158
147
  type CoreEnumMethods<TItem extends StandardEnumItem> = {
159
148
  fromValue(value: string): TItem;
160
149
  tryFromValue(value?: string | null): TItem | undefined;
161
150
  fromKey(key: string): TItem;
162
151
  tryFromKey(key?: string | null): TItem | undefined;
163
152
  items(): readonly TItem[];
164
- values(): readonly string[];
165
- keys(): readonly string[];
153
+ /** Matches runtime: `items.map(i => i.value)` (see {@link EnumLikeBase}). */
154
+ values(): readonly TItem['value'][];
155
+ /** Matches runtime: `items.map(i => i.key)` (see {@link EnumLikeBase}). */
156
+ keys(): readonly TItem['key'][];
157
+ };
158
+ /**
159
+ * Structural shape of a smart-style enum object: lookup by value/key, list items/values/keys,
160
+ * plus an index signature so registry and mapping types can treat instances as records.
161
+ * Use {@link SmartEnumLike} when items are full {@link StandardEnumItem}s (the usual case).
162
+ */
163
+ type EnumLikeBase<TItem extends StandardEnumItemBase = StandardEnumItemBase> = {
164
+ fromValue(value: string): TItem;
165
+ tryFromValue(value?: string | null): TItem | undefined;
166
+ fromKey(key: string): TItem;
167
+ tryFromKey(key?: string | null): TItem | undefined;
168
+ items(): readonly TItem[];
169
+ values(): readonly TItem['value'][];
170
+ keys(): readonly TItem['key'][];
171
+ } & Record<string, unknown>;
172
+ /**
173
+ * A {@link EnumLikeBase} whose items are branded {@link StandardEnumItem}s (typical `enumeration()` result).
174
+ */
175
+ type SmartEnumLike<TItem extends StandardEnumItem = StandardEnumItem> = EnumLikeBase<TItem>;
176
+ /** Union of branded enum member values on an enum object `T`. */
177
+ type SmartEnumMemberUnion<T extends Record<string, unknown>> = {
178
+ [K in keyof T]: T[K] extends StandardEnumItem ? T[K] : never;
179
+ }[keyof T];
180
+ /** Keys on `TEnum` whose member matches `Record<P, V>` within `ItemUnion`. */
181
+ type SmartEnumSubsetKeys<TEnum extends Record<string, unknown>, ItemUnion extends StandardEnumItem, P extends keyof ItemUnion & string, V extends ItemUnion[P]> = {
182
+ [K in keyof TEnum]: TEnum[K] extends Extract<ItemUnion, Record<P, V>> ? K : never;
183
+ }[keyof TEnum];
184
+ type SmartEnumSubsetItemUnion<ItemUnion extends StandardEnumItem, P extends keyof ItemUnion & string, V extends ItemUnion[P]> = Extract<ItemUnion, Record<P, V>>;
185
+ type SmartEnumSubsetView<TEnum extends Record<string, unknown>, ItemUnion extends StandardEnumItem, P extends keyof ItemUnion & string, V extends ItemUnion[P]> = Pick<TEnum, SmartEnumSubsetKeys<TEnum, ItemUnion, P, V>> & CoreEnumMethods<SmartEnumSubsetItemUnion<ItemUnion, P, V>>;
186
+ type FieldEnumMapping = Record<string, SmartEnumLike>;
187
+ type ReviveRowOptions = {
188
+ fieldEnumMapping: FieldEnumMapping;
189
+ strict?: boolean;
190
+ };
191
+ type PathEnumMapping = Record<string, SmartEnumLike>;
192
+ type RevivePayloadOptions = {
193
+ pathEnumMapping: PathEnumMapping;
194
+ strict?: boolean;
166
195
  };
167
- type EnumFromNormalizedObject<TObj extends ObjectEnumInput> = {
168
- [K in keyof TObj]: EnumItemFromNormalizedObject<TObj, K>;
169
- } & CoreEnumMethods<EnumMemberUnionFromNormalizedObject<TObj>>;
170
196
  type EnumerationProps<TInput> = {
171
197
  input: TInput;
172
198
  propertyAutoFormatters?: PropertyAutoFormatter[];
173
199
  };
174
- type PropertyAutoFormatter = {
175
- key: string;
176
- format: (k: string) => string;
177
- };
200
+ type Enumeration<TEnum> = TEnum extends Record<string, infer V> ? V extends {
201
+ __smart_enum_brand: true;
202
+ } ? V : never : never;
203
+
178
204
  declare function enumeration<const TArr extends readonly string[]>(enumType: string, props: EnumerationProps<TArr>): EnumFromNormalizedObject<NormalizedInputType<TArr>>;
179
205
  declare function enumeration<const TObj extends ObjectEnumInput>(enumType: string, props: EnumerationProps<TObj>): EnumFromNormalizedObject<NormalizedInputType<TObj>>;
180
206
 
@@ -266,4 +292,4 @@ declare function reviveSmartEnums<R>(input: unknown, registry: Record<string, An
266
292
  */
267
293
  declare const reviveEnumField: <TItem>(value: unknown, smartEnum: AnyEnumLike<TItem>, strict?: boolean) => TItem | undefined;
268
294
 
269
- export { type AnyEnumLike as A, type DatabaseFormat as D, type Enumeration as E, type FieldEnumMapping as F, type Logger as L, type PathEnumMapping as P, type RevivedSmartEnums as R, type SmartApiHelperConfig as S, isSmartEnum as a, reviveEnumField as b, type LogLevel as c, type SmartEnumMappingsConfig as d, enumeration as e, type SerializedSmartEnums as f, type SmartEnumItemSerialized as g, type EnumLikeBase as h, isSmartEnumItem as i, type SmartEnumLike as j, type ReviveRowOptions as k, type RevivePayloadOptions as l, type StandardEnumItemBase as m, type StandardEnumItem as n, reviveSmartEnums as r, serializeSmartEnums as s };
295
+ export { type AnyEnumLike as A, type DatabaseFormat as D, type Enumeration as E, type FieldEnumMapping as F, type Logger as L, type PathEnumMapping as P, type RevivedSmartEnums as R, type SmartApiHelperConfig as S, isSmartEnum as a, reviveEnumField as b, type LogLevel as c, type SmartEnumMappingsConfig as d, enumeration as e, type SerializedSmartEnums as f, type SmartEnumItemSerialized as g, type EnumLikeBase as h, isSmartEnumItem as i, type SmartEnumLike as j, type ReviveRowOptions as k, type RevivePayloadOptions as l, type StandardEnumItemBase as m, type StandardEnumItem as n, type SmartEnumMemberUnion as o, type SmartEnumSubsetView as p, reviveSmartEnums as r, serializeSmartEnums as s };