{"version":3,"file":"jsverse-transloco-persist-translations.mjs","sources":["../../../../libs/transloco-persist-translations/src/lib/transloco-persist-translations.config.ts","../../../../libs/transloco-persist-translations/src/lib/helpers.ts","../../../../libs/transloco-persist-translations/src/lib/transloco-persist-translations.service.ts","../../../../libs/transloco-persist-translations/src/lib/transloco-persist-translations.providers.ts","../../../../libs/transloco-persist-translations/src/jsverse-transloco-persist-translations.ts"],"sourcesContent":["import {\n  ClassProvider,\n  ExistingProvider,\n  FactoryProvider,\n  InjectionToken,\n  Type,\n  ValueProvider,\n} from '@angular/core';\nimport { TranslocoLoader } from '@jsverse/transloco';\n\nimport { MaybeAsyncStorage } from './transloco.storage';\n\nexport interface StorageConfig {\n  ttl: number;\n  storageKey: string;\n}\n\ntype providerValue =\n  | Pick<ValueProvider, 'useValue'>\n  | Pick<ClassProvider, 'useClass'>\n  | Pick<ExistingProvider, 'useExisting'>\n  | Pick<FactoryProvider, 'useFactory' | 'deps'>;\nexport interface TranslocoPersistTranslationsConfig\n  extends Partial<StorageConfig> {\n  loader: Type<TranslocoLoader>;\n  storage: providerValue;\n}\n\nconst dayInMilliseconds = 86_400;\nexport const defaultConfig: StorageConfig = {\n  ttl: dayInMilliseconds,\n  storageKey: '@transloco/translations',\n};\n\nexport const TRANSLOCO_PERSIST_TRANSLATIONS_LOADER =\n  new InjectionToken<TranslocoLoader>('TRANSLOCO_PERSIST_TRANSLATIONS_LOADER');\n\nexport const TRANSLOCO_PERSIST_TRANSLATIONS_STORAGE =\n  new InjectionToken<MaybeAsyncStorage>(\n    'The storage to use for the persistance behavior',\n  );\n\nexport const TRANSLOCO_PERSIST_TRANSLATIONS_STORAGE_CONFIG =\n  new InjectionToken<StorageConfig>('Configuration for the storage behavior');\n","import { from, isObservable, Observable, of } from 'rxjs';\nimport { isFunction } from '@jsverse/utils';\n\nexport function isPromise(value: any): value is PromiseLike<unknown> {\n  return isFunction(value?.then);\n}\n\nexport function observify<T>(\n  asyncOrValue: PromiseLike<T> | Observable<T> | T,\n): Observable<T> {\n  if (isPromise(asyncOrValue) || isObservable(asyncOrValue)) {\n    return from(asyncOrValue);\n  }\n\n  return of(asyncOrValue);\n}\n","import { Translation, TranslocoLoader } from '@jsverse/transloco';\nimport { isObject, isString } from '@jsverse/utils';\nimport { from, Observable, of, Subscription } from 'rxjs';\nimport { filter, map, switchMap, take, tap } from 'rxjs/operators';\nimport { inject, Injectable, OnDestroy } from '@angular/core';\n\nimport { observify } from './helpers';\nimport {\n  TRANSLOCO_PERSIST_TRANSLATIONS_LOADER,\n  TRANSLOCO_PERSIST_TRANSLATIONS_STORAGE,\n  TRANSLOCO_PERSIST_TRANSLATIONS_STORAGE_CONFIG,\n} from './transloco-persist-translations.config';\n\nexport function getTimestampKey(key: string) {\n  return `${key}/timestamp`;\n}\n\n@Injectable()\nexport class TranslocoPersistTranslations\n  implements TranslocoLoader, OnDestroy\n{\n  private loader = inject(TRANSLOCO_PERSIST_TRANSLATIONS_LOADER);\n  private storage = inject(TRANSLOCO_PERSIST_TRANSLATIONS_STORAGE);\n  private config = inject(TRANSLOCO_PERSIST_TRANSLATIONS_STORAGE_CONFIG);\n\n  private subscription: Subscription | null =\n    this.clearCurrentStorage().subscribe();\n  private cache: Translation | null = null;\n\n  getTranslation(lang: string): Observable<Translation> {\n    const storageKey = this.config.storageKey;\n\n    return this.getCached(storageKey).pipe(\n      switchMap((translations) => {\n        if (translations?.[lang]) {\n          return of(translations[lang]);\n        }\n\n        return from(this.loader.getTranslation(lang)).pipe(\n          tap((translation) => this.setCache(storageKey, lang, translation)),\n        );\n      }),\n    );\n  }\n\n  clearCache() {\n    this.clearTimestamp(this.config.storageKey);\n    this.clearTranslations();\n    this.cache = null;\n  }\n\n  private getCached(key: string): Observable<Translation | null> {\n    return this.cache\n      ? of(this.cache)\n      : observify(this.storage.getItem(key)).pipe(\n          map((item) => {\n            return item ? this.decode<Translation>(key, item) : null;\n          }),\n          tap((item) => {\n            this.cache = item;\n          }),\n          take(1),\n        );\n  }\n\n  private setCache(key: string, lang: string, translation: Translation) {\n    const translations = this.cache || {};\n    translations[lang] = translation;\n    this.setTimestamp(key);\n    this.storage.setItem(key, this.encode(translations));\n    this.cache = translations;\n  }\n\n  private encode(value: unknown): string {\n    return JSON.stringify(value);\n  }\n\n  private decode<T>(key: string, item: any): T | null {\n    if (isObject(item) as T) {\n      return item;\n    } else if (isString(item)) {\n      try {\n        return JSON.parse(item);\n      } catch (e) {\n        console.error(`storage key: ${key} is not serializable`);\n        return null;\n      }\n    }\n    return null;\n  }\n\n  private setTimestamp(key: string): void {\n    this.storage.setItem(getTimestampKey(key), Date.now());\n  }\n\n  private getTimestamp(key: string): Observable<number> {\n    return observify(this.storage.getItem(getTimestampKey(key))).pipe(\n      map(parseInt),\n    );\n  }\n\n  private clearTimestamp(key: string): void {\n    this.storage.removeItem(getTimestampKey(key));\n  }\n\n  private clearTranslations(): void {\n    this.storage.removeItem(this.config.storageKey);\n  }\n\n  private clearCurrentStorage(): Observable<number> {\n    const storageKey = this.config.storageKey;\n\n    return this.getTimestamp(storageKey).pipe(\n      filter(Boolean),\n      tap((time) => {\n        const isExpired = Date.now() - time >= this.config.ttl;\n        if (isExpired) {\n          this.storage.removeItem(storageKey);\n        }\n      }),\n    );\n  }\n\n  ngOnDestroy() {\n    this.subscription?.unsubscribe();\n    // Caretaker note: it's important to clean up references to subscriptions since they save the `next`\n    // callback within its `destination` property, preventing classes from being GC'd.\n    this.subscription = null;\n  }\n}\n","import { makeEnvironmentProviders } from '@angular/core';\nimport { TRANSLOCO_LOADER } from '@jsverse/transloco';\n\nimport { TranslocoPersistTranslations } from './transloco-persist-translations.service';\nimport {\n  defaultConfig,\n  StorageConfig,\n  TRANSLOCO_PERSIST_TRANSLATIONS_LOADER,\n  TRANSLOCO_PERSIST_TRANSLATIONS_STORAGE,\n  TRANSLOCO_PERSIST_TRANSLATIONS_STORAGE_CONFIG,\n  TranslocoPersistTranslationsConfig,\n} from './transloco-persist-translations.config';\n\nexport function provideTranslocoPersistTranslations({\n  storage,\n  loader,\n  ...storageConfig\n}: TranslocoPersistTranslationsConfig) {\n  return makeEnvironmentProviders([\n    { provide: TRANSLOCO_LOADER, useClass: TranslocoPersistTranslations },\n    provideTranslocoPersistTranslationsConfig(storageConfig),\n    { provide: TRANSLOCO_PERSIST_TRANSLATIONS_LOADER, useClass: loader },\n    { provide: TRANSLOCO_PERSIST_TRANSLATIONS_STORAGE, ...storage },\n  ]);\n}\n\nexport function provideTranslocoPersistTranslationsConfig(\n  config?: Partial<StorageConfig>,\n) {\n  return {\n    provide: TRANSLOCO_PERSIST_TRANSLATIONS_STORAGE_CONFIG,\n    useValue: {\n      ...defaultConfig,\n      ...config,\n    },\n  };\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}