@lenne.tech/ng-base 22.0.4 → 22.1.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 (33) hide show
  1. package/CLAUDE.md +5 -0
  2. package/README.md +34 -7
  3. package/fesm2022/lenne.tech-ng-base-ai.mjs +27 -27
  4. package/fesm2022/lenne.tech-ng-base-auth-provide.mjs +15 -14
  5. package/fesm2022/lenne.tech-ng-base-auth-provide.mjs.map +1 -1
  6. package/fesm2022/lenne.tech-ng-base-auth.mjs +17 -13
  7. package/fesm2022/lenne.tech-ng-base-auth.mjs.map +1 -1
  8. package/fesm2022/{lenne.tech-ng-base-bug-bug-report-dialog-BRzVmKJr.mjs → lenne.tech-ng-base-bug-bug-report-dialog-f6VNOWnW.mjs} +11 -11
  9. package/fesm2022/{lenne.tech-ng-base-bug-bug-report-dialog-BRzVmKJr.mjs.map → lenne.tech-ng-base-bug-bug-report-dialog-f6VNOWnW.mjs.map} +1 -1
  10. package/fesm2022/{lenne.tech-ng-base-bug-bug-report-service-DWoTb_iw.mjs → lenne.tech-ng-base-bug-bug-report-service-D6slR3GD.mjs} +4 -4
  11. package/fesm2022/{lenne.tech-ng-base-bug-bug-report-service-DWoTb_iw.mjs.map → lenne.tech-ng-base-bug-bug-report-service-D6slR3GD.mjs.map} +1 -1
  12. package/fesm2022/lenne.tech-ng-base-bug.mjs +5 -5
  13. package/fesm2022/lenne.tech-ng-base-files-ui.mjs +3 -3
  14. package/fesm2022/lenne.tech-ng-base-files.mjs +8 -4
  15. package/fesm2022/lenne.tech-ng-base-files.mjs.map +1 -1
  16. package/fesm2022/lenne.tech-ng-base-share.mjs +3 -3
  17. package/fesm2022/lenne.tech-ng-base-ui-provide.mjs +3 -3
  18. package/fesm2022/lenne.tech-ng-base-ui.mjs +1206 -1216
  19. package/fesm2022/lenne.tech-ng-base-ui.mjs.map +1 -1
  20. package/fesm2022/lenne.tech-ng-base-utils.mjs +9 -9
  21. package/fesm2022/lenne.tech-ng-base.mjs +27 -24
  22. package/fesm2022/lenne.tech-ng-base.mjs.map +1 -1
  23. package/i18n/auth/de.json +1 -3
  24. package/i18n/auth/en.json +1 -3
  25. package/i18n/de.json +1 -2
  26. package/i18n/en.json +1 -2
  27. package/i18n/ui/de.json +0 -5
  28. package/i18n/ui/en.json +0 -5
  29. package/package.json +5 -1
  30. package/types/lenne.tech-ng-base-auth-provide.d.ts +2 -3
  31. package/types/lenne.tech-ng-base-auth.d.ts +4 -1
  32. package/types/lenne.tech-ng-base-files.d.ts +5 -1
  33. package/types/lenne.tech-ng-base.d.ts +8 -1
@@ -106,7 +106,7 @@ var LtScrollService = class LtScrollService {
106
106
  }
107
107
  static ɵfac = i0.ɵɵngDeclareFactory({
108
108
  minVersion: "12.0.0",
109
- version: "22.2.4",
109
+ version: "22.2.5",
110
110
  ngImport: i0,
111
111
  type: LtScrollService,
112
112
  deps: [],
@@ -114,14 +114,14 @@ var LtScrollService = class LtScrollService {
114
114
  });
115
115
  static ɵprov = i0.ɵɵngDeclareService({
116
116
  minVersion: "22.0.0",
117
- version: "22.2.4",
117
+ version: "22.2.5",
118
118
  ngImport: i0,
119
119
  type: LtScrollService
120
120
  });
121
121
  };
122
122
  i0.ɵɵngDeclareClassMetadata({
123
123
  minVersion: "12.0.0",
124
- version: "22.2.4",
124
+ version: "22.2.5",
125
125
  ngImport: i0,
126
126
  type: LtScrollService,
127
127
  decorators: [{ type: Service }]
@@ -188,7 +188,7 @@ var LtSeoService = class LtSeoService {
188
188
  }
189
189
  static ɵfac = i0.ɵɵngDeclareFactory({
190
190
  minVersion: "12.0.0",
191
- version: "22.2.4",
191
+ version: "22.2.5",
192
192
  ngImport: i0,
193
193
  type: LtSeoService,
194
194
  deps: [],
@@ -196,14 +196,14 @@ var LtSeoService = class LtSeoService {
196
196
  });
197
197
  static ɵprov = i0.ɵɵngDeclareService({
198
198
  minVersion: "22.0.0",
199
- version: "22.2.4",
199
+ version: "22.2.5",
200
200
  ngImport: i0,
201
201
  type: LtSeoService
202
202
  });
203
203
  };
204
204
  i0.ɵɵngDeclareClassMetadata({
205
205
  minVersion: "12.0.0",
206
- version: "22.2.4",
206
+ version: "22.2.5",
207
207
  ngImport: i0,
208
208
  type: LtSeoService,
209
209
  decorators: [{ type: Service }]
@@ -262,7 +262,7 @@ var LtStorageService = class LtStorageService {
262
262
  }
263
263
  static ɵfac = i0.ɵɵngDeclareFactory({
264
264
  minVersion: "12.0.0",
265
- version: "22.2.4",
265
+ version: "22.2.5",
266
266
  ngImport: i0,
267
267
  type: LtStorageService,
268
268
  deps: [],
@@ -270,14 +270,14 @@ var LtStorageService = class LtStorageService {
270
270
  });
271
271
  static ɵprov = i0.ɵɵngDeclareService({
272
272
  minVersion: "22.0.0",
273
- version: "22.2.4",
273
+ version: "22.2.5",
274
274
  ngImport: i0,
275
275
  type: LtStorageService
276
276
  });
277
277
  };
278
278
  i0.ɵɵngDeclareClassMetadata({
279
279
  minVersion: "12.0.0",
280
- version: "22.2.4",
280
+ version: "22.2.5",
281
281
  ngImport: i0,
282
282
  type: LtStorageService,
283
283
  decorators: [{ type: Service }]
@@ -181,6 +181,15 @@ var LtApiUrlService = class LtApiUrlService {
181
181
  const normalized = path.startsWith("/") ? path : `/${path}`;
182
182
  return `${this.resolveAndWarn().baseUrl}${normalized}`;
183
183
  }
184
+ buildBrowserUrl(path) {
185
+ if (isLtAbsoluteUrl(path)) return path;
186
+ return `${resolveLtApiBaseUrl({
187
+ apiProxy: this.runtimeConfig?.apiProxy ?? null,
188
+ apiUrl: this.runtimeConfig?.apiUrl ?? "",
189
+ devMode: isDevMode(),
190
+ scope: "browser"
191
+ }).baseUrl}${path.startsWith("/") ? path : `/${path}`}`;
192
+ }
184
193
  isProxy() {
185
194
  return this.resolve().proxy;
186
195
  }
@@ -197,7 +206,7 @@ var LtApiUrlService = class LtApiUrlService {
197
206
  }
198
207
  static ɵfac = i0.ɵɵngDeclareFactory({
199
208
  minVersion: "12.0.0",
200
- version: "22.2.4",
209
+ version: "22.2.5",
201
210
  ngImport: i0,
202
211
  type: LtApiUrlService,
203
212
  deps: [],
@@ -205,14 +214,14 @@ var LtApiUrlService = class LtApiUrlService {
205
214
  });
206
215
  static ɵprov = i0.ɵɵngDeclareService({
207
216
  minVersion: "22.0.0",
208
- version: "22.2.4",
217
+ version: "22.2.5",
209
218
  ngImport: i0,
210
219
  type: LtApiUrlService
211
220
  });
212
221
  };
213
222
  i0.ɵɵngDeclareClassMetadata({
214
223
  minVersion: "12.0.0",
215
- version: "22.2.4",
224
+ version: "22.2.5",
216
225
  ngImport: i0,
217
226
  type: LtApiUrlService,
218
227
  decorators: [{ type: Service }]
@@ -264,7 +273,7 @@ var LtCookieService = class LtCookieService {
264
273
  }
265
274
  static ɵfac = i0.ɵɵngDeclareFactory({
266
275
  minVersion: "12.0.0",
267
- version: "22.2.4",
276
+ version: "22.2.5",
268
277
  ngImport: i0,
269
278
  type: LtCookieService,
270
279
  deps: [],
@@ -272,14 +281,14 @@ var LtCookieService = class LtCookieService {
272
281
  });
273
282
  static ɵprov = i0.ɵɵngDeclareService({
274
283
  minVersion: "22.0.0",
275
- version: "22.2.4",
284
+ version: "22.2.5",
276
285
  ngImport: i0,
277
286
  type: LtCookieService
278
287
  });
279
288
  };
280
289
  i0.ɵɵngDeclareClassMetadata({
281
290
  minVersion: "12.0.0",
282
- version: "22.2.4",
291
+ version: "22.2.5",
283
292
  ngImport: i0,
284
293
  type: LtCookieService,
285
294
  decorators: [{ type: Service }]
@@ -322,14 +331,8 @@ const ltCredentialsFetch = (input, init) => fetch(input, {
322
331
  credentials: "include",
323
332
  ...init
324
333
  });
325
- var de_default = { lt: { "error": {
326
- "title": "Fehler",
327
- "loadFailed": "Fehlerübersetzungen konnten nicht geladen werden"
328
- } } };
329
- var en_default = { lt: { "error": {
330
- "title": "Error",
331
- "loadFailed": "Failed to load error translations"
332
- } } };
334
+ var de_default = { lt: { "error": { "title": "Fehler" } } };
335
+ var en_default = { lt: { "error": { "title": "Error" } } };
333
336
  const LT_I18N_ADAPTER = new InjectionToken("LT_I18N_ADAPTER");
334
337
  const LT_I18N_OPTIONS = new InjectionToken("LT_I18N_OPTIONS", { factory: () => ({}) });
335
338
  const LT_I18N_MESSAGES = {
@@ -372,7 +375,7 @@ var LtI18nService = class LtI18nService {
372
375
  }
373
376
  static ɵfac = i0.ɵɵngDeclareFactory({
374
377
  minVersion: "12.0.0",
375
- version: "22.2.4",
378
+ version: "22.2.5",
376
379
  ngImport: i0,
377
380
  type: LtI18nService,
378
381
  deps: [],
@@ -380,14 +383,14 @@ var LtI18nService = class LtI18nService {
380
383
  });
381
384
  static ɵprov = i0.ɵɵngDeclareService({
382
385
  minVersion: "22.0.0",
383
- version: "22.2.4",
386
+ version: "22.2.5",
384
387
  ngImport: i0,
385
388
  type: LtI18nService
386
389
  });
387
390
  };
388
391
  i0.ɵɵngDeclareClassMetadata({
389
392
  minVersion: "12.0.0",
390
- version: "22.2.4",
393
+ version: "22.2.5",
391
394
  ngImport: i0,
392
395
  type: LtI18nService,
393
396
  decorators: [{ type: Service }]
@@ -439,7 +442,7 @@ var LtToastService = class LtToastService {
439
442
  }
440
443
  static ɵfac = i0.ɵɵngDeclareFactory({
441
444
  minVersion: "12.0.0",
442
- version: "22.2.4",
445
+ version: "22.2.5",
443
446
  ngImport: i0,
444
447
  type: LtToastService,
445
448
  deps: [],
@@ -447,14 +450,14 @@ var LtToastService = class LtToastService {
447
450
  });
448
451
  static ɵprov = i0.ɵɵngDeclareService({
449
452
  minVersion: "22.0.0",
450
- version: "22.2.4",
453
+ version: "22.2.5",
451
454
  ngImport: i0,
452
455
  type: LtToastService
453
456
  });
454
457
  };
455
458
  i0.ɵɵngDeclareClassMetadata({
456
459
  minVersion: "12.0.0",
457
- version: "22.2.4",
460
+ version: "22.2.5",
458
461
  ngImport: i0,
459
462
  type: LtToastService,
460
463
  decorators: [{ type: Service }]
@@ -537,7 +540,7 @@ var LtErrorTranslationService = class LtErrorTranslationService {
537
540
  }
538
541
  static ɵfac = i0.ɵɵngDeclareFactory({
539
542
  minVersion: "12.0.0",
540
- version: "22.2.4",
543
+ version: "22.2.5",
541
544
  ngImport: i0,
542
545
  type: LtErrorTranslationService,
543
546
  deps: [],
@@ -545,14 +548,14 @@ var LtErrorTranslationService = class LtErrorTranslationService {
545
548
  });
546
549
  static ɵprov = i0.ɵɵngDeclareService({
547
550
  minVersion: "22.0.0",
548
- version: "22.2.4",
551
+ version: "22.2.5",
549
552
  ngImport: i0,
550
553
  type: LtErrorTranslationService
551
554
  });
552
555
  };
553
556
  i0.ɵɵngDeclareClassMetadata({
554
557
  minVersion: "12.0.0",
555
- version: "22.2.4",
558
+ version: "22.2.5",
556
559
  ngImport: i0,
557
560
  type: LtErrorTranslationService,
558
561
  decorators: [{ type: Service }]
@@ -582,7 +585,7 @@ function messageOf(value) {
582
585
  if (nested && typeof nested === "object") return messageOf(nested);
583
586
  return "";
584
587
  }
585
- const LT_NG_BASE_VERSION = "22.0.4";
588
+ const LT_NG_BASE_VERSION = "22.1.0";
586
589
  const LT_HYDRATED_FLAG = "__ltNgBaseHydrated";
587
590
  function provideLtNgBase(config = {}) {
588
591
  return makeEnvironmentProviders([
@@ -1 +1 @@
1
- {"version":3,"file":"lenne.tech-ng-base.mjs","names":[],"sources":["../../../projects/ng-base/src/lib/warn-once.ts","../../../projects/ng-base/src/lib/pre-hydration-input.ts","../../../projects/ng-base/src/lib/runtime-config.ts","../../../projects/ng-base/src/lib/api-url.ts","../../../projects/ng-base/src/lib/cookie.ts","../../../projects/ng-base/src/lib/crypto.ts","../../../projects/ng-base/src/lib/fetch.ts","../tmp-esm2022/lib/i18n/de.json","../tmp-esm2022/lib/i18n/en.json","../../../projects/ng-base/src/lib/i18n.ts","../../../projects/ng-base/src/lib/toast.ts","../../../projects/ng-base/src/lib/error-translation.ts","../../../projects/ng-base/src/lib/version.ts","../../../projects/ng-base/src/lib/provide-lt-ng-base.ts","../../../projects/ng-base/src/lib/tw.ts"],"sourcesContent":["const warnedKeys = new Set<string>();\n\n/**\n * Log `message` the first time `key` is seen; ignore later calls. The conditions behind these messages (missing API\n * URL, implicit dev proxy) are constant for the process, so repeating them only drowns other output.\n */\nexport function warnLtOnce(key: string, message: string, level: 'error' | 'warn' = 'warn'): void {\n if (warnedKeys.has(key)) {\n return;\n }\n warnedKeys.add(key);\n console[level](message);\n}\n\n/** Test only: forget which one-shot messages were emitted. */\nexport function resetLtWarnOnceState(): void {\n warnedKeys.clear();\n}\n","import { isPlatformBrowser } from '@angular/common';\nimport { ApplicationRef, inject, PLATFORM_ID, provideAppInitializer, type EnvironmentProviders } from '@angular/core';\n\n/** Options of the pre-hydration input preservation (`provideLtNgBase({ preHydrationInput })`). */\nexport interface LtPreHydrationInputOptions {\n /** Keep what users type before hydration (default `true`). */\n enabled?: boolean;\n /**\n * How long after hydration to keep restoring, in milliseconds (default `1500`; `0` restores once). Clamped to 30000.\n * When it elapses the snapshot is dropped, so preserved values (passwords included) are not kept for the session.\n */\n maxRestoreMs?: number;\n}\n\ntype LtEditableField = HTMLInputElement | HTMLTextAreaElement;\n\n/** Every `input`/`textarea` under `root` whose value differs from its server-rendered default, with that value. */\nexport function collectLtEditedFields(root: ParentNode): Map<LtEditableField, string> {\n const edited = new Map<LtEditableField, string>();\n for (const node of Array.from(root.querySelectorAll('input, textarea'))) {\n const field = node as LtEditableField;\n if (field.value !== field.defaultValue) {\n edited.set(field, field.value);\n }\n }\n return edited;\n}\n\n/**\n * Write `value` back into `field` and dispatch a bubbling `input` event, so `(input)` handlers, `model()` and Signal\n * Forms adopt it. Returns `false` when the field is detached or already holds the value.\n */\nexport function restoreLtField(field: LtEditableField, value: string): boolean {\n if (!field.isConnected || field.value === value) {\n return false;\n }\n field.value = value;\n field.dispatchEvent(new Event('input', { bubbles: true }));\n return true;\n}\n\n/**\n * Pre-hydration input preservation (browser only).\n *\n * Text typed into a server-rendered field before hydration is in the DOM, but the first change detection after\n * hydration writes the component's (empty) value over it — `[value]` bindings and Signal Forms do — before the replayed\n * events run, so `withEventReplay()` alone loses it (measured in the ng-base playground E2E). The fields are snapshot\n * at app initialisation (the SSR DOM is reused by hydration, so the element references stay valid) and restored once\n * the app is stable, then every 250 ms for `maxRestoreMs` for fields hydrated late; fields stay ordinary editable\n * fields throughout (autofill and screen readers untouched).\n */\nexport function provideLtPreHydrationInput(options: LtPreHydrationInputOptions = {}): EnvironmentProviders {\n return provideAppInitializer(() => {\n if (options.enabled === false || !isPlatformBrowser(inject(PLATFORM_ID)) || typeof document === 'undefined') {\n return;\n }\n const edited = collectLtEditedFields(document);\n if (edited.size === 0) {\n return;\n }\n const configured = options.maxRestoreMs ?? 1500;\n const maxRestoreMs = Number.isFinite(configured) && configured > 0 ? Math.min(configured, 30_000) : 0;\n const sweep = (): void => {\n for (const [field, value] of edited) {\n if (restoreLtField(field, value) || !field.isConnected) {\n edited.delete(field);\n }\n }\n };\n void inject(ApplicationRef)\n .whenStable()\n .then(() => {\n sweep();\n if (maxRestoreMs <= 0 || edited.size === 0) {\n edited.clear();\n return;\n }\n const interval = setInterval(sweep, 250);\n setTimeout(() => {\n clearInterval(interval);\n edited.clear();\n }, maxRestoreMs);\n });\n });\n}\n\n/**\n * Inline script (for `<head>`) that blocks the native submission of forms without `action` until the app handles them.\n * A server-rendered login form submitted before hydration would otherwise send a native GET with the password in the\n * URL. `ltAngularRequestHandler()` writes it into every SSR HTML response; add it to `index.html` yourself without SSR.\n */\nexport const LT_PRE_HYDRATION_SUBMIT_GUARD_SCRIPT =\n \"document.addEventListener('submit',function(e){var f=e.target;if(f instanceof HTMLFormElement&&!f.hasAttribute('action')){e.preventDefault();}},true);\";\n","import { inject, InjectionToken, REQUEST_CONTEXT } from '@angular/core';\n\nimport { LT_PRE_HYDRATION_SUBMIT_GUARD_SCRIPT } from './pre-hydration-input';\n\n/**\n * Feature options that can be overridden per stage at runtime (`NG_PUBLIC_LT_<FEATURE>_<OPTION>`).\n *\n * Each feature provider (`provideLtAuth`, `provideLtFiles`, `provideLtAi`, `provideLtSync`, `provideLtNgBase`)\n * merges, in this order: its defaults, the options passed in code, and the values found here.\n */\nexport interface LtPublicFeatureConfig {\n ai?: Record<string, unknown>;\n auth?: Record<string, unknown>;\n errorTranslation?: Record<string, unknown>;\n sync?: Record<string, unknown>;\n tus?: Record<string, unknown>;\n [feature: string]: Record<string, unknown> | undefined;\n}\n\n/**\n * Public runtime configuration of the app, the Angular counterpart of Nuxt's `runtimeConfig.public`.\n *\n * With SSR the server reads it per request from the `NG_*` environment (`readLtRequestContext()` in\n * `@lenne.tech/ng-base/server`), passes it to `AngularNodeAppEngine.handle(req, context)` as request context\n * (`REQUEST_CONTEXT`) and writes it as JSON `<script id=\"ng-runtime-config\">` into every HTML response, also for\n * `RenderMode.Client` routes; the browser reads that script. One build can therefore be promoted from stage to stage.\n * Without SSR the values come from `provideLtNgBase({ runtime })`.\n *\n * Projects may carry additional public values (e.g. `plausibleApiHost`); they travel the same way.\n * Never put a secret here: everything in this object reaches the browser.\n */\nexport interface LtRuntimeConfig {\n [key: string]: unknown;\n /** Commit of the running build (`NG_PUBLIC_APP_COMMIT`, fallback `APP_VERSION_COMMIT`), `unknown` when unset. */\n appCommit?: string;\n /**\n * Deployment stage (`NG_PUBLIC_APP_ENV`), using nest-server's NODE_ENV block names: `local`, `ci`, `e2e`, `develop`,\n * `test`, `production`. Only `production` counts as production; features that are off in production fail closed.\n */\n appEnv?: string;\n /** Version of the running build (from the server, e.g. package.json). */\n appVersion?: string;\n /** Public API base URL (`NG_PUBLIC_API_URL`), e.g. `https://api.example.com`. Empty = relative to the app origin. */\n apiUrl: string;\n /**\n * Route browser API calls through the dev-server proxy under `/api` (`NG_PUBLIC_API_PROXY`).\n * `null` = not configured: the proxy is used in dev mode (`isDevMode()`) with a one-time warning.\n * Never used during SSR.\n */\n apiProxy: boolean | null;\n /** Opt-in cookie namespace (`NG_PUBLIC_COOKIE_PREFIX`); must mirror the backend `COOKIE_PREFIX`. */\n cookiePrefix: string;\n /** Feature options overridden at runtime (`NG_PUBLIC_LT_*`). */\n lt: LtPublicFeatureConfig;\n /** Absolute public URL of the app (`NG_PUBLIC_SITE_URL`), used for redirect/callback URLs, SEO and security.txt. */\n siteUrl: string;\n /** Prefix for `localStorage` keys (`NG_PUBLIC_STORAGE_PREFIX`). */\n storagePrefix: string;\n}\n\n/** Defaults of {@link LtRuntimeConfig}. */\nexport const LT_RUNTIME_CONFIG_DEFAULTS: LtRuntimeConfig = {\n apiProxy: null,\n apiUrl: '',\n cookiePrefix: '',\n lt: {},\n siteUrl: '',\n storagePrefix: '',\n};\n\n/** The resolved public runtime configuration (defaults ← `provideLtNgBase({ runtime })` ← request context / `<script id=\"ng-runtime-config\">`). */\nexport const LT_RUNTIME_CONFIG = new InjectionToken<LtRuntimeConfig>('LT_RUNTIME_CONFIG');\n\n/** What the SSR server passes to `AngularNodeAppEngine.handle(req, context)` (see `readLtRequestContext()`). */\nexport interface LtRequestContext {\n /** Public runtime configuration (also written into the HTML as `<script id=\"ng-runtime-config\">`). */\n runtimeConfig: Partial<LtRuntimeConfig>;\n /** Internal API URL for SSR requests only (`NG_API_URL`), never sent to the browser. */\n serverApiUrl?: string;\n}\n\n/**\n * Runtime configuration on the server: public part plus the server-only API URL. Read from `REQUEST_CONTEXT`\n * (an {@link LtRequestContext}) by default; `provideLtServerRuntimeConfig()` provides it from the environment instead\n * for servers that pass no request context. `null` in the browser.\n */\nexport interface LtServerRuntimeConfig {\n /** Public part. */\n public: Partial<LtRuntimeConfig>;\n /** Internal API URL for SSR requests only (`NG_API_URL`), never sent to the browser. */\n serverApiUrl: string;\n}\n\n/** Server-only runtime configuration (see {@link LtServerRuntimeConfig}). `null` in the browser. */\nexport const LT_SERVER_RUNTIME_CONFIG = new InjectionToken<LtServerRuntimeConfig | null>('LT_SERVER_RUNTIME_CONFIG', {\n factory: () => {\n const context = inject(REQUEST_CONTEXT, { optional: true }) as Partial<LtRequestContext> | null;\n if (!context || typeof context !== 'object' || !context.runtimeConfig) {\n return null;\n }\n return { public: context.runtimeConfig, serverApiUrl: context.serverApiUrl ?? '' };\n },\n});\n\n/** Id of the JSON `<script>` that carries the public runtime configuration into the browser. */\nexport const LT_RUNTIME_CONFIG_SCRIPT_ID = 'ng-runtime-config';\n\n/** Read the runtime configuration the server wrote into the document (`null` when missing or unreadable). */\nexport function readLtRuntimeConfigFromDocument(doc: Document | null | undefined): Partial<LtRuntimeConfig> | null {\n const text = doc?.getElementById?.(LT_RUNTIME_CONFIG_SCRIPT_ID)?.textContent;\n if (!text) {\n return null;\n }\n try {\n const parsed: unknown = JSON.parse(text);\n return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? (parsed as Partial<LtRuntimeConfig>) : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Serialise the public runtime configuration for an inline `<script type=\"application/json\">`: `<`, `>`, `&`, U+2028\n * and U+2029 are escaped, so a value can never close the script element, open a comment or form an HTML entity.\n */\nexport function serializeLtRuntimeConfig(config: Partial<LtRuntimeConfig>): string {\n return JSON.stringify(config)\n .replace(/</g, '\\\\u003c')\n .replace(/>/g, '\\\\u003e')\n .replace(/&/g, '\\\\u0026')\n .replace(/\\u2028/g, '\\\\u2028')\n .replace(/\\u2029/g, '\\\\u2029');\n}\n\n/**\n * Insert the runtime configuration as the first child of `<head>` (documents without `<head>` stay untouched), by\n * default preceded by the pre-hydration submit guard (`LT_PRE_HYDRATION_SUBMIT_GUARD_SCRIPT`).\n */\nexport function injectLtRuntimeConfigScript(html: string, config: Partial<LtRuntimeConfig>, options: { submitGuard?: boolean } = {}): string {\n const head = /<head(\\s[^>]*)?>/i.exec(html);\n if (!head) {\n return html;\n }\n const at = head.index + head[0].length;\n const guard = options.submitGuard === false ? '' : `<script>${LT_PRE_HYDRATION_SUBMIT_GUARD_SCRIPT}</script>`;\n return `${html.slice(0, at)}${guard}<script id=\"${LT_RUNTIME_CONFIG_SCRIPT_ID}\" type=\"application/json\">${serializeLtRuntimeConfig(config)}</script>${html.slice(at)}`;\n}\n\n/**\n * Merge partial runtime configurations onto a base. `lt` is merged per feature; `undefined` values never\n * override (an unset env variable keeps the code default).\n */\nexport function mergeLtRuntimeConfig(base: LtRuntimeConfig, ...overrides: (Partial<LtRuntimeConfig> | null | undefined)[]): LtRuntimeConfig {\n const result: LtRuntimeConfig = { ...base, lt: { ...base.lt } };\n for (const override of overrides) {\n if (!override) {\n continue;\n }\n for (const [key, value] of Object.entries(override) as [keyof LtRuntimeConfig, unknown][]) {\n if (value === undefined) {\n continue;\n }\n if (key === 'lt') {\n for (const [feature, options] of Object.entries((value ?? {}) as LtPublicFeatureConfig)) {\n result.lt[feature] = { ...result.lt[feature], ...definedEntries(options ?? {}) };\n }\n continue;\n }\n (result as unknown as Record<string, unknown>)[key] = value;\n }\n }\n return result;\n}\n\n/**\n * Merge feature options: defaults ← code options ← runtime overrides. Nested plain objects are merged one level\n * deep (e.g. `auth.interceptor`), arrays and primitives replace. `undefined` never overrides.\n */\nexport function mergeLtFeatureOptions<T extends object>(defaults: T, ...overrides: (object | null | undefined)[]): T {\n const result: Record<string, unknown> = { ...(defaults as Record<string, unknown>) };\n for (const override of overrides) {\n if (!override) {\n continue;\n }\n for (const [key, value] of Object.entries(override)) {\n if (value === undefined) {\n continue;\n }\n const current = result[key];\n result[key] = isPlainObject(current) && isPlainObject(value) ? { ...current, ...definedEntries(value) } : value;\n }\n }\n return result as T;\n}\n\nfunction definedEntries(source: object): Record<string, unknown> {\n return Object.fromEntries(Object.entries(source).filter(([, value]) => value !== undefined));\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","import { isPlatformServer } from '@angular/common';\nimport { inject, isDevMode, PLATFORM_ID, Service } from '@angular/core';\n\nimport { warnLtOnce } from './warn-once';\nimport { LT_RUNTIME_CONFIG, LT_SERVER_RUNTIME_CONFIG } from './runtime-config';\n\n/** Render scope an API URL is resolved for. */\nexport type LtRenderScope = 'browser' | 'server';\n\n/** Outcome of resolving the API base URL for the current render scope. */\nexport interface LtApiUrlResolution {\n /** Base URL to prefix onto API paths: `'/api'` in proxy mode, `''` when unresolved. No trailing slash. */\n baseUrl: string;\n /** `true` when no API URL is configured for {@link scope}. */\n missing: boolean;\n /** `true` when the dev-server proxy prefix `/api` is in use. */\n proxy: boolean;\n /** Scope the resolution was performed for. */\n scope: LtRenderScope;\n}\n\n/** Inputs of {@link resolveLtApiBaseUrl}. */\nexport interface LtApiUrlInputs {\n /** `NG_PUBLIC_API_PROXY` (`null` = unset). */\n apiProxy: boolean | null;\n /** `NG_PUBLIC_API_URL`. */\n apiUrl: string;\n /** Whether the app runs in dev mode (`isDevMode()`), used when `apiProxy` is unset. */\n devMode: boolean;\n /** Render scope. */\n scope: LtRenderScope;\n /** `NG_API_URL` (server only). */\n serverApiUrl?: string;\n}\n\nconst MISSING_API_URL_WARNING: Record<LtRenderScope, string> = {\n browser:\n '[@lenne.tech/ng-base] No API URL configured. Set NG_PUBLIC_API_URL. API paths stay relative and resolve against the app ' +\n 'origin, so auth and setup calls 404 unless the app is served behind a same-origin reverse proxy.',\n server:\n '[@lenne.tech/ng-base] No API URL configured for SSR. Set NG_API_URL or NG_PUBLIC_API_URL. API paths stay relative, so ' + 'server-side requests never reach the backend.',\n};\n\n/**\n * Pure resolution of the API base URL (no DI, no logging).\n *\n * - Server: `NG_API_URL` → `NG_PUBLIC_API_URL` → `''`. The proxy is never used during SSR.\n * - Browser: `/api` when the proxy is on (explicitly, or implicitly in dev mode while unset), else `NG_PUBLIC_API_URL` → `''`.\n *\n * Trailing slashes are stripped so `${baseUrl}${path}` never produces a double slash.\n */\nexport function resolveLtApiBaseUrl(inputs: LtApiUrlInputs): LtApiUrlResolution {\n if (inputs.scope === 'server') {\n const apiUrl = inputs.serverApiUrl || inputs.apiUrl || '';\n return { baseUrl: stripTrailingSlashes(apiUrl), missing: !apiUrl, proxy: false, scope: 'server' };\n }\n if (inputs.apiProxy === true || (inputs.apiProxy === null && inputs.devMode)) {\n return { baseUrl: '/api', missing: false, proxy: true, scope: 'browser' };\n }\n const apiUrl = inputs.apiUrl || '';\n return { baseUrl: stripTrailingSlashes(apiUrl), missing: !apiUrl, proxy: false, scope: 'browser' };\n}\n\n/** Whether `url` is absolute (`scheme:` or protocol-relative `//`). */\nexport function isLtAbsoluteUrl(url: string): boolean {\n return /^[a-z][a-z\\d+\\-.]*:/i.test(url) || url.startsWith('//');\n}\n\n/**\n * The single URL builder used by auth, system setup, error translation, files, AI and sync.\n *\n * Reads {@link LT_RUNTIME_CONFIG} and, on the server, {@link LT_SERVER_RUNTIME_CONFIG}. A missing API URL is warned\n * about once per scope; an implicit dev proxy (unset `NG_PUBLIC_API_PROXY` in dev mode) once as well.\n */\n@Service()\nexport class LtApiUrlService {\n private readonly runtimeConfig = inject(LT_RUNTIME_CONFIG, { optional: true });\n private readonly serverConfig = inject(LT_SERVER_RUNTIME_CONFIG, { optional: true });\n private readonly isServer = isPlatformServer(inject(PLATFORM_ID));\n\n /** Resolve the base URL for the current scope without logging. */\n resolve(): LtApiUrlResolution {\n return resolveLtApiBaseUrl({\n apiProxy: this.runtimeConfig?.apiProxy ?? null,\n apiUrl: this.runtimeConfig?.apiUrl ?? '',\n devMode: isDevMode(),\n scope: this.isServer ? 'server' : 'browser',\n serverApiUrl: this.serverConfig?.serverApiUrl,\n });\n }\n\n /** Base URL (no trailing slash) for the current scope. */\n baseUrl(): string {\n return this.resolveAndWarn().baseUrl;\n }\n\n /** Build a full API URL for a path such as `/iam/sign-in/email`. Absolute URLs are returned unchanged. */\n buildUrl(path: string): string {\n if (isLtAbsoluteUrl(path)) {\n return path;\n }\n const normalized = path.startsWith('/') ? path : `/${path}`;\n return `${this.resolveAndWarn().baseUrl}${normalized}`;\n }\n\n /** Whether browser requests go through the dev-server proxy under `/api`. Always `false` on the server. */\n isProxy(): boolean {\n return this.resolve().proxy;\n }\n\n /** Report a missing API URL (`dev`: warning, production: error), at most once per scope. Used by the config check. */\n reportMissing(): boolean {\n const resolution = this.resolve();\n if (resolution.missing) {\n warnLtOnce(`missing-api-url:${resolution.scope}`, MISSING_API_URL_WARNING[resolution.scope], isDevMode() ? 'warn' : 'error');\n }\n return resolution.missing;\n }\n\n private resolveAndWarn(): LtApiUrlResolution {\n const resolution = this.resolve();\n if (resolution.missing) {\n warnLtOnce(`missing-api-url:${resolution.scope}`, MISSING_API_URL_WARNING[resolution.scope]);\n }\n if (resolution.proxy && this.runtimeConfig?.apiProxy === null) {\n warnLtOnce(\n 'api-proxy-implicit',\n '[@lenne.tech/ng-base] API proxy (/api) activated implicitly because the app runs in dev mode. ' +\n 'Set NG_PUBLIC_API_PROXY=true to make it explicit, or NG_PUBLIC_API_PROXY=false to call the API directly.',\n );\n }\n return resolution;\n }\n}\n\nfunction stripTrailingSlashes(url: string): string {\n return url.replace(/\\/+$/, '');\n}\n","import { DOCUMENT, isPlatformServer } from '@angular/common';\nimport { inject, PLATFORM_ID, REQUEST, Service } from '@angular/core';\n\n/** Options for {@link LtCookieService.set}. */\nexport interface LtCookieOptions {\n /** Cookie domain. Omit for a host-only cookie. */\n domain?: string;\n /** Lifetime in seconds. Omit for a session cookie. */\n maxAge?: number;\n /** Cookie path (default `/`). */\n path?: string;\n /** SameSite attribute (default `lax`). */\n sameSite?: 'lax' | 'none' | 'strict';\n /** Secure attribute (default: `true` on `https:`). */\n secure?: boolean;\n}\n\n/**\n * SSR-aware cookie access.\n *\n * - Browser: reads and writes `document.cookie`.\n * - Server: reads the `Cookie` header of the incoming request (`REQUEST`); never writes. A server render must not\n * set auth cookies (it would write `{ user: null }` over a valid browser state), so `set`/`delete` are no-ops there.\n */\n@Service()\nexport class LtCookieService {\n private readonly document = inject(DOCUMENT);\n private readonly request = inject(REQUEST, { optional: true });\n private readonly isServer = isPlatformServer(inject(PLATFORM_ID));\n\n /** Raw cookie string (`a=1; b=2`) of the current request or document. */\n raw(): string {\n if (this.isServer) {\n return this.request?.headers.get('cookie') ?? '';\n }\n try {\n return this.document.cookie ?? '';\n } catch {\n return '';\n }\n }\n\n /** First decoded value of `name`, or `null`. */\n get(name: string): string | null {\n return this.getAll(name)[0] ?? null;\n }\n\n /**\n * Every decoded value of `name`, in header order. A host-only cookie and a domain-scoped twin can coexist; callers\n * that must pick the right one (the auth state) look at all of them.\n */\n getAll(name: string): string[] {\n return parseLtCookies(this.raw(), name);\n }\n\n /** Write a cookie (browser only). The value is URI-encoded. */\n set(name: string, value: string, options: LtCookieOptions = {}): void {\n if (this.isServer) {\n return;\n }\n const secure = options.secure ?? this.document.location?.protocol === 'https:';\n const parts = [`${name}=${encodeURIComponent(value)}`, `path=${options.path ?? '/'}`, `samesite=${options.sameSite ?? 'lax'}`];\n if (options.maxAge !== undefined) {\n parts.push(`max-age=${Math.max(0, Math.floor(options.maxAge))}`);\n }\n if (options.domain) {\n parts.push(`domain=${options.domain}`);\n }\n if (secure) {\n parts.push('secure');\n }\n this.document.cookie = parts.join('; ');\n }\n\n /** Delete a cookie on the given path/domain slot (browser only). */\n delete(name: string, options: Pick<LtCookieOptions, 'domain' | 'path'> = {}): void {\n if (this.isServer) {\n return;\n }\n const parts = [`${name}=`, `path=${options.path ?? '/'}`, 'expires=Thu, 01 Jan 1970 00:00:00 GMT', 'max-age=0'];\n if (options.domain) {\n parts.push(`domain=${options.domain}`);\n }\n this.document.cookie = parts.join('; ');\n }\n}\n\n/** Parse every value of cookie `name` out of a raw cookie string (decoded; malformed encodings are kept raw). */\nexport function parseLtCookies(cookieString: string, name: string): string[] {\n const prefix = `${name}=`;\n const values: string[] = [];\n for (const entry of (cookieString || '').split(/;\\s*/)) {\n if (!entry.startsWith(prefix)) {\n continue;\n }\n const value = entry.slice(prefix.length);\n try {\n values.push(decodeURIComponent(value));\n } catch {\n values.push(value);\n }\n }\n return values;\n}\n","/**\n * SHA-256 of a string as lowercase hex (WebCrypto).\n *\n * nest-server expects every password to arrive SHA-256 hashed (it re-hashes server-side). The auth service applies\n * this to each credential field; use it yourself only for custom endpoints that follow the same rule. Because the\n * hash hides the length, enforce password rules in the form, not on the server.\n */\nexport async function ltSha256(message: string): Promise<string> {\n const data = new TextEncoder().encode(message);\n const hash = await crypto.subtle.digest('SHA-256', data);\n return Array.from(new Uint8Array(hash), (byte) => byte.toString(16).padStart(2, '0')).join('');\n}\n\n/** Encode bytes as base64url without padding (WebAuthn). */\nexport function ltArrayBufferToBase64Url(buffer: ArrayBuffer | Uint8Array): string {\n const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);\n let binary = '';\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\n/** Decode base64url (with or without padding) into bytes (WebAuthn). */\nexport function ltBase64UrlToUint8Array(base64url: string): Uint8Array<ArrayBuffer> {\n const base64 = base64url.replace(/-/g, '+').replace(/_/g, '/');\n const padded = base64 + '='.repeat((4 - (base64.length % 4)) % 4);\n const binary = atob(padded);\n const bytes = new Uint8Array(new ArrayBuffer(binary.length));\n for (let index = 0; index < binary.length; index++) {\n bytes[index] = binary.charCodeAt(index);\n }\n return bytes;\n}\n","import { InjectionToken } from '@angular/core';\n\n/** A `fetch`-compatible function. */\nexport type LtFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;\n\n/**\n * The fetch used by every library call that does not go through `HttpClient`: error translation, system setup,\n * AI (incl. the SSE stream), offline sync and its hint stream, the Better Auth client.\n *\n * The default sends cookies (`credentials: 'include'`). `provideLtAuth()` replaces it with the auth-aware fetch\n * (Bearer token in JWT mode, cookie → JWT switch on 401, stale-JWT refresh, session-loss handling), so SSE and sync\n * get the same auth behaviour as `HttpClient` calls behind `ltAuthInterceptor`.\n */\nexport const LT_FETCH = new InjectionToken<LtFetch>('LT_FETCH', {\n factory: () => ltCredentialsFetch,\n});\n\n/** `fetch` with `credentials: 'include'` unless the caller decided otherwise. */\nexport const ltCredentialsFetch: LtFetch = (input, init) => fetch(input, { credentials: 'include', ...init });\n","","","import { isPlatformBrowser } from '@angular/common';\nimport { computed, inject, InjectionToken, PLATFORM_ID, Service, signal, type Signal } from '@angular/core';\n\nimport de from './i18n/de.json';\nimport en from './i18n/en.json';\n\n/** Nested message tree as in the shipped `i18n/de.json` / `i18n/en.json`. */\nexport interface LtI18nMessages {\n [key: string]: LtI18nMessages | string;\n}\n\n/**\n * Bridge to the app's translation library (Transloco, ngx-translate, …).\n *\n * Bind it when the app already has an i18n setup, so library texts follow the app language and can be overridden\n * in the app's own translation files (keys `lt.error.*` of the core and `lt.<entry>.*` of the entry points: `lt.auth.*`,\n * `lt.files.*`, `lt.share.*`, `lt.ui.*`, `lt.bug.*`; shipped as `i18n/{de,en}.json` and `i18n/<entry>/{de,en}.json`).\n *\n * @example Transloco\n * { provide: LT_I18N_ADAPTER, useFactory: () => {\n * const transloco = inject(TranslocoService);\n * const lang = toSignal(transloco.langChanges$, { initialValue: transloco.getActiveLang() });\n * return { locale: lang, translate: (key, params) => transloco.translate(key, params) };\n * } }\n */\nexport interface LtI18nAdapter {\n /** Active locale (`de`, `en`, …). */\n readonly locale: Signal<string>;\n /** Translate a key; return `null` (or the key itself) when the app has no translation, then the library text is used. */\n translate(key: string, params?: Record<string, unknown>): string | null;\n}\n\n/** Optional adapter to the app's i18n library. */\nexport const LT_I18N_ADAPTER = new InjectionToken<LtI18nAdapter>('LT_I18N_ADAPTER');\n\n/** Options of the built-in i18n (part of `provideLtNgBase({ i18n })`). */\nexport interface LtI18nOptions {\n /** Locale used when neither the adapter nor the browser language (de/en) decides. Default `de`. */\n defaultLocale?: string;\n /** Additional or overriding messages per locale, merged over the shipped de/en texts. */\n messages?: Record<string, LtI18nMessages>;\n}\n\n/** i18n options token (set by `provideLtNgBase`). */\nexport const LT_I18N_OPTIONS = new InjectionToken<LtI18nOptions>('LT_I18N_OPTIONS', { factory: () => ({}) });\n\n/** The core's shipped messages (`lt.error.*`); the entry points register theirs with `registerLibraryMessages()`. */\nexport const LT_I18N_MESSAGES: Readonly<Record<'de' | 'en', LtI18nMessages>> = { de, en };\n\n/**\n * Signal-based translations for library texts, with an optional adapter to the app's i18n library.\n *\n * Lookup order for `t(key)`: adapter → messages of the active locale → German messages → the key.\n * Locale order: adapter → `setLocale()` → browser language (de/en, browser only) → `defaultLocale` → `de`.\n */\n@Service()\nexport class LtI18nService {\n private readonly adapter = inject(LT_I18N_ADAPTER, { optional: true });\n private readonly options = inject(LT_I18N_OPTIONS);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n private readonly explicitLocale = signal<string | null>(null);\n private readonly extraMessages = signal<Record<string, LtI18nMessages>>(this.options.messages ?? {});\n /**\n * Texts of the entry points (`lt.ui.*`, `lt.auth.*` …) registered by {@link registerLibraryMessages}. A plain object:\n * every entry registers its texts before its own components read them, so nothing has to react to a registration.\n */\n private readonly libraryMessages: Record<string, LtI18nMessages> = {};\n private readonly libraryIds = new Set<string>();\n\n /** Active locale. */\n readonly locale = computed(() => this.adapter?.locale() || this.explicitLocale() || this.detectBrowserLocale() || this.options.defaultLocale || 'de');\n\n /** Set the locale (ignored for lookups while an adapter provides one). */\n setLocale(locale: string): void {\n this.explicitLocale.set(locale);\n }\n\n /** Merge messages for a locale over the shipped ones. */\n registerMessages(locale: string, messages: LtI18nMessages): void {\n this.extraMessages.update((current) => ({ ...current, [locale]: deepMerge(current[locale] ?? {}, messages) }));\n }\n\n /**\n * Register the default texts of an entry point once per `id` (`ui`, `auth`, `files` …). They rank below the app's\n * own texts (`provideLtNgBase({ i18n: { messages } })`, `registerMessages()`, the adapter), like the shipped core\n * texts. Entry points call it when they are first used (synchronously, on the server and in the browser alike), so\n * their texts travel with their code instead of the initial bundle.\n */\n registerLibraryMessages(id: string, messages: Readonly<Record<string, LtI18nMessages>>): void {\n if (this.libraryIds.has(id)) {\n return;\n }\n this.libraryIds.add(id);\n for (const [locale, tree] of Object.entries(messages)) {\n this.libraryMessages[locale] = deepMerge(this.libraryMessages[locale] ?? {}, tree);\n }\n }\n\n /** Translate `key`, interpolating `{name}` placeholders from `params`. */\n t(key: string, params?: Record<string, unknown>): string {\n const fromAdapter = this.adapter?.translate(key, params);\n if (fromAdapter && fromAdapter !== key) {\n return fromAdapter;\n }\n const locale = this.locale();\n const message =\n lookup(this.extraMessages()[locale], key) ??\n lookup((LT_I18N_MESSAGES as Record<string, LtI18nMessages>)[locale], key) ??\n lookup(this.libraryMessages[locale], key) ??\n lookup(this.extraMessages()['de'], key) ??\n lookup(LT_I18N_MESSAGES.de, key) ??\n lookup(this.libraryMessages['de'], key) ??\n key;\n return interpolate(message, params);\n }\n\n private detectBrowserLocale(): string | null {\n if (!this.isBrowser || typeof navigator === 'undefined' || !navigator.language) {\n return null;\n }\n const language = navigator.language.split('-')[0]?.toLowerCase() ?? '';\n return language === 'de' || language === 'en' ? language : null;\n }\n}\n\nfunction lookup(messages: LtI18nMessages | undefined, key: string): string | null {\n let node: LtI18nMessages | string | undefined = messages;\n for (const part of key.split('.')) {\n if (!node || typeof node === 'string') {\n return null;\n }\n node = node[part];\n }\n return typeof node === 'string' ? node : null;\n}\n\nfunction interpolate(message: string, params?: Record<string, unknown>): string {\n if (!params) {\n return message;\n }\n return message.replace(/\\{(\\w+)\\}/g, (match, name: string) => (name in params ? String(params[name]) : match));\n}\n\nfunction deepMerge(target: LtI18nMessages, source: LtI18nMessages): LtI18nMessages {\n const result: LtI18nMessages = { ...target };\n for (const [key, value] of Object.entries(source)) {\n const current = result[key];\n result[key] = typeof value === 'object' && typeof current === 'object' ? deepMerge(current, value) : value;\n }\n return result;\n}\n","import { inject, InjectionToken, Service } from '@angular/core';\n\n/** Toast colors (same set as Nuxt UI). */\nexport type LtToastColor = 'error' | 'info' | 'neutral' | 'primary' | 'secondary' | 'success' | 'warning';\n\n/** A toast message. */\nexport interface LtToastOptions {\n color?: LtToastColor;\n description?: string;\n /** Display time in milliseconds (adapter default when omitted). */\n duration?: number;\n title?: string;\n}\n\n/**\n * Bridge to the app's toaster. `provideLtUi()` binds it to Spartan Sonner (`<hlm-toaster />`); bind your own for\n * another UI library. Return `false` when nothing could be shown, the caller then logs to the console.\n */\nexport interface LtToastAdapter {\n show(options: LtToastOptions): boolean;\n}\n\n/** Optional toaster bridge (see {@link LtToastAdapter}). */\nexport const LT_TOAST_ADAPTER = new InjectionToken<LtToastAdapter>('LT_TOAST_ADAPTER');\n\n/** Shows toasts through {@link LT_TOAST_ADAPTER}; without an adapter, `show` returns `false`. */\n@Service()\nexport class LtToastService {\n private readonly adapter = inject(LT_TOAST_ADAPTER, { optional: true });\n\n /** Show a toast. Returns `false` when no toaster is bound or it threw. */\n show(options: LtToastOptions): boolean {\n if (!this.adapter) {\n return false;\n }\n try {\n return this.adapter.show(options) !== false;\n } catch {\n return false;\n }\n }\n\n /** Shortcut for a success toast. */\n success(title: string, description?: string): boolean {\n return this.show({ color: 'success', description, title });\n }\n\n /** Shortcut for an error toast. */\n error(title: string, description?: string): boolean {\n return this.show({ color: 'error', description, title });\n }\n}\n","import { isPlatformBrowser } from '@angular/common';\nimport { computed, inject, InjectionToken, PLATFORM_ID, Service, signal } from '@angular/core';\n\nimport { LtApiUrlService } from './api-url';\nimport { LT_FETCH } from './fetch';\nimport { LtI18nService } from './i18n';\nimport { LtToastService } from './toast';\n\n/** Response of nest-server `GET /i18n/errors/:locale`. */\nexport interface LtErrorTranslationResponse {\n errors: Record<string, string>;\n}\n\n/** Result of {@link LtErrorTranslationService.parseError}. */\nexport interface LtParsedError {\n /** Error code such as `LTNS_0100`, or `null` when the message carries none. */\n code: string | null;\n /** Message as sent by the backend (without the `#CODE:` marker). */\n developerMessage: string;\n /** Translated message for the active locale; falls back to the developer message, never empty for a message-bearing error. */\n translatedMessage: string;\n}\n\n/** Options of the error translation (part of `provideLtNgBase({ errorTranslation })`, runtime `NG_PUBLIC_LT_ERROR_TRANSLATION_*`). */\nexport interface LtErrorTranslationOptions {\n /** Locale used when i18n does not decide (default `de`). */\n defaultLocale?: string;\n /** Load and apply backend translations (default `true`). */\n enabled?: boolean;\n /** Load the translations for the detected locale while the app starts, browser only (default `true`). */\n preload?: boolean;\n}\n\n/** Resolved error translation options. */\nexport const LT_ERROR_TRANSLATION_OPTIONS = new InjectionToken<Required<LtErrorTranslationOptions>>('LT_ERROR_TRANSLATION_OPTIONS', {\n factory: () => ({ defaultLocale: 'de', enabled: true, preload: true }),\n});\n\nconst ERROR_CODE_REGEX = /^#([A-Z_]+_\\d+):\\s*(.+)$/s;\n\n/** A translation load that takes longer is aborted (the next call retries). */\nexport const LT_ERROR_TRANSLATION_TIMEOUT_MS = 10_000;\n\n/**\n * Translates nest-server error messages of the form `#LTNS_0100: Developer message` with the backend's\n * `GET /i18n/errors/:locale` table.\n */\n@Service()\nexport class LtErrorTranslationService {\n private readonly api = inject(LtApiUrlService);\n private readonly fetch = inject(LT_FETCH);\n private readonly i18n = inject(LtI18nService);\n private readonly toast = inject(LtToastService);\n private readonly options = inject(LT_ERROR_TRANSLATION_OPTIONS);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n private readonly translations = signal<Record<string, Record<string, string>>>({});\n private readonly inFlight = new Map<string, Promise<void>>();\n\n /** Locale used for lookups. */\n readonly currentLocale = computed(() => this.i18n.locale() || this.options.defaultLocale || 'de');\n /** Whether translations for the current locale are loaded. */\n readonly isLoaded = computed(() => !!this.translations()[this.currentLocale()]);\n /** Whether a load is running. */\n readonly isLoading = signal(false);\n\n /** Load the backend translations for `locale` (default: current locale). Cached per locale, one request in flight per locale. */\n async loadTranslations(locale?: string): Promise<void> {\n if (!this.options.enabled) {\n return;\n }\n const target = locale || this.currentLocale();\n if (this.translations()[target]) {\n return;\n }\n const running = this.inFlight.get(target);\n if (running) {\n return running;\n }\n const load = (async () => {\n this.isLoading.set(true);\n try {\n const response = await this.fetch(this.api.buildUrl(`/i18n/errors/${encodeURIComponent(target)}`), {\n headers: { accept: 'application/json' },\n signal: AbortSignal.timeout(LT_ERROR_TRANSLATION_TIMEOUT_MS),\n });\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}`);\n }\n const body = (await response.json()) as Partial<LtErrorTranslationResponse> | null;\n if (body?.errors && typeof body.errors === 'object') {\n this.translations.update((current) => ({ ...current, [target]: body.errors as Record<string, string> }));\n }\n } catch (error) {\n console.warn(`[@lenne.tech/ng-base] Failed to load error translations for ${target}:`, error);\n } finally {\n this.inFlight.delete(target);\n this.isLoading.set(this.inFlight.size > 0);\n }\n })();\n this.inFlight.set(target, load);\n return load;\n }\n\n /** Parse any error shape (string, `Error`, `HttpErrorResponse`, response body) into code + messages. */\n parseError(errorOrMessage: unknown): LtParsedError {\n const message = extractLtErrorMessage(errorOrMessage);\n const match = message.match(ERROR_CODE_REGEX);\n if (!match) {\n return { code: null, developerMessage: message, translatedMessage: message };\n }\n const code = match[1] ?? '';\n const developerMessage = (match[2] ?? '').trim();\n const translatedMessage = this.translations()[this.currentLocale()]?.[code] || developerMessage;\n return { code, developerMessage, translatedMessage };\n }\n\n /** Translated message for an error (never empty for a message-bearing error). */\n translateError(errorOrMessage: unknown): string {\n return this.parseError(errorOrMessage).translatedMessage;\n }\n\n /** Show the translated error as an error toast (browser only); logs to the console when no toaster is bound. */\n showErrorToast(errorOrMessage: unknown, title?: string): void {\n if (!this.isBrowser) {\n return;\n }\n const parsed = this.parseError(errorOrMessage);\n const shown = this.toast.show({ color: 'error', description: parsed.translatedMessage, title: title || this.i18n.t('lt.error.title') });\n if (!shown) {\n console.error('[@lenne.tech/ng-base]', parsed.translatedMessage);\n }\n }\n}\n\n/**\n * Extract the human-relevant message from an error.\n *\n * The response body wins over a transport message: `HttpErrorResponse.message` is\n * `Http failure response for …: 400 Bad Request`, while the backend message (the only one that can carry a\n * `#LTNS_` marker) is in `error.message`. Better Auth errors (`{ code, message }`) and arrays of messages\n * (class-validator) are handled too.\n */\nexport function extractLtErrorMessage(errorOrMessage: unknown): string {\n if (typeof errorOrMessage === 'string') {\n return errorOrMessage;\n }\n if (errorOrMessage === null || errorOrMessage === undefined) {\n return '';\n }\n if (typeof errorOrMessage !== 'object') {\n return String(errorOrMessage);\n }\n const source = errorOrMessage as Record<string, unknown>;\n for (const candidate of [source['error'], source['data'], source['body']]) {\n const fromBody = messageOf(candidate);\n if (fromBody) {\n return fromBody;\n }\n }\n return messageOf(source) || (typeof source['statusText'] === 'string' && source['statusText']) || String(errorOrMessage);\n}\n\nfunction messageOf(value: unknown): string {\n if (typeof value === 'string') {\n return value;\n }\n if (!value || typeof value !== 'object') {\n return '';\n }\n const message = (value as Record<string, unknown>)['message'];\n if (typeof message === 'string') {\n return message;\n }\n if (Array.isArray(message)) {\n return message.filter((part) => typeof part === 'string').join(', ');\n }\n const nested = (value as Record<string, unknown>)['error'];\n if (nested && typeof nested === 'object') {\n return messageOf(nested);\n }\n return '';\n}\n","/** Version of `@lenne.tech/ng-base`; kept in sync with `package.json` by `scripts/sync-version.mjs`. */\nexport const LT_NG_BASE_VERSION = '22.0.4';\n","import { DOCUMENT, isPlatformBrowser } from '@angular/common';\nimport { ApplicationRef, inject, makeEnvironmentProviders, PLATFORM_ID, provideAppInitializer, type EnvironmentProviders } from '@angular/core';\n\nimport { LtApiUrlService } from './api-url';\nimport { LT_ERROR_TRANSLATION_OPTIONS, LtErrorTranslationService, type LtErrorTranslationOptions } from './error-translation';\nimport { LT_I18N_OPTIONS, type LtI18nOptions } from './i18n';\nimport { provideLtPreHydrationInput, type LtPreHydrationInputOptions } from './pre-hydration-input';\nimport {\n LT_RUNTIME_CONFIG,\n LT_RUNTIME_CONFIG_DEFAULTS,\n LT_SERVER_RUNTIME_CONFIG,\n mergeLtFeatureOptions,\n mergeLtRuntimeConfig,\n readLtRuntimeConfigFromDocument,\n type LtRuntimeConfig,\n} from './runtime-config';\nimport { LT_NG_BASE_VERSION } from './version';\n\n/** Options of {@link provideLtNgBase}. */\nexport interface LtNgBaseConfig {\n /**\n * Check at startup that an API URL is configured for the current scope (default `true`): a warning in dev mode, a\n * console error in production. Turn it off for apps without a backend (ng-base/ui only).\n */\n configCheck?: boolean;\n /** Backend error translation (`#LTNS_xxxx`). Turn it off (`enabled: false`) for apps without nest-server. */\n errorTranslation?: LtErrorTranslationOptions;\n /** Library i18n (locale, extra messages). Bind `LT_I18N_ADAPTER` to use the app's i18n library. */\n i18n?: LtI18nOptions;\n /** Keep what users type into server-rendered fields before hydration (default on, see `provideLtPreHydrationInput`). */\n preHydrationInput?: LtPreHydrationInputOptions;\n /**\n * Static runtime configuration: the base that the per-request values of the SSR server (`NG_*` via\n * `readLtRequestContext()`, `<script id=\"ng-runtime-config\">` in the browser) override. Use it for apps without SSR,\n * tests, or defaults.\n */\n runtime?: Partial<LtRuntimeConfig>;\n}\n\n/** Name of the window flag set once the app is stable (hydrated) in the browser; read by `waitForHydration()`. */\nexport const LT_HYDRATED_FLAG = '__ltNgBaseHydrated';\n\n/**\n * Core providers of `@lenne.tech/ng-base`.\n *\n * - {@link LT_RUNTIME_CONFIG}: defaults ← `config.runtime` ← request context (server) / `<script id=\"ng-runtime-config\">` (browser).\n * - Error translation options and preload of the backend translations (browser only, in the background: the start\n * never waits for the API; until they arrive errors show the developer message).\n * - i18n options.\n * - API URL config check.\n * - Pre-hydration input preservation (typed text survives hydration).\n * - Hydration flag `window.__ltNgBaseHydrated` for the Playwright helpers.\n *\n * Feature providers live in the secondary entry points: `provideLtAuth()` (`/auth`), `provideLtFiles()` (`/files`),\n * `provideLtAi()` (`/ai`), `provideLtSync()` (`/sync`), `provideLtUi()` (`/ui`), `provideLtServerRuntimeConfig()` (`/server`).\n *\n * @example app.config.ts\n * export const appConfig: ApplicationConfig = {\n * providers: [\n * provideHttpClient(withInterceptors([ltAuthInterceptor])),\n * provideLtNgBase(),\n * provideLtAuth({ systemSetup: { enabled: true } }),\n * provideLtUi(),\n * ],\n * };\n */\nexport function provideLtNgBase(config: LtNgBaseConfig = {}): EnvironmentProviders {\n return makeEnvironmentProviders([\n {\n provide: LT_RUNTIME_CONFIG,\n useFactory: () => {\n const base = mergeLtRuntimeConfig(LT_RUNTIME_CONFIG_DEFAULTS, config.runtime);\n if (!isPlatformBrowser(inject(PLATFORM_ID))) {\n return mergeLtRuntimeConfig(base, inject(LT_SERVER_RUNTIME_CONFIG, { optional: true })?.public);\n }\n return mergeLtRuntimeConfig(base, readLtRuntimeConfigFromDocument(inject(DOCUMENT)));\n },\n },\n {\n provide: LT_ERROR_TRANSLATION_OPTIONS,\n useFactory: () =>\n mergeLtFeatureOptions<Required<LtErrorTranslationOptions>>(\n { defaultLocale: config.i18n?.defaultLocale ?? 'de', enabled: true, preload: true },\n config.errorTranslation,\n inject(LT_RUNTIME_CONFIG).lt.errorTranslation,\n ),\n },\n { provide: LT_I18N_OPTIONS, useValue: config.i18n ?? {} },\n provideLtPreHydrationInput(config.preHydrationInput),\n provideAppInitializer(() => {\n if (config.configCheck !== false) {\n inject(LtApiUrlService).reportMissing();\n }\n }),\n provideAppInitializer(() => {\n const options = inject(LT_ERROR_TRANSLATION_OPTIONS);\n if (!isPlatformBrowser(inject(PLATFORM_ID)) || !options.enabled || !options.preload) {\n return;\n }\n // Not awaited: a slow or hanging API must never hold the app start (the translations are a signal).\n void inject(LtErrorTranslationService).loadTranslations();\n }),\n provideAppInitializer(() => {\n if (!isPlatformBrowser(inject(PLATFORM_ID))) {\n return;\n }\n void inject(ApplicationRef)\n .whenStable()\n .then(() => {\n (globalThis as Record<string, unknown>)[LT_HYDRATED_FLAG] = true;\n (globalThis as Record<string, unknown>)['__ltNgBaseVersion'] = LT_NG_BASE_VERSION;\n });\n }),\n ]);\n}\n","/**\n * Identity function and tagged template for Tailwind class strings outside templates, so the Tailwind IntelliSense\n * extension recognises them (configure `\"tailwindCSS.experimental.classRegex\": [\"tw`([^`]*)`\", \"tw\\\\(['\\\"]([^'\\\"]*)\"]`).\n *\n * @example\n * const card = tw`rounded-lg border p-4`;\n * const active = tw('bg-primary text-primary-foreground');\n */\nexport function tw(strings: TemplateStringsArray | string, ...values: unknown[]): string {\n if (typeof strings === 'string') {\n return strings;\n }\n return strings.reduce((result, part, index) => result + part + (index < values.length ? String(values[index]) : ''), '');\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"lenne.tech-ng-base.mjs","names":[],"sources":["../../../projects/ng-base/src/lib/warn-once.ts","../../../projects/ng-base/src/lib/pre-hydration-input.ts","../../../projects/ng-base/src/lib/runtime-config.ts","../../../projects/ng-base/src/lib/api-url.ts","../../../projects/ng-base/src/lib/cookie.ts","../../../projects/ng-base/src/lib/crypto.ts","../../../projects/ng-base/src/lib/fetch.ts","../tmp-esm2022/lib/i18n/de.json","../tmp-esm2022/lib/i18n/en.json","../../../projects/ng-base/src/lib/i18n.ts","../../../projects/ng-base/src/lib/toast.ts","../../../projects/ng-base/src/lib/error-translation.ts","../../../projects/ng-base/src/lib/version.ts","../../../projects/ng-base/src/lib/provide-lt-ng-base.ts","../../../projects/ng-base/src/lib/tw.ts"],"sourcesContent":["const warnedKeys = new Set<string>();\n\n/**\n * Log `message` the first time `key` is seen; ignore later calls. The conditions behind these messages (missing API\n * URL, implicit dev proxy) are constant for the process, so repeating them only drowns other output.\n */\nexport function warnLtOnce(key: string, message: string, level: 'error' | 'warn' = 'warn'): void {\n if (warnedKeys.has(key)) {\n return;\n }\n warnedKeys.add(key);\n console[level](message);\n}\n\n/** Test only: forget which one-shot messages were emitted. */\nexport function resetLtWarnOnceState(): void {\n warnedKeys.clear();\n}\n","import { isPlatformBrowser } from '@angular/common';\nimport { ApplicationRef, inject, PLATFORM_ID, provideAppInitializer, type EnvironmentProviders } from '@angular/core';\n\n/** Options of the pre-hydration input preservation (`provideLtNgBase({ preHydrationInput })`). */\nexport interface LtPreHydrationInputOptions {\n /** Keep what users type before hydration (default `true`). */\n enabled?: boolean;\n /**\n * How long after hydration to keep restoring, in milliseconds (default `1500`; `0` restores once). Clamped to 30000.\n * When it elapses the snapshot is dropped, so preserved values (passwords included) are not kept for the session.\n */\n maxRestoreMs?: number;\n}\n\ntype LtEditableField = HTMLInputElement | HTMLTextAreaElement;\n\n/** Every `input`/`textarea` under `root` whose value differs from its server-rendered default, with that value. */\nexport function collectLtEditedFields(root: ParentNode): Map<LtEditableField, string> {\n const edited = new Map<LtEditableField, string>();\n for (const node of Array.from(root.querySelectorAll('input, textarea'))) {\n const field = node as LtEditableField;\n if (field.value !== field.defaultValue) {\n edited.set(field, field.value);\n }\n }\n return edited;\n}\n\n/**\n * Write `value` back into `field` and dispatch a bubbling `input` event, so `(input)` handlers, `model()` and Signal\n * Forms adopt it. Returns `false` when the field is detached or already holds the value.\n */\nexport function restoreLtField(field: LtEditableField, value: string): boolean {\n if (!field.isConnected || field.value === value) {\n return false;\n }\n field.value = value;\n field.dispatchEvent(new Event('input', { bubbles: true }));\n return true;\n}\n\n/**\n * Pre-hydration input preservation (browser only).\n *\n * Text typed into a server-rendered field before hydration is in the DOM, but the first change detection after\n * hydration writes the component's (empty) value over it — `[value]` bindings and Signal Forms do — before the replayed\n * events run, so `withEventReplay()` alone loses it (measured in the ng-base playground E2E). The fields are snapshot\n * at app initialisation (the SSR DOM is reused by hydration, so the element references stay valid) and restored once\n * the app is stable, then every 250 ms for `maxRestoreMs` for fields hydrated late; fields stay ordinary editable\n * fields throughout (autofill and screen readers untouched).\n */\nexport function provideLtPreHydrationInput(options: LtPreHydrationInputOptions = {}): EnvironmentProviders {\n return provideAppInitializer(() => {\n if (options.enabled === false || !isPlatformBrowser(inject(PLATFORM_ID)) || typeof document === 'undefined') {\n return;\n }\n const edited = collectLtEditedFields(document);\n if (edited.size === 0) {\n return;\n }\n const configured = options.maxRestoreMs ?? 1500;\n const maxRestoreMs = Number.isFinite(configured) && configured > 0 ? Math.min(configured, 30_000) : 0;\n const sweep = (): void => {\n for (const [field, value] of edited) {\n if (restoreLtField(field, value) || !field.isConnected) {\n edited.delete(field);\n }\n }\n };\n void inject(ApplicationRef)\n .whenStable()\n .then(() => {\n sweep();\n if (maxRestoreMs <= 0 || edited.size === 0) {\n edited.clear();\n return;\n }\n const interval = setInterval(sweep, 250);\n setTimeout(() => {\n clearInterval(interval);\n edited.clear();\n }, maxRestoreMs);\n });\n });\n}\n\n/**\n * Inline script (for `<head>`) that blocks the native submission of forms without `action` until the app handles them.\n * A server-rendered login form submitted before hydration would otherwise send a native GET with the password in the\n * URL. `ltAngularRequestHandler()` writes it into every SSR HTML response; add it to `index.html` yourself without SSR.\n */\nexport const LT_PRE_HYDRATION_SUBMIT_GUARD_SCRIPT =\n \"document.addEventListener('submit',function(e){var f=e.target;if(f instanceof HTMLFormElement&&!f.hasAttribute('action')){e.preventDefault();}},true);\";\n","import { inject, InjectionToken, REQUEST_CONTEXT } from '@angular/core';\n\nimport { LT_PRE_HYDRATION_SUBMIT_GUARD_SCRIPT } from './pre-hydration-input';\n\n/**\n * Feature options that can be overridden per stage at runtime (`NG_PUBLIC_LT_<FEATURE>_<OPTION>`).\n *\n * Each feature provider (`provideLtAuth`, `provideLtFiles`, `provideLtAi`, `provideLtSync`, `provideLtNgBase`)\n * merges, in this order: its defaults, the options passed in code, and the values found here.\n */\nexport interface LtPublicFeatureConfig {\n ai?: Record<string, unknown>;\n auth?: Record<string, unknown>;\n errorTranslation?: Record<string, unknown>;\n sync?: Record<string, unknown>;\n tus?: Record<string, unknown>;\n [feature: string]: Record<string, unknown> | undefined;\n}\n\n/**\n * Public runtime configuration of the app, the Angular counterpart of Nuxt's `runtimeConfig.public`.\n *\n * With SSR the server reads it per request from the `NG_*` environment (`readLtRequestContext()` in\n * `@lenne.tech/ng-base/server`), passes it to `AngularNodeAppEngine.handle(req, context)` as request context\n * (`REQUEST_CONTEXT`) and writes it as JSON `<script id=\"ng-runtime-config\">` into every HTML response, also for\n * `RenderMode.Client` routes; the browser reads that script. One build can therefore be promoted from stage to stage.\n * Without SSR the values come from `provideLtNgBase({ runtime })`.\n *\n * Projects may carry additional public values (e.g. `plausibleApiHost`); they travel the same way.\n * Never put a secret here: everything in this object reaches the browser.\n */\nexport interface LtRuntimeConfig {\n [key: string]: unknown;\n /** Commit of the running build (`NG_PUBLIC_APP_COMMIT`, fallback `APP_VERSION_COMMIT`), `unknown` when unset. */\n appCommit?: string;\n /**\n * Deployment stage (`NG_PUBLIC_APP_ENV`), using nest-server's NODE_ENV block names: `local`, `ci`, `e2e`, `develop`,\n * `test`, `production`. Only `production` counts as production; features that are off in production fail closed.\n */\n appEnv?: string;\n /** Version of the running build (from the server, e.g. package.json). */\n appVersion?: string;\n /** Public API base URL (`NG_PUBLIC_API_URL`), e.g. `https://api.example.com`. Empty = relative to the app origin. */\n apiUrl: string;\n /**\n * Route browser API calls through the dev-server proxy under `/api` (`NG_PUBLIC_API_PROXY`).\n * `null` = not configured: the proxy is used in dev mode (`isDevMode()`) with a one-time warning.\n * Never used during SSR.\n */\n apiProxy: boolean | null;\n /** Opt-in cookie namespace (`NG_PUBLIC_COOKIE_PREFIX`); must mirror the backend `COOKIE_PREFIX`. */\n cookiePrefix: string;\n /** Feature options overridden at runtime (`NG_PUBLIC_LT_*`). */\n lt: LtPublicFeatureConfig;\n /** Absolute public URL of the app (`NG_PUBLIC_SITE_URL`), used for redirect/callback URLs, SEO and security.txt. */\n siteUrl: string;\n /** Prefix for `localStorage` keys (`NG_PUBLIC_STORAGE_PREFIX`). */\n storagePrefix: string;\n}\n\n/** Defaults of {@link LtRuntimeConfig}. */\nexport const LT_RUNTIME_CONFIG_DEFAULTS: LtRuntimeConfig = {\n apiProxy: null,\n apiUrl: '',\n cookiePrefix: '',\n lt: {},\n siteUrl: '',\n storagePrefix: '',\n};\n\n/** The resolved public runtime configuration (defaults ← `provideLtNgBase({ runtime })` ← request context / `<script id=\"ng-runtime-config\">`). */\nexport const LT_RUNTIME_CONFIG = new InjectionToken<LtRuntimeConfig>('LT_RUNTIME_CONFIG');\n\n/** What the SSR server passes to `AngularNodeAppEngine.handle(req, context)` (see `readLtRequestContext()`). */\nexport interface LtRequestContext {\n /** Public runtime configuration (also written into the HTML as `<script id=\"ng-runtime-config\">`). */\n runtimeConfig: Partial<LtRuntimeConfig>;\n /** Internal API URL for SSR requests only (`NG_API_URL`), never sent to the browser. */\n serverApiUrl?: string;\n}\n\n/**\n * Runtime configuration on the server: public part plus the server-only API URL. Read from `REQUEST_CONTEXT`\n * (an {@link LtRequestContext}) by default; `provideLtServerRuntimeConfig()` provides it from the environment instead\n * for servers that pass no request context. `null` in the browser.\n */\nexport interface LtServerRuntimeConfig {\n /** Public part. */\n public: Partial<LtRuntimeConfig>;\n /** Internal API URL for SSR requests only (`NG_API_URL`), never sent to the browser. */\n serverApiUrl: string;\n}\n\n/** Server-only runtime configuration (see {@link LtServerRuntimeConfig}). `null` in the browser. */\nexport const LT_SERVER_RUNTIME_CONFIG = new InjectionToken<LtServerRuntimeConfig | null>('LT_SERVER_RUNTIME_CONFIG', {\n factory: () => {\n const context = inject(REQUEST_CONTEXT, { optional: true }) as Partial<LtRequestContext> | null;\n if (!context || typeof context !== 'object' || !context.runtimeConfig) {\n return null;\n }\n return { public: context.runtimeConfig, serverApiUrl: context.serverApiUrl ?? '' };\n },\n});\n\n/** Id of the JSON `<script>` that carries the public runtime configuration into the browser. */\nexport const LT_RUNTIME_CONFIG_SCRIPT_ID = 'ng-runtime-config';\n\n/** Read the runtime configuration the server wrote into the document (`null` when missing or unreadable). */\nexport function readLtRuntimeConfigFromDocument(doc: Document | null | undefined): Partial<LtRuntimeConfig> | null {\n const text = doc?.getElementById?.(LT_RUNTIME_CONFIG_SCRIPT_ID)?.textContent;\n if (!text) {\n return null;\n }\n try {\n const parsed: unknown = JSON.parse(text);\n return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? (parsed as Partial<LtRuntimeConfig>) : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Serialise the public runtime configuration for an inline `<script type=\"application/json\">`: `<`, `>`, `&`, U+2028\n * and U+2029 are escaped, so a value can never close the script element, open a comment or form an HTML entity.\n */\nexport function serializeLtRuntimeConfig(config: Partial<LtRuntimeConfig>): string {\n return JSON.stringify(config)\n .replace(/</g, '\\\\u003c')\n .replace(/>/g, '\\\\u003e')\n .replace(/&/g, '\\\\u0026')\n .replace(/\\u2028/g, '\\\\u2028')\n .replace(/\\u2029/g, '\\\\u2029');\n}\n\n/**\n * Insert the runtime configuration as the first child of `<head>` (documents without `<head>` stay untouched), by\n * default preceded by the pre-hydration submit guard (`LT_PRE_HYDRATION_SUBMIT_GUARD_SCRIPT`).\n */\nexport function injectLtRuntimeConfigScript(html: string, config: Partial<LtRuntimeConfig>, options: { submitGuard?: boolean } = {}): string {\n const head = /<head(\\s[^>]*)?>/i.exec(html);\n if (!head) {\n return html;\n }\n const at = head.index + head[0].length;\n const guard = options.submitGuard === false ? '' : `<script>${LT_PRE_HYDRATION_SUBMIT_GUARD_SCRIPT}</script>`;\n return `${html.slice(0, at)}${guard}<script id=\"${LT_RUNTIME_CONFIG_SCRIPT_ID}\" type=\"application/json\">${serializeLtRuntimeConfig(config)}</script>${html.slice(at)}`;\n}\n\n/**\n * Merge partial runtime configurations onto a base. `lt` is merged per feature; `undefined` values never\n * override (an unset env variable keeps the code default).\n */\nexport function mergeLtRuntimeConfig(base: LtRuntimeConfig, ...overrides: (Partial<LtRuntimeConfig> | null | undefined)[]): LtRuntimeConfig {\n const result: LtRuntimeConfig = { ...base, lt: { ...base.lt } };\n for (const override of overrides) {\n if (!override) {\n continue;\n }\n for (const [key, value] of Object.entries(override) as [keyof LtRuntimeConfig, unknown][]) {\n if (value === undefined) {\n continue;\n }\n if (key === 'lt') {\n for (const [feature, options] of Object.entries((value ?? {}) as LtPublicFeatureConfig)) {\n result.lt[feature] = { ...result.lt[feature], ...definedEntries(options ?? {}) };\n }\n continue;\n }\n (result as unknown as Record<string, unknown>)[key] = value;\n }\n }\n return result;\n}\n\n/**\n * Merge feature options: defaults ← code options ← runtime overrides. Nested plain objects are merged one level\n * deep (e.g. `auth.interceptor`), arrays and primitives replace. `undefined` never overrides.\n */\nexport function mergeLtFeatureOptions<T extends object>(defaults: T, ...overrides: (object | null | undefined)[]): T {\n const result: Record<string, unknown> = { ...(defaults as Record<string, unknown>) };\n for (const override of overrides) {\n if (!override) {\n continue;\n }\n for (const [key, value] of Object.entries(override)) {\n if (value === undefined) {\n continue;\n }\n const current = result[key];\n result[key] = isPlainObject(current) && isPlainObject(value) ? { ...current, ...definedEntries(value) } : value;\n }\n }\n return result as T;\n}\n\nfunction definedEntries(source: object): Record<string, unknown> {\n return Object.fromEntries(Object.entries(source).filter(([, value]) => value !== undefined));\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","import { isPlatformServer } from '@angular/common';\nimport { inject, isDevMode, PLATFORM_ID, Service } from '@angular/core';\n\nimport { warnLtOnce } from './warn-once';\nimport { LT_RUNTIME_CONFIG, LT_SERVER_RUNTIME_CONFIG } from './runtime-config';\n\n/** Render scope an API URL is resolved for. */\nexport type LtRenderScope = 'browser' | 'server';\n\n/** Outcome of resolving the API base URL for the current render scope. */\nexport interface LtApiUrlResolution {\n /** Base URL to prefix onto API paths: `'/api'` in proxy mode, `''` when unresolved. No trailing slash. */\n baseUrl: string;\n /** `true` when no API URL is configured for {@link scope}. */\n missing: boolean;\n /** `true` when the dev-server proxy prefix `/api` is in use. */\n proxy: boolean;\n /** Scope the resolution was performed for. */\n scope: LtRenderScope;\n}\n\n/** Inputs of {@link resolveLtApiBaseUrl}. */\nexport interface LtApiUrlInputs {\n /** `NG_PUBLIC_API_PROXY` (`null` = unset). */\n apiProxy: boolean | null;\n /** `NG_PUBLIC_API_URL`. */\n apiUrl: string;\n /** Whether the app runs in dev mode (`isDevMode()`), used when `apiProxy` is unset. */\n devMode: boolean;\n /** Render scope. */\n scope: LtRenderScope;\n /** `NG_API_URL` (server only). */\n serverApiUrl?: string;\n}\n\nconst MISSING_API_URL_WARNING: Record<LtRenderScope, string> = {\n browser:\n '[@lenne.tech/ng-base] No API URL configured. Set NG_PUBLIC_API_URL. API paths stay relative and resolve against the app ' +\n 'origin, so auth and setup calls 404 unless the app is served behind a same-origin reverse proxy.',\n server:\n '[@lenne.tech/ng-base] No API URL configured for SSR. Set NG_API_URL or NG_PUBLIC_API_URL. API paths stay relative, so ' + 'server-side requests never reach the backend.',\n};\n\n/**\n * Pure resolution of the API base URL (no DI, no logging).\n *\n * - Server: `NG_API_URL` → `NG_PUBLIC_API_URL` → `''`. The proxy is never used during SSR.\n * - Browser: `/api` when the proxy is on (explicitly, or implicitly in dev mode while unset), else `NG_PUBLIC_API_URL` → `''`.\n *\n * Trailing slashes are stripped so `${baseUrl}${path}` never produces a double slash.\n */\nexport function resolveLtApiBaseUrl(inputs: LtApiUrlInputs): LtApiUrlResolution {\n if (inputs.scope === 'server') {\n const apiUrl = inputs.serverApiUrl || inputs.apiUrl || '';\n return { baseUrl: stripTrailingSlashes(apiUrl), missing: !apiUrl, proxy: false, scope: 'server' };\n }\n if (inputs.apiProxy === true || (inputs.apiProxy === null && inputs.devMode)) {\n return { baseUrl: '/api', missing: false, proxy: true, scope: 'browser' };\n }\n const apiUrl = inputs.apiUrl || '';\n return { baseUrl: stripTrailingSlashes(apiUrl), missing: !apiUrl, proxy: false, scope: 'browser' };\n}\n\n/** Whether `url` is absolute (`scheme:` or protocol-relative `//`). */\nexport function isLtAbsoluteUrl(url: string): boolean {\n return /^[a-z][a-z\\d+\\-.]*:/i.test(url) || url.startsWith('//');\n}\n\n/**\n * The single URL builder used by auth, system setup, error translation, files, AI and sync.\n *\n * Reads {@link LT_RUNTIME_CONFIG} and, on the server, {@link LT_SERVER_RUNTIME_CONFIG}. A missing API URL is warned\n * about once per scope; an implicit dev proxy (unset `NG_PUBLIC_API_PROXY` in dev mode) once as well.\n */\n@Service()\nexport class LtApiUrlService {\n private readonly runtimeConfig = inject(LT_RUNTIME_CONFIG, { optional: true });\n private readonly serverConfig = inject(LT_SERVER_RUNTIME_CONFIG, { optional: true });\n private readonly isServer = isPlatformServer(inject(PLATFORM_ID));\n\n /** Resolve the base URL for the current scope without logging. */\n resolve(): LtApiUrlResolution {\n return resolveLtApiBaseUrl({\n apiProxy: this.runtimeConfig?.apiProxy ?? null,\n apiUrl: this.runtimeConfig?.apiUrl ?? '',\n devMode: isDevMode(),\n scope: this.isServer ? 'server' : 'browser',\n serverApiUrl: this.serverConfig?.serverApiUrl,\n });\n }\n\n /** Base URL (no trailing slash) for the current scope. */\n baseUrl(): string {\n return this.resolveAndWarn().baseUrl;\n }\n\n /** Build a full API URL for a path such as `/iam/sign-in/email`. Absolute URLs are returned unchanged. */\n buildUrl(path: string): string {\n if (isLtAbsoluteUrl(path)) {\n return path;\n }\n const normalized = path.startsWith('/') ? path : `/${path}`;\n return `${this.resolveAndWarn().baseUrl}${normalized}`;\n }\n\n /**\n * Build the URL the browser uses for `path`, also during SSR: `NG_PUBLIC_API_URL` (or `/api` behind the dev proxy),\n * never the server-only `NG_API_URL`. For links that end up in the HTML (`href`, `src`), which the browser follows\n * itself: an internal API host would be unreachable there and must not leak into the page. Absolute URLs are returned\n * unchanged.\n */\n buildBrowserUrl(path: string): string {\n if (isLtAbsoluteUrl(path)) {\n return path;\n }\n const resolution = resolveLtApiBaseUrl({\n apiProxy: this.runtimeConfig?.apiProxy ?? null,\n apiUrl: this.runtimeConfig?.apiUrl ?? '',\n devMode: isDevMode(),\n scope: 'browser',\n });\n return `${resolution.baseUrl}${path.startsWith('/') ? path : `/${path}`}`;\n }\n\n /** Whether browser requests go through the dev-server proxy under `/api`. Always `false` on the server. */\n isProxy(): boolean {\n return this.resolve().proxy;\n }\n\n /** Report a missing API URL (`dev`: warning, production: error), at most once per scope. Used by the config check. */\n reportMissing(): boolean {\n const resolution = this.resolve();\n if (resolution.missing) {\n warnLtOnce(`missing-api-url:${resolution.scope}`, MISSING_API_URL_WARNING[resolution.scope], isDevMode() ? 'warn' : 'error');\n }\n return resolution.missing;\n }\n\n private resolveAndWarn(): LtApiUrlResolution {\n const resolution = this.resolve();\n if (resolution.missing) {\n warnLtOnce(`missing-api-url:${resolution.scope}`, MISSING_API_URL_WARNING[resolution.scope]);\n }\n if (resolution.proxy && this.runtimeConfig?.apiProxy === null) {\n warnLtOnce(\n 'api-proxy-implicit',\n '[@lenne.tech/ng-base] API proxy (/api) activated implicitly because the app runs in dev mode. ' +\n 'Set NG_PUBLIC_API_PROXY=true to make it explicit, or NG_PUBLIC_API_PROXY=false to call the API directly.',\n );\n }\n return resolution;\n }\n}\n\nfunction stripTrailingSlashes(url: string): string {\n return url.replace(/\\/+$/, '');\n}\n","import { DOCUMENT, isPlatformServer } from '@angular/common';\nimport { inject, PLATFORM_ID, REQUEST, Service } from '@angular/core';\n\n/** Options for {@link LtCookieService.set}. */\nexport interface LtCookieOptions {\n /** Cookie domain. Omit for a host-only cookie. */\n domain?: string;\n /** Lifetime in seconds. Omit for a session cookie. */\n maxAge?: number;\n /** Cookie path (default `/`). */\n path?: string;\n /** SameSite attribute (default `lax`). */\n sameSite?: 'lax' | 'none' | 'strict';\n /** Secure attribute (default: `true` on `https:`). */\n secure?: boolean;\n}\n\n/**\n * SSR-aware cookie access.\n *\n * - Browser: reads and writes `document.cookie`.\n * - Server: reads the `Cookie` header of the incoming request (`REQUEST`); never writes. A server render must not\n * set auth cookies (it would write `{ user: null }` over a valid browser state), so `set`/`delete` are no-ops there.\n */\n@Service()\nexport class LtCookieService {\n private readonly document = inject(DOCUMENT);\n private readonly request = inject(REQUEST, { optional: true });\n private readonly isServer = isPlatformServer(inject(PLATFORM_ID));\n\n /** Raw cookie string (`a=1; b=2`) of the current request or document. */\n raw(): string {\n if (this.isServer) {\n return this.request?.headers.get('cookie') ?? '';\n }\n try {\n return this.document.cookie ?? '';\n } catch {\n return '';\n }\n }\n\n /** First decoded value of `name`, or `null`. */\n get(name: string): string | null {\n return this.getAll(name)[0] ?? null;\n }\n\n /**\n * Every decoded value of `name`, in header order. A host-only cookie and a domain-scoped twin can coexist; callers\n * that must pick the right one (the auth state) look at all of them.\n */\n getAll(name: string): string[] {\n return parseLtCookies(this.raw(), name);\n }\n\n /** Write a cookie (browser only). The value is URI-encoded. */\n set(name: string, value: string, options: LtCookieOptions = {}): void {\n if (this.isServer) {\n return;\n }\n const secure = options.secure ?? this.document.location?.protocol === 'https:';\n const parts = [`${name}=${encodeURIComponent(value)}`, `path=${options.path ?? '/'}`, `samesite=${options.sameSite ?? 'lax'}`];\n if (options.maxAge !== undefined) {\n parts.push(`max-age=${Math.max(0, Math.floor(options.maxAge))}`);\n }\n if (options.domain) {\n parts.push(`domain=${options.domain}`);\n }\n if (secure) {\n parts.push('secure');\n }\n this.document.cookie = parts.join('; ');\n }\n\n /** Delete a cookie on the given path/domain slot (browser only). */\n delete(name: string, options: Pick<LtCookieOptions, 'domain' | 'path'> = {}): void {\n if (this.isServer) {\n return;\n }\n const parts = [`${name}=`, `path=${options.path ?? '/'}`, 'expires=Thu, 01 Jan 1970 00:00:00 GMT', 'max-age=0'];\n if (options.domain) {\n parts.push(`domain=${options.domain}`);\n }\n this.document.cookie = parts.join('; ');\n }\n}\n\n/** Parse every value of cookie `name` out of a raw cookie string (decoded; malformed encodings are kept raw). */\nexport function parseLtCookies(cookieString: string, name: string): string[] {\n const prefix = `${name}=`;\n const values: string[] = [];\n for (const entry of (cookieString || '').split(/;\\s*/)) {\n if (!entry.startsWith(prefix)) {\n continue;\n }\n const value = entry.slice(prefix.length);\n try {\n values.push(decodeURIComponent(value));\n } catch {\n values.push(value);\n }\n }\n return values;\n}\n","/**\n * SHA-256 of a string as lowercase hex (WebCrypto).\n *\n * nest-server expects every password to arrive SHA-256 hashed (it re-hashes server-side). The auth service applies\n * this to each credential field; use it yourself only for custom endpoints that follow the same rule. Because the\n * hash hides the length, enforce password rules in the form, not on the server.\n */\nexport async function ltSha256(message: string): Promise<string> {\n const data = new TextEncoder().encode(message);\n const hash = await crypto.subtle.digest('SHA-256', data);\n return Array.from(new Uint8Array(hash), (byte) => byte.toString(16).padStart(2, '0')).join('');\n}\n\n/** Encode bytes as base64url without padding (WebAuthn). */\nexport function ltArrayBufferToBase64Url(buffer: ArrayBuffer | Uint8Array): string {\n const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);\n let binary = '';\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\n/** Decode base64url (with or without padding) into bytes (WebAuthn). */\nexport function ltBase64UrlToUint8Array(base64url: string): Uint8Array<ArrayBuffer> {\n const base64 = base64url.replace(/-/g, '+').replace(/_/g, '/');\n const padded = base64 + '='.repeat((4 - (base64.length % 4)) % 4);\n const binary = atob(padded);\n const bytes = new Uint8Array(new ArrayBuffer(binary.length));\n for (let index = 0; index < binary.length; index++) {\n bytes[index] = binary.charCodeAt(index);\n }\n return bytes;\n}\n","import { InjectionToken } from '@angular/core';\n\n/** A `fetch`-compatible function. */\nexport type LtFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;\n\n/**\n * The fetch used by every library call that does not go through `HttpClient`: error translation, system setup,\n * AI (incl. the SSE stream), offline sync and its hint stream, the Better Auth client.\n *\n * The default sends cookies (`credentials: 'include'`). `provideLtAuth()` replaces it with the auth-aware fetch\n * (Bearer token in JWT mode, cookie → JWT switch on 401, stale-JWT refresh, session-loss handling), so SSE and sync\n * get the same auth behaviour as `HttpClient` calls behind `ltAuthInterceptor`.\n */\nexport const LT_FETCH = new InjectionToken<LtFetch>('LT_FETCH', {\n factory: () => ltCredentialsFetch,\n});\n\n/** `fetch` with `credentials: 'include'` unless the caller decided otherwise. */\nexport const ltCredentialsFetch: LtFetch = (input, init) => fetch(input, { credentials: 'include', ...init });\n","","","import { isPlatformBrowser } from '@angular/common';\nimport { computed, inject, InjectionToken, PLATFORM_ID, Service, signal, type Signal } from '@angular/core';\n\nimport de from './i18n/de.json';\nimport en from './i18n/en.json';\n\n/** Nested message tree as in the shipped `i18n/de.json` / `i18n/en.json`. */\nexport interface LtI18nMessages {\n [key: string]: LtI18nMessages | string;\n}\n\n/**\n * Bridge to the app's translation library (Transloco, ngx-translate, …).\n *\n * Bind it when the app already has an i18n setup, so library texts follow the app language and can be overridden\n * in the app's own translation files (keys `lt.error.*` of the core and `lt.<entry>.*` of the entry points: `lt.auth.*`,\n * `lt.files.*`, `lt.share.*`, `lt.ui.*`, `lt.bug.*`; shipped as `i18n/{de,en}.json` and `i18n/<entry>/{de,en}.json`).\n *\n * @example Transloco\n * { provide: LT_I18N_ADAPTER, useFactory: () => {\n * const transloco = inject(TranslocoService);\n * const lang = toSignal(transloco.langChanges$, { initialValue: transloco.getActiveLang() });\n * return { locale: lang, translate: (key, params) => transloco.translate(key, params) };\n * } }\n */\nexport interface LtI18nAdapter {\n /** Active locale (`de`, `en`, …). */\n readonly locale: Signal<string>;\n /** Translate a key; return `null` (or the key itself) when the app has no translation, then the library text is used. */\n translate(key: string, params?: Record<string, unknown>): string | null;\n}\n\n/** Optional adapter to the app's i18n library. */\nexport const LT_I18N_ADAPTER = new InjectionToken<LtI18nAdapter>('LT_I18N_ADAPTER');\n\n/** Options of the built-in i18n (part of `provideLtNgBase({ i18n })`). */\nexport interface LtI18nOptions {\n /** Locale used when neither the adapter nor the browser language (de/en) decides. Default `de`. */\n defaultLocale?: string;\n /** Additional or overriding messages per locale, merged over the shipped de/en texts. */\n messages?: Record<string, LtI18nMessages>;\n}\n\n/** i18n options token (set by `provideLtNgBase`). */\nexport const LT_I18N_OPTIONS = new InjectionToken<LtI18nOptions>('LT_I18N_OPTIONS', { factory: () => ({}) });\n\n/** The core's shipped messages (`lt.error.*`); the entry points register theirs with `registerLibraryMessages()`. */\nexport const LT_I18N_MESSAGES: Readonly<Record<'de' | 'en', LtI18nMessages>> = { de, en };\n\n/**\n * Signal-based translations for library texts, with an optional adapter to the app's i18n library.\n *\n * Lookup order for `t(key)`: adapter → messages of the active locale → German messages → the key.\n * Locale order: adapter → `setLocale()` → browser language (de/en, browser only) → `defaultLocale` → `de`.\n */\n@Service()\nexport class LtI18nService {\n private readonly adapter = inject(LT_I18N_ADAPTER, { optional: true });\n private readonly options = inject(LT_I18N_OPTIONS);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n private readonly explicitLocale = signal<string | null>(null);\n private readonly extraMessages = signal<Record<string, LtI18nMessages>>(this.options.messages ?? {});\n /**\n * Texts of the entry points (`lt.ui.*`, `lt.auth.*` …) registered by {@link registerLibraryMessages}. A plain object:\n * every entry registers its texts before its own components read them, so nothing has to react to a registration.\n */\n private readonly libraryMessages: Record<string, LtI18nMessages> = {};\n private readonly libraryIds = new Set<string>();\n\n /** Active locale. */\n readonly locale = computed(() => this.adapter?.locale() || this.explicitLocale() || this.detectBrowserLocale() || this.options.defaultLocale || 'de');\n\n /** Set the locale (ignored for lookups while an adapter provides one). */\n setLocale(locale: string): void {\n this.explicitLocale.set(locale);\n }\n\n /** Merge messages for a locale over the shipped ones. */\n registerMessages(locale: string, messages: LtI18nMessages): void {\n this.extraMessages.update((current) => ({ ...current, [locale]: deepMerge(current[locale] ?? {}, messages) }));\n }\n\n /**\n * Register the default texts of an entry point once per `id` (`ui`, `auth`, `files` …). They rank below the app's\n * own texts (`provideLtNgBase({ i18n: { messages } })`, `registerMessages()`, the adapter), like the shipped core\n * texts. Entry points call it when they are first used (synchronously, on the server and in the browser alike), so\n * their texts travel with their code instead of the initial bundle.\n */\n registerLibraryMessages(id: string, messages: Readonly<Record<string, LtI18nMessages>>): void {\n if (this.libraryIds.has(id)) {\n return;\n }\n this.libraryIds.add(id);\n for (const [locale, tree] of Object.entries(messages)) {\n this.libraryMessages[locale] = deepMerge(this.libraryMessages[locale] ?? {}, tree);\n }\n }\n\n /** Translate `key`, interpolating `{name}` placeholders from `params`. */\n t(key: string, params?: Record<string, unknown>): string {\n const fromAdapter = this.adapter?.translate(key, params);\n if (fromAdapter && fromAdapter !== key) {\n return fromAdapter;\n }\n const locale = this.locale();\n const message =\n lookup(this.extraMessages()[locale], key) ??\n lookup((LT_I18N_MESSAGES as Record<string, LtI18nMessages>)[locale], key) ??\n lookup(this.libraryMessages[locale], key) ??\n lookup(this.extraMessages()['de'], key) ??\n lookup(LT_I18N_MESSAGES.de, key) ??\n lookup(this.libraryMessages['de'], key) ??\n key;\n return interpolate(message, params);\n }\n\n private detectBrowserLocale(): string | null {\n if (!this.isBrowser || typeof navigator === 'undefined' || !navigator.language) {\n return null;\n }\n const language = navigator.language.split('-')[0]?.toLowerCase() ?? '';\n return language === 'de' || language === 'en' ? language : null;\n }\n}\n\nfunction lookup(messages: LtI18nMessages | undefined, key: string): string | null {\n let node: LtI18nMessages | string | undefined = messages;\n for (const part of key.split('.')) {\n if (!node || typeof node === 'string') {\n return null;\n }\n node = node[part];\n }\n return typeof node === 'string' ? node : null;\n}\n\nfunction interpolate(message: string, params?: Record<string, unknown>): string {\n if (!params) {\n return message;\n }\n return message.replace(/\\{(\\w+)\\}/g, (match, name: string) => (name in params ? String(params[name]) : match));\n}\n\nfunction deepMerge(target: LtI18nMessages, source: LtI18nMessages): LtI18nMessages {\n const result: LtI18nMessages = { ...target };\n for (const [key, value] of Object.entries(source)) {\n const current = result[key];\n result[key] = typeof value === 'object' && typeof current === 'object' ? deepMerge(current, value) : value;\n }\n return result;\n}\n","import { inject, InjectionToken, Service } from '@angular/core';\n\n/** Toast colors (same set as Nuxt UI). */\nexport type LtToastColor = 'error' | 'info' | 'neutral' | 'primary' | 'secondary' | 'success' | 'warning';\n\n/** A toast message. */\nexport interface LtToastOptions {\n color?: LtToastColor;\n description?: string;\n /** Display time in milliseconds (adapter default when omitted). */\n duration?: number;\n title?: string;\n}\n\n/**\n * Bridge to the app's toaster. `provideLtUi()` binds it to Spartan Sonner (`<hlm-toaster />`); bind your own for\n * another UI library. Return `false` when nothing could be shown, the caller then logs to the console.\n */\nexport interface LtToastAdapter {\n show(options: LtToastOptions): boolean;\n}\n\n/** Optional toaster bridge (see {@link LtToastAdapter}). */\nexport const LT_TOAST_ADAPTER = new InjectionToken<LtToastAdapter>('LT_TOAST_ADAPTER');\n\n/** Shows toasts through {@link LT_TOAST_ADAPTER}; without an adapter, `show` returns `false`. */\n@Service()\nexport class LtToastService {\n private readonly adapter = inject(LT_TOAST_ADAPTER, { optional: true });\n\n /** Show a toast. Returns `false` when no toaster is bound or it threw. */\n show(options: LtToastOptions): boolean {\n if (!this.adapter) {\n return false;\n }\n try {\n return this.adapter.show(options) !== false;\n } catch {\n return false;\n }\n }\n\n /** Shortcut for a success toast. */\n success(title: string, description?: string): boolean {\n return this.show({ color: 'success', description, title });\n }\n\n /** Shortcut for an error toast. */\n error(title: string, description?: string): boolean {\n return this.show({ color: 'error', description, title });\n }\n}\n","import { isPlatformBrowser } from '@angular/common';\nimport { computed, inject, InjectionToken, PLATFORM_ID, Service, signal } from '@angular/core';\n\nimport { LtApiUrlService } from './api-url';\nimport { LT_FETCH } from './fetch';\nimport { LtI18nService } from './i18n';\nimport { LtToastService } from './toast';\n\n/** Response of nest-server `GET /i18n/errors/:locale`. */\nexport interface LtErrorTranslationResponse {\n errors: Record<string, string>;\n}\n\n/** Result of {@link LtErrorTranslationService.parseError}. */\nexport interface LtParsedError {\n /** Error code such as `LTNS_0100`, or `null` when the message carries none. */\n code: string | null;\n /** Message as sent by the backend (without the `#CODE:` marker). */\n developerMessage: string;\n /** Translated message for the active locale; falls back to the developer message, never empty for a message-bearing error. */\n translatedMessage: string;\n}\n\n/** Options of the error translation (part of `provideLtNgBase({ errorTranslation })`, runtime `NG_PUBLIC_LT_ERROR_TRANSLATION_*`). */\nexport interface LtErrorTranslationOptions {\n /** Locale used when i18n does not decide (default `de`). */\n defaultLocale?: string;\n /** Load and apply backend translations (default `true`). */\n enabled?: boolean;\n /** Load the translations for the detected locale while the app starts, browser only (default `true`). */\n preload?: boolean;\n}\n\n/** Resolved error translation options. */\nexport const LT_ERROR_TRANSLATION_OPTIONS = new InjectionToken<Required<LtErrorTranslationOptions>>('LT_ERROR_TRANSLATION_OPTIONS', {\n factory: () => ({ defaultLocale: 'de', enabled: true, preload: true }),\n});\n\nconst ERROR_CODE_REGEX = /^#([A-Z_]+_\\d+):\\s*(.+)$/s;\n\n/** A translation load that takes longer is aborted (the next call retries). */\nexport const LT_ERROR_TRANSLATION_TIMEOUT_MS = 10_000;\n\n/**\n * Translates nest-server error messages of the form `#LTNS_0100: Developer message` with the backend's\n * `GET /i18n/errors/:locale` table.\n */\n@Service()\nexport class LtErrorTranslationService {\n private readonly api = inject(LtApiUrlService);\n private readonly fetch = inject(LT_FETCH);\n private readonly i18n = inject(LtI18nService);\n private readonly toast = inject(LtToastService);\n private readonly options = inject(LT_ERROR_TRANSLATION_OPTIONS);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n private readonly translations = signal<Record<string, Record<string, string>>>({});\n private readonly inFlight = new Map<string, Promise<void>>();\n\n /** Locale used for lookups. */\n readonly currentLocale = computed(() => this.i18n.locale() || this.options.defaultLocale || 'de');\n /** Whether translations for the current locale are loaded. */\n readonly isLoaded = computed(() => !!this.translations()[this.currentLocale()]);\n /** Whether a load is running. */\n readonly isLoading = signal(false);\n\n /** Load the backend translations for `locale` (default: current locale). Cached per locale, one request in flight per locale. */\n async loadTranslations(locale?: string): Promise<void> {\n if (!this.options.enabled) {\n return;\n }\n const target = locale || this.currentLocale();\n if (this.translations()[target]) {\n return;\n }\n const running = this.inFlight.get(target);\n if (running) {\n return running;\n }\n const load = (async () => {\n this.isLoading.set(true);\n try {\n const response = await this.fetch(this.api.buildUrl(`/i18n/errors/${encodeURIComponent(target)}`), {\n headers: { accept: 'application/json' },\n signal: AbortSignal.timeout(LT_ERROR_TRANSLATION_TIMEOUT_MS),\n });\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}`);\n }\n const body = (await response.json()) as Partial<LtErrorTranslationResponse> | null;\n if (body?.errors && typeof body.errors === 'object') {\n this.translations.update((current) => ({ ...current, [target]: body.errors as Record<string, string> }));\n }\n } catch (error) {\n console.warn(`[@lenne.tech/ng-base] Failed to load error translations for ${target}:`, error);\n } finally {\n this.inFlight.delete(target);\n this.isLoading.set(this.inFlight.size > 0);\n }\n })();\n this.inFlight.set(target, load);\n return load;\n }\n\n /** Parse any error shape (string, `Error`, `HttpErrorResponse`, response body) into code + messages. */\n parseError(errorOrMessage: unknown): LtParsedError {\n const message = extractLtErrorMessage(errorOrMessage);\n const match = message.match(ERROR_CODE_REGEX);\n if (!match) {\n return { code: null, developerMessage: message, translatedMessage: message };\n }\n const code = match[1] ?? '';\n const developerMessage = (match[2] ?? '').trim();\n const translatedMessage = this.translations()[this.currentLocale()]?.[code] || developerMessage;\n return { code, developerMessage, translatedMessage };\n }\n\n /** Translated message for an error (never empty for a message-bearing error). */\n translateError(errorOrMessage: unknown): string {\n return this.parseError(errorOrMessage).translatedMessage;\n }\n\n /** Show the translated error as an error toast (browser only); logs to the console when no toaster is bound. */\n showErrorToast(errorOrMessage: unknown, title?: string): void {\n if (!this.isBrowser) {\n return;\n }\n const parsed = this.parseError(errorOrMessage);\n const shown = this.toast.show({ color: 'error', description: parsed.translatedMessage, title: title || this.i18n.t('lt.error.title') });\n if (!shown) {\n console.error('[@lenne.tech/ng-base]', parsed.translatedMessage);\n }\n }\n}\n\n/**\n * Extract the human-relevant message from an error.\n *\n * The response body wins over a transport message: `HttpErrorResponse.message` is\n * `Http failure response for …: 400 Bad Request`, while the backend message (the only one that can carry a\n * `#LTNS_` marker) is in `error.message`. Better Auth errors (`{ code, message }`) and arrays of messages\n * (class-validator) are handled too.\n */\nexport function extractLtErrorMessage(errorOrMessage: unknown): string {\n if (typeof errorOrMessage === 'string') {\n return errorOrMessage;\n }\n if (errorOrMessage === null || errorOrMessage === undefined) {\n return '';\n }\n if (typeof errorOrMessage !== 'object') {\n return String(errorOrMessage);\n }\n const source = errorOrMessage as Record<string, unknown>;\n for (const candidate of [source['error'], source['data'], source['body']]) {\n const fromBody = messageOf(candidate);\n if (fromBody) {\n return fromBody;\n }\n }\n return messageOf(source) || (typeof source['statusText'] === 'string' && source['statusText']) || String(errorOrMessage);\n}\n\nfunction messageOf(value: unknown): string {\n if (typeof value === 'string') {\n return value;\n }\n if (!value || typeof value !== 'object') {\n return '';\n }\n const message = (value as Record<string, unknown>)['message'];\n if (typeof message === 'string') {\n return message;\n }\n if (Array.isArray(message)) {\n return message.filter((part) => typeof part === 'string').join(', ');\n }\n const nested = (value as Record<string, unknown>)['error'];\n if (nested && typeof nested === 'object') {\n return messageOf(nested);\n }\n return '';\n}\n","/** Version of `@lenne.tech/ng-base`; kept in sync with `package.json` by `scripts/sync-version.mjs`. */\nexport const LT_NG_BASE_VERSION = '22.1.0';\n","import { DOCUMENT, isPlatformBrowser } from '@angular/common';\nimport { ApplicationRef, inject, makeEnvironmentProviders, PLATFORM_ID, provideAppInitializer, type EnvironmentProviders } from '@angular/core';\n\nimport { LtApiUrlService } from './api-url';\nimport { LT_ERROR_TRANSLATION_OPTIONS, LtErrorTranslationService, type LtErrorTranslationOptions } from './error-translation';\nimport { LT_I18N_OPTIONS, type LtI18nOptions } from './i18n';\nimport { provideLtPreHydrationInput, type LtPreHydrationInputOptions } from './pre-hydration-input';\nimport {\n LT_RUNTIME_CONFIG,\n LT_RUNTIME_CONFIG_DEFAULTS,\n LT_SERVER_RUNTIME_CONFIG,\n mergeLtFeatureOptions,\n mergeLtRuntimeConfig,\n readLtRuntimeConfigFromDocument,\n type LtRuntimeConfig,\n} from './runtime-config';\nimport { LT_NG_BASE_VERSION } from './version';\n\n/** Options of {@link provideLtNgBase}. */\nexport interface LtNgBaseConfig {\n /**\n * Check at startup that an API URL is configured for the current scope (default `true`): a warning in dev mode, a\n * console error in production. Turn it off for apps without a backend (ng-base/ui only).\n */\n configCheck?: boolean;\n /** Backend error translation (`#LTNS_xxxx`). Turn it off (`enabled: false`) for apps without nest-server. */\n errorTranslation?: LtErrorTranslationOptions;\n /** Library i18n (locale, extra messages). Bind `LT_I18N_ADAPTER` to use the app's i18n library. */\n i18n?: LtI18nOptions;\n /** Keep what users type into server-rendered fields before hydration (default on, see `provideLtPreHydrationInput`). */\n preHydrationInput?: LtPreHydrationInputOptions;\n /**\n * Static runtime configuration: the base that the per-request values of the SSR server (`NG_*` via\n * `readLtRequestContext()`, `<script id=\"ng-runtime-config\">` in the browser) override. Use it for apps without SSR,\n * tests, or defaults.\n */\n runtime?: Partial<LtRuntimeConfig>;\n}\n\n/** Name of the window flag set once the app is stable (hydrated) in the browser; read by `waitForHydration()`. */\nexport const LT_HYDRATED_FLAG = '__ltNgBaseHydrated';\n\n/**\n * Core providers of `@lenne.tech/ng-base`.\n *\n * - {@link LT_RUNTIME_CONFIG}: defaults ← `config.runtime` ← request context (server) / `<script id=\"ng-runtime-config\">` (browser).\n * - Error translation options and preload of the backend translations (browser only, in the background: the start\n * never waits for the API; until they arrive errors show the developer message).\n * - i18n options.\n * - API URL config check.\n * - Pre-hydration input preservation (typed text survives hydration).\n * - Hydration flag `window.__ltNgBaseHydrated` for the Playwright helpers.\n *\n * Feature providers live in the secondary entry points: `provideLtAuth()` (`/auth`), `provideLtFiles()` (`/files`),\n * `provideLtAi()` (`/ai`), `provideLtSync()` (`/sync`), `provideLtUi()` (`/ui`), `provideLtServerRuntimeConfig()` (`/server`).\n *\n * @example app.config.ts\n * export const appConfig: ApplicationConfig = {\n * providers: [\n * provideHttpClient(withInterceptors([ltAuthInterceptor])),\n * provideLtNgBase(),\n * provideLtAuth({ systemSetup: { enabled: true } }),\n * provideLtUi(),\n * ],\n * };\n */\nexport function provideLtNgBase(config: LtNgBaseConfig = {}): EnvironmentProviders {\n return makeEnvironmentProviders([\n {\n provide: LT_RUNTIME_CONFIG,\n useFactory: () => {\n const base = mergeLtRuntimeConfig(LT_RUNTIME_CONFIG_DEFAULTS, config.runtime);\n if (!isPlatformBrowser(inject(PLATFORM_ID))) {\n return mergeLtRuntimeConfig(base, inject(LT_SERVER_RUNTIME_CONFIG, { optional: true })?.public);\n }\n return mergeLtRuntimeConfig(base, readLtRuntimeConfigFromDocument(inject(DOCUMENT)));\n },\n },\n {\n provide: LT_ERROR_TRANSLATION_OPTIONS,\n useFactory: () =>\n mergeLtFeatureOptions<Required<LtErrorTranslationOptions>>(\n { defaultLocale: config.i18n?.defaultLocale ?? 'de', enabled: true, preload: true },\n config.errorTranslation,\n inject(LT_RUNTIME_CONFIG).lt.errorTranslation,\n ),\n },\n { provide: LT_I18N_OPTIONS, useValue: config.i18n ?? {} },\n provideLtPreHydrationInput(config.preHydrationInput),\n provideAppInitializer(() => {\n if (config.configCheck !== false) {\n inject(LtApiUrlService).reportMissing();\n }\n }),\n provideAppInitializer(() => {\n const options = inject(LT_ERROR_TRANSLATION_OPTIONS);\n if (!isPlatformBrowser(inject(PLATFORM_ID)) || !options.enabled || !options.preload) {\n return;\n }\n // Not awaited: a slow or hanging API must never hold the app start (the translations are a signal).\n void inject(LtErrorTranslationService).loadTranslations();\n }),\n provideAppInitializer(() => {\n if (!isPlatformBrowser(inject(PLATFORM_ID))) {\n return;\n }\n void inject(ApplicationRef)\n .whenStable()\n .then(() => {\n (globalThis as Record<string, unknown>)[LT_HYDRATED_FLAG] = true;\n (globalThis as Record<string, unknown>)['__ltNgBaseVersion'] = LT_NG_BASE_VERSION;\n });\n }),\n ]);\n}\n","/**\n * Identity function and tagged template for Tailwind class strings outside templates, so the Tailwind IntelliSense\n * extension recognises them (configure `\"tailwindCSS.experimental.classRegex\": [\"tw`([^`]*)`\", \"tw\\\\(['\\\"]([^'\\\"]*)\"]`).\n *\n * @example\n * const card = tw`rounded-lg border p-4`;\n * const active = tw('bg-primary text-primary-foreground');\n */\nexport function tw(strings: TemplateStringsArray | string, ...values: unknown[]): string {\n if (typeof strings === 'string') {\n return strings;\n }\n return strings.reduce((result, part, index) => result + part + (index < values.length ? String(values[index]) : ''), '');\n}\n"],"mappings":"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"}
package/i18n/auth/de.json CHANGED
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "lt": {
3
3
  "auth": {
4
- "loggingOut": "Abmelden...",
5
4
  "noPasskeySelected": "Kein Passkey ausgewählt",
6
5
  "passkeyAborted": "Passkey-Authentifizierung wurde abgebrochen",
7
6
  "passkeyAlreadyRegistered": "Du hast bereits einen Passkey für diese Website registriert. Lösche ihn zuerst oder verwende einen anderen Authenticator.",
@@ -10,8 +9,7 @@
10
9
  "passkeyFailed": "Passkey-Anmeldung fehlgeschlagen",
11
10
  "passkeyRegisterFailed": "Passkey-Registrierung fehlgeschlagen",
12
11
  "passkeyUnsupported": "Passkeys werden in diesem Browser nicht unterstützt",
13
- "registerOptionsError": "Konnte Registrierungsoptionen nicht laden",
14
- "sessionExpired": "Sitzung abgelaufen"
12
+ "registerOptionsError": "Konnte Registrierungsoptionen nicht laden"
15
13
  }
16
14
  }
17
15
  }
package/i18n/auth/en.json CHANGED
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "lt": {
3
3
  "auth": {
4
- "loggingOut": "Logging out...",
5
4
  "noPasskeySelected": "No passkey selected",
6
5
  "passkeyAborted": "Passkey authentication was cancelled",
7
6
  "passkeyAlreadyRegistered": "You already registered a passkey for this website. Delete it first or use another authenticator.",
@@ -10,8 +9,7 @@
10
9
  "passkeyFailed": "Passkey login failed",
11
10
  "passkeyRegisterFailed": "Passkey registration failed",
12
11
  "passkeyUnsupported": "Passkeys are not supported in this browser",
13
- "registerOptionsError": "Could not load registration options",
14
- "sessionExpired": "Session expired"
12
+ "registerOptionsError": "Could not load registration options"
15
13
  }
16
14
  }
17
15
  }
package/i18n/de.json CHANGED
@@ -1,8 +1,7 @@
1
1
  {
2
2
  "lt": {
3
3
  "error": {
4
- "title": "Fehler",
5
- "loadFailed": "Fehlerübersetzungen konnten nicht geladen werden"
4
+ "title": "Fehler"
6
5
  }
7
6
  }
8
7
  }
package/i18n/en.json CHANGED
@@ -1,8 +1,7 @@
1
1
  {
2
2
  "lt": {
3
3
  "error": {
4
- "title": "Error",
5
- "loadFailed": "Failed to load error translations"
4
+ "title": "Error"
6
5
  }
7
6
  }
8
7
  }