@tstdl/base 0.85.4 → 0.85.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tstdl/base",
3
- "version": "0.85.4",
3
+ "version": "0.85.6",
4
4
  "author": "Patrick Hein",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -1,9 +1,14 @@
1
- import type { PickBy, ReplaceKey } from '../types.js';
2
1
  import type { Observable } from 'rxjs';
2
+ import type { Signal } from '../signals/api.js';
3
+ import type { PickBy, ReactiveValue, ReplaceKey } from '../types.js';
3
4
  import type { LocalizableText } from './localizable-text.model.js';
4
5
  import { LocalizationService } from './localization.service.js';
5
- export type DynamicText = LocalizableText | Observable<LocalizableText>;
6
+ export type DynamicText = ReactiveValue<LocalizableText>;
7
+ export declare function resolveDynamicText(text: DynamicText, localizationService?: LocalizationService): Signal<string>;
6
8
  export declare function resolveDynamicText$(text: DynamicText, localizationService?: LocalizationService): Observable<string>;
9
+ export declare function resolveDynamicTexts(texts: DynamicText[], localizationService?: LocalizationService): Signal<string[]>;
7
10
  export declare function resolveDynamicTexts$(texts: DynamicText[], localizationService?: LocalizationService): Observable<string[]>;
11
+ export declare function resolveNestedDynamicText<T, K extends keyof PickBy<T, DynamicText>>(item: T, key: K, localizationService?: LocalizationService): Signal<ReplaceKey<T, K, string>>;
8
12
  export declare function resolveNestedDynamicText$<T, K extends keyof PickBy<T, DynamicText>>(item: T, key: K, localizationService?: LocalizationService): Observable<ReplaceKey<T, K, string>>;
13
+ export declare function resolveNestedDynamicTexts<T, K extends keyof PickBy<T, DynamicText>>(items: T[], key: K, localizationService?: LocalizationService): Signal<ReplaceKey<T, K, string>[]>;
9
14
  export declare function resolveNestedDynamicTexts$<T, K extends keyof PickBy<T, DynamicText>>(items: T[], key: K, localizationService?: LocalizationService): Observable<ReplaceKey<T, K, string>[]>;
@@ -18,34 +18,59 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var dynamic_text_model_exports = {};
20
20
  __export(dynamic_text_model_exports, {
21
+ resolveDynamicText: () => resolveDynamicText,
21
22
  resolveDynamicText$: () => resolveDynamicText$,
23
+ resolveDynamicTexts: () => resolveDynamicTexts,
22
24
  resolveDynamicTexts$: () => resolveDynamicTexts$,
25
+ resolveNestedDynamicText: () => resolveNestedDynamicText,
23
26
  resolveNestedDynamicText$: () => resolveNestedDynamicText$,
27
+ resolveNestedDynamicTexts: () => resolveNestedDynamicTexts,
24
28
  resolveNestedDynamicTexts$: () => resolveNestedDynamicTexts$
25
29
  });
26
30
  module.exports = __toCommonJS(dynamic_text_model_exports);
27
31
  var import_container = require("../container/index.js");
32
+ var import_api = require("../signals/api.js");
33
+ var import_to_observable = require("../signals/implementation/to-observable.js");
34
+ var import_to_signal = require("../signals/implementation/to-signal.js");
28
35
  var import_type_guards = require("../utils/type-guards.js");
29
36
  var import_rxjs = require("rxjs");
30
37
  var import_localization_service = require("./localization.service.js");
38
+ const missingLocalizationKeyText = "[MISSING LOCALIZATION KEY]";
39
+ function resolveDynamicText(text, localizationService) {
40
+ return (0, import_to_signal.toSignal)(resolveDynamicText$(text, localizationService), { initialValue: missingLocalizationKeyText });
41
+ }
31
42
  function resolveDynamicText$(text, localizationService) {
32
43
  const resolvedLocalizationService = localizationService ?? import_container.container.resolve(import_localization_service.LocalizationService);
33
44
  if ((0, import_rxjs.isObservable)(text)) {
34
45
  return text.pipe((0, import_rxjs.switchMap)((inner) => resolveDynamicText$(inner, localizationService)));
35
46
  }
47
+ if ((0, import_api.isSignal)(text)) {
48
+ const text$ = (0, import_to_observable.toObservable)(text);
49
+ return resolveDynamicText$(text$, resolvedLocalizationService);
50
+ }
36
51
  if ((0, import_type_guards.isString)(text)) {
37
52
  return (0, import_rxjs.of)(text);
38
53
  }
39
54
  return resolvedLocalizationService.localize$(text);
40
55
  }
56
+ function resolveDynamicTexts(texts, localizationService) {
57
+ const initialValue = texts.map(() => missingLocalizationKeyText);
58
+ return (0, import_to_signal.toSignal)(resolveDynamicTexts$(texts, localizationService), { initialValue });
59
+ }
41
60
  function resolveDynamicTexts$(texts, localizationService) {
42
61
  const resolvedLocalizationService = localizationService ?? import_container.container.resolve(import_localization_service.LocalizationService);
43
62
  const resolvedTextObservables = texts.map((text) => resolveDynamicText$(text, resolvedLocalizationService));
44
63
  return (0, import_rxjs.combineLatest)(resolvedTextObservables);
45
64
  }
65
+ function resolveNestedDynamicText(item, key, localizationService) {
66
+ return (0, import_to_signal.toSignal)(resolveNestedDynamicText$(item, key, localizationService), { requireSync: true });
67
+ }
46
68
  function resolveNestedDynamicText$(item, key, localizationService) {
47
69
  return resolveDynamicText$(item[key], localizationService).pipe((0, import_rxjs.map)((resolvedText) => ({ ...item, [key]: resolvedText })));
48
70
  }
71
+ function resolveNestedDynamicTexts(items, key, localizationService) {
72
+ return (0, import_to_signal.toSignal)(resolveNestedDynamicTexts$(items, key, localizationService), { requireSync: true });
73
+ }
49
74
  function resolveNestedDynamicTexts$(items, key, localizationService) {
50
75
  const resolvedLocalizationService = localizationService ?? import_container.container.resolve(import_localization_service.LocalizationService);
51
76
  const resolvedTextObservables = items.map((item) => resolveNestedDynamicText$(item, key, resolvedLocalizationService));
@@ -1,7 +1,8 @@
1
+ import type { Observable } from 'rxjs';
1
2
  import { Logger } from '../logger/index.js';
3
+ import type { Signal } from '../signals/api.js';
2
4
  import type { Enumeration, EnumerationValue } from '../types.js';
3
5
  import type { PropertyName } from '../utils/object/property-name.js';
4
- import type { Observable } from 'rxjs';
5
6
  export type Language = {
6
7
  code: string;
7
8
  name: string;
@@ -62,15 +63,11 @@ export declare function localizationData<T>(data: LocalizationData<T>): Localiza
62
63
  export declare function getLocalizationKeys<T extends Localization>(_localization?: T): ProxyLocalizationKeys<T['keys']>;
63
64
  export declare const autoEnumerationLocalization: typeof _autoEnumerationLocalization;
64
65
  export declare class LocalizationService {
65
- private readonly logger;
66
- private readonly localizations;
67
- private readonly activeLanguageSubject;
68
- private readonly availableLanguagesSubject;
69
- private get activeLocalization();
70
- get availableLanguages(): readonly Language[];
71
- get activeLanguage(): Language | undefined;
72
- readonly activeLanguage$: Observable<Language | undefined>;
73
- readonly availableLanguages$: Observable<readonly Language[]>;
66
+ #private;
67
+ readonly activeLanguage: Signal<Language | null>;
68
+ readonly availableLanguages: Signal<Language[]>;
69
+ readonly activeLanguage$: Observable<Language | null>;
70
+ readonly availableLanguages$: Observable<Language[]>;
74
71
  constructor(logger: Logger);
75
72
  registerLocalization(...localizations: Localization[]): void;
76
73
  hasLanguage(languageCode: string): boolean;
@@ -79,8 +76,10 @@ export declare class LocalizationService {
79
76
  setLocalization(localization: Localization): void;
80
77
  tryGetItem<Parameters>(keyOrData: LocalizationKey<Parameters> | LocalizationData<Parameters>): LocalizeItem | undefined;
81
78
  hasKey<Parameters>(key: LocalizationKey<Parameters> | LocalizationData<Parameters>): boolean;
82
- localize<Parameters = void>(keyOrData: LocalizationKey<Parameters> | LocalizationData<Parameters>): string;
83
- localizeEnum<T extends Enumeration>(enumeration: T, value?: EnumerationValue<T>, parameters?: unknown): string;
79
+ localizeOnce<Parameters = void>(keyOrData: LocalizationKey<Parameters> | LocalizationData<Parameters>): string;
80
+ localizeEnumOnce<T extends Enumeration>(enumeration: T, value?: EnumerationValue<T>, parameters?: unknown): string;
81
+ localize<Parameters>(data: LocalizationData<Parameters>): Signal<string>;
82
+ localizeEnum<T extends Enumeration>(enumeration: T, value?: EnumerationValue<T>, parameters?: unknown): Signal<string>;
84
83
  localize$<Parameters>(data: LocalizationData<Parameters>): Observable<string>;
85
84
  localizeEnum$<T extends Enumeration>(enumeration: T, value?: EnumerationValue<T>, parameters?: unknown): Observable<string>;
86
85
  private localizeItem;
@@ -33,12 +33,13 @@ module.exports = __toCommonJS(localization_service_exports);
33
33
  var import_container = require("../container/index.js");
34
34
  var import_details_error = require("../error/details.error.js");
35
35
  var import_logger = require("../logger/index.js");
36
+ var import_api = require("../signals/api.js");
37
+ var import_computed_with_dependencies = require("../signals/computed-with-dependencies.js");
36
38
  var import_enum = require("../utils/enum.js");
37
39
  var import_memoize = require("../utils/function/memoize.js");
38
40
  var import_object = require("../utils/object/object.js");
39
41
  var import_property_name = require("../utils/object/property-name.js");
40
42
  var import_type_guards = require("../utils/type-guards.js");
41
- var import_rxjs = require("rxjs");
42
43
  var __decorate = function(decorators, target, key, desc) {
43
44
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
44
45
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
@@ -83,113 +84,113 @@ const autoEnumerationLocalization = (0, import_memoize.memoize)(_autoEnumeration
83
84
  const parametersPattern = /(?:\{\{\s*(?<parameter>\w+)\s*\}\})/ug;
84
85
  const warnedMissingKeys = /* @__PURE__ */ new Set();
85
86
  let LocalizationService = class LocalizationService2 {
86
- logger;
87
- localizations;
88
- activeLanguageSubject;
89
- availableLanguagesSubject;
90
- get activeLocalization() {
91
- if ((0, import_type_guards.isUndefined)(this.activeLanguage)) {
92
- return void 0;
87
+ #logger;
88
+ #localizations = /* @__PURE__ */ new Map();
89
+ #activeLanguage = (0, import_api.signal)(null);
90
+ #availableLanguages = (0, import_api.signal)([]);
91
+ #activeLocalization = (0, import_api.computed)(() => {
92
+ const language = this.activeLanguage();
93
+ if ((0, import_type_guards.isNull)(language)) {
94
+ return null;
93
95
  }
94
- return this.localizations.get(this.activeLanguage.code);
95
- }
96
- get availableLanguages() {
97
- return this.availableLanguagesSubject.value;
98
- }
99
- get activeLanguage() {
100
- return this.activeLanguageSubject.value;
101
- }
102
- activeLanguage$;
103
- availableLanguages$;
96
+ return this.#localizations.get(language.code);
97
+ });
98
+ activeLanguage = this.#activeLanguage.asReadonly();
99
+ availableLanguages = this.#availableLanguages.asReadonly();
100
+ activeLanguage$ = (0, import_api.toObservable)(this.activeLanguage);
101
+ availableLanguages$ = (0, import_api.toObservable)(this.availableLanguages);
104
102
  constructor(logger) {
105
- this.logger = logger;
106
- this.localizations = /* @__PURE__ */ new Map();
107
- this.activeLanguageSubject = new import_rxjs.BehaviorSubject(void 0);
108
- this.availableLanguagesSubject = new import_rxjs.BehaviorSubject([]);
109
- this.activeLanguage$ = this.activeLanguageSubject.asObservable();
110
- this.availableLanguages$ = this.availableLanguagesSubject.asObservable();
103
+ this.#logger = logger;
111
104
  }
112
105
  registerLocalization(...localizations) {
113
106
  for (const localization of localizations) {
114
107
  const mappedLocalization = buildMappedLocalization(localization);
115
- if (this.localizations.has(localization.language.code)) {
116
- const existing = this.localizations.get(localization.language.code);
108
+ if (this.#localizations.has(localization.language.code)) {
109
+ const existing = this.#localizations.get(localization.language.code);
117
110
  const merged = mergeMappedLocalization(existing, mappedLocalization);
118
- this.localizations.set(localization.language.code, merged);
111
+ this.#localizations.set(localization.language.code, merged);
119
112
  } else {
120
- this.localizations.set(localization.language.code, mappedLocalization);
113
+ this.#localizations.set(localization.language.code, mappedLocalization);
121
114
  }
122
115
  if ((0, import_type_guards.isUndefined)(this.activeLanguage)) {
123
116
  this.setLocalization(localization);
124
117
  }
125
- const availableLanguages = [...this.localizations].map(([, loc]) => loc.language);
126
- this.availableLanguagesSubject.next(availableLanguages);
118
+ const availableLanguages = [...this.#localizations].map(([, loc]) => loc.language);
119
+ this.#availableLanguages.set(availableLanguages);
127
120
  }
128
121
  }
129
122
  hasLanguage(languageCode) {
130
- return this.localizations.has(languageCode);
123
+ return this.#localizations.has(languageCode);
131
124
  }
132
125
  getLanguage(languageCode) {
133
- return (0, import_type_guards.assertDefinedPass)(this.localizations.get(languageCode), "language not available").language;
126
+ return (0, import_type_guards.assertDefinedPass)(this.#localizations.get(languageCode), "language not available").language;
134
127
  }
135
128
  setLanguage(languageOrCode) {
136
- const language = (0, import_type_guards.isString)(languageOrCode) ? this.localizations.get(languageOrCode)?.language : languageOrCode;
137
- if ((0, import_type_guards.isUndefined)(language) || !this.localizations.has(language.code)) {
129
+ const language = (0, import_type_guards.isString)(languageOrCode) ? this.#localizations.get(languageOrCode)?.language : languageOrCode;
130
+ if ((0, import_type_guards.isUndefined)(language) || !this.#localizations.has(language.code)) {
138
131
  throw new Error("Language not registered.");
139
132
  }
140
- this.activeLanguageSubject.next(language);
133
+ this.#activeLanguage.set(language);
141
134
  }
142
135
  setLocalization(localization) {
143
136
  this.setLanguage(localization.language);
144
137
  }
145
138
  tryGetItem(keyOrData) {
146
- if ((0, import_type_guards.isUndefined)(this.activeLanguage)) {
139
+ const activeLanguageCode = this.#activeLanguage()?.code;
140
+ if ((0, import_type_guards.isUndefined)(activeLanguageCode)) {
147
141
  return void 0;
148
142
  }
149
143
  if (isEnumLocalizationKey(keyOrData)) {
150
- const enumEntry = this.localizations.get(this.activeLanguage.code)?.enums.get(keyOrData.enum);
144
+ const enumEntry = this.#localizations.get(activeLanguageCode)?.enums.get(keyOrData.enum);
151
145
  return (0, import_type_guards.isDefined)(keyOrData.value) ? enumEntry?.values[keyOrData.value] : enumEntry?.name;
152
146
  }
153
147
  const actualKey = getStringKey(keyOrData);
154
- return this.localizations.get(this.activeLanguage.code)?.keys.get(actualKey);
148
+ return this.#localizations.get(activeLanguageCode)?.keys.get(actualKey);
155
149
  }
156
150
  hasKey(key) {
157
151
  const item = this.tryGetItem(key);
158
152
  return (0, import_type_guards.isDefined)(item);
159
153
  }
160
154
  // eslint-disable-next-line max-statements
161
- localize(keyOrData) {
155
+ localizeOnce(keyOrData) {
162
156
  if (isEnumLocalizationKey(keyOrData)) {
163
- return this.localizeEnum(keyOrData.enum, keyOrData.value, keyOrData.parameters);
157
+ return this.localizeEnumOnce(keyOrData.enum, keyOrData.value, keyOrData.parameters);
164
158
  }
165
159
  const key = getStringKey(keyOrData);
166
160
  const parameters = (0, import_type_guards.isString)(keyOrData) || isProxyLocalizationKey(keyOrData) ? {} : keyOrData.parameters;
167
- const templateOrFunction = (0, import_type_guards.isDefined)(this.activeLanguage) ? this.localizations.get(this.activeLanguage.code)?.keys.get(key) : void 0;
161
+ const activeLanguageCode = this.#activeLanguage()?.code;
162
+ const templateOrFunction = (0, import_type_guards.isDefined)(activeLanguageCode) ? this.#localizations.get(activeLanguageCode)?.keys.get(key) : void 0;
168
163
  if ((0, import_type_guards.isUndefined)(templateOrFunction)) {
169
164
  if (!warnedMissingKeys.has(key)) {
170
- this.logger.warn(`Localization for ${key} not available.`);
165
+ this.#logger.warn(`Localization for ${key} not available.`);
171
166
  warnedMissingKeys.add(key);
172
167
  }
173
168
  }
174
169
  return this.localizeItem(key, templateOrFunction, parameters);
175
170
  }
176
- localizeEnum(enumeration, value, parameters) {
171
+ localizeEnumOnce(enumeration, value, parameters) {
177
172
  if ((0, import_type_guards.isUndefined)(value)) {
178
- const name = this.activeLocalization?.enums.get(enumeration)?.name;
173
+ const name = this.#activeLocalization()?.enums.get(enumeration)?.name;
179
174
  return this.localizeItem("ENUM", name, parameters);
180
175
  }
181
176
  const key = (0, import_type_guards.isArray)(enumeration) ? value : (0, import_enum.enumValueName)(enumeration, value);
182
- const item = this.activeLocalization?.enums.get(enumeration)?.values[value];
177
+ const item = this.#activeLocalization()?.enums.get(enumeration)?.values[value];
183
178
  if ((0, import_type_guards.isUndefined)(item)) {
184
179
  return autoEnumerationLocalization(enumeration)[2][value];
185
180
  }
186
181
  return this.localizeItem(key, item, parameters);
187
182
  }
183
+ localize(data) {
184
+ return (0, import_computed_with_dependencies.computedWithDependencies)(() => this.localizeOnce(data), [this.#activeLanguage]);
185
+ }
186
+ localizeEnum(enumeration, value, parameters) {
187
+ return (0, import_computed_with_dependencies.computedWithDependencies)(() => this.localizeEnumOnce(enumeration, value, parameters), [this.#activeLanguage]);
188
+ }
188
189
  localize$(data) {
189
- return this.activeLanguage$.pipe((0, import_rxjs.map)(() => this.localize(data)));
190
+ return (0, import_api.toObservable)(this.localize(data));
190
191
  }
191
192
  localizeEnum$(enumeration, value, parameters) {
192
- return this.activeLanguage$.pipe((0, import_rxjs.map)(() => this.localizeEnum(enumeration, value, parameters)));
193
+ return (0, import_api.toObservable)(this.localizeEnum(enumeration, value, parameters));
193
194
  }
194
195
  localizeItem(key, templateOrFunction, parameters) {
195
196
  if ((0, import_type_guards.isUndefined)(templateOrFunction)) {
package/types.d.ts CHANGED
@@ -1,4 +1,6 @@
1
+ import type { Observable } from 'rxjs';
1
2
  import type { Except, UnionToIntersection } from 'type-fest';
3
+ import type { Signal } from './signals/api.js';
2
4
  export type ObjectLiteral = {};
3
5
  export type PrimitiveTypeMap = {
4
6
  'string': string;
@@ -189,4 +191,5 @@ export type TypeFromPath<T extends Record, Path extends Paths<T> | string> = {
189
191
  [K in Path]: K extends keyof T ? T[K] : K extends `${infer P}.${infer S}` ? T[P] extends Record ? TypeFromPath<T[P], S> : never : never;
190
192
  }[Path];
191
193
  export type ConstructorParameterDecorator = (target: Object, propertyKey: undefined, parameterIndex: number) => void;
194
+ export type ReactiveValue<T> = T | Signal<T> | Observable<T>;
192
195
  export {};