@digitaldefiance/i18n-lib 3.8.16 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/package.json +4 -3
  2. package/src/branded-string-key.d.ts +203 -0
  3. package/src/branded-string-key.d.ts.map +1 -0
  4. package/src/branded-string-key.js +220 -0
  5. package/src/branded-string-key.js.map +1 -0
  6. package/src/component-definition.d.ts +46 -4
  7. package/src/component-definition.d.ts.map +1 -1
  8. package/src/component-definition.js +17 -0
  9. package/src/component-definition.js.map +1 -1
  10. package/src/component-registration.d.ts +27 -12
  11. package/src/component-registration.d.ts.map +1 -1
  12. package/src/component-registry.d.ts +30 -5
  13. package/src/component-registry.d.ts.map +1 -1
  14. package/src/component-registry.js +96 -7
  15. package/src/component-registry.js.map +1 -1
  16. package/src/core-i18n.d.ts +7 -7
  17. package/src/core-i18n.d.ts.map +1 -1
  18. package/src/core-i18n.js +2 -2
  19. package/src/core-i18n.js.map +1 -1
  20. package/src/core-string-key.d.ts +139 -48
  21. package/src/core-string-key.d.ts.map +1 -1
  22. package/src/core-string-key.js +90 -51
  23. package/src/core-string-key.js.map +1 -1
  24. package/src/errors/context-error.js +2 -2
  25. package/src/errors/context-error.js.map +1 -1
  26. package/src/errors/typed-handleable.js +1 -1
  27. package/src/errors/typed-handleable.js.map +1 -1
  28. package/src/errors/typed.d.ts +8 -8
  29. package/src/errors/typed.d.ts.map +1 -1
  30. package/src/errors/typed.js +16 -18
  31. package/src/errors/typed.js.map +1 -1
  32. package/src/index.d.ts +2 -0
  33. package/src/index.d.ts.map +1 -1
  34. package/src/index.js +5 -0
  35. package/src/index.js.map +1 -1
  36. package/src/plugin-i18n-engine.d.ts +74 -5
  37. package/src/plugin-i18n-engine.d.ts.map +1 -1
  38. package/src/plugin-i18n-engine.js +91 -13
  39. package/src/plugin-i18n-engine.js.map +1 -1
  40. package/src/registry-error.d.ts.map +1 -1
  41. package/src/registry-error.js +7 -11
  42. package/src/registry-error.js.map +1 -1
  43. package/src/strings/de.d.ts +2 -2
  44. package/src/strings/de.d.ts.map +1 -1
  45. package/src/strings/de.js +46 -46
  46. package/src/strings/de.js.map +1 -1
  47. package/src/strings/en-GB.d.ts +2 -2
  48. package/src/strings/en-GB.d.ts.map +1 -1
  49. package/src/strings/en-GB.js +46 -46
  50. package/src/strings/en-GB.js.map +1 -1
  51. package/src/strings/en-US.d.ts +2 -2
  52. package/src/strings/en-US.d.ts.map +1 -1
  53. package/src/strings/en-US.js +46 -46
  54. package/src/strings/en-US.js.map +1 -1
  55. package/src/strings/es.d.ts +2 -2
  56. package/src/strings/es.d.ts.map +1 -1
  57. package/src/strings/es.js +46 -46
  58. package/src/strings/es.js.map +1 -1
  59. package/src/strings/fr.d.ts +2 -2
  60. package/src/strings/fr.d.ts.map +1 -1
  61. package/src/strings/fr.js +46 -46
  62. package/src/strings/fr.js.map +1 -1
  63. package/src/strings/ja.d.ts +2 -2
  64. package/src/strings/ja.d.ts.map +1 -1
  65. package/src/strings/ja.js +46 -46
  66. package/src/strings/ja.js.map +1 -1
  67. package/src/strings/uk.d.ts +2 -2
  68. package/src/strings/uk.d.ts.map +1 -1
  69. package/src/strings/uk.js +46 -46
  70. package/src/strings/uk.js.map +1 -1
  71. package/src/strings/zh-CN.d.ts +2 -2
  72. package/src/strings/zh-CN.d.ts.map +1 -1
  73. package/src/strings/zh-CN.js +46 -46
  74. package/src/strings/zh-CN.js.map +1 -1
  75. package/src/types.d.ts +2 -1
  76. package/src/types.d.ts.map +1 -1
  77. package/src/types.js.map +1 -1
  78. package/src/validation-result.d.ts +16 -0
  79. package/src/validation-result.d.ts.map +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@digitaldefiance/i18n-lib",
3
- "version": "3.8.16",
3
+ "version": "4.0.0",
4
4
  "description": "i18n library with enum translation support",
5
5
  "homepage": "https://github.com/Digital-Defiance/i18n-lib",
6
6
  "repository": {
@@ -41,14 +41,15 @@
41
41
  "license": "MIT",
42
42
  "packageManager": "yarn@4.10.3",
43
43
  "dependencies": {
44
+ "@digitaldefiance/branded-enum": "0.0.4",
44
45
  "currency-codes": "^2.2.0",
45
46
  "lru-cache": "^5.1.1",
46
47
  "moment": "^2.30.1",
47
48
  "moment-timezone": "^0.6.0"
48
49
  },
49
50
  "devDependencies": {
50
- "@typescript-eslint/eslint-plugin": "^8.48.0",
51
- "@typescript-eslint/parser": "^8.48.0",
51
+ "@typescript-eslint/eslint-plugin": "^8.53.1",
52
+ "@typescript-eslint/parser": "^8.53.1",
52
53
  "eslint-plugin-import": "^2.32.0",
53
54
  "eslint-plugin-prettier": "^5.5.4",
54
55
  "fast-check": "^4.3.0"
@@ -0,0 +1,203 @@
1
+ /**
2
+ * Branded String Key utilities for runtime-identifiable i18n string keys
3
+ *
4
+ * This module provides integration between @digitaldefiance/branded-enum
5
+ * and the i18n system, enabling:
6
+ * - Runtime identification of which component a string key belongs to
7
+ * - Collision detection when registering components
8
+ * - Type-safe translation functions with branded enums
9
+ *
10
+ * @module branded-string-key
11
+ */
12
+ import { isFromEnum, findEnumSources, enumIntersect, getEnumValues, getEnumById, getAllEnumIds, mergeEnums } from '@digitaldefiance/branded-enum';
13
+ import type { BrandedEnum, BrandedEnumValue, AnyBrandedEnum } from '@digitaldefiance/branded-enum';
14
+ export type { BrandedEnum, BrandedEnumValue, AnyBrandedEnum };
15
+ export { isFromEnum, findEnumSources, enumIntersect, getEnumValues, getEnumById, getAllEnumIds, mergeEnums, };
16
+ /**
17
+ * Type alias for a branded string key enum used in i18n
18
+ */
19
+ export type BrandedStringKeys<T extends Record<string, string>> = BrandedEnum<T>;
20
+ /**
21
+ * Type alias for extracting the string key values from a branded enum
22
+ */
23
+ export type BrandedStringKeyValue<E extends AnyBrandedEnum> = BrandedEnumValue<E>;
24
+ /**
25
+ * Options for creating i18n string keys
26
+ */
27
+ export interface CreateI18nStringKeysOptions {
28
+ /**
29
+ * Prefix to add to all key values (e.g., 'user.' will make 'Welcome' become 'user.welcome')
30
+ * If not provided, no prefix is added
31
+ */
32
+ valuePrefix?: string;
33
+ /**
34
+ * Whether to lowercase the values (default: true for consistency)
35
+ */
36
+ lowercaseValues?: boolean;
37
+ }
38
+ /**
39
+ * Creates a branded enum for i18n string keys with a namespace identifier.
40
+ *
41
+ * This is the primary factory function for creating type-safe, runtime-identifiable
42
+ * string key sets for i18n components.
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * // Create user-related string keys
47
+ * const UserStringKeys = createI18nStringKeys('user-component', {
48
+ * Welcome: 'user.welcome',
49
+ * Goodbye: 'user.goodbye',
50
+ * Profile: 'user.profile',
51
+ * } as const);
52
+ *
53
+ * // Type-safe usage
54
+ * const key = UserStringKeys.Welcome; // 'user.welcome'
55
+ *
56
+ * // Runtime identification
57
+ * findEnumSources('user.welcome'); // ['user-component']
58
+ * isFromEnum('user.welcome', UserStringKeys); // true
59
+ * ```
60
+ *
61
+ * @param componentId Unique identifier for the component (used as the enum ID)
62
+ * @param keys Object mapping key names to their string values
63
+ * @returns A branded enum with runtime identification metadata
64
+ */
65
+ export declare function createI18nStringKeys<T extends Record<string, string>>(componentId: string, keys: T): BrandedStringKeys<T>;
66
+ /**
67
+ * Creates i18n string keys from an existing TypeScript enum.
68
+ *
69
+ * This function helps migrate from traditional enums to branded enums
70
+ * while maintaining the same key-value structure.
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * // Existing enum
75
+ * enum UserKeys {
76
+ * Welcome = 'user.welcome',
77
+ * Goodbye = 'user.goodbye',
78
+ * }
79
+ *
80
+ * // Convert to branded enum
81
+ * const BrandedUserKeys = createI18nStringKeysFromEnum('user-component', UserKeys);
82
+ *
83
+ * // Now has runtime identification
84
+ * findEnumSources('user.welcome'); // ['i18n:user-component']
85
+ * ```
86
+ *
87
+ * @param componentId Unique identifier for the component
88
+ * @param enumObj The TypeScript enum to convert
89
+ * @returns A branded enum with the same key-value pairs
90
+ */
91
+ export declare function createI18nStringKeysFromEnum<TEnum extends Record<string, string>>(componentId: string, enumObj: TEnum): BrandedStringKeys<TEnum>;
92
+ /**
93
+ * Result of a collision check between string key enums
94
+ */
95
+ export interface StringKeyCollisionResult {
96
+ /** Whether any collisions were found */
97
+ hasCollisions: boolean;
98
+ /** Array of collision details */
99
+ collisions: Array<{
100
+ /** The colliding value */
101
+ value: string;
102
+ /** The component IDs (enum IDs) that contain this value */
103
+ componentIds: readonly string[];
104
+ }>;
105
+ }
106
+ /**
107
+ * Checks for collisions between multiple branded string key enums.
108
+ *
109
+ * Use this to detect when multiple components have overlapping string keys,
110
+ * which could cause routing issues in translations.
111
+ *
112
+ * @example
113
+ * ```typescript
114
+ * const UserKeys = createI18nStringKeys('user', { Welcome: 'welcome' } as const);
115
+ * const AdminKeys = createI18nStringKeys('admin', { Welcome: 'welcome' } as const);
116
+ *
117
+ * const result = checkStringKeyCollisions(UserKeys, AdminKeys);
118
+ * // result.hasCollisions === true
119
+ * // result.collisions === [{ value: 'welcome', componentIds: ['i18n:user', 'i18n:admin'] }]
120
+ * ```
121
+ *
122
+ * @param enums The branded string key enums to check
123
+ * @returns Collision check result
124
+ */
125
+ export declare function checkStringKeyCollisions(...enums: AnyBrandedEnum[]): StringKeyCollisionResult;
126
+ /**
127
+ * Finds which i18n component(s) a string key belongs to.
128
+ *
129
+ * @example
130
+ * ```typescript
131
+ * const sources = findStringKeySources('user.welcome');
132
+ * // ['i18n:user-component']
133
+ * ```
134
+ *
135
+ * @param key The string key to look up
136
+ * @returns Array of component IDs that contain this key
137
+ */
138
+ export declare function findStringKeySources(key: string): string[];
139
+ /**
140
+ * Resolves a string key to its owning component ID.
141
+ *
142
+ * Returns the component ID without the 'i18n:' prefix if exactly one
143
+ * component owns the key, or null if zero or multiple components own it.
144
+ *
145
+ * @example
146
+ * ```typescript
147
+ * const componentId = resolveStringKeyComponent('user.welcome');
148
+ * // 'user-component' (or null if ambiguous)
149
+ * ```
150
+ *
151
+ * @param key The string key to resolve
152
+ * @returns The component ID, or null if not found or ambiguous
153
+ */
154
+ export declare function resolveStringKeyComponent(key: string): string | null;
155
+ /**
156
+ * Gets all registered i18n component IDs.
157
+ *
158
+ * @returns Array of component IDs (without the 'i18n:' prefix)
159
+ */
160
+ export declare function getRegisteredI18nComponents(): string[];
161
+ /**
162
+ * Gets a branded string key enum by its component ID.
163
+ *
164
+ * @param componentId The component ID to look up
165
+ * @returns The branded enum, or undefined if not found
166
+ */
167
+ export declare function getStringKeysByComponentId(componentId: string): BrandedEnum<Record<string, string>> | undefined;
168
+ /**
169
+ * Validates that a value is a valid string key from a specific branded enum.
170
+ *
171
+ * @param value The value to validate
172
+ * @param stringKeys The branded enum to validate against
173
+ * @returns True if the value is a valid key in the enum
174
+ */
175
+ export declare function isValidStringKey<E extends BrandedEnum<Record<string, string>>>(value: unknown, stringKeys: E): value is BrandedEnumValue<E>;
176
+ /**
177
+ * Merges multiple branded string key enums into a combined enum.
178
+ *
179
+ * Useful for creating a unified key set from multiple components.
180
+ *
181
+ * @example
182
+ * ```typescript
183
+ * const AllKeys = mergeI18nStringKeys('all-keys',
184
+ * CoreStringKeys,
185
+ * UserStringKeys,
186
+ * AdminStringKeys
187
+ * );
188
+ * ```
189
+ *
190
+ * @param newComponentId The ID for the merged enum
191
+ * @param enums The enums to merge
192
+ * @returns A new branded enum containing all keys from input enums
193
+ * @throws Error if there are duplicate keys across enums
194
+ */
195
+ export declare function mergeI18nStringKeys<T extends readonly BrandedEnum<Record<string, string>>[]>(newComponentId: string, ...enums: T): BrandedEnum<Record<string, string>>;
196
+ /**
197
+ * Helper to get all string key values from a branded enum as an array.
198
+ *
199
+ * @param stringKeys The branded enum
200
+ * @returns Array of all string key values
201
+ */
202
+ export declare function getStringKeyValues<E extends BrandedEnum<Record<string, string>>>(stringKeys: E): BrandedEnumValue<E>[];
203
+ //# sourceMappingURL=branded-string-key.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branded-string-key.d.ts","sourceRoot":"","sources":["../../../../packages/digitaldefiance-i18n-lib/src/branded-string-key.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,220 @@
1
+ "use strict";
2
+ /**
3
+ * Branded String Key utilities for runtime-identifiable i18n string keys
4
+ *
5
+ * This module provides integration between @digitaldefiance/branded-enum
6
+ * and the i18n system, enabling:
7
+ * - Runtime identification of which component a string key belongs to
8
+ * - Collision detection when registering components
9
+ * - Type-safe translation functions with branded enums
10
+ *
11
+ * @module branded-string-key
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.mergeEnums = exports.getAllEnumIds = exports.getEnumById = exports.getEnumValues = exports.enumIntersect = exports.findEnumSources = exports.isFromEnum = void 0;
15
+ exports.createI18nStringKeys = createI18nStringKeys;
16
+ exports.createI18nStringKeysFromEnum = createI18nStringKeysFromEnum;
17
+ exports.checkStringKeyCollisions = checkStringKeyCollisions;
18
+ exports.findStringKeySources = findStringKeySources;
19
+ exports.resolveStringKeyComponent = resolveStringKeyComponent;
20
+ exports.getRegisteredI18nComponents = getRegisteredI18nComponents;
21
+ exports.getStringKeysByComponentId = getStringKeysByComponentId;
22
+ exports.isValidStringKey = isValidStringKey;
23
+ exports.mergeI18nStringKeys = mergeI18nStringKeys;
24
+ exports.getStringKeyValues = getStringKeyValues;
25
+ const branded_enum_1 = require("@digitaldefiance/branded-enum");
26
+ Object.defineProperty(exports, "isFromEnum", { enumerable: true, get: function () { return branded_enum_1.isFromEnum; } });
27
+ Object.defineProperty(exports, "findEnumSources", { enumerable: true, get: function () { return branded_enum_1.findEnumSources; } });
28
+ Object.defineProperty(exports, "enumIntersect", { enumerable: true, get: function () { return branded_enum_1.enumIntersect; } });
29
+ Object.defineProperty(exports, "getEnumValues", { enumerable: true, get: function () { return branded_enum_1.getEnumValues; } });
30
+ Object.defineProperty(exports, "getEnumById", { enumerable: true, get: function () { return branded_enum_1.getEnumById; } });
31
+ Object.defineProperty(exports, "getAllEnumIds", { enumerable: true, get: function () { return branded_enum_1.getAllEnumIds; } });
32
+ Object.defineProperty(exports, "mergeEnums", { enumerable: true, get: function () { return branded_enum_1.mergeEnums; } });
33
+ /**
34
+ * Creates a branded enum for i18n string keys with a namespace identifier.
35
+ *
36
+ * This is the primary factory function for creating type-safe, runtime-identifiable
37
+ * string key sets for i18n components.
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * // Create user-related string keys
42
+ * const UserStringKeys = createI18nStringKeys('user-component', {
43
+ * Welcome: 'user.welcome',
44
+ * Goodbye: 'user.goodbye',
45
+ * Profile: 'user.profile',
46
+ * } as const);
47
+ *
48
+ * // Type-safe usage
49
+ * const key = UserStringKeys.Welcome; // 'user.welcome'
50
+ *
51
+ * // Runtime identification
52
+ * findEnumSources('user.welcome'); // ['user-component']
53
+ * isFromEnum('user.welcome', UserStringKeys); // true
54
+ * ```
55
+ *
56
+ * @param componentId Unique identifier for the component (used as the enum ID)
57
+ * @param keys Object mapping key names to their string values
58
+ * @returns A branded enum with runtime identification metadata
59
+ */
60
+ function createI18nStringKeys(componentId, keys) {
61
+ return (0, branded_enum_1.createBrandedEnum)(`i18n:${componentId}`, keys);
62
+ }
63
+ /**
64
+ * Creates i18n string keys from an existing TypeScript enum.
65
+ *
66
+ * This function helps migrate from traditional enums to branded enums
67
+ * while maintaining the same key-value structure.
68
+ *
69
+ * @example
70
+ * ```typescript
71
+ * // Existing enum
72
+ * enum UserKeys {
73
+ * Welcome = 'user.welcome',
74
+ * Goodbye = 'user.goodbye',
75
+ * }
76
+ *
77
+ * // Convert to branded enum
78
+ * const BrandedUserKeys = createI18nStringKeysFromEnum('user-component', UserKeys);
79
+ *
80
+ * // Now has runtime identification
81
+ * findEnumSources('user.welcome'); // ['i18n:user-component']
82
+ * ```
83
+ *
84
+ * @param componentId Unique identifier for the component
85
+ * @param enumObj The TypeScript enum to convert
86
+ * @returns A branded enum with the same key-value pairs
87
+ */
88
+ function createI18nStringKeysFromEnum(componentId, enumObj) {
89
+ // Filter out reverse mappings (numeric enums have value -> key mappings)
90
+ const filteredObj = Object.fromEntries(Object.entries(enumObj).filter(([_key, value]) => typeof value === 'string' &&
91
+ !Object.prototype.hasOwnProperty.call(enumObj, value)));
92
+ return createI18nStringKeys(componentId, filteredObj);
93
+ }
94
+ /**
95
+ * Checks for collisions between multiple branded string key enums.
96
+ *
97
+ * Use this to detect when multiple components have overlapping string keys,
98
+ * which could cause routing issues in translations.
99
+ *
100
+ * @example
101
+ * ```typescript
102
+ * const UserKeys = createI18nStringKeys('user', { Welcome: 'welcome' } as const);
103
+ * const AdminKeys = createI18nStringKeys('admin', { Welcome: 'welcome' } as const);
104
+ *
105
+ * const result = checkStringKeyCollisions(UserKeys, AdminKeys);
106
+ * // result.hasCollisions === true
107
+ * // result.collisions === [{ value: 'welcome', componentIds: ['i18n:user', 'i18n:admin'] }]
108
+ * ```
109
+ *
110
+ * @param enums The branded string key enums to check
111
+ * @returns Collision check result
112
+ */
113
+ function checkStringKeyCollisions(...enums) {
114
+ const collisions = (0, branded_enum_1.enumIntersect)(...enums);
115
+ return {
116
+ hasCollisions: collisions.length > 0,
117
+ collisions: collisions.map((c) => ({
118
+ value: c.value,
119
+ componentIds: c.enumIds,
120
+ })),
121
+ };
122
+ }
123
+ /**
124
+ * Finds which i18n component(s) a string key belongs to.
125
+ *
126
+ * @example
127
+ * ```typescript
128
+ * const sources = findStringKeySources('user.welcome');
129
+ * // ['i18n:user-component']
130
+ * ```
131
+ *
132
+ * @param key The string key to look up
133
+ * @returns Array of component IDs that contain this key
134
+ */
135
+ function findStringKeySources(key) {
136
+ return (0, branded_enum_1.findEnumSources)(key).filter((id) => id.startsWith('i18n:'));
137
+ }
138
+ /**
139
+ * Resolves a string key to its owning component ID.
140
+ *
141
+ * Returns the component ID without the 'i18n:' prefix if exactly one
142
+ * component owns the key, or null if zero or multiple components own it.
143
+ *
144
+ * @example
145
+ * ```typescript
146
+ * const componentId = resolveStringKeyComponent('user.welcome');
147
+ * // 'user-component' (or null if ambiguous)
148
+ * ```
149
+ *
150
+ * @param key The string key to resolve
151
+ * @returns The component ID, or null if not found or ambiguous
152
+ */
153
+ function resolveStringKeyComponent(key) {
154
+ const sources = findStringKeySources(key);
155
+ if (sources.length === 1) {
156
+ return sources[0].replace(/^i18n:/, '');
157
+ }
158
+ return null;
159
+ }
160
+ /**
161
+ * Gets all registered i18n component IDs.
162
+ *
163
+ * @returns Array of component IDs (without the 'i18n:' prefix)
164
+ */
165
+ function getRegisteredI18nComponents() {
166
+ return (0, branded_enum_1.getAllEnumIds)()
167
+ .filter((id) => id.startsWith('i18n:'))
168
+ .map((id) => id.replace(/^i18n:/, ''));
169
+ }
170
+ /**
171
+ * Gets a branded string key enum by its component ID.
172
+ *
173
+ * @param componentId The component ID to look up
174
+ * @returns The branded enum, or undefined if not found
175
+ */
176
+ function getStringKeysByComponentId(componentId) {
177
+ return (0, branded_enum_1.getEnumById)(`i18n:${componentId}`);
178
+ }
179
+ /**
180
+ * Validates that a value is a valid string key from a specific branded enum.
181
+ *
182
+ * @param value The value to validate
183
+ * @param stringKeys The branded enum to validate against
184
+ * @returns True if the value is a valid key in the enum
185
+ */
186
+ function isValidStringKey(value, stringKeys) {
187
+ return (0, branded_enum_1.isFromEnum)(value, stringKeys);
188
+ }
189
+ /**
190
+ * Merges multiple branded string key enums into a combined enum.
191
+ *
192
+ * Useful for creating a unified key set from multiple components.
193
+ *
194
+ * @example
195
+ * ```typescript
196
+ * const AllKeys = mergeI18nStringKeys('all-keys',
197
+ * CoreStringKeys,
198
+ * UserStringKeys,
199
+ * AdminStringKeys
200
+ * );
201
+ * ```
202
+ *
203
+ * @param newComponentId The ID for the merged enum
204
+ * @param enums The enums to merge
205
+ * @returns A new branded enum containing all keys from input enums
206
+ * @throws Error if there are duplicate keys across enums
207
+ */
208
+ function mergeI18nStringKeys(newComponentId, ...enums) {
209
+ return (0, branded_enum_1.mergeEnums)(`i18n:${newComponentId}`, ...enums);
210
+ }
211
+ /**
212
+ * Helper to get all string key values from a branded enum as an array.
213
+ *
214
+ * @param stringKeys The branded enum
215
+ * @returns Array of all string key values
216
+ */
217
+ function getStringKeyValues(stringKeys) {
218
+ return ((0, branded_enum_1.getEnumValues)(stringKeys) ?? []);
219
+ }
220
+ //# sourceMappingURL=branded-string-key.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branded-string-key.js","sourceRoot":"","sources":["../../../../packages/digitaldefiance-i18n-lib/src/branded-string-key.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,54 @@
1
1
  /**
2
- * Component definition with its string keys
2
+ * Component definition with branded string keys
3
+ *
4
+ * @module component-definition
3
5
  */
4
- export interface ComponentDefinition<TStringKeys extends string> {
6
+ import type { AnyBrandedEnum, BrandedEnumValue } from '@digitaldefiance/branded-enum';
7
+ /**
8
+ * Component definition using branded enums for runtime-identifiable string keys
9
+ *
10
+ * This interface provides:
11
+ * - Runtime identification of string key sources
12
+ * - Automatic collision detection during registration
13
+ * - Type-safe string key validation
14
+ * - Automatic translation routing
15
+ *
16
+ * @template TBrandedEnum - The branded enum type containing string keys
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * const MyKeys = createI18nStringKeys('my-component', {
21
+ * Key1: 'key1',
22
+ * Key2: 'key2',
23
+ * } as const);
24
+ *
25
+ * const myComponent: ComponentDefinition<typeof MyKeys> = {
26
+ * id: 'my-component',
27
+ * name: 'My Component',
28
+ * stringKeys: MyKeys,
29
+ * };
30
+ * ```
31
+ */
32
+ export interface ComponentDefinition<TBrandedEnum extends AnyBrandedEnum> {
5
33
  /** Unique identifier for the component */
6
34
  readonly id: string;
7
35
  /** Human-readable name for the component */
8
36
  readonly name: string;
9
- /** Array of all string keys this component requires */
10
- readonly stringKeys: readonly TStringKeys[];
37
+ /**
38
+ * Branded enum containing all string keys for this component
39
+ * Provides runtime identification and collision detection
40
+ */
41
+ readonly stringKeys: TBrandedEnum;
11
42
  }
43
+ /**
44
+ * Helper to extract string key values from a component definition
45
+ *
46
+ * @param definition - The component definition
47
+ * @returns Array of all string key values
48
+ */
49
+ export declare function getComponentStringKeys<TBrandedEnum extends AnyBrandedEnum>(definition: ComponentDefinition<TBrandedEnum>): BrandedEnumValue<TBrandedEnum>[];
50
+ /**
51
+ * Type to extract string key type from a component definition
52
+ */
53
+ export type ComponentStringKeys<T extends ComponentDefinition<AnyBrandedEnum>> = T extends ComponentDefinition<infer E> ? BrandedEnumValue<E> : never;
12
54
  //# sourceMappingURL=component-definition.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"component-definition.d.ts","sourceRoot":"","sources":["../../../../packages/digitaldefiance-i18n-lib/src/component-definition.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,mBAAmB,CAAC,WAAW,SAAS,MAAM;IAC7D,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,4CAA4C;IAC5C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,uDAAuD;IACvD,QAAQ,CAAC,UAAU,EAAE,SAAS,WAAW,EAAE,CAAC;CAC7C"}
1
+ {"version":3,"file":"component-definition.d.ts","sourceRoot":"","sources":["../../../../packages/digitaldefiance-i18n-lib/src/component-definition.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EACjB,MAAM,+BAA+B,CAAC;AAGvC;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,WAAW,mBAAmB,CAAC,YAAY,SAAS,cAAc;IACtE,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,4CAA4C;IAC5C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC;CACnC;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,YAAY,SAAS,cAAc,EACxE,UAAU,EAAE,mBAAmB,CAAC,YAAY,CAAC,GAC5C,gBAAgB,CAAC,YAAY,CAAC,EAAE,CAGlC;AAED;;GAEG;AACH,MAAM,MAAM,mBAAmB,CAAC,CAAC,SAAS,mBAAmB,CAAC,cAAc,CAAC,IAC3E,CAAC,SAAS,mBAAmB,CAAC,MAAM,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC"}
@@ -1,3 +1,20 @@
1
1
  "use strict";
2
+ /**
3
+ * Component definition with branded string keys
4
+ *
5
+ * @module component-definition
6
+ */
2
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.getComponentStringKeys = getComponentStringKeys;
9
+ const branded_enum_1 = require("@digitaldefiance/branded-enum");
10
+ /**
11
+ * Helper to extract string key values from a component definition
12
+ *
13
+ * @param definition - The component definition
14
+ * @returns Array of all string key values
15
+ */
16
+ function getComponentStringKeys(definition) {
17
+ const values = (0, branded_enum_1.getEnumValues)(definition.stringKeys);
18
+ return (values ?? []);
19
+ }
3
20
  //# sourceMappingURL=component-definition.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"component-definition.js","sourceRoot":"","sources":["../../../../packages/digitaldefiance-i18n-lib/src/component-definition.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"component-definition.js","sourceRoot":"","sources":["../../../../packages/digitaldefiance-i18n-lib/src/component-definition.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;AAmDH,wDAKC;AAlDD,gEAA8D;AAuC9D;;;;;GAKG;AACH,SAAgB,sBAAsB,CACpC,UAA6C;IAE7C,MAAM,MAAM,GAAG,IAAA,4BAAa,EAAC,UAAU,CAAC,UAAU,CAAC,CAAC;IACpD,OAAO,CAAC,MAAM,IAAI,EAAE,CAAqC,CAAC;AAC5D,CAAC"}
@@ -1,22 +1,37 @@
1
+ import type { AnyBrandedEnum, BrandedEnumValue } from '@digitaldefiance/branded-enum';
1
2
  import { ComponentDefinition } from './component-definition';
2
3
  import { PartialComponentLanguageStrings } from './types';
3
4
  /**
4
5
  * Registration payload for a component with its strings
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * const MyKeys = createI18nStringKeys('my-component', {
10
+ * Welcome: 'my.welcome',
11
+ * Goodbye: 'my.goodbye',
12
+ * } as const);
13
+ *
14
+ * const registration: ComponentRegistration<typeof MyKeys, 'en' | 'es'> = {
15
+ * component: {
16
+ * id: 'my-component',
17
+ * name: 'My Component',
18
+ * stringKeys: MyKeys,
19
+ * },
20
+ * strings: {
21
+ * en: { 'my.welcome': 'Welcome!', 'my.goodbye': 'Goodbye!' },
22
+ * es: { 'my.welcome': '¡Bienvenido!', 'my.goodbye': '¡Adiós!' },
23
+ * },
24
+ * };
25
+ * ```
5
26
  */
6
- export interface ComponentRegistration<TStringKeys extends string, TLanguages extends string> {
7
- readonly component: ComponentDefinition<TStringKeys>;
8
- readonly strings: PartialComponentLanguageStrings<TStringKeys, TLanguages>;
9
- readonly enumName?: string;
10
- readonly enumObject?: Record<string, TStringKeys>;
27
+ export interface ComponentRegistration<TBrandedEnum extends AnyBrandedEnum, TLanguages extends string> {
28
+ readonly component: ComponentDefinition<TBrandedEnum>;
29
+ readonly strings: PartialComponentLanguageStrings<BrandedEnumValue<TBrandedEnum>, TLanguages>;
30
+ /** Optional aliases for resolving component references */
11
31
  readonly aliases?: readonly string[];
12
32
  }
13
33
  /**
14
- * Type utility to extract string keys from a component definition
34
+ * Type utility to extract string keys type from a component registration
15
35
  */
16
- type ExtractStringKeys<T> = T extends ComponentDefinition<infer K> ? K : never;
17
- /**
18
- * Type utility to create a strongly typed component registration
19
- */
20
- export type CreateComponentRegistration<TComponent extends ComponentDefinition<string>, TLanguages extends string> = ComponentRegistration<ExtractStringKeys<TComponent>, TLanguages>;
21
- export {};
36
+ export type RegistrationStringKeys<T extends ComponentRegistration<AnyBrandedEnum, string>> = T extends ComponentRegistration<infer E, string> ? BrandedEnumValue<E> : never;
22
37
  //# sourceMappingURL=component-registration.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"component-registration.d.ts","sourceRoot":"","sources":["../../../../packages/digitaldefiance-i18n-lib/src/component-registration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,+BAA+B,EAAE,MAAM,SAAS,CAAC;AAE1D;;GAEG;AACH,MAAM,WAAW,qBAAqB,CACpC,WAAW,SAAS,MAAM,EAC1B,UAAU,SAAS,MAAM;IAEzB,QAAQ,CAAC,SAAS,EAAE,mBAAmB,CAAC,WAAW,CAAC,CAAC;IACrD,QAAQ,CAAC,OAAO,EAAE,+BAA+B,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IAC3E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAClD,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED;;GAEG;AACH,KAAK,iBAAiB,CAAC,CAAC,IAAI,CAAC,SAAS,mBAAmB,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAE/E;;GAEG;AACH,MAAM,MAAM,2BAA2B,CACrC,UAAU,SAAS,mBAAmB,CAAC,MAAM,CAAC,EAC9C,UAAU,SAAS,MAAM,IACvB,qBAAqB,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC,CAAC"}
1
+ {"version":3,"file":"component-registration.d.ts","sourceRoot":"","sources":["../../../../packages/digitaldefiance-i18n-lib/src/component-registration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EACjB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,+BAA+B,EAAE,MAAM,SAAS,CAAC;AAE1D;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,WAAW,qBAAqB,CACpC,YAAY,SAAS,cAAc,EACnC,UAAU,SAAS,MAAM;IAEzB,QAAQ,CAAC,SAAS,EAAE,mBAAmB,CAAC,YAAY,CAAC,CAAC;IACtD,QAAQ,CAAC,OAAO,EAAE,+BAA+B,CAC/C,gBAAgB,CAAC,YAAY,CAAC,EAC9B,UAAU,CACX,CAAC;IACF,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,MAAM,sBAAsB,CAChC,CAAC,SAAS,qBAAqB,CAAC,cAAc,EAAE,MAAM,CAAC,IAEvD,CAAC,SAAS,qBAAqB,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,GAC5C,gBAAgB,CAAC,CAAC,CAAC,GACnB,KAAK,CAAC"}